1 2 /** 3 * Copyright (C) 2018-present MongoDB, Inc. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the Server Side Public License, version 1, 7 * as published by MongoDB, Inc. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * Server Side Public License for more details. 13 * 14 * You should have received a copy of the Server Side Public License 15 * along with this program. If not, see 16 * <http://www.mongodb.com/licensing/server-side-public-license>. 17 * 18 * As a special exception, the copyright holders give permission to link the 19 * code of portions of this program with the OpenSSL library under certain 20 * conditions as described in each individual source file and distribute 21 * linked combinations including the program with the OpenSSL library. You 22 * must comply with the Server Side Public License in all respects for 23 * all of the code used other than as permitted herein. If you modify file(s) 24 * with this exception, you may extend this exception to your version of the 25 * file(s), but you are not obligated to do so. If you do not wish to do so, 26 * delete this exception statement from your version. If you delete this 27 * exception statement from all source files in the program, then also delete 28 * it in the license file. 29 */ 30 31 #pragma once 32 33 #include <string> 34 35 #include "mongo/base/disallow_copying.h" 36 #include "mongo/db/catalog/collection.h" 37 #include "mongo/db/catalog/collection_options.h" 38 #include "mongo/db/jsobj.h" 39 #include "mongo/db/s/collection_sharding_state.h" 40 41 namespace mongo { 42 struct CollectionOptions; 43 struct InsertStatement; 44 class NamespaceString; 45 class OperationContext; 46 struct OplogSlot; 47 48 namespace repl { 49 class OpTime; 50 } // repl 51 52 /** 53 * Holds document update information used in logging. 54 */ 55 struct OplogUpdateEntryArgs { 56 enum class StoreDocOption { None, PreImage, PostImage }; 57 58 // Name of the collection in which document is being updated. 59 NamespaceString nss; 60 61 OptionalCollectionUUID uuid; 62 63 StmtId stmtId = kUninitializedStmtId; 64 65 // The document before modifiers were applied. 66 boost::optional<BSONObj> preImageDoc; 67 68 // Fully updated document with damages (update modifiers) applied. 69 BSONObj updatedDoc; 70 71 // Document containing update modifiers -- e.g. $set and $unset 72 BSONObj update; 73 74 // Document containing the _id field of the doc being updated. 75 BSONObj criteria; 76 77 // True if this update comes from a chunk migration. 78 bool fromMigrate = false; 79 80 StoreDocOption storeDocOption = StoreDocOption::None; 81 }; 82 83 struct TTLCollModInfo { 84 Seconds expireAfterSeconds; 85 Seconds oldExpireAfterSeconds; 86 std::string indexName; 87 }; 88 89 class OpObserver { 90 MONGO_DISALLOW_COPYING(OpObserver); 91 92 public: 93 OpObserver() = default; 94 virtual ~OpObserver() = default; 95 96 virtual void onCreateIndex(OperationContext* opCtx, 97 const NamespaceString& nss, 98 OptionalCollectionUUID uuid, 99 BSONObj indexDoc, 100 bool fromMigrate) = 0; 101 virtual void onInserts(OperationContext* opCtx, 102 const NamespaceString& nss, 103 OptionalCollectionUUID uuid, 104 std::vector<InsertStatement>::const_iterator begin, 105 std::vector<InsertStatement>::const_iterator end, 106 bool fromMigrate) = 0; 107 virtual void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) = 0; 108 virtual CollectionShardingState::DeleteState aboutToDelete(OperationContext* opCtx, 109 const NamespaceString& nss, 110 const BSONObj& doc) = 0; 111 /** 112 * Handles logging before document is deleted. 113 * 114 * "ns" name of the collection from which deleteState.idDoc will be deleted. 115 * "deleteState" holds information about the deleted document. 116 * "fromMigrate" indicates whether the delete was induced by a chunk migration, and 117 * so should be ignored by the user as an internal maintenance operation and not a 118 * real delete. 119 */ 120 virtual void onDelete(OperationContext* opCtx, 121 const NamespaceString& nss, 122 OptionalCollectionUUID uuid, 123 StmtId stmtId, 124 CollectionShardingState::DeleteState deleteState, 125 bool fromMigrate, 126 const boost::optional<BSONObj>& deletedDoc) = 0; 127 /** 128 * Logs a no-op with "msgObj" in the o field into oplog. 129 * 130 * This function should only be used internally. "nss", "uuid" and the o2 field should never be 131 * exposed to users (for instance through the appendOplogNote command). 132 */ 133 virtual void onInternalOpMessage(OperationContext* opCtx, 134 const NamespaceString& nss, 135 const boost::optional<UUID> uuid, 136 const BSONObj& msgObj, 137 const boost::optional<BSONObj> o2MsgObj) = 0; 138 139 /** 140 * Logs a no-op with "msgObj" in the o field into oplog. 141 */ onOpMessage(OperationContext * opCtx,const BSONObj & msgObj)142 void onOpMessage(OperationContext* opCtx, const BSONObj& msgObj) { 143 onInternalOpMessage(opCtx, {}, boost::none, msgObj, boost::none); 144 } 145 146 virtual void onCreateCollection(OperationContext* opCtx, 147 Collection* coll, 148 const NamespaceString& collectionName, 149 const CollectionOptions& options, 150 const BSONObj& idIndex, 151 const OplogSlot& createOpTime) = 0; 152 /** 153 * This function logs an oplog entry when a 'collMod' command on a collection is executed. 154 * Since 'collMod' commands can take a variety of different formats, the 'o' field of the 155 * oplog entry is populated with the 'collMod' command object. For TTL index updates, we 156 * transform key pattern index specifications into index name specifications, for uniformity. 157 * All other collMod fields are added to the 'o' object without modifications. 158 * 159 * To facilitate the rollback process, 'oldCollOptions' contains the previous state of all 160 * collection options i.e. the state prior to completion of the current collMod command. 161 * 'ttlInfo' contains the index name and previous expiration time of a TTL index. The old 162 * collection options will be stored in the 'o2.collectionOptions_old' field, and the old TTL 163 * expiration value in the 'o2.expireAfterSeconds_old' field. 164 * 165 * Oplog Entry Example ('o' and 'o2' fields shown): 166 * 167 * { 168 * ... 169 * o: { 170 * collMod: "test", 171 * validationLevel: "off", 172 * index: {name: "indexName_1", expireAfterSeconds: 600} 173 * } 174 * o2: { 175 * collectionOptions_old: { 176 * validationLevel: "strict", 177 * }, 178 * expireAfterSeconds_old: 300 179 * } 180 * } 181 * 182 */ 183 virtual void onCollMod(OperationContext* opCtx, 184 const NamespaceString& nss, 185 OptionalCollectionUUID uuid, 186 const BSONObj& collModCmd, 187 const CollectionOptions& oldCollOptions, 188 boost::optional<TTLCollModInfo> ttlInfo) = 0; 189 virtual void onDropDatabase(OperationContext* opCtx, const std::string& dbName) = 0; 190 191 /** 192 * This function logs an oplog entry when a 'drop' command on a collection is executed. 193 * Returns the optime of the oplog entry successfully written to the oplog. 194 * Returns a null optime if an oplog entry was not written for this operation. 195 */ 196 virtual repl::OpTime onDropCollection(OperationContext* opCtx, 197 const NamespaceString& collectionName, 198 OptionalCollectionUUID uuid) = 0; 199 200 /** 201 * This function logs an oplog entry when an index is dropped. The namespace of the index, 202 * the index name, and the index info from the index descriptor are used to create a 203 * 'dropIndexes' op where the 'o' field is the name of the index and the 'o2' field is the 204 * index info. The index info can then be used to reconstruct the index on rollback. 205 * 206 * If a user specifies {dropIndexes: 'foo', index: '*'}, each index dropped will have its own 207 * oplog entry. This means it's possible to roll back half of the index drops. 208 */ 209 virtual void onDropIndex(OperationContext* opCtx, 210 const NamespaceString& nss, 211 OptionalCollectionUUID uuid, 212 const std::string& indexName, 213 const BSONObj& indexInfo) = 0; 214 215 /** 216 * This function logs an oplog entry when a 'renameCollection' command on a collection is 217 * executed. 218 * Returns the optime of the oplog entry successfully written to the oplog. 219 * Returns a null optime if an oplog entry was not written for this operation. 220 */ 221 virtual repl::OpTime onRenameCollection(OperationContext* opCtx, 222 const NamespaceString& fromCollection, 223 const NamespaceString& toCollection, 224 OptionalCollectionUUID uuid, 225 bool dropTarget, 226 OptionalCollectionUUID dropTargetUUID, 227 bool stayTemp) = 0; 228 virtual void onApplyOps(OperationContext* opCtx, 229 const std::string& dbName, 230 const BSONObj& applyOpCmd) = 0; 231 virtual void onEmptyCapped(OperationContext* opCtx, 232 const NamespaceString& collectionName, 233 OptionalCollectionUUID uuid) = 0; 234 }; 235 236 } // namespace mongo 237