summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/historical_ident_tracker.h
blob: fe14e83a04f74dbbd5559de3260e79ba0c76dc95 (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
/**
 *    Copyright (C) 2022-present MongoDB, Inc.
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the Server Side Public License, version 1,
 *    as published by MongoDB, Inc.
 *
 *    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
 *    Server Side Public License for more details.
 *
 *    You should have received a copy of the Server Side Public License
 *    along with this program. If not, see
 *    <http://www.mongodb.com/licensing/server-side-public-license>.
 *
 *    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 Server Side 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 <list>
#include <string>
#include <unordered_map>

#include "mongo/bson/timestamp.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context.h"
#include "mongo/platform/mutex.h"
#include "mongo/util/uuid.h"

namespace mongo {

/**
 * Keeps track of historical ident information when a collection is renamed or dropped.
 */
class HistoricalIdentTracker final {
public:
    HistoricalIdentTracker(const HistoricalIdentTracker&) = delete;
    HistoricalIdentTracker(HistoricalIdentTracker&&) = delete;

    static HistoricalIdentTracker& get(ServiceContext* svcCtx);
    static HistoricalIdentTracker& get(OperationContext* opCtx);

    HistoricalIdentTracker() = default;
    ~HistoricalIdentTracker() = default;

    /**
     * Returns the historical namespace and UUID for 'ident' at 'timestamp'. Returns boost::none if
     * there was no historical namespace.
     */
    boost::optional<std::pair<NamespaceString, UUID>> lookup(const std::string& ident,
                                                             Timestamp timestamp) const;

    /**
     * Pins the historical content to the given timestamp, preventing it from being removed.
     *
     * This is necessary for backup cursors, which need to report the namespace and UUID at the time
     * of the checkpoint the backup is being taken on. When a backup cursor is open, it pins the
     * checkpoint the backup is being taken on. Checkpoints can still be taken, which advances the
     * last checkpoint timestamp and would remove historical content needed by the open backup
     * cursor. This method prevents that from happening by pinning the content.
     *
     * The checkpoint timestamp of the backup can be earlier than the oldest timestamp, which
     * prevents us from opening a snapshot at the checkpoint timestamp as history before the oldest
     * timestamp is discarded.
     */
    void pinAtTimestamp(Timestamp timestamp);
    void unpin();

    /**
     * Records the idents namespace and UUID before it was renamed.
     */
    void recordRename(const std::string& ident,
                      const NamespaceString& oldNss,
                      const UUID& uuid,
                      Timestamp timestamp) {
        _addHistoricalIdent(ident, oldNss, uuid, timestamp);
    }

    /**
     * Records the idents namespace and UUID before it was dropped.
     */
    void recordDrop(const std::string& ident,
                    const NamespaceString& nss,
                    const UUID& uuid,
                    Timestamp timestamp) {
        _addHistoricalIdent(ident, nss, uuid, timestamp);
    }

    /**
     * Removes historical content that is no longer necessary. This is anything older than the last
     * checkpoint timestamp.
     *
     * If there's a pinned timestamp, min(timestamp, _pinnedTimestamp) is used.
     */
    void removeEntriesOlderThan(Timestamp timestamp);

    /**
     * Historical content added may not be stable yet and can be rolled back. When rollback to
     * stable runs, we need to remove any historical content that is considered current.
     *
     * If there's a pinned timestamp, max(timestamp, _pinnedTimestamp) is used.
     */
    void rollbackTo(Timestamp timestamp);

private:
    /**
     * Helper function for recordRename() and recordDrop().
     *
     * Appends a new historical entry with 'nss' and 'uuid' for 'ident' in '_historicalIdents'.
     * Sets the 'end' timestamp to be 'timestamp - 1'.
     * Sets the 'start' timestamp to the timestamp of the last entry + 1, or Timestamp::min() if
     * there was no earlier entry.
     */
    void _addHistoricalIdent(const std::string& ident,
                             const NamespaceString& nss,
                             const UUID& uuid,
                             Timestamp timestamp);

    struct HistoricalIdentEntry {
        const NamespaceString nss;
        const UUID uuid;
        Timestamp start;
        Timestamp end;
    };

    // Protects all the member variables below.
    mutable Mutex _mutex = MONGO_MAKE_LATCH("HistoricalIdentTracker::_mutex");
    stdx::unordered_map<std::string, std::list<HistoricalIdentEntry>> _historicalIdents;
    Timestamp _pinnedTimestamp;
};

}  // namespace mongo