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 #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kStorage
32
33 #include "mongo/platform/basic.h"
34
35 #include <algorithm>
36
37 #include "mongo/base/checked_cast.h"
38 #include "mongo/db/concurrency/write_conflict_exception.h"
39 #include "mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.h"
40 #include "mongo/db/storage/wiredtiger/wiredtiger_record_store.h"
41 #include "mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h"
42 #include "mongo/db/storage/wiredtiger/wiredtiger_session_cache.h"
43 #include "mongo/db/storage/wiredtiger/wiredtiger_snapshot_manager.h"
44 #include "mongo/util/log.h"
45 #include "mongo/util/mongoutils/str.h"
46 #include "mongo/util/scopeguard.h"
47
48 namespace mongo {
49
prepareForCreateSnapshot(OperationContext * opCtx)50 Status WiredTigerSnapshotManager::prepareForCreateSnapshot(OperationContext* opCtx) {
51 WiredTigerRecoveryUnit::get(opCtx)->prepareForCreateSnapshot(opCtx);
52 return Status::OK();
53 }
54
setCommittedSnapshot(const Timestamp & timestamp)55 void WiredTigerSnapshotManager::setCommittedSnapshot(const Timestamp& timestamp) {
56 stdx::lock_guard<stdx::mutex> lock(_mutex);
57
58 invariant(!_committedSnapshot || *_committedSnapshot <= timestamp);
59 _committedSnapshot = timestamp;
60 }
61
cleanupUnneededSnapshots()62 void WiredTigerSnapshotManager::cleanupUnneededSnapshots() {}
63
dropAllSnapshots()64 void WiredTigerSnapshotManager::dropAllSnapshots() {
65 stdx::lock_guard<stdx::mutex> lock(_mutex);
66 _committedSnapshot = boost::none;
67 }
68
shutdown()69 void WiredTigerSnapshotManager::shutdown() {
70 stdx::lock_guard<stdx::mutex> lock(_mutex);
71 if (!_session)
72 return;
73 invariantWTOK(_session->close(_session, NULL));
74 _session = nullptr;
75 }
76
getMinSnapshotForNextCommittedRead() const77 boost::optional<Timestamp> WiredTigerSnapshotManager::getMinSnapshotForNextCommittedRead() const {
78 stdx::lock_guard<stdx::mutex> lock(_mutex);
79 return _committedSnapshot;
80 }
81
setTransactionReadTimestamp(Timestamp pointInTime,WT_SESSION * session) const82 Status WiredTigerSnapshotManager::setTransactionReadTimestamp(Timestamp pointInTime,
83 WT_SESSION* session) const {
84 char readTSConfigString[15 /* read_timestamp= */ + 16 /* 16 hexadecimal digits */ +
85 1 /* trailing null */];
86 auto size = std::snprintf(
87 readTSConfigString, sizeof(readTSConfigString), "read_timestamp=%llx", pointInTime.asULL());
88 if (size < 0) {
89 int e = errno;
90 error() << "error snprintf " << errnoWithDescription(e);
91 fassertFailedNoTrace(40664);
92 }
93 invariant(static_cast<std::size_t>(size) < sizeof(readTSConfigString));
94
95 return wtRCToStatus(session->timestamp_transaction(session, readTSConfigString));
96 }
97
beginTransactionOnCommittedSnapshot(WT_SESSION * session) const98 Timestamp WiredTigerSnapshotManager::beginTransactionOnCommittedSnapshot(
99 WT_SESSION* session) const {
100 invariantWTOK(session->begin_transaction(session, nullptr));
101 auto rollbacker =
102 MakeGuard([&] { invariant(session->rollback_transaction(session, nullptr) == 0); });
103
104 stdx::lock_guard<stdx::mutex> lock(_mutex);
105 uassert(ErrorCodes::ReadConcernMajorityNotAvailableYet,
106 "Committed view disappeared while running operation",
107 _committedSnapshot);
108
109 auto status = setTransactionReadTimestamp(_committedSnapshot.get(), session);
110 fassertStatusOK(30635, status);
111 rollbacker.Dismiss();
112 return *_committedSnapshot;
113 }
114
beginTransactionOnOplog(WiredTigerOplogManager * oplogManager,WT_SESSION * session) const115 void WiredTigerSnapshotManager::beginTransactionOnOplog(WiredTigerOplogManager* oplogManager,
116 WT_SESSION* session) const {
117 invariantWTOK(session->begin_transaction(session, nullptr));
118 auto rollbacker =
119 MakeGuard([&] { invariant(session->rollback_transaction(session, nullptr) == 0); });
120
121 stdx::lock_guard<stdx::mutex> lock(_mutex);
122 auto allCommittedTimestamp = oplogManager->getOplogReadTimestamp();
123 invariant(Timestamp(static_cast<unsigned long long>(allCommittedTimestamp)).asULL() ==
124 allCommittedTimestamp);
125 auto status = setTransactionReadTimestamp(
126 Timestamp(static_cast<unsigned long long>(allCommittedTimestamp)), session);
127
128 // If we failed to set the read timestamp, we assume it is due to the oldest_timestamp racing
129 // ahead. Rather than synchronizing for this rare case, if requested, throw a
130 // WriteConflictException which will be retried.
131 if (!status.isOK() && status.code() == ErrorCodes::BadValue) {
132 throw WriteConflictException();
133 }
134 fassert(50771, status);
135 rollbacker.Dismiss();
136 }
137
138 } // namespace mongo
139