/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 | | 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 |