1 /*
2 * FDBTypes.h
3 *
4 * This source file is part of the FoundationDB open source project
5 *
6 * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #ifndef FDBCLIENT_FDBTYPES_H
22 #define FDBCLIENT_FDBTYPES_H
23
24 #include "flow/flow.h"
25 #include "fdbclient/Knobs.h"
26
27 using std::vector;
28 using std::pair;
29 typedef int64_t Version;
30 typedef uint64_t LogEpoch;
31 typedef uint64_t Sequence;
32 typedef StringRef KeyRef;
33 typedef StringRef ValueRef;
34 typedef int64_t Generation;
35
36 enum { tagLocalitySpecial = -1, tagLocalityLogRouter = -2, tagLocalityRemoteLog = -3, tagLocalityUpgraded = -4, tagLocalitySatellite = -5, tagLocalityInvalid = -99 }; //The TLog and LogRouter require these number to be as compact as possible
37
38 #pragma pack(push, 1)
39 struct Tag {
40 int8_t locality;
41 uint16_t id;
42
TagTag43 Tag() : locality(tagLocalitySpecial), id(0) {}
TagTag44 Tag(int8_t locality, uint16_t id) : locality(locality), id(id) {}
45
46 bool operator == ( const Tag& r ) const { return locality==r.locality && id==r.id; }
47 bool operator != ( const Tag& r ) const { return locality!=r.locality || id!=r.id; }
48 bool operator < ( const Tag& r ) const { return locality < r.locality || (locality == r.locality && id < r.id); }
49
toStringTag50 std::string toString() const {
51 return format("%d:%d", locality, id);
52 }
53
54 template <class Ar>
serialize_unversionedTag55 force_inline void serialize_unversioned(Ar& ar) {
56 serializer(ar, locality, id);
57 }
58 };
59 #pragma pack(pop)
60
load(Ar & ar,Tag & tag)61 template <class Ar> void load( Ar& ar, Tag& tag ) { tag.serialize_unversioned(ar); }
save(Ar & ar,Tag const & tag)62 template <class Ar> void save( Ar& ar, Tag const& tag ) { const_cast<Tag&>(tag).serialize_unversioned(ar); }
63
64 static const Tag invalidTag {tagLocalitySpecial, 0};
65 static const Tag txsTag {tagLocalitySpecial, 1};
66
67 enum { txsTagOld = -1, invalidTagOld = -100 };
68
69 struct TagsAndMessage {
70 StringRef message;
71 std::vector<Tag> tags;
72
TagsAndMessageTagsAndMessage73 TagsAndMessage() {}
TagsAndMessageTagsAndMessage74 TagsAndMessage(StringRef message, const std::vector<Tag>& tags) : message(message), tags(tags) {}
75 };
76
77 struct KeyRangeRef;
78 struct KeyValueRef;
79
80 template <class Collection>
uniquify(Collection & c)81 void uniquify( Collection& c ) {
82 std::sort(c.begin(), c.end());
83 c.resize( std::unique(c.begin(), c.end()) - c.begin() );
84 }
85
describe(const Tag item)86 static std::string describe( const Tag item ) {
87 return format("%d:%d", item.locality, item.id);
88 }
89
describe(const int item)90 static std::string describe( const int item ) {
91 return format("%d", item);
92 }
93
94 template <class T>
describe(Reference<T> const & item)95 static std::string describe( Reference<T> const& item ) {
96 return item->toString();
97 }
98
99 template <class T>
describe(T const & item)100 static std::string describe( T const& item ) {
101 return item.toString();
102 }
103
104 template <class K, class V>
105 static std::string describe( std::map<K, V> const& items, int max_items = -1 ) {
106 if(!items.size())
107 return "[no items]";
108
109 std::string s;
110 int count = 0;
111 for(auto it = items.begin(); it != items.end(); it++) {
112 if( ++count > max_items && max_items >= 0)
113 break;
114 if (count > 1) s += ",";
115 s += describe(it->first) + "=>" + describe(it->second);
116 }
117 return s;
118 }
119
120 template <class T>
describeList(T const & items,int max_items)121 static std::string describeList( T const& items, int max_items ) {
122 if(!items.size())
123 return "[no items]";
124
125 std::string s;
126 int count = 0;
127 for(auto const& item : items) {
128 if( ++count > max_items && max_items >= 0)
129 break;
130 if (count > 1) s += ",";
131 s += describe(item);
132 }
133 return s;
134 }
135
136 template <class T>
137 static std::string describe( std::vector<T> const& items, int max_items = -1 ) {
138 return describeList(items, max_items);
139 }
140
141 template <class T>
142 static std::string describe( std::set<T> const& items, int max_items = -1 ) {
143 return describeList(items, max_items);
144 }
145
146 std::string printable( const StringRef& val );
147 std::string printable( const std::string& val );
148 std::string printable( const KeyRangeRef& range );
149 std::string printable( const VectorRef<StringRef>& val );
150 std::string printable( const VectorRef<KeyValueRef>& val );
151 std::string printable( const KeyValueRef& val );
152
153 template <class T>
printable(const Optional<T> & val)154 std::string printable( const Optional<T>& val ) {
155 if( val.present() )
156 return printable( val.get() );
157 return "[not set]";
158 }
159
equalsKeyAfter(const KeyRef & key,const KeyRef & compareKey)160 inline bool equalsKeyAfter( const KeyRef& key, const KeyRef& compareKey ) {
161 if( key.size()+1 != compareKey.size() || compareKey[compareKey.size()-1] != 0 )
162 return false;
163 return compareKey.startsWith( key );
164 }
165
166 struct KeyRangeRef {
167 const KeyRef begin, end;
KeyRangeRefKeyRangeRef168 KeyRangeRef() {}
KeyRangeRefKeyRangeRef169 KeyRangeRef( const KeyRef& begin, const KeyRef& end ) : begin(begin), end(end) {
170 if( begin > end ) {
171 throw inverted_range();
172 }
173 }
KeyRangeRefKeyRangeRef174 KeyRangeRef( Arena& a, const KeyRangeRef& copyFrom ) : begin(a, copyFrom.begin), end(a, copyFrom.end) {}
175 bool operator == ( const KeyRangeRef& r ) const { return begin == r.begin && end == r.end; }
176 bool operator != ( const KeyRangeRef& r ) const { return begin != r.begin || end != r.end; }
containsKeyRangeRef177 bool contains( const KeyRef& key ) const { return begin <= key && key < end; }
containsKeyRangeRef178 bool contains( const KeyRangeRef& keys ) const { return begin <= keys.begin && keys.end <= end; }
intersectsKeyRangeRef179 bool intersects( const KeyRangeRef& keys ) const { return begin < keys.end && keys.begin < end; }
emptyKeyRangeRef180 bool empty() const { return begin == end; }
singleKeyRangeKeyRangeRef181 bool singleKeyRange() const { return equalsKeyAfter(begin, end); }
182
withPrefixKeyRangeRef183 Standalone<KeyRangeRef> withPrefix( const StringRef& prefix ) const {
184 return KeyRangeRef( begin.withPrefix(prefix), end.withPrefix(prefix) );
185 }
186
removePrefixKeyRangeRef187 KeyRangeRef removePrefix( const StringRef& prefix ) const {
188 return KeyRangeRef( begin.removePrefix(prefix), end.removePrefix(prefix) );
189 }
190
191 const KeyRangeRef& operator = (const KeyRangeRef& rhs) {
192 const_cast<KeyRef&>(begin) = rhs.begin;
193 const_cast<KeyRef&>(end) = rhs.end;
194 return *this;
195 }
196
expectedSizeKeyRangeRef197 int expectedSize() const { return begin.expectedSize() + end.expectedSize(); }
198
199 template <class Ar>
serializeKeyRangeRef200 force_inline void serialize(Ar& ar) {
201 serializer(ar, const_cast<KeyRef&>(begin), const_cast<KeyRef&>(end));
202 if( begin > end ) {
203 throw inverted_range();
204 };
205 }
206
207 struct ArbitraryOrder {
operatorKeyRangeRef::ArbitraryOrder208 bool operator()(KeyRangeRef const& a, KeyRangeRef const& b) const {
209 if (a.begin < b.begin) return true;
210 if (a.begin > b.begin) return false;
211 return a.end < b.end;
212 }
213 };
214 };
215
216 template<>
217 struct Traceable<KeyRangeRef> : std::true_type {
218 static std::string toString(const KeyRangeRef& value) {
219 auto begin = Traceable<StringRef>::toString(value.begin);
220 auto end = Traceable<StringRef>::toString(value.end);
221 std::string result;
222 result.reserve(begin.size() + end.size() + 3);
223 std::copy(begin.begin(), begin.end(), std::back_inserter(result));
224 result.push_back(' ');
225 result.push_back('-');
226 result.push_back(' ');
227 std::copy(end.begin(), end.end(), std::back_inserter(result));
228 return result;
229 }
230 };
231
232
233 inline KeyRangeRef operator & (const KeyRangeRef& lhs, const KeyRangeRef& rhs) {
234 KeyRef b = std::max(lhs.begin, rhs.begin), e = std::min(lhs.end, rhs.end);
235 if (e < b)
236 return KeyRangeRef();
237 return KeyRangeRef(b,e);
238 }
239
240 struct KeyValueRef {
241 KeyRef key;
242 ValueRef value;
243 KeyValueRef() {}
244 KeyValueRef( const KeyRef& key, const ValueRef& value ) : key(key), value(value) {}
245 KeyValueRef( Arena& a, const KeyValueRef& copyFrom ) : key(a, copyFrom.key), value(a, copyFrom.value) {}
246 bool operator == ( const KeyValueRef& r ) const { return key == r.key && value == r.value; }
247 bool operator != ( const KeyValueRef& r ) const { return key != r.key || value != r.value; }
248
249 int expectedSize() const { return key.expectedSize() + value.expectedSize(); }
250
251 template <class Ar>
252 force_inline void serialize(Ar& ar) { serializer(ar, key, value); }
253
254 struct OrderByKey {
255 bool operator()(KeyValueRef const& a, KeyValueRef const& b) const {
256 return a.key < b.key;
257 }
258 template <class T>
259 bool operator()(T const& a, KeyValueRef const& b) const {
260 return a < b.key;
261 }
262 template <class T>
263 bool operator()(KeyValueRef const& a, T const& b) const {
264 return a.key < b;
265 }
266 };
267
268 struct OrderByKeyBack {
269 bool operator()(KeyValueRef const& a, KeyValueRef const& b) const {
270 return a.key > b.key;
271 }
272 template <class T>
273 bool operator()(T const& a, KeyValueRef const& b) const {
274 return a > b.key;
275 }
276 template <class T>
277 bool operator()(KeyValueRef const& a, T const& b) const {
278 return a.key > b;
279 }
280 };
281 };
282
283 template<>
284 struct Traceable<KeyValueRef> : std::true_type {
285 static std::string toString(const KeyValueRef& value) {
286 return Traceable<KeyRef>::toString(value.key) + format(":%d", value.value.size());
287 }
288 };
289
290 typedef Standalone<KeyRef> Key;
291 typedef Standalone<ValueRef> Value;
292 typedef Standalone<KeyRangeRef> KeyRange;
293 typedef Standalone<KeyValueRef> KeyValue;
294 typedef Standalone<struct KeySelectorRef> KeySelector;
295
296 enum { invalidVersion = -1, latestVersion = -2 };
297
298 inline Key keyAfter( const KeyRef& key ) {
299 if(key == LiteralStringRef("\xff\xff"))
300 return key;
301
302 Standalone<StringRef> r;
303 uint8_t* s = new (r.arena()) uint8_t[ key.size() + 1 ];
304 memcpy(s, key.begin(), key.size() );
305 s[key.size()] = 0;
306 ((StringRef&) r) = StringRef( s, key.size() + 1 );
307 return r;
308 }
309 inline KeyRef keyAfter( const KeyRef& key, Arena& arena ) {
310 if(key == LiteralStringRef("\xff\xff"))
311 return key;
312 uint8_t* t = new ( arena ) uint8_t[ key.size()+1 ];
313 memcpy(t, key.begin(), key.size() );
314 t[key.size()] = 0;
315 return KeyRef(t,key.size()+1);
316 }
317 inline KeyRange singleKeyRange( const KeyRef& a ) {
318 return KeyRangeRef(a, keyAfter(a));
319 }
320 inline KeyRangeRef singleKeyRange( KeyRef const& key, Arena& arena ) {
321 uint8_t* t = new ( arena ) uint8_t[ key.size()+1 ];
322 memcpy(t, key.begin(), key.size() );
323 t[key.size()] = 0;
324 return KeyRangeRef( KeyRef(t,key.size()), KeyRef(t, key.size()+1) );
325 }
326 inline KeyRange prefixRange( KeyRef prefix ) {
327 Standalone<KeyRangeRef> range;
328 KeyRef start = KeyRef(range.arena(), prefix);
329 KeyRef end = strinc(prefix, range.arena());
330 range.contents() = KeyRangeRef(start, end);
331 return range;
332 }
333 inline KeyRef keyBetween( const KeyRangeRef& keys ) {
334 // Returns (one of) the shortest key(s) either contained in keys or equal to keys.end,
335 // assuming its length is no more than CLIENT_KNOBS->SPLIT_KEY_SIZE_LIMIT. If the length of
336 // the shortest key exceeds that limit, then the end key is returned.
337 // The returned reference is valid as long as keys is valid.
338
339 int pos = 0; // will be the position of the first difference between keys.begin and keys.end
340 int minSize = std::min( keys.begin.size(), keys.end.size() );
341 for(; pos < minSize && pos < CLIENT_KNOBS->SPLIT_KEY_SIZE_LIMIT; pos++ ) {
342 if( keys.begin[pos] != keys.end[pos] ) {
343 return keys.end.substr(0,pos+1);
344 }
345 }
346
347 // If one more character keeps us in the limit, and the latter key is simply
348 // longer, then we only need one more byte of the end string.
349 if (pos < CLIENT_KNOBS->SPLIT_KEY_SIZE_LIMIT && keys.begin.size() < keys.end.size()) {
350 return keys.end.substr(0,pos+1);
351 }
352
353 return keys.end;
354 }
355
356 struct KeySelectorRef {
357 private:
358 KeyRef key; // Find the last item less than key
359
360 public:
361 bool orEqual; // (or equal to key, if this is true)
362 int offset; // and then move forward this many items (or backward if negative)
363 KeySelectorRef() {}
364 KeySelectorRef( const KeyRef& key, bool orEqual, int offset ) : orEqual(orEqual), offset(offset) {
365 setKey(key);
366 }
367
368 KeySelectorRef( Arena& arena, const KeySelectorRef& copyFrom ) : key(arena, copyFrom.key), orEqual(copyFrom.orEqual), offset(copyFrom.offset) {}
369 int expectedSize() const { return key.expectedSize(); }
370
371 void removeOrEqual(Arena &arena) {
372 if(orEqual) {
373 setKey(keyAfter(key, arena));
374 orEqual = false;
375 }
376 }
377
378 KeyRef getKey() const {
379 return key;
380 }
381
382 void setKey(KeyRef const& key) {
383 //There are no keys in the database with size greater than KEY_SIZE_LIMIT, so if this key selector has a key which is large,
384 //then we can translate it to an equivalent key selector with a smaller key
385 if(key.size() > (key.startsWith(LiteralStringRef("\xff")) ? CLIENT_KNOBS->SYSTEM_KEY_SIZE_LIMIT : CLIENT_KNOBS->KEY_SIZE_LIMIT))
386 this->key = key.substr(0, (key.startsWith(LiteralStringRef("\xff")) ? CLIENT_KNOBS->SYSTEM_KEY_SIZE_LIMIT : CLIENT_KNOBS->KEY_SIZE_LIMIT)+1);
387 else
388 this->key = key;
389 }
390
391 std::string toString() const {
392 if (offset > 0) {
393 if (orEqual) return format("%d+firstGreaterThan(%s)", offset-1, printable(key).c_str());
394 else return format("%d+firstGreaterOrEqual(%s)", offset-1, printable(key).c_str());
395 } else {
396 if (orEqual) return format("%d+lastLessOrEqual(%s)", offset, printable(key).c_str());
397 else return format("%d+lastLessThan(%s)", offset, printable(key).c_str());
398 }
399 }
400
401 bool isBackward() const { return !orEqual && offset<=0; } // True if the resolution of the KeySelector depends only on keys less than key
402 bool isFirstGreaterOrEqual() const { return !orEqual && offset==1; }
403 bool isFirstGreaterThan() const { return orEqual && offset==1; }
404 bool isLastLessOrEqual() const { return orEqual && offset==0; }
405
406 // True iff, regardless of the contents of the database, lhs must resolve to a key > rhs
407 bool isDefinitelyGreater( KeyRef const& k ) {
408 return offset >= 1 && ( isFirstGreaterOrEqual() ? key > k : key >= k );
409 }
410 // True iff, regardless of the contents of the database, lhs must resolve to a key < rhs
411 bool isDefinitelyLess( KeyRef const& k ) {
412 return offset <= 0 && ( isLastLessOrEqual() ? key < k : key <= k );
413 }
414
415 template <class Ar>
416 void serialize( Ar& ar ) {
417 serializer(ar, key, orEqual, offset);
418 }
419 };
420
421 inline bool operator == (const KeySelectorRef& lhs, const KeySelectorRef& rhs) { return lhs.getKey() == rhs.getKey() && lhs.orEqual==rhs.orEqual && lhs.offset==rhs.offset; }
422 inline KeySelectorRef lastLessThan( const KeyRef& k ) {
423 return KeySelectorRef( k, false, 0 );
424 }
425 inline KeySelectorRef lastLessOrEqual( const KeyRef& k ) {
426 return KeySelectorRef( k, true, 0 );
427 }
428 inline KeySelectorRef firstGreaterThan( const KeyRef& k ) {
429 return KeySelectorRef( k, true, +1 );
430 }
431 inline KeySelectorRef firstGreaterOrEqual( const KeyRef& k ) {
432 return KeySelectorRef( k, false, +1 );
433 }
434 inline KeySelectorRef operator + (const KeySelectorRef& s, int off) {
435 return KeySelectorRef(s.getKey(), s.orEqual, s.offset+off);
436 }
437 inline KeySelectorRef operator - (const KeySelectorRef& s, int off) {
438 return KeySelectorRef(s.getKey(), s.orEqual, s.offset-off);
439 }
440
441 template <class Val>
442 struct KeyRangeWith : KeyRange {
443 Val value;
444 KeyRangeWith() {}
445 KeyRangeWith( const KeyRangeRef& range, const Val& value ) : KeyRange(range), value(value) {}
446 bool operator == ( const KeyRangeWith& r ) const { return KeyRangeRef::operator==(r) && value == r.value; }
447
448 template <class Ar>
449 void serialize( Ar& ar ) {
450 serializer(ar, ((KeyRange&)*this), value);
451 }
452 };
453 template <class Val>
454 static inline KeyRangeWith<Val> keyRangeWith( const KeyRangeRef& range, const Val& value ) {
455 return KeyRangeWith<Val>(range, value);
456 }
457
458 struct GetRangeLimits {
459 enum { ROW_LIMIT_UNLIMITED = -1, BYTE_LIMIT_UNLIMITED = -1 };
460
461 int rows;
462 int minRows;
463 int bytes;
464
465 GetRangeLimits() : rows( ROW_LIMIT_UNLIMITED ), minRows(1), bytes( BYTE_LIMIT_UNLIMITED ) {}
466 explicit GetRangeLimits( int rowLimit ) : rows( rowLimit ), minRows(1), bytes( BYTE_LIMIT_UNLIMITED ) {}
467 GetRangeLimits( int rowLimit, int byteLimit ) : rows( rowLimit ), minRows(1), bytes( byteLimit ) {}
468
469 void decrement( VectorRef<KeyValueRef> const& data );
470 void decrement( KeyValueRef const& data );
471
472 // True if either the row or byte limit has been reached
473 bool isReached();
474
475 // True if data would cause the row or byte limit to be reached
476 bool reachedBy( VectorRef<KeyValueRef> const& data );
477
478 bool hasByteLimit();
479 bool hasRowLimit();
480
481 bool hasSatisfiedMinRows();
482 bool isValid() { return (rows >= 0 || rows == ROW_LIMIT_UNLIMITED)
483 && (bytes >= 0 || bytes == BYTE_LIMIT_UNLIMITED)
484 && minRows >= 0 && (minRows <= rows || rows == ROW_LIMIT_UNLIMITED); }
485 };
486
487 struct RangeResultRef : VectorRef<KeyValueRef> {
488 bool more; // True if (but not necessarily only if) values remain in the *key* range requested (possibly beyond the limits requested)
489 // False implies that no such values remain
490 Optional<KeyRef> readThrough; // Only present when 'more' is true. When present, this value represent the end (or beginning if reverse) of the range
491 // which was read to produce these results. This is guarenteed to be less than the requested range.
492 bool readToBegin;
493 bool readThroughEnd;
494
495 RangeResultRef() : more(false), readToBegin(false), readThroughEnd(false) {}
496 RangeResultRef( Arena& p, const RangeResultRef& toCopy ) : more( toCopy.more ), readToBegin( toCopy.readToBegin ), readThroughEnd( toCopy.readThroughEnd ), readThrough( toCopy.readThrough.present() ? KeyRef( p, toCopy.readThrough.get() ) : Optional<KeyRef>() ), VectorRef<KeyValueRef>( p, toCopy ) {}
497 RangeResultRef( const VectorRef<KeyValueRef>& value, bool more, Optional<KeyRef> readThrough = Optional<KeyRef>() ) : VectorRef<KeyValueRef>( value ), more( more ), readThrough( readThrough ), readToBegin( false ), readThroughEnd( false ) {}
498 RangeResultRef( bool readToBegin, bool readThroughEnd ) : more(false), readToBegin(readToBegin), readThroughEnd(readThroughEnd) { }
499
500 template <class Ar>
501 void serialize( Ar& ar ) {
502 serializer(ar, ((VectorRef<KeyValueRef>&)*this), more, readThrough, readToBegin, readThroughEnd);
503 }
504 };
505
506 template<>
507 struct Traceable<RangeResultRef> : std::true_type {
508 static std::string toString(const RangeResultRef& value) {
509 return Traceable<VectorRef<KeyValueRef>>::toString(value);
510 }
511 };
512
513 struct KeyValueStoreType {
514 // These enumerated values are stored in the database configuration, so can NEVER be changed. Only add new ones just before END.
515 enum StoreType {
516 SSD_BTREE_V1,
517 MEMORY,
518 SSD_BTREE_V2,
519 SSD_REDWOOD_V1,
520 END
521 };
522
523 KeyValueStoreType() : type(END) {}
524 KeyValueStoreType( StoreType type ) : type(type) {
525 if ((uint32_t)type > END)
526 this->type = END;
527 }
528 operator StoreType() const { return StoreType(type); }
529
530 template <class Ar>
531 void serialize(Ar& ar) { serializer(ar, type); }
532
533 std::string toString() const {
534 switch( type ) {
535 case SSD_BTREE_V1: return "ssd-1";
536 case SSD_BTREE_V2: return "ssd-2";
537 case SSD_REDWOOD_V1: return "ssd-redwood-experimental";
538 case MEMORY: return "memory";
539 default: return "unknown";
540 }
541 }
542
543 private:
544 uint32_t type;
545 };
546
547 template<>
548 struct Traceable<KeyValueStoreType> : std::true_type {
549 static std::string toString(KeyValueStoreType const& value) {
550 return value.toString();
551 }
552 };
553
554 struct TLogVersion {
555 enum Version {
556 UNSET = 0,
557 // Everything between BEGIN and END should be densely packed, so that we
558 // can iterate over them easily.
559 // V1 = 1, // 4.6 is dispatched to via 6.0
560 V2 = 2, // 6.0
561 V3 = 3, // 6.1
562 MIN_SUPPORTED = V2,
563 MAX_SUPPORTED = V3,
564 MIN_RECRUITABLE = V2,
565 DEFAULT = V2,
566 } version;
567
568 TLogVersion() : version(UNSET) {}
569 TLogVersion( Version v ) : version(v) {}
570
571 operator Version() const {
572 return version;
573 }
574
575 template <class Ar>
576 void serialize(Ar& ar) {
577 uint32_t v = (uint32_t)version;
578 serializer(ar, v);
579 version = (Version)v;
580 }
581
582 static ErrorOr<TLogVersion> FromStringRef( StringRef s ) {
583 if (s == LiteralStringRef("2")) return V2;
584 if (s == LiteralStringRef("3")) return V3;
585 return default_error_or();
586 }
587 };
588
589 template<>
590 struct Traceable<TLogVersion> : std::true_type {
591 static std::string toString(TLogVersion const& value) {
592 return Traceable<Version>::toString(value.version);
593 }
594 };
595
596 struct TLogSpillType {
597 // These enumerated values are stored in the database configuration, so can NEVER be changed. Only add new ones just before END.
598 enum SpillType {
599 UNSET = 0,
600 DEFAULT = 1,
601 VALUE = 1,
602 REFERENCE = 2,
603 END = 3,
604 };
605
606 TLogSpillType() : type(DEFAULT) {}
607 TLogSpillType( SpillType type ) : type(type) {
608 if ((uint32_t)type >= END) {
609 this->type = UNSET;
610 }
611 }
612 operator SpillType() const { return SpillType(type); }
613
614 template <class Ar>
615 void serialize(Ar& ar) { serializer(ar, type); }
616
617 std::string toString() const {
618 switch( type ) {
619 case VALUE: return "value";
620 case REFERENCE: return "reference";
621 case UNSET: return "unset";
622 default: ASSERT(false);
623 }
624 return "";
625 }
626
627 static ErrorOr<TLogSpillType> FromStringRef( StringRef s ) {
628 if ( s == LiteralStringRef("1") ) return VALUE;
629 if ( s == LiteralStringRef("2") ) return REFERENCE;
630 return default_error_or();
631 }
632
633 private:
634 uint32_t type;
635 };
636
637 //Contains the amount of free and total space for a storage server, in bytes
638 struct StorageBytes {
639 int64_t free;
640 int64_t total;
641 int64_t used; // Used by *this* store, not total-free
642 int64_t available; // Amount of disk space that can be used by data structure, including free disk space and internally reusable space
643
644 StorageBytes() { }
645 StorageBytes(int64_t free, int64_t total, int64_t used, int64_t available) : free(free), total(total), used(used), available(available) { }
646
647 template <class Ar>
648 void serialize(Ar& ar) {
649 serializer(ar, free, total, used, available);
650 }
651 };
652
653 struct LogMessageVersion {
654 // Each message pushed into the log system has a unique, totally ordered LogMessageVersion
655 // See ILogSystem::push() for how these are assigned
656 Version version;
657 uint32_t sub;
658
659 void reset(Version v) {
660 version = v;
661 sub = 0;
662 }
663
664 bool operator<(LogMessageVersion const& r) const {
665 if (version<r.version) return true;
666 if (r.version<version) return false;
667 return sub < r.sub;
668 }
669
670 bool operator==(LogMessageVersion const& r) const { return version == r.version && sub == r.sub; }
671
672 std::string toString() const { return format("%lld.%d", version, sub); }
673
674 LogMessageVersion(Version version, uint32_t sub) : version(version), sub(sub) {}
675 explicit LogMessageVersion(Version version) : version(version), sub(0) {}
676 LogMessageVersion() : version(0), sub(0) {}
677 bool empty() const { return (version == 0) && (sub == 0); }
678 };
679
680 struct AddressExclusion {
681 IPAddress ip;
682 int port;
683
684 AddressExclusion() : ip(0), port(0) {}
685 explicit AddressExclusion(const IPAddress& ip) : ip(ip), port(0) {}
686 explicit AddressExclusion(const IPAddress& ip, int port) : ip(ip), port(port) {}
687
688 bool operator<(AddressExclusion const& r) const {
689 if (ip != r.ip) return ip < r.ip;
690 return port < r.port;
691 }
692 bool operator==(AddressExclusion const& r) const { return ip == r.ip && port == r.port; }
693
694 bool isWholeMachine() const { return port == 0; }
695 bool isValid() const { return ip.isValid() || port != 0; }
696
697 bool excludes( NetworkAddress const& addr ) const {
698 if(isWholeMachine())
699 return ip == addr.ip;
700 return ip == addr.ip && port == addr.port;
701 }
702
703 // This is for debugging and IS NOT to be used for serialization to persistant state
704 std::string toString() const {
705 if (!isWholeMachine())
706 return formatIpPort(ip, port);
707 return ip.toString();
708 }
709
710 static AddressExclusion parse( StringRef const& );
711
712 template <class Ar>
713 void serialize(Ar& ar) {
714 serializer(ar, ip, port);
715 }
716 };
717
718 static bool addressExcluded( std::set<AddressExclusion> const& exclusions, NetworkAddress const& addr ) {
719 return exclusions.count( AddressExclusion(addr.ip, addr.port) ) || exclusions.count( AddressExclusion(addr.ip) );
720 }
721
722 struct ClusterControllerPriorityInfo {
723 enum DCFitness { FitnessPrimary, FitnessRemote, FitnessPreferred, FitnessUnknown, FitnessBad }; //cannot be larger than 7 because of leader election mask
724
725 static DCFitness calculateDCFitness(Optional<Key> const& dcId, vector<Optional<Key>> const& dcPriority) {
726 if(!dcPriority.size()) {
727 return FitnessUnknown;
728 } else if(dcPriority.size() == 1) {
729 if(dcId == dcPriority[0]) {
730 return FitnessPreferred;
731 } else {
732 return FitnessUnknown;
733 }
734 } else {
735 if(dcId == dcPriority[0]) {
736 return FitnessPrimary;
737 } else if(dcId == dcPriority[1]) {
738 return FitnessRemote;
739 } else {
740 return FitnessBad;
741 }
742 }
743 }
744
745 uint8_t processClassFitness;
746 bool isExcluded;
747 uint8_t dcFitness;
748
749 bool operator== (ClusterControllerPriorityInfo const& r) const { return processClassFitness == r.processClassFitness && isExcluded == r.isExcluded && dcFitness == r.dcFitness; }
750
751 ClusterControllerPriorityInfo(uint8_t processClassFitness, bool isExcluded, uint8_t dcFitness) : processClassFitness(processClassFitness), isExcluded(isExcluded), dcFitness(dcFitness) {}
752
753 template <class Ar>
754 void serialize(Ar& ar) {
755 serializer(ar, processClassFitness, isExcluded, dcFitness);
756 }
757 };
758
759 struct HealthMetrics {
760 struct StorageStats {
761 int64_t storageQueue;
762 int64_t storageDurabilityLag;
763 double diskUsage;
764 double cpuUsage;
765
766 bool operator==(StorageStats const &r) const {
767 return (
768 (storageQueue == r.storageQueue) &&
769 (storageDurabilityLag == r.storageDurabilityLag) &&
770 (diskUsage == r.diskUsage) &&
771 (cpuUsage == r.cpuUsage)
772 );
773 }
774
775 template <class Ar>
776 void serialize(Ar& ar) {
777 serializer(ar, storageQueue, storageDurabilityLag, diskUsage, cpuUsage);
778 }
779 };
780
781 int64_t worstStorageQueue;
782 int64_t worstStorageDurabilityLag;
783 int64_t worstTLogQueue;
784 double tpsLimit;
785 bool batchLimited;
786 std::map<UID, StorageStats> storageStats;
787 std::map<UID, int64_t> tLogQueue;
788
789 HealthMetrics()
790 : worstStorageQueue(0)
791 , worstStorageDurabilityLag(0)
792 , worstTLogQueue(0)
793 , tpsLimit(0.0)
794 , batchLimited(false)
795 {}
796
797 void update(const HealthMetrics& hm, bool detailedInput, bool detailedOutput)
798 {
799 worstStorageQueue = hm.worstStorageQueue;
800 worstStorageDurabilityLag = hm.worstStorageDurabilityLag;
801 worstTLogQueue = hm.worstTLogQueue;
802 tpsLimit = hm.tpsLimit;
803 batchLimited = hm.batchLimited;
804
805 if (!detailedOutput) {
806 storageStats.clear();
807 tLogQueue.clear();
808 } else if (detailedInput) {
809 storageStats = hm.storageStats;
810 tLogQueue = hm.tLogQueue;
811 }
812 }
813
814 bool operator==(HealthMetrics const& r) const {
815 return (
816 worstStorageQueue == r.worstStorageQueue &&
817 worstStorageDurabilityLag == r.worstStorageDurabilityLag &&
818 worstTLogQueue == r.worstTLogQueue &&
819 storageStats == r.storageStats &&
820 tLogQueue == r.tLogQueue &&
821 batchLimited == r.batchLimited
822 );
823 }
824
825 template <class Ar>
826 void serialize(Ar& ar) {
827 serializer(ar, worstStorageQueue, worstStorageDurabilityLag, worstTLogQueue, tpsLimit, batchLimited, storageStats, tLogQueue);
828 }
829 };
830
831 #endif
832