]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab ft=cpp | |
3 | ||
4 | /* | |
5 | * Ceph - scalable distributed file system | |
6 | * | |
7 | * Copyright (C) 2020 Red Hat, Inc | |
8 | * | |
9 | * This is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License version 2.1, as published by the Free Software | |
12 | * Foundation. See file COPYING. | |
13 | */ | |
14 | ||
15 | #pragma once | |
16 | ||
17 | #include <boost/smart_ptr/intrusive_ref_counter.hpp> | |
18 | #include "common/intrusive_lru.h" | |
19 | #include "rgw_data_sync.h" | |
20 | ||
21 | namespace rgw::bucket_sync { | |
22 | ||
23 | // per bucket-shard state cached by DataSyncShardCR | |
24 | struct State { | |
25 | // the source bucket shard to sync | |
26 | rgw_bucket_shard key; | |
27 | // current sync obligation being processed by DataSyncSingleEntry | |
28 | std::optional<rgw_data_sync_obligation> obligation; | |
29 | // incremented with each new obligation | |
30 | uint32_t counter = 0; | |
31 | // highest timestamp applied by all sources | |
32 | ceph::real_time progress_timestamp; | |
33 | ||
34 | State(const rgw_bucket_shard& key) noexcept : key(key) {} | |
35 | }; | |
36 | ||
37 | struct Entry; | |
38 | struct EntryToKey; | |
39 | class Handle; | |
40 | ||
41 | using lru_config = ceph::common::intrusive_lru_config< | |
42 | rgw_bucket_shard, Entry, EntryToKey>; | |
43 | ||
44 | // a recyclable cache entry | |
45 | struct Entry : State, ceph::common::intrusive_lru_base<lru_config> { | |
46 | using State::State; | |
47 | }; | |
48 | ||
49 | struct EntryToKey { | |
50 | using type = rgw_bucket_shard; | |
51 | const type& operator()(const Entry& e) { return e.key; } | |
52 | }; | |
53 | ||
54 | // use a non-atomic reference count since these aren't shared across threads | |
55 | template <typename T> | |
56 | using thread_unsafe_ref_counter = boost::intrusive_ref_counter< | |
57 | T, boost::thread_unsafe_counter>; | |
58 | ||
59 | // a state cache for entries within a single datalog shard | |
60 | class Cache : public thread_unsafe_ref_counter<Cache> { | |
61 | ceph::common::intrusive_lru<lru_config> cache; | |
62 | protected: | |
63 | // protected ctor to enforce the use of factory function create() | |
64 | explicit Cache(size_t target_size) { | |
65 | cache.set_target_size(target_size); | |
66 | } | |
67 | public: | |
68 | static boost::intrusive_ptr<Cache> create(size_t target_size) { | |
69 | return new Cache(target_size); | |
70 | } | |
71 | ||
72 | // find or create a cache entry for the given key, and return a Handle that | |
73 | // keeps it lru-pinned until destruction | |
74 | Handle get(const rgw_bucket_shard& key); | |
75 | }; | |
76 | ||
77 | // a State handle that keeps the Cache referenced | |
78 | class Handle { | |
79 | boost::intrusive_ptr<Cache> cache; | |
80 | boost::intrusive_ptr<Entry> entry; | |
81 | public: | |
82 | Handle() noexcept = default; | |
83 | ~Handle() = default; | |
84 | Handle(boost::intrusive_ptr<Cache> cache, | |
85 | boost::intrusive_ptr<Entry> entry) noexcept | |
86 | : cache(std::move(cache)), entry(std::move(entry)) {} | |
87 | Handle(Handle&&) = default; | |
88 | Handle(const Handle&) = default; | |
89 | Handle& operator=(Handle&& o) noexcept { | |
90 | // move the entry first so that its cache stays referenced over destruction | |
91 | entry = std::move(o.entry); | |
92 | cache = std::move(o.cache); | |
93 | return *this; | |
94 | } | |
95 | Handle& operator=(const Handle& o) noexcept { | |
96 | // copy the entry first so that its cache stays referenced over destruction | |
97 | entry = o.entry; | |
98 | cache = o.cache; | |
99 | return *this; | |
100 | } | |
101 | ||
102 | explicit operator bool() const noexcept { return static_cast<bool>(entry); } | |
103 | State& operator*() const noexcept { return *entry; } | |
104 | State* operator->() const noexcept { return entry.get(); } | |
105 | }; | |
106 | ||
107 | inline Handle Cache::get(const rgw_bucket_shard& key) | |
108 | { | |
109 | auto result = cache.get_or_create(key); | |
110 | return {this, std::move(result.first)}; | |
111 | } | |
112 | ||
113 | } // namespace rgw::bucket_sync |