Simplifications and addressed reviews

This commit is contained in:
mpilman 2019-06-16 11:07:10 -07:00
parent 882fa39e80
commit 52da31bfb3
1 changed files with 20 additions and 51 deletions

View File

@ -3,7 +3,7 @@
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
* Copyright 2013-2019 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,60 +21,21 @@
#pragma once
#include <cstdint>
namespace fdb_versions {
#define PROTOCOAL_VERSION_FEATURE(v, x) \
struct x { \
static constexpr uint64_t protocolVersion = v; \
}; \
constexpr bool has##x() const { return this->version() >= x ::protocolVersion; } \
static constexpr ProtocolVersion with##x() { return ProtocolVersion(x ::protocolVersion); }
// Whenever a new breaking feature is introduced in FDB for which we need code
// that tests whether the serialized version of the code was serialized with
// that feature, the author should add this macro with the name of the feature
// to the corresponding version. Users can than later call `version->hasFeature()`
// on a deserialized `ProtocolVersion` to test for the feature.
#define VERSION_FEATURE(x) \
constexpr bool has##x() const { return static_cast<const P*>(this)->version() >= protocolVersion; }
// A version-class. These need to be ordered by version and the ordering
// happens through inheritance. Each of these structs need to know about
// the `ProtocolVersion`-class (through the template parameter) and it has
// to be named `P` (otherwise the VERSION_FEATURE macro won't work anymore).
// These classes are used to determine if a feature was available at a certain
// protocol version. It does determine that through static polymorphism.
template<class P>
struct v5_5 {
static constexpr uint64_t protocolVersion = 0x0FDB00A551000000LL;
VERSION_FEATURE(MultiVersionClient)
};
template<class P>
struct v5_6 : v5_5<P> {
static constexpr uint64_t protocolVersion = 0x0FDB00A560010001LL;
VERSION_FEATURE(TagLocality)
};
template <class P>
struct v6_0 : v5_6<P> {
static constexpr uint64_t protocolVersion = 0x0FDB00B060000001LL;
VERSION_FEATURE(Fearless)
};
template <class P>
struct v6_1 : v6_0<P> {};
// This typedef needs to be updated whenever a new version is added
template <class P>
using latest_version = v6_1<P>;
} // namespace fdb_versions
// ProtocolVersion wraps a uint64_t to make it type safe. It has to inherit
// from the newest version object and it will know about the current version.
// ProtocolVersion wraps a uint64_t to make it type safe. It will know about the current versions.
// The default constuctor will initialize the version to 0 (which is an invalid
// version). ProtocolVersion objects should never be compared to version numbers
// directly. Instead one should always use the type-safe version types from which
// this class inherits all.
class ProtocolVersion : public fdb_versions::latest_version<ProtocolVersion> {
class ProtocolVersion {
uint64_t _version;
public: // constants
static constexpr uint64_t versionFlagMask = 0x0FFFFFFFFFFFFFFFLL;
static constexpr uint64_t objectSerializerFlag = 0x1000000000000000LL;
@ -102,12 +63,20 @@ public:
constexpr operator bool() const { return _version != 0; }
// comparison operators
// Comparison operators ignore the flags - this is because the version flags are stored in the
// most significant byte which can make comparison confusing. Also, generally, when one wants to
// compare versions, we are usually not interested in the flags.
constexpr bool operator==(const ProtocolVersion other) const { return version() == other.version(); }
constexpr bool operator!=(const ProtocolVersion other) const { return version() != other.version(); }
constexpr bool operator<=(const ProtocolVersion other) const { return version() <= other.version(); }
constexpr bool operator>=(const ProtocolVersion other) const { return version() >= other.version(); }
constexpr bool operator<(const ProtocolVersion other) const { return version() < other.version(); }
constexpr bool operator>(const ProtocolVersion other) const { return version() > other.version(); }
public: // introduced features
PROTOCOAL_VERSION_FEATURE(0x0FDB00A560010001LL, TagLocality);
PROTOCOAL_VERSION_FEATURE(0x0FDB00B060000001LL, Fearless);
PROTOCOAL_VERSION_FEATURE(0x0FDB00A551000000LL, MultiVersionClient);
};
// These impact both communications and the deserialization of certain database and IKeyValueStore keys.
@ -115,8 +84,8 @@ public:
// The convention is that 'x' and 'y' should match the major and minor version of the software, and 'z' should be 0.
// To make a change without a corresponding increase to the x.y version, increment the 'dev' digit.
//
// xyzdev
// vvvv
// xyzdev
// vvvv
constexpr ProtocolVersion currentProtocolVersion(0x0FDB00B061070001LL);
// This assert is intended to help prevent incrementing the leftmost digits accidentally. It will probably need to
// change when we reach version 10.