Committed by
Gerrit Code Review
ONOS-2097: Ensure updates made via transactional map result in state change notifications
Change-Id: Iecc1b54d2c4c976278e77dbd825d3e3954c53602
Showing
11 changed files
with
122 additions
and
56 deletions
1 | +package org.onosproject.store.consistent.impl; | ||
2 | + | ||
3 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
4 | + | ||
5 | +import java.util.Collections; | ||
6 | +import java.util.List; | ||
7 | + | ||
8 | +import com.google.common.collect.ImmutableList; | ||
9 | + | ||
10 | +/** | ||
11 | + * Result of a Transaction commit operation. | ||
12 | + */ | ||
13 | +public final class CommitResponse { | ||
14 | + | ||
15 | + private boolean success; | ||
16 | + private List<UpdateResult<String, byte[]>> updates; | ||
17 | + | ||
18 | + public static CommitResponse success(List<UpdateResult<String, byte[]>> updates) { | ||
19 | + return new CommitResponse(true, updates); | ||
20 | + } | ||
21 | + | ||
22 | + public static CommitResponse failure() { | ||
23 | + return new CommitResponse(false, Collections.emptyList()); | ||
24 | + } | ||
25 | + | ||
26 | + private CommitResponse(boolean success, List<UpdateResult<String, byte[]>> updates) { | ||
27 | + this.success = success; | ||
28 | + this.updates = ImmutableList.copyOf(updates); | ||
29 | + } | ||
30 | + | ||
31 | + public boolean success() { | ||
32 | + return success; | ||
33 | + } | ||
34 | + | ||
35 | + public List<UpdateResult<String, byte[]>> updates() { | ||
36 | + return updates; | ||
37 | + } | ||
38 | + | ||
39 | + @Override | ||
40 | + public String toString() { | ||
41 | + return toStringHelper(this) | ||
42 | + .add("success", success) | ||
43 | + .add("udpates", updates) | ||
44 | + .toString(); | ||
45 | + } | ||
46 | +} |
... | @@ -193,7 +193,7 @@ public interface DatabaseProxy<K, V> { | ... | @@ -193,7 +193,7 @@ public interface DatabaseProxy<K, V> { |
193 | * @param transaction transaction to commit (after preparation) | 193 | * @param transaction transaction to commit (after preparation) |
194 | * @return A completable future to be completed with the result once complete | 194 | * @return A completable future to be completed with the result once complete |
195 | */ | 195 | */ |
196 | - CompletableFuture<Boolean> prepareAndCommit(Transaction transaction); | 196 | + CompletableFuture<CommitResponse> prepareAndCommit(Transaction transaction); |
197 | 197 | ||
198 | /** | 198 | /** |
199 | * Prepare the specified transaction for commit. A successful prepare implies | 199 | * Prepare the specified transaction for commit. A successful prepare implies |
... | @@ -213,7 +213,7 @@ public interface DatabaseProxy<K, V> { | ... | @@ -213,7 +213,7 @@ public interface DatabaseProxy<K, V> { |
213 | * @param transaction transaction to commit | 213 | * @param transaction transaction to commit |
214 | * @return A completable future to be completed with the result once complete | 214 | * @return A completable future to be completed with the result once complete |
215 | */ | 215 | */ |
216 | - CompletableFuture<Boolean> commit(Transaction transaction); | 216 | + CompletableFuture<CommitResponse> commit(Transaction transaction); |
217 | 217 | ||
218 | /** | 218 | /** |
219 | * Rollback the specified transaction. A successful rollback implies | 219 | * Rollback the specified transaction. A successful rollback implies | ... | ... |
... | @@ -75,6 +75,7 @@ public class DatabaseSerializer extends SerializerConfig { | ... | @@ -75,6 +75,7 @@ public class DatabaseSerializer extends SerializerConfig { |
75 | .register(Result.Status.class) | 75 | .register(Result.Status.class) |
76 | .register(DefaultTransaction.class) | 76 | .register(DefaultTransaction.class) |
77 | .register(Transaction.State.class) | 77 | .register(Transaction.State.class) |
78 | + .register(org.onosproject.store.consistent.impl.CommitResponse.class) | ||
78 | .register(Match.class) | 79 | .register(Match.class) |
79 | .register(NodeId.class) | 80 | .register(NodeId.class) |
80 | .build(); | 81 | .build(); | ... | ... |
... | @@ -102,13 +102,13 @@ public interface DatabaseState<K, V> { | ... | @@ -102,13 +102,13 @@ public interface DatabaseState<K, V> { |
102 | Long counterGet(String counterName); | 102 | Long counterGet(String counterName); |
103 | 103 | ||
104 | @Command | 104 | @Command |
105 | - boolean prepareAndCommit(Transaction transaction); | 105 | + CommitResponse prepareAndCommit(Transaction transaction); |
106 | 106 | ||
107 | @Command | 107 | @Command |
108 | boolean prepare(Transaction transaction); | 108 | boolean prepare(Transaction transaction); |
109 | 109 | ||
110 | @Command | 110 | @Command |
111 | - boolean commit(Transaction transaction); | 111 | + CommitResponse commit(Transaction transaction); |
112 | 112 | ||
113 | @Command | 113 | @Command |
114 | boolean rollback(Transaction transaction); | 114 | boolean rollback(Transaction transaction); | ... | ... |
... | @@ -32,6 +32,7 @@ import org.onosproject.store.service.Serializer; | ... | @@ -32,6 +32,7 @@ import org.onosproject.store.service.Serializer; |
32 | import org.onosproject.store.service.Versioned; | 32 | import org.onosproject.store.service.Versioned; |
33 | import org.slf4j.Logger; | 33 | import org.slf4j.Logger; |
34 | 34 | ||
35 | + | ||
35 | import java.util.Collection; | 36 | import java.util.Collection; |
36 | import java.util.Map; | 37 | import java.util.Map; |
37 | import java.util.Map.Entry; | 38 | import java.util.Map.Entry; |
... | @@ -47,6 +48,7 @@ import java.util.stream.Collectors; | ... | @@ -47,6 +48,7 @@ import java.util.stream.Collectors; |
47 | 48 | ||
48 | import static com.google.common.base.Preconditions.checkNotNull; | 49 | import static com.google.common.base.Preconditions.checkNotNull; |
49 | import static org.onosproject.store.consistent.impl.StateMachineUpdate.Target.MAP; | 50 | import static org.onosproject.store.consistent.impl.StateMachineUpdate.Target.MAP; |
51 | +import static org.onosproject.store.consistent.impl.StateMachineUpdate.Target.TX_COMMIT; | ||
50 | import static org.slf4j.LoggerFactory.getLogger; | 52 | import static org.slf4j.LoggerFactory.getLogger; |
51 | 53 | ||
52 | /** | 54 | /** |
... | @@ -83,7 +85,6 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V | ... | @@ -83,7 +85,6 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V |
83 | private static final String REPLACE = "replace"; | 85 | private static final String REPLACE = "replace"; |
84 | private static final String COMPUTE_IF_ABSENT = "computeIfAbsent"; | 86 | private static final String COMPUTE_IF_ABSENT = "computeIfAbsent"; |
85 | 87 | ||
86 | - | ||
87 | private final Set<MapEventListener<K, V>> listeners = new CopyOnWriteArraySet<>(); | 88 | private final Set<MapEventListener<K, V>> listeners = new CopyOnWriteArraySet<>(); |
88 | 89 | ||
89 | private final Logger log = getLogger(getClass()); | 90 | private final Logger log = getLogger(getClass()); |
... | @@ -127,6 +128,16 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V | ... | @@ -127,6 +128,16 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V |
127 | MapEvent<K, V> mapEvent = result.value().<K, V>map(this::dK, serializer::decode).toMapEvent(); | 128 | MapEvent<K, V> mapEvent = result.value().<K, V>map(this::dK, serializer::decode).toMapEvent(); |
128 | notifyListeners(mapEvent); | 129 | notifyListeners(mapEvent); |
129 | } | 130 | } |
131 | + } else if (update.target() == TX_COMMIT) { | ||
132 | + CommitResponse response = update.output(); | ||
133 | + if (response.success()) { | ||
134 | + response.updates().forEach(u -> { | ||
135 | + if (u.mapName().equals(name)) { | ||
136 | + MapEvent<K, V> mapEvent = u.<K, V>map(this::dK, serializer::decode).toMapEvent(); | ||
137 | + notifyListeners(mapEvent); | ||
138 | + } | ||
139 | + }); | ||
140 | + } | ||
130 | } | 141 | } |
131 | }); | 142 | }); |
132 | }); | 143 | }); | ... | ... |
... | @@ -174,7 +174,7 @@ public class DefaultDatabase extends AbstractResource<Database> implements Datab | ... | @@ -174,7 +174,7 @@ public class DefaultDatabase extends AbstractResource<Database> implements Datab |
174 | } | 174 | } |
175 | 175 | ||
176 | @Override | 176 | @Override |
177 | - public CompletableFuture<Boolean> prepareAndCommit(Transaction transaction) { | 177 | + public CompletableFuture<CommitResponse> prepareAndCommit(Transaction transaction) { |
178 | return checkOpen(() -> proxy.prepareAndCommit(transaction)); | 178 | return checkOpen(() -> proxy.prepareAndCommit(transaction)); |
179 | } | 179 | } |
180 | 180 | ||
... | @@ -184,7 +184,7 @@ public class DefaultDatabase extends AbstractResource<Database> implements Datab | ... | @@ -184,7 +184,7 @@ public class DefaultDatabase extends AbstractResource<Database> implements Datab |
184 | } | 184 | } |
185 | 185 | ||
186 | @Override | 186 | @Override |
187 | - public CompletableFuture<Boolean> commit(Transaction transaction) { | 187 | + public CompletableFuture<CommitResponse> commit(Transaction transaction) { |
188 | return checkOpen(() -> proxy.commit(transaction)); | 188 | return checkOpen(() -> proxy.commit(transaction)); |
189 | } | 189 | } |
190 | 190 | ... | ... |
... | @@ -31,11 +31,10 @@ import org.onosproject.cluster.NodeId; | ... | @@ -31,11 +31,10 @@ import org.onosproject.cluster.NodeId; |
31 | import org.onosproject.store.service.DatabaseUpdate; | 31 | import org.onosproject.store.service.DatabaseUpdate; |
32 | import org.onosproject.store.service.Transaction; | 32 | import org.onosproject.store.service.Transaction; |
33 | import org.onosproject.store.service.Versioned; | 33 | import org.onosproject.store.service.Versioned; |
34 | -import org.onosproject.store.service.DatabaseUpdate.Type; | ||
35 | - | ||
36 | import com.google.common.base.Objects; | 34 | import com.google.common.base.Objects; |
37 | import com.google.common.collect.ImmutableList; | 35 | import com.google.common.collect.ImmutableList; |
38 | import com.google.common.collect.ImmutableSet; | 36 | import com.google.common.collect.ImmutableSet; |
37 | +import com.google.common.collect.Lists; | ||
39 | import com.google.common.collect.Maps; | 38 | import com.google.common.collect.Maps; |
40 | 39 | ||
41 | import net.kuujo.copycat.state.Initializer; | 40 | import net.kuujo.copycat.state.Initializer; |
... | @@ -239,11 +238,11 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { | ... | @@ -239,11 +238,11 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { |
239 | } | 238 | } |
240 | 239 | ||
241 | @Override | 240 | @Override |
242 | - public boolean prepareAndCommit(Transaction transaction) { | 241 | + public CommitResponse prepareAndCommit(Transaction transaction) { |
243 | if (prepare(transaction)) { | 242 | if (prepare(transaction)) { |
244 | return commit(transaction); | 243 | return commit(transaction); |
245 | } | 244 | } |
246 | - return false; | 245 | + return CommitResponse.failure(); |
247 | } | 246 | } |
248 | 247 | ||
249 | @Override | 248 | @Override |
... | @@ -263,9 +262,9 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { | ... | @@ -263,9 +262,9 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { |
263 | } | 262 | } |
264 | 263 | ||
265 | @Override | 264 | @Override |
266 | - public boolean commit(Transaction transaction) { | 265 | + public CommitResponse commit(Transaction transaction) { |
267 | - transaction.updates().forEach(update -> commitProvisionalUpdate(update, transaction.id())); | 266 | + return CommitResponse.success(Lists.transform(transaction.updates(), |
268 | - return true; | 267 | + update -> commitProvisionalUpdate(update, transaction.id()))); |
269 | } | 268 | } |
270 | 269 | ||
271 | @Override | 270 | @Override |
... | @@ -334,32 +333,16 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { | ... | @@ -334,32 +333,16 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { |
334 | } | 333 | } |
335 | } | 334 | } |
336 | 335 | ||
337 | - private void commitProvisionalUpdate(DatabaseUpdate update, long transactionId) { | 336 | + private UpdateResult<String, byte[]> commitProvisionalUpdate(DatabaseUpdate update, long transactionId) { |
338 | String mapName = update.mapName(); | 337 | String mapName = update.mapName(); |
339 | String key = update.key(); | 338 | String key = update.key(); |
340 | - Type type = update.type(); | ||
341 | Update provisionalUpdate = getLockMap(mapName).get(key); | 339 | Update provisionalUpdate = getLockMap(mapName).get(key); |
342 | if (Objects.equal(transactionId, provisionalUpdate.transactionId())) { | 340 | if (Objects.equal(transactionId, provisionalUpdate.transactionId())) { |
343 | getLockMap(mapName).remove(key); | 341 | getLockMap(mapName).remove(key); |
344 | } else { | 342 | } else { |
345 | - return; | 343 | + throw new IllegalStateException("Invalid transaction Id"); |
346 | - } | ||
347 | - | ||
348 | - switch (type) { | ||
349 | - case PUT: | ||
350 | - case PUT_IF_ABSENT: | ||
351 | - case PUT_IF_VERSION_MATCH: | ||
352 | - case PUT_IF_VALUE_MATCH: | ||
353 | - mapUpdate(mapName, key, Match.any(), Match.any(), provisionalUpdate.value()); | ||
354 | - break; | ||
355 | - case REMOVE: | ||
356 | - case REMOVE_IF_VERSION_MATCH: | ||
357 | - case REMOVE_IF_VALUE_MATCH: | ||
358 | - mapUpdate(mapName, key, Match.any(), Match.any(), null); | ||
359 | - break; | ||
360 | - default: | ||
361 | - break; | ||
362 | } | 344 | } |
345 | + return mapUpdate(mapName, key, Match.any(), Match.any(), provisionalUpdate.value()).value(); | ||
363 | } | 346 | } |
364 | 347 | ||
365 | private void undoProvisionalUpdate(DatabaseUpdate update, long transactionId) { | 348 | private void undoProvisionalUpdate(DatabaseUpdate update, long transactionId) { | ... | ... |
... | @@ -25,12 +25,13 @@ import static com.google.common.base.Preconditions.*; | ... | @@ -25,12 +25,13 @@ import static com.google.common.base.Preconditions.*; |
25 | import org.onosproject.store.service.ConsistentMapBuilder; | 25 | import org.onosproject.store.service.ConsistentMapBuilder; |
26 | import org.onosproject.store.service.DatabaseUpdate; | 26 | import org.onosproject.store.service.DatabaseUpdate; |
27 | import org.onosproject.store.service.Serializer; | 27 | import org.onosproject.store.service.Serializer; |
28 | +import org.onosproject.store.service.Transaction; | ||
28 | import org.onosproject.store.service.TransactionContext; | 29 | import org.onosproject.store.service.TransactionContext; |
29 | -import org.onosproject.store.service.TransactionException; | ||
30 | import org.onosproject.store.service.TransactionalMap; | 30 | import org.onosproject.store.service.TransactionalMap; |
31 | 31 | ||
32 | import com.google.common.collect.Lists; | 32 | import com.google.common.collect.Lists; |
33 | import com.google.common.collect.Maps; | 33 | import com.google.common.collect.Maps; |
34 | +import com.google.common.util.concurrent.Futures; | ||
34 | 35 | ||
35 | /** | 36 | /** |
36 | * Default TransactionContext implementation. | 37 | * Default TransactionContext implementation. |
... | @@ -86,24 +87,30 @@ public class DefaultTransactionContext implements TransactionContext { | ... | @@ -86,24 +87,30 @@ public class DefaultTransactionContext implements TransactionContext { |
86 | @SuppressWarnings("unchecked") | 87 | @SuppressWarnings("unchecked") |
87 | @Override | 88 | @Override |
88 | public void commit() { | 89 | public void commit() { |
90 | + // TODO: rework commit implementation to be more intuitive | ||
89 | checkState(isOpen, TX_NOT_OPEN_ERROR); | 91 | checkState(isOpen, TX_NOT_OPEN_ERROR); |
92 | + CommitResponse response = null; | ||
90 | try { | 93 | try { |
91 | List<DatabaseUpdate> updates = Lists.newLinkedList(); | 94 | List<DatabaseUpdate> updates = Lists.newLinkedList(); |
92 | - txMaps.values() | 95 | + txMaps.values().forEach(m -> updates.addAll(m.prepareDatabaseUpdates())); |
93 | - .forEach(m -> { updates.addAll(m.prepareDatabaseUpdates()); }); | 96 | + Transaction transaction = new DefaultTransaction(transactionId, updates); |
94 | - // FIXME: Updates made via transactional context currently do not result in notifications. (ONOS-2097) | 97 | + response = Futures.getUnchecked(database.prepareAndCommit(transaction)); |
95 | - database.prepareAndCommit(new DefaultTransaction(transactionId, updates)); | ||
96 | - } catch (Exception e) { | ||
97 | - abort(); | ||
98 | - throw new TransactionException(e); | ||
99 | } finally { | 98 | } finally { |
99 | + if (response != null && !response.success()) { | ||
100 | + abort(); | ||
101 | + } | ||
100 | isOpen = false; | 102 | isOpen = false; |
101 | } | 103 | } |
102 | } | 104 | } |
103 | 105 | ||
104 | @Override | 106 | @Override |
105 | public void abort() { | 107 | public void abort() { |
106 | - checkState(isOpen, TX_NOT_OPEN_ERROR); | 108 | + if (isOpen) { |
109 | + try { | ||
107 | txMaps.values().forEach(m -> m.rollback()); | 110 | txMaps.values().forEach(m -> m.rollback()); |
111 | + } finally { | ||
112 | + isOpen = false; | ||
113 | + } | ||
114 | + } | ||
108 | } | 115 | } |
109 | } | 116 | } | ... | ... |
... | @@ -33,6 +33,7 @@ import org.onosproject.store.service.DatabaseUpdate; | ... | @@ -33,6 +33,7 @@ import org.onosproject.store.service.DatabaseUpdate; |
33 | import org.onosproject.store.service.Transaction; | 33 | import org.onosproject.store.service.Transaction; |
34 | import org.onosproject.store.service.Versioned; | 34 | import org.onosproject.store.service.Versioned; |
35 | 35 | ||
36 | +import com.google.common.collect.ImmutableList; | ||
36 | import com.google.common.collect.Lists; | 37 | import com.google.common.collect.Lists; |
37 | import com.google.common.collect.Maps; | 38 | import com.google.common.collect.Maps; |
38 | import com.google.common.collect.Sets; | 39 | import com.google.common.collect.Sets; |
... | @@ -246,10 +247,10 @@ public class PartitionedDatabase implements Database { | ... | @@ -246,10 +247,10 @@ public class PartitionedDatabase implements Database { |
246 | } | 247 | } |
247 | 248 | ||
248 | @Override | 249 | @Override |
249 | - public CompletableFuture<Boolean> prepareAndCommit(Transaction transaction) { | 250 | + public CompletableFuture<CommitResponse> prepareAndCommit(Transaction transaction) { |
250 | Map<Database, Transaction> subTransactions = createSubTransactions(transaction); | 251 | Map<Database, Transaction> subTransactions = createSubTransactions(transaction); |
251 | if (subTransactions.isEmpty()) { | 252 | if (subTransactions.isEmpty()) { |
252 | - return CompletableFuture.completedFuture(true); | 253 | + return CompletableFuture.completedFuture(CommitResponse.success(ImmutableList.of())); |
253 | } else if (subTransactions.size() == 1) { | 254 | } else if (subTransactions.size() == 1) { |
254 | Entry<Database, Transaction> entry = | 255 | Entry<Database, Transaction> entry = |
255 | subTransactions.entrySet().iterator().next(); | 256 | subTransactions.entrySet().iterator().next(); |
... | @@ -277,13 +278,22 @@ public class PartitionedDatabase implements Database { | ... | @@ -277,13 +278,22 @@ public class PartitionedDatabase implements Database { |
277 | } | 278 | } |
278 | 279 | ||
279 | @Override | 280 | @Override |
280 | - public CompletableFuture<Boolean> commit(Transaction transaction) { | 281 | + public CompletableFuture<CommitResponse> commit(Transaction transaction) { |
281 | Map<Database, Transaction> subTransactions = createSubTransactions(transaction); | 282 | Map<Database, Transaction> subTransactions = createSubTransactions(transaction); |
283 | + AtomicBoolean success = new AtomicBoolean(true); | ||
284 | + List<UpdateResult<String, byte[]>> allUpdates = Lists.newArrayList(); | ||
282 | return CompletableFuture.allOf(subTransactions.entrySet() | 285 | return CompletableFuture.allOf(subTransactions.entrySet() |
283 | .stream() | 286 | .stream() |
284 | - .map(entry -> entry.getKey().commit(entry.getValue())) | 287 | + .map(entry -> entry.getKey().commit(entry.getValue()) |
288 | + .thenAccept(response -> { | ||
289 | + success.set(success.get() && response.success()); | ||
290 | + if (success.get()) { | ||
291 | + allUpdates.addAll(response.updates()); | ||
292 | + } | ||
293 | + })) | ||
285 | .toArray(CompletableFuture[]::new)) | 294 | .toArray(CompletableFuture[]::new)) |
286 | - .thenApply(v -> true); | 295 | + .thenApply(v -> success.get() ? |
296 | + CommitResponse.success(allUpdates) : CommitResponse.failure()); | ||
287 | } | 297 | } |
288 | 298 | ||
289 | @Override | 299 | @Override | ... | ... |
... | @@ -32,6 +32,11 @@ public class StateMachineUpdate { | ... | @@ -32,6 +32,11 @@ public class StateMachineUpdate { |
32 | MAP, | 32 | MAP, |
33 | 33 | ||
34 | /** | 34 | /** |
35 | + * Update is a transaction commit. | ||
36 | + */ | ||
37 | + TX_COMMIT, | ||
38 | + | ||
39 | + /** | ||
35 | * Update is for a non-map data structure. | 40 | * Update is for a non-map data structure. |
36 | */ | 41 | */ |
37 | OTHER | 42 | OTHER |
... | @@ -51,6 +56,8 @@ public class StateMachineUpdate { | ... | @@ -51,6 +56,8 @@ public class StateMachineUpdate { |
51 | // FIXME: This check is brittle | 56 | // FIXME: This check is brittle |
52 | if (operationName.contains("mapUpdate")) { | 57 | if (operationName.contains("mapUpdate")) { |
53 | return Target.MAP; | 58 | return Target.MAP; |
59 | + } else if (operationName.contains("commit") || operationName.contains("prepareAndCommit")) { | ||
60 | + return Target.TX_COMMIT; | ||
54 | } else { | 61 | } else { |
55 | return Target.OTHER; | 62 | return Target.OTHER; |
56 | } | 63 | } | ... | ... |
... | @@ -32,6 +32,8 @@ import org.onosproject.store.service.Transaction; | ... | @@ -32,6 +32,8 @@ import org.onosproject.store.service.Transaction; |
32 | import org.onosproject.store.service.Versioned; | 32 | import org.onosproject.store.service.Versioned; |
33 | import org.onosproject.store.service.Transaction.State; | 33 | import org.onosproject.store.service.Transaction.State; |
34 | 34 | ||
35 | +import com.google.common.collect.ImmutableList; | ||
36 | + | ||
35 | /** | 37 | /** |
36 | * Agent that runs the two phase commit protocol. | 38 | * Agent that runs the two phase commit protocol. |
37 | */ | 39 | */ |
... | @@ -71,15 +73,15 @@ public class TransactionManager { | ... | @@ -71,15 +73,15 @@ public class TransactionManager { |
71 | * @return transaction result. Result value true indicates a successful commit, false | 73 | * @return transaction result. Result value true indicates a successful commit, false |
72 | * indicates abort | 74 | * indicates abort |
73 | */ | 75 | */ |
74 | - public CompletableFuture<Boolean> execute(Transaction transaction) { | 76 | + public CompletableFuture<CommitResponse> execute(Transaction transaction) { |
75 | // clean up if this transaction in already in a terminal state. | 77 | // clean up if this transaction in already in a terminal state. |
76 | if (transaction.state() == Transaction.State.COMMITTED || | 78 | if (transaction.state() == Transaction.State.COMMITTED || |
77 | transaction.state() == Transaction.State.ROLLEDBACK) { | 79 | transaction.state() == Transaction.State.ROLLEDBACK) { |
78 | - return transactions.remove(transaction.id()).thenApply(v -> true); | 80 | + return transactions.remove(transaction.id()).thenApply(v -> CommitResponse.success(ImmutableList.of())); |
79 | } else if (transaction.state() == Transaction.State.COMMITTING) { | 81 | } else if (transaction.state() == Transaction.State.COMMITTING) { |
80 | return commit(transaction); | 82 | return commit(transaction); |
81 | } else if (transaction.state() == Transaction.State.ROLLINGBACK) { | 83 | } else if (transaction.state() == Transaction.State.ROLLINGBACK) { |
82 | - return rollback(transaction); | 84 | + return rollback(transaction).thenApply(v -> CommitResponse.success(ImmutableList.of())); |
83 | } else { | 85 | } else { |
84 | return prepare(transaction).thenCompose(v -> v ? commit(transaction) : rollback(transaction)); | 86 | return prepare(transaction).thenCompose(v -> v ? commit(transaction) : rollback(transaction)); |
85 | } | 87 | } |
... | @@ -107,19 +109,18 @@ public class TransactionManager { | ... | @@ -107,19 +109,18 @@ public class TransactionManager { |
107 | .thenApply(v -> status)); | 109 | .thenApply(v -> status)); |
108 | } | 110 | } |
109 | 111 | ||
110 | - private CompletableFuture<Boolean> commit(Transaction transaction) { | 112 | + private CompletableFuture<CommitResponse> commit(Transaction transaction) { |
111 | return database.commit(transaction) | 113 | return database.commit(transaction) |
112 | - .thenCompose(v -> transactions.put( | 114 | + .whenComplete((r, e) -> transactions.put( |
113 | transaction.id(), | 115 | transaction.id(), |
114 | - transaction.transition(Transaction.State.COMMITTED))) | 116 | + transaction.transition(Transaction.State.COMMITTED))); |
115 | - .thenApply(v -> true); | ||
116 | } | 117 | } |
117 | 118 | ||
118 | - private CompletableFuture<Boolean> rollback(Transaction transaction) { | 119 | + private CompletableFuture<CommitResponse> rollback(Transaction transaction) { |
119 | return database.rollback(transaction) | 120 | return database.rollback(transaction) |
120 | .thenCompose(v -> transactions.put( | 121 | .thenCompose(v -> transactions.put( |
121 | transaction.id(), | 122 | transaction.id(), |
122 | transaction.transition(Transaction.State.ROLLEDBACK))) | 123 | transaction.transition(Transaction.State.ROLLEDBACK))) |
123 | - .thenApply(v -> true); | 124 | + .thenApply(v -> CommitResponse.failure()); |
124 | } | 125 | } |
125 | } | 126 | } | ... | ... |
-
Please register or login to post a comment