summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/rollback_fix_up_info.h
blob: 53964ce2b4fd09cc56725548b0770959fc579f08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/**
 *    Copyright (C) 2017 MongoDB Inc.
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    As a special exception, the copyright holders give permission to link the
 *    code of portions of this program with the OpenSSL library under certain
 *    conditions as described in each individual source file and distribute
 *    linked combinations including the program with the OpenSSL library. You
 *    must comply with the GNU Affero General Public License in all respects for
 *    all of the code used other than as permitted herein. If you modify file(s)
 *    with this exception, you may extend this exception to your version of the
 *    file(s), but you are not obligated to do so. If you do not wish to do so,
 *    delete this exception statement from your version. If you delete this
 *    exception statement from all source files in the program, then also delete
 *    it in the license file.
 */

#pragma once

#include <boost/optional.hpp>
#include <utility>

#include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h"
#include "mongo/base/status_with.h"
#include "mongo/db/namespace_string.h"
#include "mongo/util/duration.h"
#include "mongo/util/uuid.h"

namespace mongo {

class BSONElement;
class OperationContext;

namespace repl {

class StorageInterface;

/**
 * RollbackFixUpInfo represents information derived from processing local oplog entries that have to
 * be rolled back. This information may be supplemented by requesting additional data from the sync
 * source if the local oplog entry is not reversible on its own. For example, when rolling back a
 * document deletion, the oplog entry contains the _id of the deleted document but not the complete
 * document that was removed. We have to request the most recent copy of the document by collection
 * UUID and document _id in order to restore the deleted document.
 *
 * This rollback fix-up information is persisted in "local.system.rollback.*" collections. See
 * description of "kRollback*Namespace" constants.
 */
class RollbackFixUpInfo {
private:
    MONGO_DISALLOW_COPYING(RollbackFixUpInfo);

public:
    /**
     * Contains documents affected by rolling back CRUD operations on documents.
     */
    static const NamespaceString kRollbackDocsNamespace;

    /**
     * Contains mappings of collection UUID -> namespace.
     * This collection is used to roll back create, drop and rename operations.
     * For drops and renames, the namespace in the mapping will be the full namespace to restore
     * in the database catalog.
     * For collection creation, the namespace will be set to empty to indicate that the collection
     * should be dropped.
     */
    static const NamespaceString kRollbackCollectionUuidNamespace;

    /**
     * Contains mappings of collection UUID -> collection options.
     * This collection is used to roll back non-TTL collMod changes to collections.
     */
    static const NamespaceString kRollbackCollectionOptionsNamespace;

    /**
     * Contains mappings of (collection UUID, index name) -> index info.
     * This collection is used to roll back create, drop and TTL changes to indexes.
     */
    static const NamespaceString kRollbackIndexNamespace;

    /**
     * Creates an instance of RollbackFixUpInfo.
     */
    explicit RollbackFixUpInfo(StorageInterface* storageInterface);

    /**
     * Processes an oplog entry representing an insert/delete/update operation on a single document
     * in a collection. Stores information about this operation into "kRollbackDocsNamespace".
     * This allows us to roll back the operation later.
     * For delete and update operations, we will also fetch a more recent copy of the document
     * affected by this operation and store it in the same collection.
     *
     * "docId" is the _id field of the modified document.
     *
     * "dbName" is required for the find command request used to fetch the document from the sync
     * source.
     *
     * For index creation operations, which are represented in the oplog as insert operations in
     * "*.system.indexes", use processCreateIndexOplogEntry() instead.
     */
    enum class SingleDocumentOpType { kInsert, kDelete, kUpdate };
    class SingleDocumentOperationDescription;
    Status processSingleDocumentOplogEntry(OperationContext* opCtx,
                                           const UUID& collectionUuid,
                                           const BSONElement& docId,
                                           SingleDocumentOpType opType,
                                           const std::string& dbName);

    /**
     * Processes an oplog entry representing a create collection command. Stores information about
     * this operation into "kRollbackCollectionUuidNamespace" to allow us to roll back this
     * operation later by dropping the collection from the catalog by UUID.
     *
     * The mapping in the "kRollbackCollectionUuidNamespace" collection will contain the
     * empty namespace.
     */
    class CollectionUuidDescription;
    Status processCreateCollectionOplogEntry(OperationContext* opCtx, const UUID& collectionUuid);

    /**
     * Processes an oplog entry representing a drop collection command. Stores information about
     * this operation into "kRollbackCollectionUuidNamespace" to allow us to roll back this
     * operation later by restoring the UUID mapping in the catalog.
     */
    Status processDropCollectionOplogEntry(OperationContext* opCtx,
                                           const UUID& collectionUuid,
                                           const NamespaceString& nss);

    /**
     * Processes an oplog entry representing a rename collection command. Stores information about
     * this operation into "kRollbackCollectionUuidNamespace" to allow us to roll back this
     * operation later by restoring the UUID mapping(s) in the catalog.
     *
     * "targetCollectionUuidAndNss" is derived from the "dropTarget" and "to" fields of the
     * renameCollection oplogEntry.
     *
     * If the target collection did not exist when the rename operation was applied
     * (targetCollectionUuidAndNss is valid), this function will insert one document into
     * "kRollbackCollectionUuidNamespace":
     *     source UUID -> namespace mapping.
     *
     * If the target collection was dropped when the rename operation was applied
     * (targetCollectionUuidAndNss is valid), this function will insert two documents into
     * "kRollbackCollectionUuidNamespace":
     *     source UUID -> namespace mapping; and
     *     dropped target UUID -> namespace mapping
     */
    using CollectionUuidAndNss = std::pair<UUID, NamespaceString>;
    Status processRenameCollectionOplogEntry(
        OperationContext* opCtx,
        const UUID& sourceCollectionUuid,
        const NamespaceString& sourceNss,
        boost::optional<CollectionUuidAndNss> targetCollectionUuidAndNss);

    /**
     * Processes an oplog entry representing a non-TTL collMod command. Stores information about
     * this operation into "kRollbackCollectionOptionsNamespace" to allow us to roll back this
     * operation later by restoring the collection options in the catalog.
     */
    class CollectionOptionsDescription;
    Status processCollModOplogEntry(OperationContext* opCtx,
                                    const UUID& collectionUuid,
                                    const BSONObj& optionsObj);

    /**
     * Processes an oplog entry representing a createIndex command. Stores information about
     * this operation into "kRollbackIndexNamespace" to allow us to roll back this
     * operation later by dropping the index from the catalog by UUID/index name.
     *
     * The mapping in the "kRollbackCollectionUuidNamespace" collection will contain the
     * empty namespace.
     */
    Status processCreateIndexOplogEntry(OperationContext* opCtx,
                                        const UUID& collectionUuid,
                                        const std::string& indexName);
    enum class IndexOpType { kCreate, kDrop, kUpdateTTL };
    class IndexDescription;

    /**
     * Processes an oplog entry representing a collMod command that updates the expiration setting
     * on a TTL index. Stores information about this operation into "kRollbackIndexNamespace" to
     * allow us to roll back this operation later by updating the TTL expiration to the previous
     * value.
     */
    Status processUpdateIndexTTLOplogEntry(OperationContext* opCtx,
                                           const UUID& collectionUuid,
                                           const std::string& indexName,
                                           Seconds expireAfterSeconds);

    /**
     * Processes an oplog entry representing a dropIndexes command with a single index. Stores
     * information about this operation into "kRollbackIndexNamespace" to allow us to roll back this
     * operation later by recreating the index.
     */
    Status processDropIndexOplogEntry(OperationContext* opCtx,
                                      const UUID& collectionUuid,
                                      const std::string& indexName,
                                      const BSONObj& infoObj);

private:
    /**
     * Upserts a single document using the _id field of the document in "update".
     */
    Status _upsertById(OperationContext* opCtx, const NamespaceString& nss, const BSONObj& update);

    /**
     * Upserts an IndexDescription.
     */
    Status _upsertIndexDescription(OperationContext* opCtx, const IndexDescription& description);

    StorageInterface* const _storageInterface;
};

}  // namespace repl
}  // namespace mongo