9
9
import com .scalar .db .api .Get ;
10
10
import com .scalar .db .api .Operation ;
11
11
import com .scalar .db .api .Put ;
12
+ import com .scalar .db .api .PutBuilder ;
12
13
import com .scalar .db .api .Result ;
13
14
import com .scalar .db .api .Scan ;
14
15
import com .scalar .db .api .ScanAll ;
30
31
import java .util .Comparator ;
31
32
import java .util .HashMap ;
32
33
import java .util .HashSet ;
34
+ import java .util .LinkedHashMap ;
33
35
import java .util .List ;
34
36
import java .util .Map ;
35
37
import java .util .Map .Entry ;
@@ -113,45 +115,62 @@ Isolation getIsolation() {
113
115
114
116
// Although this class is not thread-safe, this method is actually thread-safe because the readSet
115
117
// is a concurrent map
116
- public void put (Key key , Optional <TransactionResult > result ) {
118
+ public void putIntoReadSet (Key key , Optional <TransactionResult > result ) {
117
119
readSet .put (key , result );
118
120
}
119
121
120
122
// Although this class is not thread-safe, this method is actually thread-safe because the getSet
121
123
// is a concurrent map
122
- public void put (Get get , Optional <TransactionResult > result ) {
124
+ public void putIntoGetSet (Get get , Optional <TransactionResult > result ) {
123
125
getSet .put (get , result );
124
126
}
125
127
126
- public void put (Scan scan , Map <Key , TransactionResult > results ) {
128
+ public void putIntoScanSet (Scan scan , Map <Key , TransactionResult > results ) {
127
129
scanSet .put (scan , results );
128
130
}
129
131
130
- public void put (Key key , Put put ) {
132
+ public void putIntoWriteSet (Key key , Put put ) {
131
133
if (deleteSet .containsKey (key )) {
132
134
throw new IllegalArgumentException (
133
135
CoreError .CONSENSUS_COMMIT_WRITING_ALREADY_DELETED_DATA_NOT_ALLOWED .buildMessage ());
134
136
}
135
137
if (writeSet .containsKey (key )) {
138
+ if (put .isInsertModeEnabled ()) {
139
+ throw new IllegalArgumentException (
140
+ CoreError .CONSENSUS_COMMIT_INSERTING_ALREADY_WRITTEN_DATA_NOT_ALLOWED .buildMessage ());
141
+ }
142
+
136
143
// merge the previous put in the write set and the new put
137
144
Put originalPut = writeSet .get (key );
138
- put .getColumns ().values ().forEach (originalPut ::withValue );
145
+ PutBuilder .BuildableFromExisting putBuilder = Put .newBuilder (originalPut );
146
+ put .getColumns ().values ().forEach (putBuilder ::value );
147
+
148
+ // If the implicit pre-read is enabled for the new put, it should also be enabled for the
149
+ // merged put. However, if the previous put is in insert mode, this doesn’t apply. This is
150
+ // because, in insert mode, the read set is not used during the preparation phase. Therefore,
151
+ // we only need to enable the implicit pre-read if the previous put is not in insert mode
152
+ if (put .isImplicitPreReadEnabled () && !originalPut .isInsertModeEnabled ()) {
153
+ putBuilder .enableImplicitPreRead ();
154
+ }
155
+
156
+ writeSet .put (key , putBuilder .build ());
139
157
} else {
140
158
writeSet .put (key , put );
141
159
}
142
160
}
143
161
144
- public void put (Key key , Delete delete ) {
145
- writeSet .remove (key );
146
- deleteSet .put (key , delete );
147
- }
162
+ public void putIntoDeleteSet (Key key , Delete delete ) {
163
+ Put put = writeSet .get (key );
164
+ if (put != null ) {
165
+ if (put .isInsertModeEnabled ()) {
166
+ throw new IllegalArgumentException (
167
+ CoreError .CONSENSUS_COMMIT_DELETING_ALREADY_INSERTED_DATA_NOT_ALLOWED .buildMessage ());
168
+ }
148
169
149
- public boolean containsKeyInReadSet (Key key ) {
150
- return readSet .containsKey (key );
151
- }
170
+ writeSet .remove (key );
171
+ }
152
172
153
- public Optional <TransactionResult > getFromReadSet (Key key ) {
154
- return readSet .getOrDefault (key , Optional .empty ());
173
+ deleteSet .put (key , delete );
155
174
}
156
175
157
176
public List <Put > getPutsInWriteSet () {
@@ -166,7 +185,39 @@ public ReadWriteSets getReadWriteSets() {
166
185
return new ReadWriteSets (id , readSet , writeSet .entrySet (), deleteSet .entrySet ());
167
186
}
168
187
169
- public Optional <TransactionResult > mergeResult (Key key , Optional <TransactionResult > result )
188
+ public boolean containsKeyInReadSet (Key key ) {
189
+ return readSet .containsKey (key );
190
+ }
191
+
192
+ public boolean containsKeyInGetSet (Get get ) {
193
+ return getSet .containsKey (get );
194
+ }
195
+
196
+ public Optional <TransactionResult > getResult (Key key ) throws CrudException {
197
+ Optional <TransactionResult > result = readSet .getOrDefault (key , Optional .empty ());
198
+ return mergeResult (key , result );
199
+ }
200
+
201
+ public Optional <TransactionResult > getResult (Key key , Get get ) throws CrudException {
202
+ Optional <TransactionResult > result = getSet .getOrDefault (get , Optional .empty ());
203
+ return mergeResult (key , result , get .getConjunctions ());
204
+ }
205
+
206
+ public Optional <Map <Snapshot .Key , TransactionResult >> getResults (Scan scan ) throws CrudException {
207
+ if (!scanSet .containsKey (scan )) {
208
+ return Optional .empty ();
209
+ }
210
+
211
+ Map <Key , TransactionResult > results = new LinkedHashMap <>();
212
+ for (Entry <Snapshot .Key , TransactionResult > entry : scanSet .get (scan ).entrySet ()) {
213
+ mergeResult (entry .getKey (), Optional .of (entry .getValue ()))
214
+ .ifPresent (result -> results .put (entry .getKey (), result ));
215
+ }
216
+
217
+ return Optional .of (results );
218
+ }
219
+
220
+ private Optional <TransactionResult > mergeResult (Key key , Optional <TransactionResult > result )
170
221
throws CrudException {
171
222
if (deleteSet .containsKey (key )) {
172
223
return Optional .empty ();
@@ -180,7 +231,7 @@ public Optional<TransactionResult> mergeResult(Key key, Optional<TransactionResu
180
231
}
181
232
}
182
233
183
- public Optional <TransactionResult > mergeResult (
234
+ private Optional <TransactionResult > mergeResult (
184
235
Key key , Optional <TransactionResult > result , Set <Conjunction > conjunctions )
185
236
throws CrudException {
186
237
return mergeResult (key , result )
@@ -209,32 +260,6 @@ private TableMetadata getTableMetadata(Key key) throws CrudException {
209
260
}
210
261
}
211
262
212
- private TableMetadata getTableMetadata (Scan scan ) throws ExecutionException {
213
- TransactionTableMetadata metadata = tableMetadataManager .getTransactionTableMetadata (scan );
214
- if (metadata == null ) {
215
- throw new IllegalArgumentException (
216
- CoreError .TABLE_NOT_FOUND .buildMessage (scan .forFullTableName ().get ()));
217
- }
218
- return metadata .getTableMetadata ();
219
- }
220
-
221
- public boolean containsKeyInGetSet (Get get ) {
222
- return getSet .containsKey (get );
223
- }
224
-
225
- public Optional <TransactionResult > get (Get get ) {
226
- // We expect this method is called after putting the result of the get operation in the get set.
227
- assert getSet .containsKey (get );
228
- return getSet .get (get );
229
- }
230
-
231
- public Optional <Map <Key , TransactionResult >> get (Scan scan ) {
232
- if (scanSet .containsKey (scan )) {
233
- return Optional .ofNullable (scanSet .get (scan ));
234
- }
235
- return Optional .empty ();
236
- }
237
-
238
263
public void verify (Scan scan ) {
239
264
if (isWriteSetOverlappedWith (scan )) {
240
265
throw new IllegalArgumentException (
@@ -536,6 +561,15 @@ void toSerializableWithExtraRead(DistributedStorage storage)
536
561
parallelExecutor .validate (tasks , getId ());
537
562
}
538
563
564
+ private TableMetadata getTableMetadata (Scan scan ) throws ExecutionException {
565
+ TransactionTableMetadata metadata = tableMetadataManager .getTransactionTableMetadata (scan );
566
+ if (metadata == null ) {
567
+ throw new IllegalArgumentException (
568
+ CoreError .TABLE_NOT_FOUND .buildMessage (scan .forFullTableName ().get ()));
569
+ }
570
+ return metadata .getTableMetadata ();
571
+ }
572
+
539
573
private boolean isChanged (
540
574
Optional <TransactionResult > latestResult , Optional <TransactionResult > result ) {
541
575
if (latestResult .isPresent () != result .isPresent ()) {
0 commit comments