/src/rocksdb/db/pinned_iterators_manager.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | // |
6 | | #pragma once |
7 | | #include <algorithm> |
8 | | #include <memory> |
9 | | #include <utility> |
10 | | #include <vector> |
11 | | |
12 | | #include "table/internal_iterator.h" |
13 | | |
14 | | namespace ROCKSDB_NAMESPACE { |
15 | | |
16 | | // PinnedIteratorsManager will be notified whenever we need to pin an Iterator |
17 | | // and it will be responsible for deleting pinned Iterators when they are |
18 | | // not needed anymore. |
19 | | class PinnedIteratorsManager : public Cleanable { |
20 | | public: |
21 | 23.7k | PinnedIteratorsManager() : pinning_enabled(false) {} |
22 | 23.7k | ~PinnedIteratorsManager() { |
23 | 23.7k | if (pinning_enabled) { |
24 | 11.5k | ReleasePinnedData(); |
25 | 11.5k | } |
26 | 23.7k | } |
27 | | |
28 | | // Move constructor and move assignment is allowed. |
29 | | PinnedIteratorsManager(PinnedIteratorsManager&& other) noexcept = default; |
30 | | PinnedIteratorsManager& operator=(PinnedIteratorsManager&& other) noexcept = |
31 | 0 | default; |
32 | | |
33 | | // Enable Iterators pinning |
34 | 11.9k | void StartPinning() { |
35 | 11.9k | assert(pinning_enabled == false); |
36 | 11.9k | pinning_enabled = true; |
37 | 11.9k | } |
38 | | |
39 | | // Is pinning enabled ? |
40 | 54.8k | bool PinningEnabled() { return pinning_enabled; } |
41 | | |
42 | | // Take ownership of iter and delete it when ReleasePinnedData() is called |
43 | 10.1k | void PinIterator(InternalIterator* iter, bool arena = false) { |
44 | 10.1k | if (arena) { |
45 | 0 | PinPtr(iter, &PinnedIteratorsManager::ReleaseArenaInternalIterator); |
46 | 10.1k | } else { |
47 | 10.1k | PinPtr(iter, &PinnedIteratorsManager::ReleaseInternalIterator); |
48 | 10.1k | } |
49 | 10.1k | } |
50 | | |
51 | | using ReleaseFunction = void (*)(void* arg1); |
52 | 10.1k | void PinPtr(void* ptr, ReleaseFunction release_func) { |
53 | 10.1k | assert(pinning_enabled); |
54 | 10.1k | if (ptr == nullptr) { |
55 | 89 | return; |
56 | 89 | } |
57 | 10.0k | pinned_ptrs_.emplace_back(ptr, release_func); |
58 | 10.0k | } |
59 | | |
60 | | // Release pinned Iterators |
61 | 11.9k | inline void ReleasePinnedData() { |
62 | 11.9k | assert(pinning_enabled == true); |
63 | 11.9k | pinning_enabled = false; |
64 | | |
65 | | // Remove duplicate pointers |
66 | 11.9k | std::sort(pinned_ptrs_.begin(), pinned_ptrs_.end()); |
67 | 11.9k | auto unique_end = std::unique(pinned_ptrs_.begin(), pinned_ptrs_.end()); |
68 | | |
69 | 22.0k | for (auto i = pinned_ptrs_.begin(); i != unique_end; ++i) { |
70 | 10.0k | void* ptr = i->first; |
71 | 10.0k | ReleaseFunction release_func = i->second; |
72 | 10.0k | release_func(ptr); |
73 | 10.0k | } |
74 | 11.9k | pinned_ptrs_.clear(); |
75 | | // Also do cleanups from the base Cleanable |
76 | 11.9k | Cleanable::Reset(); |
77 | 11.9k | } |
78 | | |
79 | | private: |
80 | 10.0k | static void ReleaseInternalIterator(void* ptr) { |
81 | 10.0k | delete static_cast<InternalIterator*>(ptr); |
82 | 10.0k | } |
83 | | |
84 | 0 | static void ReleaseArenaInternalIterator(void* ptr) { |
85 | 0 | static_cast<InternalIterator*>(ptr)->~InternalIterator(); |
86 | 0 | } |
87 | | |
88 | | bool pinning_enabled; |
89 | | std::vector<std::pair<void*, ReleaseFunction>> pinned_ptrs_; |
90 | | }; |
91 | | |
92 | | } // namespace ROCKSDB_NAMESPACE |