/usr/include/mongo/s/chunk_version.h is in mongodb-dev 1:2.4.9-1ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | /**
* Copyright (C) 2012 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "mongo/db/jsobj.h"
namespace mongo {
//
// ChunkVersions consist of a major/minor version scoped to a version epoch
//
struct ChunkVersion {
union {
struct {
int _minor;
int _major;
};
unsigned long long _combined;
};
OID _epoch;
ChunkVersion() : _minor(0), _major(0), _epoch(OID()) {}
//
// Constructors shouldn't have default parameters here, since it's vital we track from
// here on the epochs of versions, even if not used.
//
ChunkVersion( int major, int minor, const OID& epoch )
: _minor(minor),_major(major), _epoch(epoch) {
}
ChunkVersion( unsigned long long ll, const OID& epoch )
: _combined( ll ), _epoch(epoch) {
}
void inc( bool major ) {
if ( major )
incMajor();
else
incMinor();
}
void incMajor() {
_major++;
_minor = 0;
}
void incMinor() {
_minor++;
}
// Incrementing an epoch creates a new, randomly generated identifier
void incEpoch() {
_epoch = OID::gen();
_major = 0;
_minor = 0;
}
// Note: this shouldn't be used as a substitute for version except in specific cases -
// epochs make versions more complex
unsigned long long toLong() const {
return _combined;
}
bool isSet() const {
return _combined > 0;
}
bool isEpochSet() const {
return _epoch.isSet();
}
string toString() const {
stringstream ss;
// Similar to month/day/year. For the most part when debugging, we care about major
// so it's first
ss << _major << "|" << _minor << "||" << _epoch;
return ss.str();
}
int majorVersion() const { return _major; }
int minorVersion() const { return _minor; }
OID epoch() const { return _epoch; }
//
// Explicit comparison operators - versions with epochs have non-trivial comparisons.
// > < operators do not check epoch cases. Generally if using == we need to handle
// more complex cases.
//
bool operator>( const ChunkVersion& otherVersion ) const {
return this->_combined > otherVersion._combined;
}
bool operator>=( const ChunkVersion& otherVersion ) const {
return this->_combined >= otherVersion._combined;
}
bool operator<( const ChunkVersion& otherVersion ) const {
return this->_combined < otherVersion._combined;
}
bool operator<=( const ChunkVersion& otherVersion ) const {
return this->_combined <= otherVersion._combined;
}
//
// Equivalence comparison types.
//
// Can we write to this data and not have a problem?
bool isWriteCompatibleWith( const ChunkVersion& otherVersion ) const {
if( ! hasCompatibleEpoch( otherVersion ) ) return false;
return otherVersion._major == _major;
}
// Is this the same version?
bool isEquivalentTo( const ChunkVersion& otherVersion ) const {
if( ! hasCompatibleEpoch( otherVersion ) ) return false;
return otherVersion._combined == _combined;
}
// Is this in the same epoch?
bool hasCompatibleEpoch( const ChunkVersion& otherVersion ) const {
return hasCompatibleEpoch( otherVersion._epoch );
}
bool hasCompatibleEpoch( const OID& otherEpoch ) const {
// TODO : Change logic from eras are not-unequal to eras are equal
if( otherEpoch.isSet() && _epoch.isSet() && otherEpoch != _epoch ) return false;
return true;
}
//
// BSON input/output
//
// The idea here is to make the BSON input style very flexible right now, so we
// can then tighten it up in the next version. We can accept either a BSONObject field
// with version and epoch, or version and epoch in different fields (either is optional).
// In this case, epoch always is stored in a field name of the version field name + "Epoch"
//
//
// { version : <TS> } and { version : [<TS>,<OID>] } format
//
static bool canParseBSON( const BSONElement& el, const string& prefix="" ){
bool canParse;
fromBSON( el, prefix, &canParse );
return canParse;
}
static ChunkVersion fromBSON( const BSONElement& el, const string& prefix="" ){
bool canParse;
return fromBSON( el, prefix, &canParse );
}
static ChunkVersion fromBSON( const BSONElement& el,
const string& prefix,
bool* canParse )
{
*canParse = true;
int type = el.type();
if( type == Array ){
return fromBSON( BSONArray( el.Obj() ), canParse );
}
if( type == jstOID ){
return ChunkVersion( 0, 0, el.OID() );
}
if( el.isNumber() ){
return ChunkVersion( static_cast<unsigned long long>(el.numberLong()), OID() );
}
if( type == Timestamp || type == Date ){
return ChunkVersion( el._numberLong(), OID() );
}
*canParse = false;
return ChunkVersion( 0, OID() );
}
//
// { version : <TS>, versionEpoch : <OID> } object format
//
static bool canParseBSON( const BSONObj& obj, const string& prefix="" ){
bool canParse;
fromBSON( obj, prefix, &canParse );
return canParse;
}
static ChunkVersion fromBSON( const BSONObj& obj, const string& prefix="" ){
bool canParse;
return fromBSON( obj, prefix, &canParse );
}
static ChunkVersion fromBSON( const BSONObj& obj,
const string& prefixIn,
bool* canParse )
{
*canParse = true;
string prefix = prefixIn;
// "version" doesn't have a "cluster constanst" because that field is never
// written to the config.
if( prefixIn == "" && ! obj[ "version" ].eoo() ){
prefix = (string)"version";
}
// TODO: use ChunkType::DEPRECATED_lastmod()
// NOTE: type_chunk.h includes this file
else if( prefixIn == "" && ! obj["lastmod"].eoo() ){
prefix = (string)"lastmod";
}
ChunkVersion version = fromBSON( obj[ prefix ], prefixIn, canParse );
if( obj[ prefix + "Epoch" ].type() == jstOID ){
version._epoch = obj[ prefix + "Epoch" ].OID();
*canParse = true;
}
return version;
}
//
// { version : [<TS>, <OID>] } format
//
static bool canParseBSON( const BSONArray& arr ){
bool canParse;
fromBSON( arr, &canParse );
return canParse;
}
static ChunkVersion fromBSON( const BSONArray& arr ){
bool canParse;
return fromBSON( arr, &canParse );
}
static ChunkVersion fromBSON( const BSONArray& arr,
bool* canParse )
{
*canParse = false;
ChunkVersion version;
BSONObjIterator it( arr );
if( ! it.more() ) return version;
version = fromBSON( it.next(), "", canParse );
if( ! canParse ) return version;
*canParse = true;
if( ! it.more() ) return version;
BSONElement next = it.next();
if( next.type() != jstOID ) return version;
version._epoch = next.OID();
return version;
}
//
// Currently our BSON output is to two different fields, to cleanly work with older
// versions that know nothing about epochs.
//
BSONObj toBSON( const string& prefixIn="" ) const {
BSONObjBuilder b;
string prefix = prefixIn;
if( prefix == "" ) prefix = "version";
b.appendTimestamp( prefix, _combined );
b.append( prefix + "Epoch", _epoch );
return b.obj();
}
void addToBSON( BSONObjBuilder& b, const string& prefix="" ) const {
b.appendElements( toBSON( prefix ) );
}
void addEpochToBSON( BSONObjBuilder& b, const string& prefix="" ) const {
b.append( prefix + "Epoch", _epoch );
}
};
inline ostream& operator<<( ostream &s , const ChunkVersion& v) {
s << v.toString();
return s;
}
} // namespace mongo
|