]> git.proxmox.com Git - ceph.git/blob - ceph/src/osd/object_state.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / osd / object_state.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #pragma once
5
6 #include "osd_types.h"
7
8 struct ObjectState {
9 object_info_t oi;
10 bool exists; ///< the stored object exists (i.e., we will remember the object_info_t)
11
12 ObjectState() : exists(false) {}
13
14 ObjectState(const object_info_t &oi_, bool exists_)
15 : oi(oi_), exists(exists_) {}
16 ObjectState(object_info_t &&oi_, bool exists_)
17 : oi(std::move(oi_)), exists(exists_) {}
18 ObjectState(const hobject_t &obj) : oi(obj), exists(false) {}
19 };
20
21 struct RWState {
22 enum State {
23 RWNONE,
24 RWREAD,
25 RWWRITE,
26 RWEXCL,
27 };
28 static const char *get_state_name(State s) {
29 switch (s) {
30 case RWNONE: return "none";
31 case RWREAD: return "read";
32 case RWWRITE: return "write";
33 case RWEXCL: return "excl";
34 default: return "???";
35 }
36 }
37 const char *get_state_name() const {
38 return get_state_name(state);
39 }
40
41 int count; ///< number of readers or writers
42 int waiters = 0; ///< number waiting
43
44 State state:4; ///< rw state
45 /// if set, restart backfill when we can get a read lock
46 bool recovery_read_marker:1;
47 /// if set, requeue snaptrim on lock release
48 bool snaptrimmer_write_marker:1;
49
50 RWState()
51 : count(0),
52 state(RWNONE),
53 recovery_read_marker(false),
54 snaptrimmer_write_marker(false)
55 {}
56
57 /// this function adjusts the counts if necessary
58 bool get_read_lock() {
59 // don't starve anybody!
60 if (waiters > 0) {
61 return false;
62 }
63 switch (state) {
64 case RWNONE:
65 ceph_assert(count == 0);
66 state = RWREAD;
67 // fall through
68 case RWREAD:
69 count++;
70 return true;
71 case RWWRITE:
72 return false;
73 case RWEXCL:
74 return false;
75 default:
76 ceph_abort_msg("unhandled case");
77 return false;
78 }
79 }
80
81 bool get_write_lock(bool greedy=false) {
82 if (!greedy) {
83 // don't starve anybody!
84 if (waiters > 0 ||
85 recovery_read_marker) {
86 return false;
87 }
88 }
89 switch (state) {
90 case RWNONE:
91 ceph_assert(count == 0);
92 state = RWWRITE;
93 // fall through
94 case RWWRITE:
95 count++;
96 return true;
97 case RWREAD:
98 return false;
99 case RWEXCL:
100 return false;
101 default:
102 ceph_abort_msg("unhandled case");
103 return false;
104 }
105 }
106 bool get_excl_lock() {
107 switch (state) {
108 case RWNONE:
109 ceph_assert(count == 0);
110 state = RWEXCL;
111 count = 1;
112 return true;
113 case RWWRITE:
114 return false;
115 case RWREAD:
116 return false;
117 case RWEXCL:
118 return false;
119 default:
120 ceph_abort_msg("unhandled case");
121 return false;
122 }
123 }
124 /// same as get_write_lock, but ignore starvation
125 bool take_write_lock() {
126 if (state == RWWRITE) {
127 count++;
128 return true;
129 }
130 return get_write_lock();
131 }
132 bool dec() {
133 ceph_assert(count > 0);
134 count--;
135 if (count == 0) {
136 state = RWNONE;
137 return true;
138 } else {
139 return false;
140 }
141 }
142 bool put_read() {
143 ceph_assert(state == RWREAD);
144 return dec();
145 }
146 bool put_write() {
147 ceph_assert(state == RWWRITE);
148 return dec();
149 }
150 bool put_excl() {
151 ceph_assert(state == RWEXCL);
152 return dec();
153 }
154 void inc_waiters() {
155 ++waiters;
156 }
157 void release_waiters() {
158 waiters = 0;
159 }
160 void dec_waiters(int count) {
161 ceph_assert(waiters >= count);
162 waiters -= count;
163 }
164 bool empty() const { return state == RWNONE; }
165
166 bool get_snaptrimmer_write(bool mark_if_unsuccessful) {
167 if (get_write_lock()) {
168 return true;
169 } else {
170 if (mark_if_unsuccessful)
171 snaptrimmer_write_marker = true;
172 return false;
173 }
174 }
175 bool get_recovery_read() {
176 recovery_read_marker = true;
177 if (get_read_lock()) {
178 return true;
179 }
180 return false;
181 }
182 };
183
184 inline ostream& operator<<(ostream& out, const RWState& rw)
185 {
186 return out << "rwstate(" << rw.get_state_name()
187 << " n=" << rw.count
188 << " w=" << rw.waiters
189 << ")";
190 }