YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/utilities/transaction.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
// This source code is licensed under the BSD-style license found in the
3
// LICENSE file in the root directory of this source tree. An additional grant
4
// of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
#ifndef ROCKSDB_INCLUDE_ROCKSDB_UTILITIES_TRANSACTION_H
21
#define ROCKSDB_INCLUDE_ROCKSDB_UTILITIES_TRANSACTION_H
22
23
#pragma once
24
25
#ifndef ROCKSDB_LITE
26
27
#include <string>
28
#include <vector>
29
30
#include "yb/rocksdb/comparator.h"
31
#include "yb/rocksdb/db.h"
32
#include "yb/rocksdb/status.h"
33
34
namespace rocksdb {
35
36
class Iterator;
37
class TransactionDB;
38
class WriteBatchWithIndex;
39
40
// Provides notification to the caller of SetSnapshotOnNextOperation when
41
// the actual snapshot gets created
42
class TransactionNotifier {
43
 public:
44
1
  virtual ~TransactionNotifier() {}
45
46
  // Implement this method to receive notification when a snapshot is
47
  // requested via SetSnapshotOnNextOperation.
48
  virtual void SnapshotCreated(const Snapshot* newSnapshot) = 0;
49
};
50
51
// Provides BEGIN/COMMIT/ROLLBACK transactions.
52
//
53
// To use transactions, you must first create either an OptimisticTransactionDB
54
// or a TransactionDB.  See examples/[optimistic_]transaction_example.cc for
55
// more information.
56
//
57
// To create a transaction, use [Optimistic]TransactionDB::BeginTransaction().
58
//
59
// It is up to the caller to synchronize access to this object.
60
//
61
// See examples/transaction_example.cc for some simple examples.
62
//
63
// TODO(agiardullo): Not yet implemented
64
//  -PerfContext statistics
65
//  -Support for using Transactions with DBWithTTL
66
class Transaction {
67
 public:
68
3.23k
  virtual ~Transaction() {}
69
70
  // If a transaction has a snapshot set, the transaction will ensure that
71
  // any keys successfully written(or fetched via GetForUpdate()) have not
72
  // been modified outside of this transaction since the time the snapshot was
73
  // set.
74
  // If a snapshot has not been set, the transaction guarantees that keys have
75
  // not been modified since the time each key was first written (or fetched via
76
  // GetForUpdate()).
77
  //
78
  // Using SetSnapshot() will provide stricter isolation guarantees at the
79
  // expense of potentially more transaction failures due to conflicts with
80
  // other writes.
81
  //
82
  // Calling SetSnapshot() has no effect on keys written before this function
83
  // has been called.
84
  //
85
  // SetSnapshot() may be called multiple times if you would like to change
86
  // the snapshot used for different operations in this transaction.
87
  //
88
  // Calling SetSnapshot will not affect the version of Data returned by Get()
89
  // methods.  See Transaction::Get() for more details.
90
  virtual void SetSnapshot() = 0;
91
92
  // Similar to SetSnapshot(), but will not change the current snapshot
93
  // until Put/Merge/Delete/GetForUpdate/MultigetForUpdate is called.
94
  // By calling this function, the transaction will essentially call
95
  // SetSnapshot() for you right before performing the next write/GetForUpdate.
96
  //
97
  // Calling SetSnapshotOnNextOperation() will not affect what snapshot is
98
  // returned by GetSnapshot() until the next write/GetForUpdate is executed.
99
  //
100
  // When the snapshot is created the notifier's SnapshotCreated method will
101
  // be called so that the caller can get access to the snapshot.
102
  //
103
  // This is an optimization to reduce the likelihood of conflicts that
104
  // could occur in between the time SetSnapshot() is called and the first
105
  // write/GetForUpdate operation.  Eg, this prevents the following
106
  // race-condition:
107
  //
108
  //   txn1->SetSnapshot();
109
  //                             txn2->Put("A", ...);
110
  //                             txn2->Commit();
111
  //   txn1->GetForUpdate(opts, "A", ...);  // FAIL!
112
  virtual void SetSnapshotOnNextOperation(
113
      std::shared_ptr<TransactionNotifier> notifier = nullptr) = 0;
114
115
  // Returns the Snapshot created by the last call to SetSnapshot().
116
  //
117
  // REQUIRED: The returned Snapshot is only valid up until the next time
118
  // SetSnapshot()/SetSnapshotOnNextSavePoint() is called, ClearSnapshot()
119
  // is called, or the Transaction is deleted.
120
  virtual const Snapshot* GetSnapshot() const = 0;
121
122
  // Clears the current snapshot (i.e. no snapshot will be 'set')
123
  //
124
  // This removes any snapshot that currently exists or is set to be created
125
  // on the next update operation (SetSnapshotOnNextOperation).
126
  //
127
  // Calling ClearSnapshot() has no effect on keys written before this function
128
  // has been called.
129
  //
130
  // If a reference to a snapshot was retrieved via GetSnapshot(), it will no
131
  // longer be valid and should be discarded after a call to ClearSnapshot().
132
  virtual void ClearSnapshot() = 0;
133
134
  // Write all batched keys to the db atomically.
135
  //
136
  // Returns OK on success.
137
  //
138
  // May return any error status that could be returned by DB:Write().
139
  //
140
  // If this transaction was created by an OptimisticTransactionDB(),
141
  // STATUS(Busy, "") may be returned if the transaction could not guarantee
142
  // that there are no write conflicts.  Status::TryAgain() may be returned
143
  // if the memtable history size is not large enough
144
  //  (See max_write_buffer_number_to_maintain).
145
  //
146
  // If this transaction was created by a TransactionDB(), STATUS(Expired, "")
147
  // may be returned if this transaction has lived for longer than
148
  // TransactionOptions.expiration.
149
  virtual Status Commit() = 0;
150
151
  // Discard all batched writes in this transaction.
152
  virtual void Rollback() = 0;
153
154
  // Records the state of the transaction for future calls to
155
  // RollbackToSavePoint().  May be called multiple times to set multiple save
156
  // points.
157
  virtual void SetSavePoint() = 0;
158
159
  // Undo all operations in this transaction (Put, Merge, Delete, PutLogData)
160
  // since the most recent call to SetSavePoint() and removes the most recent
161
  // SetSavePoint().
162
  // If there is no previous call to SetSavePoint(), returns STATUS(NotFound, "")
163
  virtual Status RollbackToSavePoint() = 0;
164
165
  // This function is similar to DB::Get() except it will also read pending
166
  // changes in this transaction.  Currently, this function will return
167
  // Status::MergeInProgress if the most recent write to the queried key in
168
  // this batch is a Merge.
169
  //
170
  // If read_options.snapshot is not set, the current version of the key will
171
  // be read.  Calling SetSnapshot() does not affect the version of the data
172
  // returned.
173
  //
174
  // Note that setting read_options.snapshot will affect what is read from the
175
  // DB but will NOT change which keys are read from this transaction (the keys
176
  // in this transaction do not yet belong to any snapshot and will be fetched
177
  // regardless).
178
  virtual Status Get(const ReadOptions& options,
179
                     ColumnFamilyHandle* column_family, const Slice& key,
180
                     std::string* value) = 0;
181
182
  virtual Status Get(const ReadOptions& options, const Slice& key,
183
                     std::string* value) = 0;
184
185
  virtual std::vector<Status> MultiGet(
186
      const ReadOptions& options,
187
      const std::vector<ColumnFamilyHandle*>& column_family,
188
      const std::vector<Slice>& keys, std::vector<std::string>* values) = 0;
189
190
  virtual std::vector<Status> MultiGet(const ReadOptions& options,
191
                                       const std::vector<Slice>& keys,
192
                                       std::vector<std::string>* values) = 0;
193
194
  // Read this key and ensure that this transaction will only
195
  // be able to be committed if this key is not written outside this
196
  // transaction after it has first been read (or after the snapshot if a
197
  // snapshot is set in this transaction).  The transaction behavior is the
198
  // same regardless of whether the key exists or not.
199
  //
200
  // Note: Currently, this function will return Status::MergeInProgress
201
  // if the most recent write to the queried key in this batch is a Merge.
202
  //
203
  // The values returned by this function are similar to Transaction::Get().
204
  // If value==nullptr, then this function will not read any data, but will
205
  // still ensure that this key cannot be written to by outside of this
206
  // transaction.
207
  //
208
  // If this transaction was created by an OptimisticTransaction, GetForUpdate()
209
  // could cause commit() to fail.  Otherwise, it could return any error
210
  // that could be returned by DB::Get().
211
  //
212
  // If this transaction was created by a TransactionDB, it can return
213
  // Status::OK() on success,
214
  // STATUS(Busy, "") if there is a write conflict,
215
  // Status::TimedOut() if a lock could not be acquired,
216
  // Status::TryAgain() if the memtable history size is not large enough
217
  //  (See max_write_buffer_number_to_maintain)
218
  // Status::MergeInProgress() if merge operations cannot be resolved.
219
  // or other errors if this key could not be read.
220
  virtual Status GetForUpdate(const ReadOptions& options,
221
                              ColumnFamilyHandle* column_family,
222
                              const Slice& key, std::string* value) = 0;
223
224
  virtual Status GetForUpdate(const ReadOptions& options, const Slice& key,
225
                              std::string* value) = 0;
226
227
  virtual std::vector<Status> MultiGetForUpdate(
228
      const ReadOptions& options,
229
      const std::vector<ColumnFamilyHandle*>& column_family,
230
      const std::vector<Slice>& keys, std::vector<std::string>* values) = 0;
231
232
  virtual std::vector<Status> MultiGetForUpdate(
233
      const ReadOptions& options, const std::vector<Slice>& keys,
234
      std::vector<std::string>* values) = 0;
235
236
  // Returns an iterator that will iterate on all keys in the default
237
  // column family including both keys in the DB and uncommitted keys in this
238
  // transaction.
239
  //
240
  // Setting read_options.snapshot will affect what is read from the
241
  // DB but will NOT change which keys are read from this transaction (the keys
242
  // in this transaction do not yet belong to any snapshot and will be fetched
243
  // regardless).
244
  //
245
  // Caller is responsible for deleting the returned Iterator.
246
  //
247
  // The returned iterator is only valid until Commit(), Rollback(), or
248
  // RollbackToSavePoint() is called.
249
  virtual Iterator* GetIterator(const ReadOptions& read_options) = 0;
250
251
  virtual Iterator* GetIterator(const ReadOptions& read_options,
252
                                ColumnFamilyHandle* column_family) = 0;
253
254
  // Put, Merge, Delete, and SingleDelete behave similarly to the corresponding
255
  // functions in WriteBatch, but will also do conflict checking on the
256
  // keys being written.
257
  //
258
  // If this Transaction was created on an OptimisticTransactionDB, these
259
  // functions should always return Status::OK().
260
  //
261
  // If this Transaction was created on a TransactionDB, the status returned
262
  // can be:
263
  // Status::OK() on success,
264
  // STATUS(Busy, "") if there is a write conflict,
265
  // Status::TimedOut() if a lock could not be acquired,
266
  // Status::TryAgain() if the memtable history size is not large enough
267
  //  (See max_write_buffer_number_to_maintain)
268
  // or other errors on unexpected failures.
269
  virtual Status Put(ColumnFamilyHandle* column_family, const Slice& key,
270
                     const Slice& value) = 0;
271
  virtual Status Put(const Slice& key, const Slice& value) = 0;
272
  virtual Status Put(ColumnFamilyHandle* column_family, const SliceParts& key,
273
                     const SliceParts& value) = 0;
274
  virtual Status Put(const SliceParts& key, const SliceParts& value) = 0;
275
276
  virtual Status Merge(ColumnFamilyHandle* column_family, const Slice& key,
277
                       const Slice& value) = 0;
278
  virtual Status Merge(const Slice& key, const Slice& value) = 0;
279
280
  virtual Status Delete(ColumnFamilyHandle* column_family,
281
                        const Slice& key) = 0;
282
  virtual Status Delete(const Slice& key) = 0;
283
  virtual Status Delete(ColumnFamilyHandle* column_family,
284
                        const SliceParts& key) = 0;
285
  virtual Status Delete(const SliceParts& key) = 0;
286
287
  virtual Status SingleDelete(ColumnFamilyHandle* column_family,
288
                              const Slice& key) = 0;
289
  virtual Status SingleDelete(const Slice& key) = 0;
290
  virtual Status SingleDelete(ColumnFamilyHandle* column_family,
291
                              const SliceParts& key) = 0;
292
  virtual Status SingleDelete(const SliceParts& key) = 0;
293
294
  // PutUntracked() will write a Put to the batch of operations to be committed
295
  // in this transaction.  This write will only happen if this transaction
296
  // gets committed successfully.  But unlike Transaction::Put(),
297
  // no conflict checking will be done for this key.
298
  //
299
  // If this Transaction was created on a TransactionDB, this function will
300
  // still acquire locks necessary to make sure this write doesn't cause
301
  // conflicts in other transactions and may return STATUS(Busy, "").
302
  virtual Status PutUntracked(ColumnFamilyHandle* column_family,
303
                              const Slice& key, const Slice& value) = 0;
304
  virtual Status PutUntracked(const Slice& key, const Slice& value) = 0;
305
  virtual Status PutUntracked(ColumnFamilyHandle* column_family,
306
                              const SliceParts& key,
307
                              const SliceParts& value) = 0;
308
  virtual Status PutUntracked(const SliceParts& key,
309
                              const SliceParts& value) = 0;
310
311
  virtual Status MergeUntracked(ColumnFamilyHandle* column_family,
312
                                const Slice& key, const Slice& value) = 0;
313
  virtual Status MergeUntracked(const Slice& key, const Slice& value) = 0;
314
315
  virtual Status DeleteUntracked(ColumnFamilyHandle* column_family,
316
                                 const Slice& key) = 0;
317
318
  virtual Status DeleteUntracked(const Slice& key) = 0;
319
  virtual Status DeleteUntracked(ColumnFamilyHandle* column_family,
320
                                 const SliceParts& key) = 0;
321
  virtual Status DeleteUntracked(const SliceParts& key) = 0;
322
323
  // Similar to WriteBatch::PutLogData
324
  virtual void PutLogData(const Slice& blob) = 0;
325
326
  // By default, all Put/Merge/Delete operations will be indexed in the
327
  // transaction so that Get/GetForUpdate/GetIterator can search for these
328
  // keys.
329
  //
330
  // If the caller does not want to fetch the keys about to be written,
331
  // they may want to avoid indexing as a performance optimization.
332
  // Calling DisableIndexing() will turn off indexing for all future
333
  // Put/Merge/Delete operations until EnableIndexing() is called.
334
  //
335
  // If a key is Put/Merge/Deleted after DisableIndexing is called and then
336
  // is fetched via Get/GetForUpdate/GetIterator, the result of the fetch is
337
  // undefined.
338
  virtual void DisableIndexing() = 0;
339
  virtual void EnableIndexing() = 0;
340
341
  // Returns the number of distinct Keys being tracked by this transaction.
342
  // If this transaction was created by a TransactinDB, this is the number of
343
  // keys that are currently locked by this transaction.
344
  // If this transaction was created by an OptimisticTransactionDB, this is the
345
  // number of keys that need to be checked for conflicts at commit time.
346
  virtual uint64_t GetNumKeys() const = 0;
347
348
  // Returns the number of Puts/Deletes/Merges that have been applied to this
349
  // transaction so far.
350
  virtual uint64_t GetNumPuts() const = 0;
351
  virtual uint64_t GetNumDeletes() const = 0;
352
  virtual uint64_t GetNumMerges() const = 0;
353
354
  // Returns the elapsed time in milliseconds since this Transaction began.
355
  virtual uint64_t GetElapsedTime() const = 0;
356
357
  // Fetch the underlying write batch that contains all pending changes to be
358
  // committed.
359
  //
360
  // Note:  You should not write or delete anything from the batch directly and
361
  // should only use the the functions in the Transaction class to
362
  // write to this transaction.
363
  virtual WriteBatchWithIndex* GetWriteBatch() = 0;
364
365
  // Change the value of TransactionOptions.lock_timeout (in milliseconds) for
366
  // this transaction.
367
  // Has no effect on OptimisticTransactions.
368
  virtual void SetLockTimeout(int64_t timeout) = 0;
369
370
  // Return the WriteOptions that will be used during Commit()
371
  virtual const WriteOptions* GetWriteOptions() = 0;
372
373
  // Reset the WriteOptions that will be used during Commit().
374
  virtual void SetWriteOptions(const WriteOptions& write_options) = 0;
375
376
  // If this key was previously fetched in this transaction using
377
  // GetForUpdate/MultigetForUpdate(), calling UndoGetForUpdate will tell
378
  // the transaction that it no longer needs to do any conflict checking
379
  // for this key.
380
  //
381
  // If a key has been fetched N times via GetForUpdate/MultigetForUpdate(),
382
  // then UndoGetForUpdate will only have an effect if it is also called N
383
  // times.  If this key has been written to in this transaction,
384
  // UndoGetForUpdate() will have no effect.
385
  //
386
  // If SetSavePoint() has been called after the GetForUpdate(),
387
  // UndoGetForUpdate() will not have any effect.
388
  //
389
  // If this Transaction was created by an OptimisticTransactionDB,
390
  // calling UndoGetForUpdate can affect whether this key is conflict checked
391
  // at commit time.
392
  // If this Transaction was created by a TransactionDB,
393
  // calling UndoGetForUpdate may release any held locks for this key.
394
  virtual void UndoGetForUpdate(ColumnFamilyHandle* column_family,
395
                                const Slice& key) = 0;
396
  virtual void UndoGetForUpdate(const Slice& key) = 0;
397
398
 protected:
399
0
  explicit Transaction(const TransactionDB* db) {}
400
3.23k
  Transaction() {}
401
402
 private:
403
  // No copying allowed
404
  Transaction(const Transaction&);
405
  void operator=(const Transaction&);
406
};
407
408
}  // namespace rocksdb
409
410
#endif  // ROCKSDB_LITE
411
412
#endif // ROCKSDB_INCLUDE_ROCKSDB_UTILITIES_TRANSACTION_H