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