Make protocol version a type

This fixes #1214

The basic idea is that ProtocolVersion is now its own type. This
alone is an improvement as it makes many things more typesafe. For
each version, we can now add breaking features (for example Fearless).
After that, there's no need to test against actual (confusing) version
numbers. Instead a developer can simply test
`protocolVersion->hasFearless()` and this will return true iff the
protocolVersion is newer than the newest version that didn't support
fearless.
This commit is contained in:
mpilman 2019-05-16 13:43:21 -07:00
parent 2b60d6fd12
commit da53a92bec
13 changed files with 168 additions and 96 deletions

View File

@ -736,7 +736,7 @@ void MultiVersionDatabase::DatabaseState::stateChanged() {
for(int i = 0; i < clients.size(); ++i) {
if(i != currentClientIndex && connectionAttempts[i]->connected) {
if(currentClientIndex >= 0 && !clients[i]->canReplace(clients[currentClientIndex])) {
TraceEvent(SevWarn, "DuplicateClientVersion").detail("Keeping", clients[currentClientIndex]->libPath).detail("KeptClientProtocolVersion", clients[currentClientIndex]->protocolVersion).detail("Disabling", clients[i]->libPath).detail("DisabledClientProtocolVersion", clients[i]->protocolVersion);
TraceEvent(SevWarn, "DuplicateClientVersion").detail("Keeping", clients[currentClientIndex]->libPath).detail("KeptClientProtocolVersion", clients[currentClientIndex]->protocolVersion.version()).detail("Disabling", clients[i]->libPath).detail("DisabledClientProtocolVersion", clients[i]->protocolVersion.version());
connectionAttempts[i]->connected = false; // Permanently disable this client in favor of the current one
clients[i]->failed = true;
MultiVersionApi::api->updateSupportedVersions();
@ -1277,15 +1277,15 @@ MultiVersionApi* MultiVersionApi::api = new MultiVersionApi();
void ClientInfo::loadProtocolVersion() {
std::string version = api->getClientVersion();
if(version == "unknown") {
protocolVersion = 0;
protocolVersion = ProtocolVersion(0);
return;
}
char *next;
std::string protocolVersionStr = ClientVersionRef(version).protocolVersion.toString();
protocolVersion = strtoull(protocolVersionStr.c_str(), &next, 16);
protocolVersion = ProtocolVersion(strtoull(protocolVersionStr.c_str(), &next, 16));
ASSERT(protocolVersion != 0 && protocolVersion != ULLONG_MAX);
ASSERT(protocolVersion.version() != 0 && protocolVersion.version() != ULLONG_MAX);
ASSERT(next == &protocolVersionStr[protocolVersionStr.length()]);
}
@ -1298,7 +1298,7 @@ bool ClientInfo::canReplace(Reference<ClientInfo> other) const {
return true;
}
return (protocolVersion & compatibleProtocolVersionMask) != (other->protocolVersion & compatibleProtocolVersionMask);
return !protocolVersion.isCompatible(other->protocolVersion);
}
// UNIT TESTS

View File

@ -264,7 +264,7 @@ private:
};
struct ClientInfo : ThreadSafeReferenceCounted<ClientInfo> {
uint64_t protocolVersion;
ProtocolVersion protocolVersion;
IClientApi *api;
std::string libPath;
bool external;

View File

@ -181,7 +181,7 @@ Version decodeServerTagHistoryKey( KeyRef const& key ) {
Tag decodeServerTagValue( ValueRef const& value ) {
Tag s;
BinaryReader reader( value, IncludeVersion() );
if( reader.protocolVersion() < 0x0FDB00A560010001LL ) {
if(!reader.protocolVersion().hasTagLocality()) {
int16_t id;
reader >> id;
if(id == invalidTagOld) {

View File

@ -218,7 +218,7 @@ struct ConnectPacket {
// The value does not inclueds the size of `connectPacketLength` itself,
// but only the other fields of this structure.
uint32_t connectPacketLength;
uint64_t protocolVersion; // Expect currentProtocolVersion
ProtocolVersion protocolVersion; // Expect currentProtocolVersion
uint16_t canonicalRemotePort; // Port number to reconnect to the originating process
uint64_t connectionId; // Multi-version clients will use the same Id for both connections, other connections will set this to zero. Added at protocol Version 0x0FDB00A444020001.
@ -326,13 +326,16 @@ struct Peer : NonCopyable {
pkt.canonicalRemotePort = transport->localAddresses.secondaryAddress.get().port;
pkt.setCanonicalRemoteIp(transport->localAddresses.secondaryAddress.get().ip);
} else {
pkt.canonicalRemotePort = 0; // a "mixed" TLS/non-TLS connection is like a client/server connection - there's no way to reverse it
pkt.canonicalRemotePort =
0; // a "mixed" TLS/non-TLS connection is like a client/server connection - there's no way to reverse it
pkt.setCanonicalRemoteIp(IPAddress(0));
}
pkt.connectPacketLength = sizeof(pkt) - sizeof(pkt.connectPacketLength);
pkt.protocolVersion =
g_network->useObjectSerializer() ? addObjectSerializerFlag(currentProtocolVersion) : currentProtocolVersion;
pkt.protocolVersion = currentProtocolVersion;
if (g_network->useObjectSerializer()) {
pkt.protocolVersion.addObjectSerializerFlag();
}
pkt.connectionId = transport->transportId;
PacketBuffer* pb_first = new PacketBuffer;
@ -784,14 +787,14 @@ ACTOR static Future<Void> connectionReader(
// At the beginning of a connection, we expect to receive a packet containing the protocol version and the listening port of the remote process
int32_t connectPacketSize = ((ConnectPacket*)unprocessed_begin)->totalPacketSize();
if ( unprocessed_end-unprocessed_begin >= connectPacketSize ) {
uint64_t protocolVersion = ((ConnectPacket*)unprocessed_begin)->protocolVersion;
auto protocolVersion = ((ConnectPacket*)unprocessed_begin)->protocolVersion;
BinaryReader pktReader(unprocessed_begin, connectPacketSize, AssumeVersion(protocolVersion));
ConnectPacket pkt;
serializer(pktReader, pkt);
uint64_t connectionId = pkt.connectionId;
if(g_network->useObjectSerializer() != hasObjectSerializerFlag(pkt.protocolVersion) ||
(removeFlags(pkt.protocolVersion) & compatibleProtocolVersionMask) != (currentProtocolVersion & compatibleProtocolVersionMask)) {
if(g_network->useObjectSerializer() != pkt.protocolVersion.hasObjectSerializerFlag() ||
!pkt.protocolVersion.isCompatible(currentProtocolVersion)) {
incompatibleProtocolVersionNewer = pkt.protocolVersion > currentProtocolVersion;
NetworkAddress addr = pkt.canonicalRemotePort
? NetworkAddress(pkt.canonicalRemoteIp(), pkt.canonicalRemotePort)
@ -802,9 +805,9 @@ ACTOR static Future<Void> connectionReader(
if(now() - transport->lastIncompatibleMessage > FLOW_KNOBS->CONNECTION_REJECTED_MESSAGE_DELAY) {
TraceEvent(SevWarn, "ConnectionRejected", conn->getDebugID())
.detail("Reason", "IncompatibleProtocolVersion")
.detail("LocalVersion", currentProtocolVersion)
.detail("RejectedVersion", pkt.protocolVersion)
.detail("VersionMask", compatibleProtocolVersionMask)
.detail("LocalVersion", currentProtocolVersion.version())
.detail("RejectedVersion", pkt.protocolVersion.version())
.detail("VersionMask", ProtocolVersion::compatibleProtocolVersionMask)
.detail("Peer", pkt.canonicalRemotePort ? NetworkAddress(pkt.canonicalRemoteIp(), pkt.canonicalRemotePort)
: conn->getPeerAddress())
.detail("ConnectionId", connectionId);
@ -818,7 +821,7 @@ ACTOR static Future<Void> connectionReader(
}
compatible = false;
if(protocolVersion < 0x0FDB00A551000000LL) {
if(!protocolVersion.hasMultiVersionClient()) {
// Older versions expected us to hang up. It may work even if we don't hang up here, but it's safer to keep the old behavior.
throw incompatible_protocol_version();
}

View File

@ -301,7 +301,7 @@ struct ILogSystem {
//clones the peek cursor, however you cannot call getMore() on the cloned cursor.
virtual Reference<IPeekCursor> cloneNoMore() = 0;
virtual void setProtocolVersion( uint64_t version ) = 0;
virtual void setProtocolVersion( ProtocolVersion version ) = 0;
//if hasMessage() returns true, getMessage(), getMessageWithTags(), or reader() can be called.
//does not modify the cursor
@ -397,7 +397,7 @@ struct ILogSystem {
ServerPeekCursor( TLogPeekReply const& results, LogMessageVersion const& messageVersion, LogMessageVersion const& end, int32_t messageLength, int32_t rawLength, bool hasMsg, Version poppedVersion, Tag tag );
virtual Reference<IPeekCursor> cloneNoMore();
virtual void setProtocolVersion( uint64_t version );
virtual void setProtocolVersion( ProtocolVersion version );
virtual Arena& arena();
virtual ArenaReader* reader();
virtual bool hasMessage();
@ -443,7 +443,7 @@ struct ILogSystem {
MergedPeekCursor( std::vector< Reference<IPeekCursor> > const& serverCursors, LogMessageVersion const& messageVersion, int bestServer, int readQuorum, Optional<LogMessageVersion> nextVersion, Reference<LogSet> logSet, int tLogReplicationFactor );
virtual Reference<IPeekCursor> cloneNoMore();
virtual void setProtocolVersion( uint64_t version );
virtual void setProtocolVersion( ProtocolVersion version );
virtual Arena& arena();
virtual ArenaReader* reader();
void calcHasMessage();
@ -488,7 +488,7 @@ struct ILogSystem {
SetPeekCursor( std::vector<Reference<LogSet>> const& logSets, std::vector< std::vector< Reference<IPeekCursor> > > const& serverCursors, LogMessageVersion const& messageVersion, int bestSet, int bestServer, Optional<LogMessageVersion> nextVersion, bool useBestSet );
virtual Reference<IPeekCursor> cloneNoMore();
virtual void setProtocolVersion( uint64_t version );
virtual void setProtocolVersion( ProtocolVersion version );
virtual Arena& arena();
virtual ArenaReader* reader();
void calcHasMessage();
@ -524,7 +524,7 @@ struct ILogSystem {
MultiCursor( std::vector<Reference<IPeekCursor>> cursors, std::vector<LogMessageVersion> epochEnds );
virtual Reference<IPeekCursor> cloneNoMore();
virtual void setProtocolVersion( uint64_t version );
virtual void setProtocolVersion( ProtocolVersion version );
virtual Arena& arena();
virtual ArenaReader* reader();
virtual bool hasMessage();
@ -584,7 +584,7 @@ struct ILogSystem {
BufferedCursor( std::vector<Reference<IPeekCursor>> cursors, Version begin, Version end, bool collectTags );
virtual Reference<IPeekCursor> cloneNoMore();
virtual void setProtocolVersion( uint64_t version );
virtual void setProtocolVersion( ProtocolVersion version );
virtual Arena& arena();
virtual ArenaReader* reader();
virtual bool hasMessage();

View File

@ -47,7 +47,7 @@ Reference<ILogSystem::IPeekCursor> ILogSystem::ServerPeekCursor::cloneNoMore() {
return Reference<ILogSystem::ServerPeekCursor>( new ILogSystem::ServerPeekCursor( results, messageVersion, end, messageLength, rawLength, hasMsg, poppedVersion, tag ) );
}
void ILogSystem::ServerPeekCursor::setProtocolVersion( uint64_t version ) {
void ILogSystem::ServerPeekCursor::setProtocolVersion( ProtocolVersion version ) {
rd.setProtocolVersion(version);
}
@ -306,7 +306,7 @@ Reference<ILogSystem::IPeekCursor> ILogSystem::MergedPeekCursor::cloneNoMore() {
return Reference<ILogSystem::MergedPeekCursor>( new ILogSystem::MergedPeekCursor( cursors, messageVersion, bestServer, readQuorum, nextVersion, logSet, tLogReplicationFactor ) );
}
void ILogSystem::MergedPeekCursor::setProtocolVersion( uint64_t version ) {
void ILogSystem::MergedPeekCursor::setProtocolVersion( ProtocolVersion version ) {
for( auto it : serverCursors )
if( it->hasMessage() )
it->setProtocolVersion( version );
@ -532,7 +532,7 @@ Reference<ILogSystem::IPeekCursor> ILogSystem::SetPeekCursor::cloneNoMore() {
return Reference<ILogSystem::SetPeekCursor>( new ILogSystem::SetPeekCursor( logSets, cursors, messageVersion, bestSet, bestServer, nextVersion, useBestSet ) );
}
void ILogSystem::SetPeekCursor::setProtocolVersion( uint64_t version ) {
void ILogSystem::SetPeekCursor::setProtocolVersion( ProtocolVersion version ) {
for( auto& cursors : serverCursors ) {
for( auto& it : cursors ) {
if( it->hasMessage() ) {
@ -807,7 +807,7 @@ Reference<ILogSystem::IPeekCursor> ILogSystem::MultiCursor::cloneNoMore() {
return cursors.back()->cloneNoMore();
}
void ILogSystem::MultiCursor::setProtocolVersion( uint64_t version ) {
void ILogSystem::MultiCursor::setProtocolVersion( ProtocolVersion version ) {
cursors.back()->setProtocolVersion(version);
}
@ -918,7 +918,7 @@ Reference<ILogSystem::IPeekCursor> ILogSystem::BufferedCursor::cloneNoMore() {
return Reference<ILogSystem::IPeekCursor>();
}
void ILogSystem::BufferedCursor::setProtocolVersion( uint64_t version ) {
void ILogSystem::BufferedCursor::setProtocolVersion( ProtocolVersion version ) {
for(auto& c : cursors) {
c->setProtocolVersion(version);
}

View File

@ -472,7 +472,7 @@ struct LogData : NonCopyable, public ReferenceCounted<LogData> {
Counter bytesDurable;
UID logId;
uint64_t protocolVersion;
ProtocolVersion protocolVersion;
Version newPersistentDataVersion;
Future<Void> removed;
PromiseStream<Future<Void>> addActor;

View File

@ -409,7 +409,7 @@ public:
Deque<std::pair<Version,Version>> recoveryVersionSkips;
int64_t versionLag; // An estimate for how many versions it takes for the data to move from the logs to this storage server
uint64_t logProtocol;
ProtocolVersion logProtocol;
Reference<ILogSystem> logSystem;
Reference<ILogSystem::IPeekCursor> logCursor;
@ -3163,7 +3163,7 @@ ACTOR Future<bool> restoreDurableState( StorageServer* data, IKeyValueStore* sto
data->sk = serverKeysPrefixFor( data->thisServerID ).withPrefix(systemKeys.begin); // FFFF/serverKeys/[this server]/
if (fLogProtocol.get().present())
data->logProtocol = BinaryReader::fromStringRef<uint64_t>(fLogProtocol.get().get(), Unversioned());
data->logProtocol = BinaryReader::fromStringRef<ProtocolVersion>(fLogProtocol.get().get(), Unversioned());
if (fPrimaryLocality.get().present())
data->primaryLocality = BinaryReader::fromStringRef<int8_t>(fPrimaryLocality.get().get(), Unversioned());

View File

@ -27,7 +27,7 @@ static const int trIdFormatSize = 16;
// Checks TransactionInfo format
bool checkTxInfoEntryFormat(BinaryReader &reader) {
// Check protocol version
uint64_t protocolVersion;
ProtocolVersion protocolVersion;
reader >> protocolVersion;
reader.setProtocolVersion(protocolVersion);

View File

@ -36,6 +36,7 @@
#include "flow/TDMetric.actor.h"
#include "flow/AsioReactor.h"
#include "flow/Profiler.h"
#include "flow/ProtocolVersion.h"
#ifdef WIN32
#include <mmsystem.h>
@ -48,31 +49,6 @@ intptr_t g_stackYieldLimit = 0;
using namespace boost::asio::ip;
// These impact both communications and the deserialization of certain database and IKeyValueStore keys.
//
// 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
const uint64_t currentProtocolVersion = 0x0FDB00B061070001LL;
const uint64_t compatibleProtocolVersionMask = 0xffffffffffff0000LL;
const uint64_t minValidProtocolVersion = 0x0FDB00A200060001LL;
const uint64_t objectSerializerFlag = 0x1000000000000000LL;
const uint64_t versionFlagMask = 0x0FFFFFFFFFFFFFFFLL;
uint64_t removeFlags(uint64_t version) {
return version & versionFlagMask;
}
uint64_t addObjectSerializerFlag(uint64_t version) {
return version | objectSerializerFlag;
}
bool hasObjectSerializerFlag(uint64_t version) {
return (version & objectSerializerFlag) > 0;
}
// This assert is intended to help prevent incrementing the leftmost digits accidentally. It will probably need to change when we reach version 10.
static_assert(currentProtocolVersion < 0x0FDB00B100000000LL, "Unexpected protocol version");
#if defined(__linux__)
#include <execinfo.h>

85
flow/ProtocolVersion.h Normal file
View File

@ -0,0 +1,85 @@
#pragma once
#include <cstdint>
namespace fdb_versions {
#define VERSION_FEATURE(x) \
constexpr bool has##x() const { return static_cast<const P*>(this)->version() >= protocolVersion; }
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> {};
template <class P>
using latest_version = v6_1<P>;
} // namespace fdb_versions
class ProtocolVersion : public fdb_versions::latest_version<ProtocolVersion> {
uint64_t _version;
public: // constants
static constexpr uint64_t versionFlagMask = 0x0FFFFFFFFFFFFFFFLL;
static constexpr uint64_t objectSerializerFlag = 0x1000000000000000LL;
static constexpr uint64_t compatibleProtocolVersionMask = 0xffffffffffff0000LL;
static constexpr uint64_t minValidProtocolVersion = 0x0FDB00A200060001LL;
public:
constexpr explicit ProtocolVersion(uint64_t version) : _version(version) {}
constexpr ProtocolVersion() : _version(0) {}
constexpr bool isCompatible(ProtocolVersion other) const {
return (other.version() & compatibleProtocolVersionMask) == (version() & compatibleProtocolVersionMask);
}
constexpr bool isValid() const { return version() >= minValidProtocolVersion; }
constexpr uint64_t version() const { return _version & versionFlagMask; }
constexpr uint64_t versionWithFlags() const { return _version; }
constexpr bool hasObjectSerializerFlag() const { return (_version & objectSerializerFlag) > 0; }
constexpr void addObjectSerializerFlag() { _version = _version | objectSerializerFlag; }
constexpr void removeObjectSerializerFlag() {
_version = hasObjectSerializerFlag() ? _version ^ objectSerializerFlag : _version;
}
constexpr void removeAllFlags() { _version = version(); }
constexpr operator bool() const { return _version != 0; }
// comparison operators
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(); }
};
// These impact both communications and the deserialization of certain database and IKeyValueStore keys.
//
// 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
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.
static_assert(currentProtocolVersion.version() < 0x0FDB00B100000000LL, "Unexpected protocol version");

View File

@ -21,8 +21,8 @@
#include "flow/serialize.h"
#include "flow/network.h"
_AssumeVersion::_AssumeVersion( uint64_t version ) : v(version) {
if( version < minValidProtocolVersion ) {
_AssumeVersion::_AssumeVersion( ProtocolVersion version ) : v(version) {
if(!version.isValid()) {
ASSERT(!g_network->isSimulated());
throw serialization_failed();
}

View File

@ -25,6 +25,7 @@
#include <stdint.h>
#include <array>
#include <set>
#include "flow/ProtocolVersion.h"
#include "flow/Error.h"
#include "flow/Arena.h"
#include "flow/FileIdentifier.h"
@ -52,6 +53,22 @@ BINARY_SERIALIZABLE( int64_t );
BINARY_SERIALIZABLE( uint64_t );
BINARY_SERIALIZABLE( bool );
BINARY_SERIALIZABLE( double );
BINARY_SERIALIZABLE( ProtocolVersion );
template<>
struct scalar_traits<ProtocolVersion> : std::true_type {
constexpr static size_t size = sizeof(uint64_t);
static void save(uint8_t* out, const ProtocolVersion& v) {
*reinterpret_cast<uint64_t*>(out) = v.versionWithFlags();
}
template <class Context>
static void load(const uint8_t* i, ProtocolVersion& out, Context& context) {
const uint64_t* in = reinterpret_cast<const uint64_t*>(i);
out = ProtocolVersion(*in);
}
};
template <class Archive, class Item>
inline typename Archive::WRITER& operator << (Archive& ar, const Item& item ) {
@ -87,7 +104,7 @@ class Serializer {
public:
static void serialize( Archive& ar, T& t ) {
t.serialize(ar);
ASSERT( ar.protocolVersion() != 0 );
ASSERT( ar.protocolVersion() );
}
};
@ -250,19 +267,10 @@ static bool valgrindCheck( const void* data, int bytes, const char* context ) {
static inline bool valgrindCheck( const void* data, int bytes, const char* context ) { return true; }
#endif
extern const uint64_t currentProtocolVersion;
extern const uint64_t minValidProtocolVersion;
extern const uint64_t compatibleProtocolVersionMask;
extern const uint64_t objectSerializerFlag;
extern uint64_t removeFlags(uint64_t version);
extern uint64_t addObjectSerializerFlag(uint64_t version);
extern bool hasObjectSerializerFlag(uint64_t version);
struct _IncludeVersion {
uint64_t v;
explicit _IncludeVersion( uint64_t defaultVersion ) : v(defaultVersion) {
ASSERT( defaultVersion >= minValidProtocolVersion );
ProtocolVersion v;
explicit _IncludeVersion( ProtocolVersion defaultVersion ) : v(defaultVersion) {
ASSERT( defaultVersion.isValid() );
}
template <class Ar>
void write( Ar& ar ) {
@ -272,7 +280,7 @@ struct _IncludeVersion {
template <class Ar>
void read( Ar& ar ) {
ar >> v;
if (v < minValidProtocolVersion) {
if (!v.isValid()) {
auto err = incompatible_protocol_version();
TraceEvent(SevError, "InvalidSerializationVersion").error(err).detailf("Version", "%llx", v);
throw err;
@ -289,19 +297,19 @@ struct _IncludeVersion {
}
};
struct _AssumeVersion {
uint64_t v;
explicit _AssumeVersion( uint64_t version );
ProtocolVersion v;
explicit _AssumeVersion( ProtocolVersion version );
template <class Ar> void write( Ar& ar ) { ar.setProtocolVersion(v); }
template <class Ar> void read( Ar& ar ) { ar.setProtocolVersion(v); }
};
struct _Unversioned {
template <class Ar> void write( Ar& ar ) { ar.setProtocolVersion(0); }
template <class Ar> void read( Ar& ar ) { ar.setProtocolVersion(0); }
template <class Ar> void write( Ar& ar ) {}
template <class Ar> void read( Ar& ar ) {}
};
// These functions return valid options to the VersionOptions parameter of the constructor of each archive type
inline _IncludeVersion IncludeVersion( uint64_t defaultVersion = currentProtocolVersion ) { return _IncludeVersion(defaultVersion); }
inline _AssumeVersion AssumeVersion( uint64_t version ) { return _AssumeVersion(version); }
inline _IncludeVersion IncludeVersion( ProtocolVersion defaultVersion = currentProtocolVersion ) { return _IncludeVersion(defaultVersion); }
inline _AssumeVersion AssumeVersion( ProtocolVersion version ) { return _AssumeVersion(version); }
inline _Unversioned Unversioned() { return _Unversioned(); }
//static uint64_t size_limits[] = { 0ULL, 255ULL, 65535ULL, 16777215ULL, 4294967295ULL, 1099511627775ULL, 281474976710655ULL, 72057594037927935ULL, 18446744073709551615ULL };
@ -426,13 +434,13 @@ public:
}
}
uint64_t protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
ProtocolVersion protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(ProtocolVersion pv) { m_protocolVersion = pv; }
private:
Arena arena;
uint8_t* data;
int size, allocated;
uint64_t m_protocolVersion;
ProtocolVersion m_protocolVersion;
void* writeBytes(int s) {
int p = size;
@ -491,13 +499,13 @@ public:
writeBytes(&t, sizeof(T));
}
uint64_t protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
ProtocolVersion protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(ProtocolVersion pv) { m_protocolVersion = pv; }
private:
int len;
SplitBuffer buf;
uint64_t m_protocolVersion;
ProtocolVersion m_protocolVersion;
void writeBytes(const void *data, int wlen) {
ASSERT(wlen <= len);
@ -551,8 +559,8 @@ public:
Arena& arena() { return m_pool; }
uint64_t protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
ProtocolVersion protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(ProtocolVersion pv) { m_protocolVersion = pv; }
bool empty() const { return begin == end; }
@ -569,7 +577,7 @@ public:
private:
const char *begin, *end, *check;
Arena m_pool;
uint64_t m_protocolVersion;
ProtocolVersion m_protocolVersion;
};
class BinaryReader {
@ -625,8 +633,8 @@ public:
return t;
}
uint64_t protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
ProtocolVersion protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(ProtocolVersion pv) { m_protocolVersion = pv; }
void assertEnd() { ASSERT( begin == end ); }
@ -646,7 +654,7 @@ public:
private:
const char *begin, *end, *check;
Arena m_pool;
uint64_t m_protocolVersion;
ProtocolVersion m_protocolVersion;
};
struct SendBuffer {
@ -679,7 +687,7 @@ struct PacketWriter {
PacketBuffer* buffer;
struct ReliablePacket *reliable; // NULL if this is unreliable; otherwise the last entry in the ReliablePacket::cont chain
int length;
uint64_t m_protocolVersion;
ProtocolVersion m_protocolVersion;
// reliable is NULL if this is an unreliable packet, or points to a ReliablePacket. PacketWriter is responsible
// for filling in reliable->buffer, ->cont, ->begin, and ->end, but not ->prev or ->next.
@ -712,8 +720,8 @@ struct PacketWriter {
serializeBytesAcrossBoundary(&t, sizeof(T));
}
}
uint64_t protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
ProtocolVersion protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(ProtocolVersion pv) { m_protocolVersion = pv; }
private:
void init( PacketBuffer* buf, ReliablePacket* reliable );
};