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