summaryrefslogtreecommitdiff
path: root/src/mongo/bson/oid.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/bson/oid.h')
-rw-r--r--src/mongo/bson/oid.h368
1 files changed, 188 insertions, 180 deletions
diff --git a/src/mongo/bson/oid.h b/src/mongo/bson/oid.h
index a4ae3269d5f..476e15d1048 100644
--- a/src/mongo/bson/oid.h
+++ b/src/mongo/bson/oid.h
@@ -36,195 +36,203 @@
#include "mongo/util/time_support.h"
namespace mongo {
- class SecureRandom;
-
+class SecureRandom;
+
+/**
+ * Object ID type.
+ * BSON objects typically have an _id field for the object id. This field should be the first
+ * member of the object when present. The OID class is a special type that is a 12 byte id which
+ * is likely to be unique to the system. You may also use other types for _id's.
+ * When _id field is missing from a BSON object, on an insert the database may insert one
+ * automatically in certain circumstances.
+ *
+ * The BSON ObjectID is a 12-byte value consisting of a 4-byte timestamp (seconds since epoch),
+ * in the highest order 4 bytes followed by a 5 byte value unique to this machine AND process,
+ * followed by a 3 byte counter.
+ *
+ * 4 byte timestamp 5 byte process unique 3 byte counter
+ * |<----------------->|<---------------------->|<------------->
+ * OID layout: [----|----|----|----|----|----|----|----|----|----|----|----]
+ * 0 4 8 12
+ *
+ * The timestamp is a big endian 4 byte signed-integer.
+ *
+ * The process unique is an arbitrary sequence of 5 bytes. There are no endianness concerns
+ * since it is never interpreted as a multi-byte value.
+ *
+ * The counter is a big endian 3 byte unsigned integer.
+ *
+ * Note: The timestamp and counter are big endian (in contrast to the rest of BSON) because
+ * we use memcmp to order OIDs, and we want to ensure an increasing order.
+ *
+ * Warning: You MUST call OID::justForked() after a fork(). This ensures that each process will
+ * generate unique OIDs.
+ */
+class OID {
+public:
/**
- * Object ID type.
- * BSON objects typically have an _id field for the object id. This field should be the first
- * member of the object when present. The OID class is a special type that is a 12 byte id which
- * is likely to be unique to the system. You may also use other types for _id's.
- * When _id field is missing from a BSON object, on an insert the database may insert one
- * automatically in certain circumstances.
- *
- * The BSON ObjectID is a 12-byte value consisting of a 4-byte timestamp (seconds since epoch),
- * in the highest order 4 bytes followed by a 5 byte value unique to this machine AND process,
- * followed by a 3 byte counter.
- *
- * 4 byte timestamp 5 byte process unique 3 byte counter
- * |<----------------->|<---------------------->|<------------->
- * OID layout: [----|----|----|----|----|----|----|----|----|----|----|----]
- * 0 4 8 12
- *
- * The timestamp is a big endian 4 byte signed-integer.
- *
- * The process unique is an arbitrary sequence of 5 bytes. There are no endianness concerns
- * since it is never interpreted as a multi-byte value.
- *
- * The counter is a big endian 3 byte unsigned integer.
- *
- * Note: The timestamp and counter are big endian (in contrast to the rest of BSON) because
- * we use memcmp to order OIDs, and we want to ensure an increasing order.
- *
- * Warning: You MUST call OID::justForked() after a fork(). This ensures that each process will
- * generate unique OIDs.
+ * Functor compatible with std::hash for std::unordered_{map,set}
+ * Warning: The hash function is subject to change. Do not use in cases where hashes need
+ * to be consistent across versions.
*/
- class OID {
- public:
-
- /**
- * Functor compatible with std::hash for std::unordered_{map,set}
- * Warning: The hash function is subject to change. Do not use in cases where hashes need
- * to be consistent across versions.
- */
- struct Hasher {
- size_t operator() (const OID& oid) const;
- };
-
- OID() : _data() {}
-
- enum {
- kOIDSize = 12,
- kTimestampSize = 4,
- kInstanceUniqueSize = 5,
- kIncrementSize = 3
- };
-
- /** init from a 24 char hex std::string */
- explicit OID(const std::string &s) {
- init(s);
- }
-
- /** init from a reference to a 12-byte array */
- explicit OID(const unsigned char (&arr)[kOIDSize]) {
- std::memcpy(_data, arr, sizeof(arr));
- }
-
- /** initialize to 'null' */
- void clear() { std::memset(_data, 0, kOIDSize); }
-
- int compare( const OID& other ) const { return memcmp( _data , other._data , kOIDSize ); }
-
- /** @return the object ID output as 24 hex digits */
- std::string toString() const;
- /** @return the random/sequential part of the object ID as 6 hex digits */
- std::string toIncString() const;
-
- static OID gen() {
- OID o((no_initialize_tag()));
- o.init();
- return o;
- }
-
- // Caller must ensure that the buffer is valid for kOIDSize bytes.
- // this is templated because some places use unsigned char vs signed char
- template<typename T>
- static OID from(T* buf) {
- OID o((no_initialize_tag()));
- std::memcpy(o._data, buf, OID::kOIDSize);
- return o;
- }
-
- static OID max() {
- OID o((no_initialize_tag()));
- std::memset(o._data, 0xFF, kOIDSize);
- return o;
- }
-
- /** sets the contents to a new oid / randomized value */
- void init();
-
- /** init from a 24 char hex std::string */
- void init( const std::string& s );
-
- /** Set to the min/max OID that could be generated at given timestamp. */
- void init( Date_t date, bool max=false );
-
- time_t asTimeT() const;
- Date_t asDateT() const { return Date_t::fromMillisSinceEpoch(asTimeT() * 1000LL); }
-
- // True iff the OID is not empty
- bool isSet() const {
- return compare(OID()) != 0;
- }
-
- /**
- * this is not consistent
- * do not store on disk
- */
- void hash_combine(size_t &seed) const;
-
- /** call this after a fork to update the process id */
- static void justForked();
-
- static unsigned getMachineId(); // used by the 'features' command
- static void regenMachineId();
-
- // Timestamp is 4 bytes so we just use int32_t
- typedef int32_t Timestamp;
-
- // Wrappers so we can return stuff by value.
- struct InstanceUnique {
- static InstanceUnique generate(SecureRandom& entropy);
- uint8_t bytes[kInstanceUniqueSize];
- };
-
- struct Increment {
- public:
- static Increment next();
- uint8_t bytes[kIncrementSize];
- };
-
- void setTimestamp(Timestamp timestamp);
- void setInstanceUnique(InstanceUnique unique);
- void setIncrement(Increment inc);
-
- Timestamp getTimestamp() const;
- InstanceUnique getInstanceUnique() const;
- Increment getIncrement() const;
-
- ConstDataView view() const {
- return ConstDataView(_data);
- }
-
- private:
- // Internal mutable view
- DataView _view() {
- return DataView(_data);
- }
-
- // When we are going to immediately overwrite the bytes, there is no point in zero
- // initializing the data first.
- struct no_initialize_tag {};
- explicit OID(no_initialize_tag) {}
-
- char _data[kOIDSize];
+ struct Hasher {
+ size_t operator()(const OID& oid) const;
};
- inline std::ostream& operator<<(std::ostream &s, const OID &o) {
- return (s << o.toString());
+ OID() : _data() {}
+
+ enum { kOIDSize = 12, kTimestampSize = 4, kInstanceUniqueSize = 5, kIncrementSize = 3 };
+
+ /** init from a 24 char hex std::string */
+ explicit OID(const std::string& s) {
+ init(s);
+ }
+
+ /** init from a reference to a 12-byte array */
+ explicit OID(const unsigned char(&arr)[kOIDSize]) {
+ std::memcpy(_data, arr, sizeof(arr));
+ }
+
+ /** initialize to 'null' */
+ void clear() {
+ std::memset(_data, 0, kOIDSize);
+ }
+
+ int compare(const OID& other) const {
+ return memcmp(_data, other._data, kOIDSize);
+ }
+
+ /** @return the object ID output as 24 hex digits */
+ std::string toString() const;
+ /** @return the random/sequential part of the object ID as 6 hex digits */
+ std::string toIncString() const;
+
+ static OID gen() {
+ OID o((no_initialize_tag()));
+ o.init();
+ return o;
+ }
+
+ // Caller must ensure that the buffer is valid for kOIDSize bytes.
+ // this is templated because some places use unsigned char vs signed char
+ template <typename T>
+ static OID from(T* buf) {
+ OID o((no_initialize_tag()));
+ std::memcpy(o._data, buf, OID::kOIDSize);
+ return o;
+ }
+
+ static OID max() {
+ OID o((no_initialize_tag()));
+ std::memset(o._data, 0xFF, kOIDSize);
+ return o;
+ }
+
+ /** sets the contents to a new oid / randomized value */
+ void init();
+
+ /** init from a 24 char hex std::string */
+ void init(const std::string& s);
+
+ /** Set to the min/max OID that could be generated at given timestamp. */
+ void init(Date_t date, bool max = false);
+
+ time_t asTimeT() const;
+ Date_t asDateT() const {
+ return Date_t::fromMillisSinceEpoch(asTimeT() * 1000LL);
}
- inline StringBuilder& operator<<(StringBuilder& s, const OID& o) {
- return (s << o.toString());
+ // True iff the OID is not empty
+ bool isSet() const {
+ return compare(OID()) != 0;
}
- /** Formatting mode for generating JSON from BSON.
- See <http://dochub.mongodb.org/core/mongodbextendedjson>
- for details.
- */
- enum JsonStringFormat {
- /** strict RFC format */
- Strict,
- /** 10gen format, which is close to JS format. This form is understandable by
- javascript running inside the Mongo server via eval() */
- TenGen,
- /** Javascript JSON compatible */
- JS
+ /**
+ * this is not consistent
+ * do not store on disk
+ */
+ void hash_combine(size_t& seed) const;
+
+ /** call this after a fork to update the process id */
+ static void justForked();
+
+ static unsigned getMachineId(); // used by the 'features' command
+ static void regenMachineId();
+
+ // Timestamp is 4 bytes so we just use int32_t
+ typedef int32_t Timestamp;
+
+ // Wrappers so we can return stuff by value.
+ struct InstanceUnique {
+ static InstanceUnique generate(SecureRandom& entropy);
+ uint8_t bytes[kInstanceUniqueSize];
+ };
+
+ struct Increment {
+ public:
+ static Increment next();
+ uint8_t bytes[kIncrementSize];
};
- inline bool operator==(const OID& lhs, const OID& rhs) { return lhs.compare(rhs) == 0; }
- inline bool operator!=(const OID& lhs, const OID& rhs) { return lhs.compare(rhs) != 0; }
- inline bool operator<(const OID& lhs, const OID& rhs) { return lhs.compare(rhs) < 0; }
- inline bool operator<=(const OID& lhs, const OID& rhs) { return lhs.compare(rhs) <= 0; }
+ void setTimestamp(Timestamp timestamp);
+ void setInstanceUnique(InstanceUnique unique);
+ void setIncrement(Increment inc);
+
+ Timestamp getTimestamp() const;
+ InstanceUnique getInstanceUnique() const;
+ Increment getIncrement() const;
+
+ ConstDataView view() const {
+ return ConstDataView(_data);
+ }
+
+private:
+ // Internal mutable view
+ DataView _view() {
+ return DataView(_data);
+ }
+
+ // When we are going to immediately overwrite the bytes, there is no point in zero
+ // initializing the data first.
+ struct no_initialize_tag {};
+ explicit OID(no_initialize_tag) {}
+
+ char _data[kOIDSize];
+};
+
+inline std::ostream& operator<<(std::ostream& s, const OID& o) {
+ return (s << o.toString());
+}
+
+inline StringBuilder& operator<<(StringBuilder& s, const OID& o) {
+ return (s << o.toString());
+}
+
+/** Formatting mode for generating JSON from BSON.
+ See <http://dochub.mongodb.org/core/mongodbextendedjson>
+ for details.
+*/
+enum JsonStringFormat {
+ /** strict RFC format */
+ Strict,
+ /** 10gen format, which is close to JS format. This form is understandable by
+ javascript running inside the Mongo server via eval() */
+ TenGen,
+ /** Javascript JSON compatible */
+ JS
+};
+
+inline bool operator==(const OID& lhs, const OID& rhs) {
+ return lhs.compare(rhs) == 0;
+}
+inline bool operator!=(const OID& lhs, const OID& rhs) {
+ return lhs.compare(rhs) != 0;
+}
+inline bool operator<(const OID& lhs, const OID& rhs) {
+ return lhs.compare(rhs) < 0;
+}
+inline bool operator<=(const OID& lhs, const OID& rhs) {
+ return lhs.compare(rhs) <= 0;
+}
} // namespace mongo