/Users/deen/code/yugabyte-db/src/yb/consensus/log_anchor_registry.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | #include "yb/consensus/log_anchor_registry.h" |
33 | | |
34 | | #include <mutex> |
35 | | #include <string> |
36 | | |
37 | | #include "yb/consensus/opid_util.h" |
38 | | |
39 | | namespace yb { |
40 | | namespace log { |
41 | | |
42 | | using consensus::kInvalidOpIdIndex; |
43 | | using std::pair; |
44 | | using std::string; |
45 | | using strings::Substitute; |
46 | | using strings::SubstituteAndAppend; |
47 | | |
48 | 89.1k | LogAnchorRegistry::LogAnchorRegistry() { |
49 | 89.1k | } |
50 | | |
51 | 47.5k | LogAnchorRegistry::~LogAnchorRegistry() { |
52 | 47.5k | CHECK(anchors_.empty()); |
53 | 47.5k | } |
54 | | |
55 | | void LogAnchorRegistry::Register(int64_t log_index, |
56 | | const string& owner, |
57 | 1.52k | LogAnchor* anchor) { |
58 | 1.52k | std::lock_guard<simple_spinlock> l(lock_); |
59 | 1.52k | RegisterUnlocked(log_index, owner, anchor); |
60 | 1.52k | } |
61 | | |
62 | | Status LogAnchorRegistry::UpdateRegistration(int64_t log_index, |
63 | 1.46k | LogAnchor* anchor) { |
64 | 1.46k | std::lock_guard<simple_spinlock> l(lock_); |
65 | 1.46k | RETURN_NOT_OK_PREPEND(UnregisterUnlocked(anchor), |
66 | 1.46k | "Unable to swap registration, anchor not registered") |
67 | 1.46k | RegisterUnlocked(log_index, std::string(), anchor); |
68 | 1.46k | return Status::OK(); |
69 | 1.46k | } |
70 | | |
71 | 55 | Status LogAnchorRegistry::Unregister(LogAnchor* anchor) { |
72 | 55 | std::lock_guard<simple_spinlock> l(lock_); |
73 | 55 | return UnregisterUnlocked(anchor); |
74 | 55 | } |
75 | | |
76 | 2.40k | Status LogAnchorRegistry::UnregisterIfAnchored(LogAnchor* anchor) { |
77 | 2.40k | std::lock_guard<simple_spinlock> l(lock_); |
78 | 2.40k | if (!anchor->is_registered) return Status::OK(); |
79 | 960 | return UnregisterUnlocked(anchor); |
80 | 960 | } |
81 | | |
82 | 6.40M | Status LogAnchorRegistry::GetEarliestRegisteredLogIndex(int64_t* log_index) { |
83 | 6.40M | std::lock_guard<simple_spinlock> l(lock_); |
84 | 6.40M | auto iter = anchors_.begin(); |
85 | 6.40M | if (iter == anchors_.end()) { |
86 | 6.39M | static Status no_anchors_status = STATUS(NotFound, "No anchors in registry"); |
87 | 6.39M | return no_anchors_status; |
88 | 6.39M | } |
89 | | |
90 | | // Since this is a sorted map, the first element is the one we want. |
91 | 9.05k | *log_index = iter->first; |
92 | 9.05k | return Status::OK(); |
93 | 9.05k | } |
94 | | |
95 | 1 | size_t LogAnchorRegistry::GetAnchorCountForTests() const { |
96 | 1 | std::lock_guard<simple_spinlock> l(lock_); |
97 | 1 | return anchors_.size(); |
98 | 1 | } |
99 | | |
100 | 1 | std::string LogAnchorRegistry::DumpAnchorInfo() const { |
101 | 1 | string buf; |
102 | 1 | std::lock_guard<simple_spinlock> l(lock_); |
103 | 1 | MonoTime now = MonoTime::Now(); |
104 | 4 | for (const AnchorMultiMap::value_type& entry : anchors_) { |
105 | 4 | const LogAnchor* anchor = entry.second; |
106 | 4 | DCHECK(anchor->is_registered); |
107 | 4 | if (!buf.empty()) buf += ", "; |
108 | 4 | SubstituteAndAppend(&buf, "LogAnchor[index=$0, age=$1s, owner=$2]", |
109 | 4 | anchor->log_index, |
110 | 4 | now.GetDeltaSince(anchor->when_registered).ToSeconds(), |
111 | 4 | anchor->owner); |
112 | 4 | } |
113 | 1 | return buf; |
114 | 1 | } |
115 | | |
116 | | void LogAnchorRegistry::RegisterUnlocked(int64_t log_index, |
117 | | const std::string& owner, |
118 | 2.98k | LogAnchor* anchor) { |
119 | 2.98k | DCHECK(anchor != nullptr); |
120 | 2.98k | DCHECK(!anchor->is_registered); |
121 | | |
122 | 2.98k | anchor->log_index = log_index; |
123 | 2.98k | if (!owner.empty()) { // Keep existing owner during registration update. |
124 | 1.52k | anchor->owner = owner; |
125 | 1.52k | } |
126 | 2.98k | anchor->is_registered = true; |
127 | 2.98k | anchor->when_registered = MonoTime::Now(); |
128 | 2.98k | AnchorMultiMap::value_type value(log_index, anchor); |
129 | 2.98k | anchors_.insert(value); |
130 | 2.98k | } |
131 | | |
132 | 2.47k | Status LogAnchorRegistry::UnregisterUnlocked(LogAnchor* anchor) { |
133 | 2.47k | DCHECK(anchor != nullptr); |
134 | 2.47k | DCHECK(anchor->is_registered); |
135 | | |
136 | 2.47k | auto iter = anchors_.find(anchor->log_index); |
137 | 2.48k | while (iter != anchors_.end()) { |
138 | 2.48k | if (iter->second == anchor) { |
139 | 2.47k | anchor->is_registered = false; |
140 | 2.47k | anchors_.erase(iter); |
141 | | // No need for the iterator to remain valid since we return here. |
142 | 2.47k | return Status::OK(); |
143 | 11 | } else { |
144 | 11 | ++iter; |
145 | 11 | } |
146 | 2.48k | } |
147 | 18.4E | return STATUS(NotFound, Substitute("Anchor with index $0 and owner $1 not found", |
148 | 2.47k | anchor->log_index, anchor->owner)); |
149 | 2.47k | } |
150 | | |
151 | | LogAnchor::LogAnchor() |
152 | | : is_registered(false), |
153 | 1.52k | log_index(kInvalidOpIdIndex) { |
154 | 1.52k | } |
155 | | |
156 | 1.01k | LogAnchor::~LogAnchor() { |
157 | 0 | CHECK(!is_registered) << "Attempted to destruct a registered LogAnchor"; |
158 | 1.01k | } |
159 | | |
160 | | } // namespace log |
161 | | } // namespace yb |