/** * Copyright (C) 2018-present MongoDB, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the Server Side Public License, version 1, * as published by MongoDB, Inc. * * 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 * Server Side Public License for more details. * * You should have received a copy of the Server Side Public License * along with this program. If not, see * . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the Server Side Public License in all respects for * all of the code used other than as permitted herein. If you modify file(s) * with this exception, you may extend this exception to your version of the * file(s), but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. */ #pragma once #include #include #include #include "mongo/base/data_range.h" #include "mongo/base/status_with.h" #include "mongo/bson/bsonelement.h" #include "mongo/bson/bsonmisc.h" #include "mongo/bson/bsonobj.h" #include "mongo/logv2/log_attr.h" namespace mongo { namespace repl { class CollectionInfo; class OplogEntryBase; class DurableReplOperation; class InitialSyncIdDocument; } // namespace repl namespace idl { namespace import { class One_UUID; } // namespace import } // namespace idl /** * A UUID is a 128-bit unique identifier, per RFC 4122, v4, using * a secure random number generator. */ class UUID { using UUIDStorage = std::array; // Make the IDL generated parser a friend friend class ConfigsvrShardCollectionResponse; friend class CommonReshardingMetadata; friend class DonorAbortMigration; friend class DonorStartMigration; friend class DonorWaitForMigrationToCommit; friend class DonorForgetMigration; friend class DonorStateMachine; friend class DatabaseVersion; friend class DbCheckOplogCollection; friend class EncryptionPlaceholder; friend class ExternalKeysCollectionDocument; friend class idl::import::One_UUID; friend class IndexBuildEntry; friend class KeyStoreRecord; friend class ListCollectionsReplyInfo; friend class LogicalSessionId; friend class LogicalSessionToClient; friend class LogicalSessionIdToClient; friend class LogicalSessionFromClient; friend class MigrationCoordinatorDocument; friend class MigrationDestinationManager; friend class MigrationRecipientCommonData; friend class RangeDeletionTask; friend class ResolvedKeyId; friend class repl::CollectionInfo; friend class repl::OplogEntryBase; friend class repl::DurableReplOperation; friend class repl::InitialSyncIdDocument; friend class RecipientForgetMigration; friend class RecipientSyncData; friend class ReshardingDonorDocument; friend class ReshardingSourceId; friend class ResumeIndexInfo; friend class ResumeTokenInternal; friend class ShardCollectionTypeBase; friend class ShardsvrShardCollectionResponse; friend class ShardsvrRenameCollection; friend class TenantMigrationDonorDocument; friend class TenantMigrationRecipientDocument; friend class TestReshardCloneCollection; friend class TypeCollectionRecipientFields; friend class TypeCollectionReshardingFields; friend class VoteCommitIndexBuild; friend class ImportCollectionOplogEntry; friend class VoteCommitImportCollection; public: /** * The number of bytes contained in a UUID. */ static constexpr int kNumBytes = sizeof(UUIDStorage); /** * Generate a new random v4 UUID per RFC 4122. */ static UUID gen(); /** * If the given string represents a valid UUID, constructs and returns the UUID, * otherwise returns an error. */ static StatusWith parse(const std::string& s); /** * If the given BSONElement represents a valid UUID, constructs and returns the UUID, * otherwise returns an error. */ static StatusWith parse(BSONElement from); /** * Parses a BSON document of the form { uuid: BinData(4, "...") }. * * For IDL. */ static UUID parse(const BSONObj& obj); static UUID fromCDR(ConstDataRange cdr) { UUID uuid; invariant(cdr.length() == uuid._uuid.size()); memcpy(uuid._uuid.data(), cdr.data(), uuid._uuid.size()); return uuid; } /** * Returns whether this string represents a valid UUID. */ static bool isUUIDString(const std::string& s); /* * Return the underlying 128-bit array. */ std::array data() const { return _uuid; } /** * Returns a ConstDataRange view of the UUID. */ ConstDataRange toCDR() const { return ConstDataRange(_uuid); } /** * Appends to builder as BinData(4, "...") element with the given name. */ void appendToBuilder(BSONObjBuilder* builder, StringData name) const; /** * Appends to array builder as BinData(4, "..."). */ void appendToArrayBuilder(BSONArrayBuilder* builder) const; /** * Returns a BSON object of the form { uuid: BinData(4, "...") }. */ BSONObj toBSON() const; /** * Returns a string representation of this UUID, in hexadecimal, * as per RFC 4122: * * 4 Octets - 2 Octets - 2 Octets - 2 Octets - 6 Octets */ std::string toString() const; inline int compare(const UUID& rhs) const { return memcmp(&_uuid, &rhs._uuid, sizeof(_uuid)); } inline bool operator==(const UUID& rhs) const { return !compare(rhs); } inline bool operator!=(const UUID& rhs) const { return !(*this == rhs); } inline bool operator<(const UUID& rhs) const { return _uuid < rhs._uuid; } inline bool operator>(const UUID& rhs) const { return _uuid > rhs._uuid; } inline bool operator<=(const UUID& rhs) const { return _uuid <= rhs._uuid; } inline bool operator>=(const UUID& rhs) const { return _uuid >= rhs._uuid; } /** * Returns true only if the UUID is the RFC 4122 variant, v4 (random). */ bool isRFC4122v4() const; /** * Custom hasher so UUIDs can be used in unordered data structures. * * ex: std::unordered_set uuidSet; */ struct Hash { std::size_t operator()(const UUID& uuid) const { uint32_t hash; MurmurHash3_x86_32(uuid._uuid.data(), UUID::kNumBytes, 0, &hash); return hash; } }; friend auto logAttrs(const UUID& uuid) { return "uuid"_attr = uuid; } private: UUID(const UUIDStorage& uuid) : _uuid(uuid) {} /** * Should never be used, as the resulting UUID will not be unique. * The exception is in code generated by the IDL compiler, which itself ensures * such an invalid value cannot propagate. */ friend class LogicalSessionId; UUID() = default; UUIDStorage _uuid{}; // UUID in network byte order }; inline std::ostream& operator<<(std::ostream& s, const UUID& uuid) { return (s << uuid.toString()); } inline StringBuilder& operator<<(StringBuilder& s, const UUID& uuid) { return (s << uuid.toString()); } /** * Supports use of UUID with the BSON macro: * BSON("uuid" << uuid) -> { uuid: BinData(4, "...") } */ template <> BSONObjBuilder& BSONObjBuilderValueStream::operator<<(UUID value); } // namespace mongo