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 <memcached/dockey.h> 21 22#include "atomic.h" 23#include "ep_types.h" 24 25#include <string> 26 27class Item; 28class KVStore; 29class SystemEventMessage; 30 31/// underlying size of uint32_t as this is to be stored in the Item flags field. 32enum class SystemEvent : uint32_t { 33 /** 34 * The Collection system event represents the beginning or end of a 35 * collection. Each Collection system event has a key which contains the 36 * collection name. When the event is queued in a checkpoint or stored on 37 * disk the seqno of that item states that this is the point when that 38 * collection became accessible unless that queued/stored item is deleted, 39 * then it represent when that collection became inaccesible (logically 40 * deleted). 41 * 42 * A Collection system event when queued into a checkpoint carries with it 43 * a value, the value is used to maintain a per vbucket JSON collection's 44 * manifest (for persisted buckets). 45 */ 46 Collection, 47 48 /** 49 * The DeleteCollectionHard system event is generated when a VBucket has 50 * completed the deletion of all items of a collection. The hard delete 51 * carries data to the flusher so we can persist a JSON manifest that now 52 * fully removes the collection and also deleted the special marker document 53 * created by CreateCollection. 54 */ 55 DeleteCollectionHard, 56 57 /** 58 * The DeleteCollectionSoft system event is generated when a VBucket has 59 * completed the deletion of all items of a collection *but* a 60 * collection of the same name was added back during the deletion. The soft 61 * delete carries data to the flusher so we can persist a JSON manifest that 62 * only updates the end-seqno of the deleted collection entry. The soft 63 * delete also deleted the special marker document created by 64 * CreateCollection. 65 */ 66 DeleteCollectionSoft, 67 68 /** 69 * The CollectionsSeparatorChanged system event is generated when a VBucket 70 * changes the separator used for identifying collections in keys. This 71 * must result in a vbucket manifest update and a SystemEvent document is 72 * stored. All separator changes write to the same SystemEvent document. 73 */ 74 CollectionsSeparatorChanged 75}; 76 77static inline std::string to_string(const SystemEvent se) { 78 switch (se) { 79 case SystemEvent::Collection: 80 return "Collection"; 81 case SystemEvent::DeleteCollectionHard: 82 return "DeleteCollectionHard"; 83 case SystemEvent::DeleteCollectionSoft: 84 return "DeleteCollectionSoft"; 85 case SystemEvent::CollectionsSeparatorChanged: 86 return "CollectionSeparatorChanged"; 87 } 88 throw std::invalid_argument("to_string(SystemEvent) unknown " + 89 std::to_string(int(se))); 90} 91 92class SystemEventFactory { 93public: 94 /** 95 * Make an Item representing the SystemEvent 96 * @param se The SystemEvent being created. The returned Item will have this 97 * value stored in the flags field. 98 * @param keyExtra Every SystemEvent has defined key, keyExtra is appended 99 * to the defined key 100 * @param itemSize The returned Item can be requested to allocate a value 101 * of itemSize. Some SystemEvents will update the value with data to 102 * be persisted/replicated. 103 * @param seqno An OptionalSeqno - if defined the returned Item will have 104 * the seqno value set as its bySeqno. 105 */ 106 static std::unique_ptr<Item> make(SystemEvent se, 107 const std::string& keyExtra, 108 size_t itemSize, 109 OptionalSeqno seqno); 110 111 static std::unique_ptr<Item> make(const DocKey& key, SystemEvent se); 112 113private: 114 static std::string makeKey(SystemEvent se, 115 const std::string& keyExtra); 116}; 117 118enum class ProcessStatus { Skip, Continue }; 119 120/** 121 * SystemEventFlush holds all SystemEvent data for a single invocation of a 122 * vbucket's flush 123 * If the flush encountered no SystemEvents then this class does nothing 124 * If the flush has SystemEvents then this class will ensure the correct 125 * actions occur. 126 */ 127class SystemEventFlush { 128public: 129 /** 130 * Get the Item which is updating the collections manifest (if any) 131 * 132 * @return nullptr if no manifest exists or the Item to be used in writing 133 * a manifest. 134 */ 135 const Item* getCollectionsManifestItem() const; 136 137 /** 138 * The flusher passes each item into this function and process determines 139 * what needs to happen (possibly updating the Item). 140 * 141 * This function /may/ take a reference to the ref-counted Item if the Item 142 * is required for a collections manifest update. 143 * 144 * Warning: Even though the input is a const queued_item, the Item* is not 145 * const. This function may call setOperation on the shared item 146 * 147 * @param item an item from the flushers items to flush. 148 * @returns Skip if the flusher should not continue with the item or 149 * Continue if the flusher can continue the rest of the flushing 150 * function against the item. 151 */ 152 ProcessStatus process(const queued_item& item); 153 154private: 155 /** 156 * Save the item as the item which contains the manifest which will be 157 * used in the flush's update of the vbucket's metadata documents. 158 * The function will only set the them if it has a seqno higher than any 159 * previously saved item. 160 */ 161 void saveCollectionsManifestItem(const queued_item& item); 162 163 /** 164 * Shared pointer to an Item which holds collections manifest data that 165 * maybe needed by the flush::commit 166 */ 167 queued_item collectionManifestItem; 168}; 169 170class SystemEventReplicate { 171public: 172 static ProcessStatus process(const Item& item); 173}; 174