1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2017 Couchbase, Inc
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17
18#pragma once
19
20#include <platform/sized_buffer.h>
21
22namespace Collections {
23
24// The reserved name of the system owned, default collection.
25const char* const _DefaultCollectionIdentifier = "$default";
26static cb::const_char_buffer DefaultCollectionIdentifier(
27        _DefaultCollectionIdentifier);
28
29// The default separator we will use for identifying collections in keys.
30const char* const DefaultSeparator = ":";
31
32// SystemEvent keys or parts which will be made into keys
33const char* const SystemSeparator = ":"; // Note this never changes
34const char* const SystemEventPrefix = "$collections";
35const char* const SystemEventPrefixWithSeparator = "$collections:";
36const char* const SeparatorChangePrefix = "$collections_separator";
37const char* const SeparatorChangePrefixWithSeparator =
38        "$collections_separator:";
39const char* const DeleteKey = "$collections:delete:";
40
41// Couchstore private file name for manifest data
42const char CouchstoreManifest[] = "_local/collections_manifest";
43
44// Length of the string excluding the zero terminator (i.e. strlen)
45const size_t CouchstoreManifestLen = sizeof(CouchstoreManifest) - 1;
46
47using uid_t = uint64_t;
48
49/**
50 * Return a uid from a C-string.
51 * A valid uid is a C-string where each character satisfies std::isxdigit
52 * and can be converted to a uid_t by std::strtoull.
53 *
54 * @param uid C-string uid
55 * @throws std::invalid_argument if uid is invalid
56 */
57uid_t makeUid(const char* uid);
58
59/**
60 * Interface definition for the a collection identifier - a pair of name and UID
61 * Forces compile time dispatch for the 3 required methods.
62 * getUid, getName and isDefaultCollection
63 */
64template <class T>
65class IdentifierInterface {
66public:
67    /// @returns the UID for this identifier
68    uid_t getUid() const {
69        return static_cast<const T*>(this)->getUid();
70    }
71
72    /// @returns the name for this identifier
73    cb::const_char_buffer getName() const {
74        return static_cast<const T*>(this)->getName();
75    }
76
77    /// @returns true if the identifer's name matches the default name
78    bool isDefaultCollection() const {
79        return getName() == DefaultCollectionIdentifier;
80    }
81};
82
83/**
84 * A collection may exist concurrently, where one maybe open and the others
85 * are in the process of being erased. This class carries the information for
86 * locating the correct "generation" of a collection.
87 */
88class Identifier : public IdentifierInterface<Identifier> {
89public:
90    Identifier(cb::const_char_buffer name, uid_t uid) : name(name), uid(uid) {
91    }
92
93    template <class T>
94    Identifier(const IdentifierInterface<T>& identifier)
95        : name(identifier.getName()), uid(identifier.getUid()) {
96    }
97
98    cb::const_char_buffer getName() const {
99        return name;
100    }
101
102    uid_t getUid() const {
103        return uid;
104    }
105
106private:
107    cb::const_char_buffer name;
108    uid_t uid;
109};
110
111/**
112 * All of the data a DCP system event message will carry.
113 * This covers create and delete collection.
114 * This struct is not the layout of such data.
115 */
116struct SystemEventData {
117    /// UID of manifest which triggered the event
118    Collections::uid_t manifestUid;
119    /// Identifier of the affected collection (name and UID).
120    Identifier id;
121};
122
123/**
124 * All of the data a DCP system event message will carry (for create/delete).
125 * This is the layout of such data and the collection name is the key of the
126 * event packet.
127 */
128struct SystemEventDCPData {
129    /// The manifest uid stored in network byte order ready for sending
130    Collections::uid_t manifestUid;
131    /// The collection uid stored in network byte order ready for sending
132    Collections::uid_t collectionUid;
133};
134
135/**
136 * All of the data a DCP separator changed system event message will carry.
137 * This struct is not the layout of such data.
138 */
139struct SystemEventSeparatorData {
140    /// UID of manifest which triggered the change of separator
141    Collections::uid_t manifestUid;
142    /// The new separator
143    cb::const_char_buffer separator;
144};
145
146std::string to_string(const Identifier& identifier);
147
148std::ostream& operator<<(std::ostream& os, const Identifier& identifier);
149
150} // end namespace Collections
151