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 "collections/collections_types.h" 21 #include "stored-value.h" 22 #include "systemevent.h" 23 24 #include <platform/make_unique.h> 25 #include <platform/sized_buffer.h> 26 27 #include <memory> 28 29 namespace Collections { 30 namespace VB { 31 32 /** 33 * The Collections::VB::ManifestEntry stores the data a collection 34 * needs from a vbucket's perspective. 35 * - The Collections::Manifest revision 36 * - The seqno lifespace of the collection 37 * 38 * Additionally this object is designed for use by Collections::VB::Manifest, 39 * this is why the object stores a pointer to a std::string collection name, 40 * rather than including the entire object std::string. 41 * Thus a std::map can map from cb::const_char_buffer, ManifestEntry, where 42 * the buffer refers to the key we own via the pointer. 43 */ 44 class ManifestEntry { 45 public: ManifestEntry(Identifier identifier,int64_t _startSeqno,int64_t _endSeqno)46 ManifestEntry(Identifier identifier, int64_t _startSeqno, int64_t _endSeqno) 47 : collectionName(std::make_unique<std::string>( 48 identifier.getName().data(), identifier.getName().size())), 49 uid(identifier.getUid()), 50 startSeqno(-1), 51 endSeqno(-1) { 52 // Setters validate the start/end range is valid 53 setStartSeqno(_startSeqno); 54 setEndSeqno(_endSeqno); 55 } 56 ManifestEntry(const ManifestEntry & rhs)57 ManifestEntry(const ManifestEntry& rhs) 58 : collectionName( 59 std::make_unique<std::string>(rhs.collectionName->c_str())), 60 uid(rhs.uid), 61 startSeqno(rhs.startSeqno), 62 endSeqno(rhs.endSeqno) { 63 } 64 ManifestEntry(ManifestEntry && rhs)65 ManifestEntry(ManifestEntry&& rhs) 66 : collectionName(std::move(rhs.collectionName)), 67 uid(rhs.uid), 68 startSeqno(rhs.startSeqno), 69 endSeqno(rhs.endSeqno) { 70 } 71 72 ManifestEntry& operator=(ManifestEntry&& rhs) { 73 std::swap(collectionName, rhs.collectionName); 74 uid = rhs.uid; 75 startSeqno = rhs.startSeqno; 76 endSeqno = rhs.endSeqno; 77 return *this; 78 } 79 80 ManifestEntry& operator=(const ManifestEntry& rhs) { 81 collectionName.reset(new std::string(rhs.collectionName->c_str())); 82 uid = rhs.uid; 83 startSeqno = rhs.startSeqno; 84 endSeqno = rhs.endSeqno; 85 return *this; 86 } 87 getCollectionName()88 const std::string& getCollectionName() const { 89 return *collectionName; 90 } 91 92 /** 93 * @return const_char_buffer initialised with address/size of the internal 94 * collection-name string data. 95 */ getCharBuffer()96 cb::const_char_buffer getCharBuffer() const { 97 return cb::const_char_buffer(collectionName->data(), 98 collectionName->size()); 99 } 100 getIdentifier()101 Identifier getIdentifier() const { 102 return {getCharBuffer(), getUid()}; 103 } 104 getStartSeqno()105 int64_t getStartSeqno() const { 106 return startSeqno; 107 } 108 setStartSeqno(int64_t seqno)109 void setStartSeqno(int64_t seqno) { 110 // Enforcing that start/end are not the same, they should always be 111 // separated because they represent start/end mutations. 112 if (seqno < 0 || seqno <= startSeqno || seqno == endSeqno) { 113 throwException<std::invalid_argument>( 114 __FUNCTION__, 115 "cannot set startSeqno to " + std::to_string(seqno)); 116 } 117 startSeqno = seqno; 118 } 119 getEndSeqno()120 int64_t getEndSeqno() const { 121 return endSeqno; 122 } 123 setEndSeqno(int64_t seqno)124 void setEndSeqno(int64_t seqno) { 125 // Enforcing that start/end are not the same, they should always be 126 // separated because they represent start/end mutations. 127 if (seqno != StoredValue::state_collection_open && 128 (seqno <= endSeqno || seqno == startSeqno)) { 129 throwException<std::invalid_argument>( 130 __FUNCTION__, 131 "cannot set " 132 "endSeqno to " + 133 std::to_string(seqno)); 134 } 135 endSeqno = seqno; 136 } 137 resetEndSeqno()138 void resetEndSeqno() { 139 endSeqno = StoredValue::state_collection_open; 140 } 141 getUid()142 uid_t getUid() const { 143 return uid; 144 } 145 setUid(uid_t uid)146 void setUid(uid_t uid) { 147 this->uid = uid; 148 } 149 150 /** 151 * A collection is open when the start is greater than the end. 152 * An open collection is one that is readable and writable by the data 153 * path. 154 */ isOpen()155 bool isOpen() const { 156 return startSeqno > endSeqno; 157 } 158 159 /** 160 * A collection is being deleted when the endSeqno is not the special 161 * state_collection_open value. 162 */ isDeleting()163 bool isDeleting() const { 164 return endSeqno != StoredValue::state_collection_open; 165 } 166 167 /** 168 * A collection can be open whilst at the same time a previous incarnation 169 * of it is being deleted. 170 * isOpenAndDeleted returns true for exactly this case 171 */ isOpenAndDeleting()172 bool isOpenAndDeleting() const { 173 return isOpen() && isDeleting(); 174 } 175 176 /** 177 * A collection can be open whilst at the same time a previous incarnation 178 * of it is being deleted. 179 * Exclusively Open is true only when there is no deletion in progress. 180 */ isExclusiveOpen()181 bool isExclusiveOpen() const { 182 return isOpen() && !isDeleting(); 183 } 184 185 /** 186 * A collection can be open whilst at the same time a previous incarnation 187 * of it is being deleted. 188 * Exclusively Deleting means that there was no re-addition of the 189 * collection, it is only deleting. 190 */ isExclusiveDeleting()191 bool isExclusiveDeleting() const { 192 return !isOpen() && isDeleting(); 193 } 194 195 /** 196 * Inform the collection that all items of the collection up to endSeqno 197 * have been deleted. 198 * 199 * @return the correct SystemEvent for vbucket manifest management. If the 200 * collection has been reopened, a soft delete, else hard. 201 */ 202 SystemEvent completeDeletion(); 203 204 private: 205 /** 206 * Return a string for use in throwException, returns: 207 * "VB::ManifestEntry::<thrower>:<error>, this:<ostream *this>" 208 * 209 * @param thrower a string for who is throwing, typically __FUNCTION__ 210 * @param error a string containing the error and useful data 211 * @returns string as per description above 212 */ 213 std::string getExceptionString(const std::string& thrower, 214 const std::string& error) const; 215 216 /** 217 * throw exception with the following error string: 218 * "VB::ManifestEntry::<thrower>:<error>, this:<ostream *this>" 219 * 220 * @param thrower a string for who is throwing, typically __FUNCTION__ 221 * @param error a string containing the error and useful data 222 * @throws exception 223 */ 224 template <class exception> throwException(const std::string & thrower,const std::string & error)225 [[noreturn]] void throwException(const std::string& thrower, 226 const std::string& error) const { 227 throw exception(getExceptionString(thrower, error)); 228 } 229 230 /** 231 * An entry has a name that is heap allocated... this is due to the 232 * way ManifestEntry objects are stored in the VB::Manifest 233 */ 234 std::unique_ptr<std::string> collectionName; 235 236 /** 237 * The uid of the collection 238 */ 239 uid_t uid; 240 241 /** 242 * Collection life-time is recorded as the seqno the collection was added 243 * to the seqno of the point we started to delete it. 244 * 245 * If a collection is not being deleted then endSeqno has a value of 246 * StoredValue::state_collection_open to indicate this. 247 */ 248 int64_t startSeqno; 249 int64_t endSeqno; 250 }; 251 252 std::ostream& operator<<(std::ostream& os, const ManifestEntry& manifestEntry); 253 254 } // end namespace VB 255 } // end namespace Collections