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 
22 namespace Collections {
23 
24 // The reserved name of the system owned, default collection.
25 const char* const _DefaultCollectionIdentifier = "$default";
26 static cb::const_char_buffer DefaultCollectionIdentifier(
27         _DefaultCollectionIdentifier);
28 
29 // The default separator we will use for identifying collections in keys.
30 const char* const DefaultSeparator = ":";
31 
32 // SystemEvent keys or parts which will be made into keys
33 const char* const SystemSeparator = ":"; // Note this never changes
34 const char* const SystemEventPrefix = "$collections";
35 const char* const SystemEventPrefixWithSeparator = "$collections:";
36 const char* const SeparatorChangePrefix = "$collections_separator";
37 const char* const SeparatorChangePrefixWithSeparator =
38         "$collections_separator:";
39 const char* const DeleteKey = "$collections:delete:";
40 
41 // Couchstore private file name for manifest data
42 const char CouchstoreManifest[] = "_local/collections_manifest";
43 
44 // Length of the string excluding the zero terminator (i.e. strlen)
45 const size_t CouchstoreManifestLen = sizeof(CouchstoreManifest) - 1;
46 
47 using 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  */
57 uid_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  */
64 template <class T>
65 class IdentifierInterface {
66 public:
67     /// @returns the UID for this identifier
getUid() const68     uid_t getUid() const {
69         return static_cast<const T*>(this)->getUid();
70     }
71 
72     /// @returns the name for this identifier
getName() const73     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
isDefaultCollection() const78     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  */
88 class Identifier : public IdentifierInterface<Identifier> {
89 public:
Identifier(cb::const_char_buffer name, uid_t uid)90     Identifier(cb::const_char_buffer name, uid_t uid) : name(name), uid(uid) {
91     }
92 
93     template <class T>
Identifier(const IdentifierInterface<T>& identifier)94     Identifier(const IdentifierInterface<T>& identifier)
95         : name(identifier.getName()), uid(identifier.getUid()) {
96     }
97 
getName() const98     cb::const_char_buffer getName() const {
99         return name;
100     }
101 
getUid() const102     uid_t getUid() const {
103         return uid;
104     }
105 
106 private:
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  */
116 struct 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  */
128 struct 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  */
139 struct 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 
146 std::string to_string(const Identifier& identifier);
147 
148 std::ostream& operator<<(std::ostream& os, const Identifier& identifier);
149 
150 } // end namespace Collections
151