1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5
6 #ifndef ROCKSDB_LITE
7
8 #include "rocksdb/db.h"
9 #include "rocksdb/options.h"
10 #include "rocksdb/slice.h"
11 #include "rocksdb/utilities/transaction.h"
12 #include "rocksdb/utilities/optimistic_transaction_db.h"
13
14 using namespace ROCKSDB_NAMESPACE;
15
16 std::string kDBPath = "/tmp/rocksdb_transaction_example";
17
main()18 int main() {
19 // open DB
20 Options options;
21 options.create_if_missing = true;
22 DB* db;
23 OptimisticTransactionDB* txn_db;
24
25 Status s = OptimisticTransactionDB::Open(options, kDBPath, &txn_db);
26 assert(s.ok());
27 db = txn_db->GetBaseDB();
28
29 WriteOptions write_options;
30 ReadOptions read_options;
31 OptimisticTransactionOptions txn_options;
32 std::string value;
33
34 ////////////////////////////////////////////////////////
35 //
36 // Simple OptimisticTransaction Example ("Read Committed")
37 //
38 ////////////////////////////////////////////////////////
39
40 // Start a transaction
41 Transaction* txn = txn_db->BeginTransaction(write_options);
42 assert(txn);
43
44 // Read a key in this transaction
45 s = txn->Get(read_options, "abc", &value);
46 assert(s.IsNotFound());
47
48 // Write a key in this transaction
49 s = txn->Put("abc", "xyz");
50 assert(s.ok());
51
52 // Read a key OUTSIDE this transaction. Does not affect txn.
53 s = db->Get(read_options, "abc", &value);
54 assert(s.IsNotFound());
55
56 // Write a key OUTSIDE of this transaction.
57 // Does not affect txn since this is an unrelated key. If we wrote key 'abc'
58 // here, the transaction would fail to commit.
59 s = db->Put(write_options, "xyz", "zzz");
60 assert(s.ok());
61 s = db->Put(write_options, "abc", "def");
62 assert(s.ok());
63
64 // Commit transaction
65 s = txn->Commit();
66 assert(s.IsBusy());
67 delete txn;
68
69 s = db->Get(read_options, "xyz", &value);
70 assert(s.ok());
71 assert(value == "zzz");
72
73 s = db->Get(read_options, "abc", &value);
74 assert(s.ok());
75 assert(value == "def");
76
77 ////////////////////////////////////////////////////////
78 //
79 // "Repeatable Read" (Snapshot Isolation) Example
80 // -- Using a single Snapshot
81 //
82 ////////////////////////////////////////////////////////
83
84 // Set a snapshot at start of transaction by setting set_snapshot=true
85 txn_options.set_snapshot = true;
86 txn = txn_db->BeginTransaction(write_options, txn_options);
87
88 const Snapshot* snapshot = txn->GetSnapshot();
89
90 // Write a key OUTSIDE of transaction
91 s = db->Put(write_options, "abc", "xyz");
92 assert(s.ok());
93
94 // Read a key using the snapshot
95 read_options.snapshot = snapshot;
96 s = txn->GetForUpdate(read_options, "abc", &value);
97 assert(s.ok());
98 assert(value == "def");
99
100 // Attempt to commit transaction
101 s = txn->Commit();
102
103 // Transaction could not commit since the write outside of the txn conflicted
104 // with the read!
105 assert(s.IsBusy());
106
107 delete txn;
108 // Clear snapshot from read options since it is no longer valid
109 read_options.snapshot = nullptr;
110 snapshot = nullptr;
111
112 s = db->Get(read_options, "abc", &value);
113 assert(s.ok());
114 assert(value == "xyz");
115
116 ////////////////////////////////////////////////////////
117 //
118 // "Read Committed" (Monotonic Atomic Views) Example
119 // --Using multiple Snapshots
120 //
121 ////////////////////////////////////////////////////////
122
123 // In this example, we set the snapshot multiple times. This is probably
124 // only necessary if you have very strict isolation requirements to
125 // implement.
126
127 // Set a snapshot at start of transaction
128 txn_options.set_snapshot = true;
129 txn = txn_db->BeginTransaction(write_options, txn_options);
130
131 // Do some reads and writes to key "x"
132 read_options.snapshot = db->GetSnapshot();
133 s = txn->Get(read_options, "x", &value);
134 assert(s.IsNotFound());
135 s = txn->Put("x", "x");
136 assert(s.ok());
137
138 // The transaction hasn't committed, so the write is not visible
139 // outside of txn.
140 s = db->Get(read_options, "x", &value);
141 assert(s.IsNotFound());
142
143 // Do a write outside of the transaction to key "y"
144 s = db->Put(write_options, "y", "z");
145 assert(s.ok());
146
147 // Set a new snapshot in the transaction
148 txn->SetSnapshot();
149 read_options.snapshot = db->GetSnapshot();
150
151 // Do some reads and writes to key "y"
152 s = txn->GetForUpdate(read_options, "y", &value);
153 assert(s.ok());
154 assert(value == "z");
155 txn->Put("y", "y");
156
157 // Commit. Since the snapshot was advanced, the write done outside of the
158 // transaction does not prevent this transaction from Committing.
159 s = txn->Commit();
160 assert(s.ok());
161 delete txn;
162 // Clear snapshot from read options since it is no longer valid
163 read_options.snapshot = nullptr;
164
165 // txn is committed, read the latest values.
166 s = db->Get(read_options, "x", &value);
167 assert(s.ok());
168 assert(value == "x");
169
170 s = db->Get(read_options, "y", &value);
171 assert(s.ok());
172 assert(value == "y");
173
174 // Cleanup
175 delete txn_db;
176 DestroyDB(kDBPath, options);
177 return 0;
178 }
179
180 #endif // ROCKSDB_LITE
181