99import com .scalar .db .api .Get ;
1010import com .scalar .db .api .Operation ;
1111import com .scalar .db .api .Put ;
12+ import com .scalar .db .api .PutBuilder ;
1213import com .scalar .db .api .Result ;
1314import com .scalar .db .api .Scan ;
1415import com .scalar .db .api .ScanAll ;
3031import java .util .Comparator ;
3132import java .util .HashMap ;
3233import java .util .HashSet ;
34+ import java .util .LinkedHashMap ;
3335import java .util .List ;
3436import java .util .Map ;
3537import java .util .Map .Entry ;
@@ -113,45 +115,62 @@ Isolation getIsolation() {
113115
114116 // Although this class is not thread-safe, this method is actually thread-safe because the readSet
115117 // is a concurrent map
116- public void put (Key key , Optional <TransactionResult > result ) {
118+ public void putIntoReadSet (Key key , Optional <TransactionResult > result ) {
117119 readSet .put (key , result );
118120 }
119121
120122 // Although this class is not thread-safe, this method is actually thread-safe because the getSet
121123 // is a concurrent map
122- public void put (Get get , Optional <TransactionResult > result ) {
124+ public void putIntoGetSet (Get get , Optional <TransactionResult > result ) {
123125 getSet .put (get , result );
124126 }
125127
126- public void put (Scan scan , Map <Key , TransactionResult > results ) {
128+ public void putIntoScanSet (Scan scan , Map <Key , TransactionResult > results ) {
127129 scanSet .put (scan , results );
128130 }
129131
130- public void put (Key key , Put put ) {
132+ public void putIntoWriteSet (Key key , Put put ) {
131133 if (deleteSet .containsKey (key )) {
132134 throw new IllegalArgumentException (
133135 CoreError .CONSENSUS_COMMIT_WRITING_ALREADY_DELETED_DATA_NOT_ALLOWED .buildMessage ());
134136 }
135137 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+
136143 // merge the previous put in the write set and the new put
137144 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 ());
139157 } else {
140158 writeSet .put (key , put );
141159 }
142160 }
143161
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+ }
148169
149- public boolean containsKeyInReadSet (Key key ) {
150- return readSet .containsKey (key );
151- }
170+ writeSet .remove (key );
171+ }
152172
153- public Optional <TransactionResult > getFromReadSet (Key key ) {
154- return readSet .getOrDefault (key , Optional .empty ());
173+ deleteSet .put (key , delete );
155174 }
156175
157176 public List <Put > getPutsInWriteSet () {
@@ -166,7 +185,39 @@ public ReadWriteSets getReadWriteSets() {
166185 return new ReadWriteSets (id , readSet , writeSet .entrySet (), deleteSet .entrySet ());
167186 }
168187
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 )
170221 throws CrudException {
171222 if (deleteSet .containsKey (key )) {
172223 return Optional .empty ();
@@ -180,7 +231,7 @@ public Optional<TransactionResult> mergeResult(Key key, Optional<TransactionResu
180231 }
181232 }
182233
183- public Optional <TransactionResult > mergeResult (
234+ private Optional <TransactionResult > mergeResult (
184235 Key key , Optional <TransactionResult > result , Set <Conjunction > conjunctions )
185236 throws CrudException {
186237 return mergeResult (key , result )
@@ -209,32 +260,6 @@ private TableMetadata getTableMetadata(Key key) throws CrudException {
209260 }
210261 }
211262
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-
238263 public void verify (Scan scan ) {
239264 if (isWriteSetOverlappedWith (scan )) {
240265 throw new IllegalArgumentException (
@@ -536,6 +561,15 @@ void toSerializableWithExtraRead(DistributedStorage storage)
536561 parallelExecutor .validate (tasks , getId ());
537562 }
538563
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+
539573 private boolean isChanged (
540574 Optional <TransactionResult > latestResult , Optional <TransactionResult > result ) {
541575 if (latestResult .isPresent () != result .isPresent ()) {
0 commit comments