Madan Jampani
Committed by Gerrit Code Review

Refactor transaction support in preparation for migration to latest APIs

 - Added a explicit transaction id type
 - cli command now just returns the identifiers of in-progress transactions
 - Removed redriveTransactions until a better alternative is provided
 - Removed DatabaseUpdate and replaced its usage with MapUpdate

Change-Id: Ic4a14967072068834510cd8459fd2a6790e456ef
Showing 34 changed files with 389 additions and 702 deletions
...@@ -18,81 +18,41 @@ package org.onosproject.cli.net; ...@@ -18,81 +18,41 @@ package org.onosproject.cli.net;
18 import java.util.Collection; 18 import java.util.Collection;
19 19
20 import org.apache.karaf.shell.commands.Command; 20 import org.apache.karaf.shell.commands.Command;
21 -import org.apache.karaf.shell.commands.Option;
22 -import org.onlab.util.Tools;
23 import org.onosproject.cli.AbstractShellCommand; 21 import org.onosproject.cli.AbstractShellCommand;
22 +import org.onosproject.store.primitives.TransactionId;
24 import org.onosproject.store.service.StorageAdminService; 23 import org.onosproject.store.service.StorageAdminService;
25 -import org.onosproject.store.service.Transaction;
26 24
27 import com.fasterxml.jackson.databind.JsonNode; 25 import com.fasterxml.jackson.databind.JsonNode;
28 import com.fasterxml.jackson.databind.ObjectMapper; 26 import com.fasterxml.jackson.databind.ObjectMapper;
29 import com.fasterxml.jackson.databind.node.ArrayNode; 27 import com.fasterxml.jackson.databind.node.ArrayNode;
30 -import com.fasterxml.jackson.databind.node.ObjectNode;
31 28
32 /** 29 /**
33 - * CLI to work with database transactions in the system. 30 + * CLI to view in-progress database transactions in the system.
34 */ 31 */
35 @Command(scope = "onos", name = "transactions", 32 @Command(scope = "onos", name = "transactions",
36 - description = "Utility for viewing and redriving database transactions") 33 + description = "Utility for listing pending/inprogress transactions")
37 public class TransactionsCommand extends AbstractShellCommand { 34 public class TransactionsCommand extends AbstractShellCommand {
38 35
39 - @Option(name = "-r", aliases = "--redrive",
40 - description = "Redrive stuck transactions while removing those that are done",
41 - required = false, multiValued = false)
42 - private boolean redrive = false;
43 -
44 - private static final String FMT = "%-20s %-15s %-10s";
45 -
46 - /**
47 - * Displays transactions as text.
48 - *
49 - * @param transactions transactions
50 - */
51 - private void displayTransactions(Collection<Transaction> transactions) {
52 - print("---------------------------------------------");
53 - print(FMT, "Id", "State", "Updated");
54 - print("---------------------------------------------");
55 - transactions.forEach(txn -> print(FMT, txn.id(), txn.state(), Tools.timeAgo(txn.lastUpdated())));
56 - if (transactions.size() > 0) {
57 - print("---------------------------------------------");
58 - }
59 - }
60 -
61 /** 36 /**
62 * Converts collection of transactions into a JSON object. 37 * Converts collection of transactions into a JSON object.
63 * 38 *
64 - * @param transactions transactions 39 + * @param transactionIds transaction identifiers
65 */ 40 */
66 - private JsonNode json(Collection<Transaction> transactions) { 41 + private JsonNode json(Collection<TransactionId> transactionIds) {
67 ObjectMapper mapper = new ObjectMapper(); 42 ObjectMapper mapper = new ObjectMapper();
68 ArrayNode txns = mapper.createArrayNode(); 43 ArrayNode txns = mapper.createArrayNode();
69 - 44 + transactionIds.forEach(id -> txns.add(id.toString()));
70 - // Create a JSON node for each transaction
71 - transactions.stream().forEach(txn -> {
72 - ObjectNode txnNode = mapper.createObjectNode();
73 - txnNode.put("id", txn.id())
74 - .put("state", txn.state().toString())
75 - .put("lastUpdated", txn.lastUpdated());
76 - txns.add(txnNode);
77 - });
78 -
79 return txns; 45 return txns;
80 } 46 }
81 47
82 @Override 48 @Override
83 protected void execute() { 49 protected void execute() {
84 StorageAdminService storageAdminService = get(StorageAdminService.class); 50 StorageAdminService storageAdminService = get(StorageAdminService.class);
85 - 51 + Collection<TransactionId> transactionIds = storageAdminService.getPendingTransactions();
86 - if (redrive) {
87 - storageAdminService.redriveTransactions();
88 - return;
89 - }
90 -
91 - Collection<Transaction> transactions = storageAdminService.getTransactions();
92 if (outputJson()) { 52 if (outputJson()) {
93 - print("%s", json(transactions)); 53 + print("%s", json(transactionIds));
94 } else { 54 } else {
95 - displayTransactions(transactions); 55 + transactionIds.forEach(id -> print("%s", id.toString()));
96 } 56 }
97 } 57 }
98 } 58 }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.store.primitives.resources.impl; 16 +package org.onosproject.store.primitives;
17 17
18 import com.google.common.base.Objects; 18 import com.google.common.base.Objects;
19 19
......
1 -/*
2 - * Copyright 2015 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.store.service;
18 -
19 -import static com.google.common.base.Preconditions.checkArgument;
20 -import static com.google.common.base.Preconditions.checkNotNull;
21 -import static com.google.common.base.Preconditions.checkState;
22 -
23 -import com.google.common.base.MoreObjects;
24 -
25 -/**
26 - * Database update operation.
27 - *
28 - */
29 -public final class DatabaseUpdate {
30 -
31 - /**
32 - * Type of database update operation.
33 - */
34 - public enum Type {
35 - /**
36 - * Insert/Update entry without any checks.
37 - */
38 - PUT,
39 - /**
40 - * Insert an entry iff there is no existing entry for that key.
41 - */
42 - PUT_IF_ABSENT,
43 -
44 - /**
45 - * Update entry if the current version matches specified version.
46 - */
47 - PUT_IF_VERSION_MATCH,
48 -
49 - /**
50 - * Update entry if the current value matches specified value.
51 - */
52 - PUT_IF_VALUE_MATCH,
53 -
54 - /**
55 - * Remove entry without any checks.
56 - */
57 - REMOVE,
58 -
59 - /**
60 - * Remove entry if the current version matches specified version.
61 - */
62 - REMOVE_IF_VERSION_MATCH,
63 -
64 - /**
65 - * Remove entry if the current value matches specified value.
66 - */
67 - REMOVE_IF_VALUE_MATCH,
68 - }
69 -
70 - private Type type;
71 - private String mapName;
72 - private String key;
73 - private byte[] value;
74 - private byte[] currentValue;
75 - private long currentVersion = -1;
76 -
77 - /**
78 - * Returns the type of update operation.
79 - * @return type of update.
80 - */
81 - public Type type() {
82 - return type;
83 - }
84 -
85 - /**
86 - * Returns the name of map being updated.
87 - * @return map name.
88 - */
89 - public String mapName() {
90 - return mapName;
91 - }
92 -
93 - /**
94 - * Returns the item key being updated.
95 - * @return item key
96 - */
97 - public String key() {
98 - return key;
99 - }
100 -
101 - /**
102 - * Returns the new value.
103 - * @return item's target value.
104 - */
105 - public byte[] value() {
106 - return value;
107 - }
108 -
109 - /**
110 - * Returns the expected current value in the database value for the key.
111 - * @return current value in database.
112 - */
113 - public byte[] currentValue() {
114 - return currentValue;
115 - }
116 -
117 - /**
118 - * Returns the expected current version in the database for the key.
119 - * @return expected version.
120 - */
121 - public long currentVersion() {
122 - return currentVersion;
123 - }
124 -
125 - @Override
126 - public String toString() {
127 - return MoreObjects.toStringHelper(this)
128 - .add("type", type)
129 - .add("mapName", mapName)
130 - .add("key", key)
131 - .add("value", value)
132 - .add("currentValue", currentValue)
133 - .add("currentVersion", currentVersion)
134 - .toString();
135 - }
136 -
137 - /**
138 - * Creates a new builder instance.
139 - *
140 - * @return builder.
141 - */
142 - public static Builder newBuilder() {
143 - return new Builder();
144 - }
145 -
146 - /**
147 - * DatabaseUpdate builder.
148 - *
149 - */
150 - public static final class Builder {
151 -
152 - private DatabaseUpdate update = new DatabaseUpdate();
153 -
154 - public DatabaseUpdate build() {
155 - validateInputs();
156 - return update;
157 - }
158 -
159 - public Builder withType(Type type) {
160 - update.type = checkNotNull(type, "type cannot be null");
161 - return this;
162 - }
163 -
164 - public Builder withMapName(String mapName) {
165 - update.mapName = checkNotNull(mapName, "mapName cannot be null");
166 - return this;
167 - }
168 -
169 - public Builder withKey(String key) {
170 - update.key = checkNotNull(key, "key cannot be null");
171 - return this;
172 - }
173 -
174 - public Builder withCurrentValue(byte[] value) {
175 - update.currentValue = checkNotNull(value, "currentValue cannot be null");
176 - return this;
177 - }
178 -
179 - public Builder withValue(byte[] value) {
180 - update.value = checkNotNull(value, "value cannot be null");
181 - return this;
182 - }
183 -
184 - public Builder withCurrentVersion(long version) {
185 - checkArgument(version >= 0, "version cannot be negative");
186 - update.currentVersion = version;
187 - return this;
188 - }
189 -
190 - private void validateInputs() {
191 - checkNotNull(update.type, "type must be specified");
192 - checkNotNull(update.mapName, "map name must be specified");
193 - checkNotNull(update.key, "key must be specified");
194 - switch (update.type) {
195 - case PUT:
196 - case PUT_IF_ABSENT:
197 - checkNotNull(update.value, "value must be specified.");
198 - break;
199 - case PUT_IF_VERSION_MATCH:
200 - checkNotNull(update.value, "value must be specified.");
201 - checkState(update.currentVersion >= 0, "current version must be specified");
202 - break;
203 - case PUT_IF_VALUE_MATCH:
204 - checkNotNull(update.value, "value must be specified.");
205 - checkNotNull(update.currentValue, "currentValue must be specified.");
206 - break;
207 - case REMOVE:
208 - break;
209 - case REMOVE_IF_VERSION_MATCH:
210 - checkState(update.currentVersion >= 0, "current version must be specified");
211 - break;
212 - case REMOVE_IF_VALUE_MATCH:
213 - checkNotNull(update.currentValue, "currentValue must be specified.");
214 - break;
215 - default:
216 - throw new IllegalStateException("Unknown operation type");
217 - }
218 - }
219 - }
220 -}
...@@ -61,7 +61,12 @@ public interface DistributedPrimitive { ...@@ -61,7 +61,12 @@ public interface DistributedPrimitive {
61 /** 61 /**
62 * Leader elector. 62 * Leader elector.
63 */ 63 */
64 - LEADER_ELECTOR 64 + LEADER_ELECTOR,
65 +
66 + /**
67 + * Transaction Context.
68 + */
69 + TRANSACTION_CONTEXT
65 } 70 }
66 71
67 static final long DEFAULT_OPERTATION_TIMEOUT_MILLIS = 5000L; 72 static final long DEFAULT_OPERTATION_TIMEOUT_MILLIS = 5000L;
......
...@@ -19,6 +19,8 @@ import java.util.Collection; ...@@ -19,6 +19,8 @@ import java.util.Collection;
19 import java.util.List; 19 import java.util.List;
20 import java.util.Map; 20 import java.util.Map;
21 21
22 +import org.onosproject.store.primitives.TransactionId;
23 +
22 /** 24 /**
23 * Service for administering storage instances. 25 * Service for administering storage instances.
24 */ 26 */
...@@ -62,14 +64,9 @@ public interface StorageAdminService { ...@@ -62,14 +64,9 @@ public interface StorageAdminService {
62 Map<String, Long> getInMemoryDatabaseCounters(); 64 Map<String, Long> getInMemoryDatabaseCounters();
63 65
64 /** 66 /**
65 - * Returns all the transactions in the system. 67 + * Returns all pending transactions.
66 * 68 *
67 - * @return collection of transactions 69 + * @return collection of pending transaction identifiers.
68 - */
69 - Collection<Transaction> getTransactions();
70 -
71 - /**
72 - * Redrives stuck transactions while removing those that are done.
73 */ 70 */
74 - void redriveTransactions(); 71 + Collection<TransactionId> getPendingTransactions();
75 } 72 }
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
16 16
17 package org.onosproject.store.service; 17 package org.onosproject.store.service;
18 18
19 +import org.onosproject.store.primitives.TransactionId;
20 +
19 /** 21 /**
20 * Provides a context for transactional operations. 22 * Provides a context for transactional operations.
21 * <p> 23 * <p>
...@@ -31,14 +33,19 @@ package org.onosproject.store.service; ...@@ -31,14 +33,19 @@ package org.onosproject.store.service;
31 * context isolation level is REPEATABLE_READS i.e. only data that is committed can be read. 33 * context isolation level is REPEATABLE_READS i.e. only data that is committed can be read.
32 * The only uncommitted data that can be read is the data modified by the current transaction. 34 * The only uncommitted data that can be read is the data modified by the current transaction.
33 */ 35 */
34 -public interface TransactionContext { 36 +public interface TransactionContext extends DistributedPrimitive {
37 +
38 + @Override
39 + default DistributedPrimitive.Type type() {
40 + return DistributedPrimitive.Type.TRANSACTION_CONTEXT;
41 + }
35 42
36 /** 43 /**
37 - * Returns the unique transactionId. 44 + * Returns the transaction identifier.
38 * 45 *
39 * @return transaction id 46 * @return transaction id
40 */ 47 */
41 - long transactionId(); 48 + TransactionId transactionId();
42 49
43 /** 50 /**
44 * Returns if this transaction context is open. 51 * Returns if this transaction context is open.
......
...@@ -15,33 +15,14 @@ ...@@ -15,33 +15,14 @@
15 */ 15 */
16 package org.onosproject.store.service; 16 package org.onosproject.store.service;
17 17
18 -/** 18 +import org.onosproject.store.primitives.DistributedPrimitiveBuilder;
19 - * Interface definition for a transaction context builder.
20 - */
21 -public interface TransactionContextBuilder {
22 19
23 - /** 20 +/**
24 - * Disables distribution of map entries across multiple database partitions. 21 + * Abstract base class for a transaction context builder.
25 - * <p>
26 - * When partitioning is disabled, the returned map will have a single
27 - * partition that spans the entire cluster. Furthermore, the changes made to
28 - * the map are ephemeral and do not survive a full cluster restart.
29 - * </p>
30 - * <p>
31 - * Note: By default, partitions are enabled. This feature is intended to
32 - * simplify debugging.
33 - * </p>
34 - *
35 - * @return this TransactionalContextBuilder
36 */ 22 */
37 - TransactionContextBuilder withPartitionsDisabled(); 23 +public abstract class TransactionContextBuilder extends DistributedPrimitiveBuilder<TransactionContext> {
38 24
39 - /** 25 + public TransactionContextBuilder() {
40 - * Builds a TransactionContext based on configuration options supplied to this 26 + super(DistributedPrimitive.Type.TRANSACTION_CONTEXT);
41 - * builder. 27 + }
42 - *
43 - * @return a new TransactionalContext
44 - * @throws java.lang.RuntimeException if a mandatory parameter is missing
45 - */
46 - TransactionContext build();
47 } 28 }
......
...@@ -32,6 +32,7 @@ import java.util.Scanner; ...@@ -32,6 +32,7 @@ import java.util.Scanner;
32 import org.onlab.util.Match; 32 import org.onlab.util.Match;
33 import org.onosproject.cluster.NodeId; 33 import org.onosproject.cluster.NodeId;
34 import org.onosproject.event.Change; 34 import org.onosproject.event.Change;
35 +import org.onosproject.store.primitives.TransactionId;
35 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMapCommands; 36 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMapCommands;
36 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMapState; 37 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMapState;
37 import org.onosproject.store.primitives.resources.impl.AtomixLeaderElectorCommands; 38 import org.onosproject.store.primitives.resources.impl.AtomixLeaderElectorCommands;
...@@ -40,8 +41,6 @@ import org.onosproject.store.primitives.resources.impl.MapEntryUpdateResult; ...@@ -40,8 +41,6 @@ import org.onosproject.store.primitives.resources.impl.MapEntryUpdateResult;
40 import org.onosproject.store.primitives.resources.impl.MapUpdate; 41 import org.onosproject.store.primitives.resources.impl.MapUpdate;
41 import org.onosproject.store.primitives.resources.impl.PrepareResult; 42 import org.onosproject.store.primitives.resources.impl.PrepareResult;
42 import org.onosproject.store.primitives.resources.impl.RollbackResult; 43 import org.onosproject.store.primitives.resources.impl.RollbackResult;
43 -import org.onosproject.store.primitives.resources.impl.TransactionId;
44 -import org.onosproject.store.primitives.resources.impl.TransactionalMapUpdate;
45 import org.onosproject.store.serializers.KryoNamespaces; 44 import org.onosproject.store.serializers.KryoNamespaces;
46 import org.onosproject.store.service.MapEvent; 45 import org.onosproject.store.service.MapEvent;
47 import org.onosproject.store.service.Versioned; 46 import org.onosproject.store.service.Versioned;
...@@ -66,7 +65,8 @@ public final class CatalystSerializers { ...@@ -66,7 +65,8 @@ public final class CatalystSerializers {
66 MapEntryUpdateResult.Status.class, 65 MapEntryUpdateResult.Status.class,
67 MapUpdate.class, 66 MapUpdate.class,
68 MapUpdate.Type.class, 67 MapUpdate.Type.class,
69 - TransactionalMapUpdate.class, 68 + Transaction.class,
69 + Transaction.State.class,
70 TransactionId.class, 70 TransactionId.class,
71 PrepareResult.class, 71 PrepareResult.class,
72 CommitResult.class, 72 CommitResult.class,
...@@ -99,7 +99,8 @@ public final class CatalystSerializers { ...@@ -99,7 +99,8 @@ public final class CatalystSerializers {
99 serializer.register(Match.class, factory); 99 serializer.register(Match.class, factory);
100 serializer.register(MapEntryUpdateResult.class, factory); 100 serializer.register(MapEntryUpdateResult.class, factory);
101 serializer.register(MapEntryUpdateResult.Status.class, factory); 101 serializer.register(MapEntryUpdateResult.Status.class, factory);
102 - serializer.register(TransactionalMapUpdate.class, factory); 102 + serializer.register(Transaction.class, factory);
103 + serializer.register(Transaction.State.class, factory);
103 serializer.register(PrepareResult.class, factory); 104 serializer.register(PrepareResult.class, factory);
104 serializer.register(CommitResult.class, factory); 105 serializer.register(CommitResult.class, factory);
105 serializer.register(RollbackResult.class, factory); 106 serializer.register(RollbackResult.class, factory);
......
...@@ -24,6 +24,7 @@ import java.util.Collection; ...@@ -24,6 +24,7 @@ import java.util.Collection;
24 import java.util.List; 24 import java.util.List;
25 import java.util.Map; 25 import java.util.Map;
26 import java.util.Set; 26 import java.util.Set;
27 +import java.util.UUID;
27 import java.util.concurrent.CompletableFuture; 28 import java.util.concurrent.CompletableFuture;
28 import java.util.concurrent.ExecutionException; 29 import java.util.concurrent.ExecutionException;
29 import java.util.concurrent.Executors; 30 import java.util.concurrent.Executors;
...@@ -46,7 +47,6 @@ import net.kuujo.copycat.protocol.Consistency; ...@@ -46,7 +47,6 @@ import net.kuujo.copycat.protocol.Consistency;
46 import net.kuujo.copycat.protocol.Protocol; 47 import net.kuujo.copycat.protocol.Protocol;
47 import net.kuujo.copycat.util.concurrent.NamedThreadFactory; 48 import net.kuujo.copycat.util.concurrent.NamedThreadFactory;
48 49
49 -import org.apache.commons.lang.math.RandomUtils;
50 import org.apache.felix.scr.annotations.Activate; 50 import org.apache.felix.scr.annotations.Activate;
51 import org.apache.felix.scr.annotations.Component; 51 import org.apache.felix.scr.annotations.Component;
52 import org.apache.felix.scr.annotations.Deactivate; 52 import org.apache.felix.scr.annotations.Deactivate;
...@@ -63,10 +63,12 @@ import org.onosproject.cluster.ControllerNode; ...@@ -63,10 +63,12 @@ import org.onosproject.cluster.ControllerNode;
63 import org.onosproject.cluster.NodeId; 63 import org.onosproject.cluster.NodeId;
64 import org.onosproject.cluster.PartitionId; 64 import org.onosproject.cluster.PartitionId;
65 import org.onosproject.core.ApplicationId; 65 import org.onosproject.core.ApplicationId;
66 -import org.onosproject.core.IdGenerator;
67 import org.onosproject.persistence.PersistenceService; 66 import org.onosproject.persistence.PersistenceService;
68 import org.onosproject.store.cluster.messaging.ClusterCommunicationService; 67 import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
68 +import org.onosproject.store.primitives.TransactionId;
69 +import org.onosproject.store.primitives.resources.impl.MapUpdate;
69 import org.onosproject.store.serializers.KryoNamespaces; 70 import org.onosproject.store.serializers.KryoNamespaces;
71 +import org.onosproject.store.service.AsyncConsistentMap;
70 import org.onosproject.store.service.AtomicCounterBuilder; 72 import org.onosproject.store.service.AtomicCounterBuilder;
71 import org.onosproject.store.service.AtomicValueBuilder; 73 import org.onosproject.store.service.AtomicValueBuilder;
72 import org.onosproject.store.service.ConsistentMapBuilder; 74 import org.onosproject.store.service.ConsistentMapBuilder;
...@@ -79,7 +81,6 @@ import org.onosproject.store.service.PartitionInfo; ...@@ -79,7 +81,6 @@ import org.onosproject.store.service.PartitionInfo;
79 import org.onosproject.store.service.Serializer; 81 import org.onosproject.store.service.Serializer;
80 import org.onosproject.store.service.StorageAdminService; 82 import org.onosproject.store.service.StorageAdminService;
81 import org.onosproject.store.service.StorageService; 83 import org.onosproject.store.service.StorageService;
82 -import org.onosproject.store.service.Transaction;
83 import org.onosproject.store.service.TransactionContextBuilder; 84 import org.onosproject.store.service.TransactionContextBuilder;
84 import org.slf4j.Logger; 85 import org.slf4j.Logger;
85 86
...@@ -112,7 +113,8 @@ public class DatabaseManager implements StorageService, StorageAdminService { ...@@ -112,7 +113,8 @@ public class DatabaseManager implements StorageService, StorageAdminService {
112 protected NodeId localNodeId; 113 protected NodeId localNodeId;
113 114
114 private TransactionManager transactionManager; 115 private TransactionManager transactionManager;
115 - private final IdGenerator transactionIdGenerator = () -> RandomUtils.nextLong(); 116 + private final Supplier<TransactionId> transactionIdGenerator =
117 + () -> TransactionId.from(UUID.randomUUID().toString());
116 118
117 private ApplicationListener appListener = new InternalApplicationListener(); 119 private ApplicationListener appListener = new InternalApplicationListener();
118 120
...@@ -212,7 +214,17 @@ public class DatabaseManager implements StorageService, StorageAdminService { ...@@ -212,7 +214,17 @@ public class DatabaseManager implements StorageService, StorageAdminService {
212 214
213 Futures.getUnchecked(status); 215 Futures.getUnchecked(status);
214 216
215 - transactionManager = new TransactionManager(partitionedDatabase, consistentMapBuilder()); 217 + AsyncConsistentMap<TransactionId, Transaction> transactions =
218 + this.<TransactionId, Transaction>consistentMapBuilder()
219 + .withName("onos-transactions")
220 + .withSerializer(Serializer.using(KryoNamespaces.API,
221 + MapUpdate.class,
222 + MapUpdate.Type.class,
223 + Transaction.class,
224 + Transaction.State.class))
225 + .buildAsyncMap();
226 +
227 + transactionManager = new TransactionManager(partitionedDatabase, transactions);
216 partitionedDatabase.setTransactionManager(transactionManager); 228 partitionedDatabase.setTransactionManager(transactionManager);
217 229
218 log.info("Started"); 230 log.info("Started");
...@@ -238,7 +250,9 @@ public class DatabaseManager implements StorageService, StorageAdminService { ...@@ -238,7 +250,9 @@ public class DatabaseManager implements StorageService, StorageAdminService {
238 250
239 @Override 251 @Override
240 public TransactionContextBuilder transactionContextBuilder() { 252 public TransactionContextBuilder transactionContextBuilder() {
241 - return new DefaultTransactionContextBuilder(this, transactionIdGenerator.getNewId()); 253 + return new DefaultTransactionContextBuilder(this::consistentMapBuilder,
254 + transactionManager::execute,
255 + transactionIdGenerator.get());
242 } 256 }
243 257
244 @Override 258 @Override
...@@ -385,8 +399,8 @@ public class DatabaseManager implements StorageService, StorageAdminService { ...@@ -385,8 +399,8 @@ public class DatabaseManager implements StorageService, StorageAdminService {
385 } 399 }
386 400
387 @Override 401 @Override
388 - public Collection<Transaction> getTransactions() { 402 + public Collection<TransactionId> getPendingTransactions() {
389 - return complete(transactionManager.getTransactions()); 403 + return complete(transactionManager.getPendingTransactionIds());
390 } 404 }
391 405
392 private static <T> T complete(CompletableFuture<T> future) { 406 private static <T> T complete(CompletableFuture<T> future) {
...@@ -402,11 +416,6 @@ public class DatabaseManager implements StorageService, StorageAdminService { ...@@ -402,11 +416,6 @@ public class DatabaseManager implements StorageService, StorageAdminService {
402 } 416 }
403 } 417 }
404 418
405 - @Override
406 - public void redriveTransactions() {
407 - getTransactions().stream().forEach(transactionManager::execute);
408 - }
409 -
410 protected <K, V> DefaultAsyncConsistentMap<K, V> registerMap(DefaultAsyncConsistentMap<K, V> map) { 419 protected <K, V> DefaultAsyncConsistentMap<K, V> registerMap(DefaultAsyncConsistentMap<K, V> map) {
411 maps.put(map.name(), map); 420 maps.put(map.name(), map);
412 if (map.applicationId() != null) { 421 if (map.applicationId() != null) {
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
17 package org.onosproject.store.primitives.impl; 17 package org.onosproject.store.primitives.impl;
18 18
19 import org.onlab.util.Match; 19 import org.onlab.util.Match;
20 -import org.onosproject.store.service.Transaction;
21 import org.onosproject.store.service.Versioned; 20 import org.onosproject.store.service.Versioned;
22 21
23 import java.util.Collection; 22 import java.util.Collection;
......
...@@ -21,10 +21,10 @@ import java.nio.ByteBuffer; ...@@ -21,10 +21,10 @@ import java.nio.ByteBuffer;
21 import org.onlab.util.KryoNamespace; 21 import org.onlab.util.KryoNamespace;
22 import org.onlab.util.Match; 22 import org.onlab.util.Match;
23 import org.onosproject.cluster.NodeId; 23 import org.onosproject.cluster.NodeId;
24 +import org.onosproject.store.primitives.TransactionId;
25 +import org.onosproject.store.primitives.resources.impl.MapUpdate;
24 import org.onosproject.store.serializers.KryoNamespaces; 26 import org.onosproject.store.serializers.KryoNamespaces;
25 import org.onosproject.store.serializers.KryoSerializer; 27 import org.onosproject.store.serializers.KryoSerializer;
26 -import org.onosproject.store.service.DatabaseUpdate;
27 -import org.onosproject.store.service.Transaction;
28 import org.onosproject.store.service.Versioned; 28 import org.onosproject.store.service.Versioned;
29 29
30 import net.kuujo.copycat.cluster.internal.MemberInfo; 30 import net.kuujo.copycat.cluster.internal.MemberInfo;
...@@ -69,13 +69,14 @@ public class DatabaseSerializer extends SerializerConfig { ...@@ -69,13 +69,14 @@ public class DatabaseSerializer extends SerializerConfig {
69 private static final KryoNamespace ONOS_STORE = KryoNamespace.newBuilder() 69 private static final KryoNamespace ONOS_STORE = KryoNamespace.newBuilder()
70 .nextId(KryoNamespace.FLOATING_ID) 70 .nextId(KryoNamespace.FLOATING_ID)
71 .register(Versioned.class) 71 .register(Versioned.class)
72 - .register(DatabaseUpdate.class) 72 + .register(MapUpdate.class)
73 - .register(DatabaseUpdate.Type.class) 73 + .register(MapUpdate.Type.class)
74 .register(Result.class) 74 .register(Result.class)
75 .register(UpdateResult.class) 75 .register(UpdateResult.class)
76 .register(Result.Status.class) 76 .register(Result.Status.class)
77 - .register(DefaultTransaction.class) 77 + .register(Transaction.class)
78 .register(Transaction.State.class) 78 .register(Transaction.State.class)
79 + .register(TransactionId.class)
79 .register(org.onosproject.store.primitives.impl.CommitResponse.class) 80 .register(org.onosproject.store.primitives.impl.CommitResponse.class)
80 .register(Match.class) 81 .register(Match.class)
81 .register(NodeId.class) 82 .register(NodeId.class)
......
...@@ -22,7 +22,6 @@ import net.kuujo.copycat.state.Query; ...@@ -22,7 +22,6 @@ import net.kuujo.copycat.state.Query;
22 import net.kuujo.copycat.state.StateContext; 22 import net.kuujo.copycat.state.StateContext;
23 23
24 import org.onlab.util.Match; 24 import org.onlab.util.Match;
25 -import org.onosproject.store.service.Transaction;
26 import org.onosproject.store.service.Versioned; 25 import org.onosproject.store.service.Versioned;
27 26
28 import java.util.Collection; 27 import java.util.Collection;
......
...@@ -26,7 +26,6 @@ import net.kuujo.copycat.util.concurrent.Futures; ...@@ -26,7 +26,6 @@ import net.kuujo.copycat.util.concurrent.Futures;
26 import net.kuujo.copycat.util.function.TriConsumer; 26 import net.kuujo.copycat.util.function.TriConsumer;
27 27
28 import org.onlab.util.Match; 28 import org.onlab.util.Match;
29 -import org.onosproject.store.service.Transaction;
30 import org.onosproject.store.service.Versioned; 29 import org.onosproject.store.service.Versioned;
31 30
32 import java.util.Collection; 31 import java.util.Collection;
......
...@@ -26,8 +26,8 @@ import net.kuujo.copycat.state.Initializer; ...@@ -26,8 +26,8 @@ import net.kuujo.copycat.state.Initializer;
26 import net.kuujo.copycat.state.StateContext; 26 import net.kuujo.copycat.state.StateContext;
27 27
28 import org.onlab.util.Match; 28 import org.onlab.util.Match;
29 -import org.onosproject.store.service.DatabaseUpdate; 29 +import org.onosproject.store.primitives.TransactionId;
30 -import org.onosproject.store.service.Transaction; 30 +import org.onosproject.store.primitives.resources.impl.MapUpdate;
31 import org.onosproject.store.service.Versioned; 31 import org.onosproject.store.service.Versioned;
32 32
33 import java.util.Arrays; 33 import java.util.Arrays;
...@@ -278,7 +278,7 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { ...@@ -278,7 +278,7 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> {
278 return queues.computeIfAbsent(queueName, name -> new LinkedList<>()); 278 return queues.computeIfAbsent(queueName, name -> new LinkedList<>());
279 } 279 }
280 280
281 - private boolean isUpdatePossible(DatabaseUpdate update) { 281 + private boolean isUpdatePossible(MapUpdate<String, byte[]> update) {
282 Versioned<byte[]> existingEntry = mapGet(update.mapName(), update.key()); 282 Versioned<byte[]> existingEntry = mapGet(update.mapName(), update.key());
283 switch (update.type()) { 283 switch (update.type()) {
284 case PUT: 284 case PUT:
...@@ -299,7 +299,7 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { ...@@ -299,7 +299,7 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> {
299 } 299 }
300 } 300 }
301 301
302 - private void doProvisionalUpdate(DatabaseUpdate update, long transactionId) { 302 + private void doProvisionalUpdate(MapUpdate<String, byte[]> update, TransactionId transactionId) {
303 Map<String, Update> lockMap = getLockMap(update.mapName()); 303 Map<String, Update> lockMap = getLockMap(update.mapName());
304 switch (update.type()) { 304 switch (update.type()) {
305 case PUT: 305 case PUT:
...@@ -318,7 +318,8 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { ...@@ -318,7 +318,8 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> {
318 } 318 }
319 } 319 }
320 320
321 - private UpdateResult<String, byte[]> commitProvisionalUpdate(DatabaseUpdate update, long transactionId) { 321 + private UpdateResult<String, byte[]> commitProvisionalUpdate(
322 + MapUpdate<String, byte[]> update, TransactionId transactionId) {
322 String mapName = update.mapName(); 323 String mapName = update.mapName();
323 String key = update.key(); 324 String key = update.key();
324 Update provisionalUpdate = getLockMap(mapName).get(key); 325 Update provisionalUpdate = getLockMap(mapName).get(key);
...@@ -330,7 +331,7 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { ...@@ -330,7 +331,7 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> {
330 return mapUpdate(mapName, key, Match.any(), Match.any(), provisionalUpdate.value()).value(); 331 return mapUpdate(mapName, key, Match.any(), Match.any(), provisionalUpdate.value()).value();
331 } 332 }
332 333
333 - private void undoProvisionalUpdate(DatabaseUpdate update, long transactionId) { 334 + private void undoProvisionalUpdate(MapUpdate<String, byte[]> update, TransactionId transactionId) {
334 String mapName = update.mapName(); 335 String mapName = update.mapName();
335 String key = update.key(); 336 String key = update.key();
336 Update provisionalUpdate = getLockMap(mapName).get(key); 337 Update provisionalUpdate = getLockMap(mapName).get(key);
...@@ -342,7 +343,7 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { ...@@ -342,7 +343,7 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> {
342 } 343 }
343 } 344 }
344 345
345 - private boolean isLockedByAnotherTransaction(String mapName, String key, long transactionId) { 346 + private boolean isLockedByAnotherTransaction(String mapName, String key, TransactionId transactionId) {
346 Update update = getLockMap(mapName).get(key); 347 Update update = getLockMap(mapName).get(key);
347 return update != null && !Objects.equal(transactionId, update.transactionId()); 348 return update != null && !Objects.equal(transactionId, update.transactionId());
348 } 349 }
...@@ -356,15 +357,15 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> { ...@@ -356,15 +357,15 @@ public class DefaultDatabaseState implements DatabaseState<String, byte[]> {
356 } 357 }
357 358
358 private class Update { 359 private class Update {
359 - private final long transactionId; 360 + private final TransactionId transactionId;
360 private final byte[] value; 361 private final byte[] value;
361 362
362 - public Update(long txId, byte[] value) { 363 + public Update(TransactionId txId, byte[] value) {
363 this.transactionId = txId; 364 this.transactionId = txId;
364 this.value = value; 365 this.value = value;
365 } 366 }
366 367
367 - public long transactionId() { 368 + public TransactionId transactionId() {
368 return this.transactionId; 369 return this.transactionId;
369 } 370 }
370 371
......
1 -/*
2 - * Copyright 2015 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.store.primitives.impl;
17 -
18 -import java.util.List;
19 -
20 -import org.onosproject.store.service.DatabaseUpdate;
21 -import org.onosproject.store.service.Transaction;
22 -
23 -import com.google.common.collect.ImmutableList;
24 -
25 -/**
26 - * A Default transaction implementation.
27 - */
28 -public class DefaultTransaction implements Transaction {
29 -
30 - private final long transactionId;
31 - private final List<DatabaseUpdate> updates;
32 - private final State state;
33 - private final long lastUpdated;
34 -
35 - public DefaultTransaction(long transactionId, List<DatabaseUpdate> updates) {
36 - this(transactionId, updates, State.PREPARING, System.currentTimeMillis());
37 - }
38 -
39 - private DefaultTransaction(long transactionId, List<DatabaseUpdate> updates, State state, long lastUpdated) {
40 - this.transactionId = transactionId;
41 - this.updates = ImmutableList.copyOf(updates);
42 - this.state = state;
43 - this.lastUpdated = lastUpdated;
44 - }
45 -
46 - @Override
47 - public long id() {
48 - return transactionId;
49 - }
50 -
51 - @Override
52 - public List<DatabaseUpdate> updates() {
53 - return updates;
54 - }
55 -
56 - @Override
57 - public State state() {
58 - return state;
59 - }
60 -
61 - @Override
62 - public Transaction transition(State newState) {
63 - return new DefaultTransaction(transactionId, updates, newState, System.currentTimeMillis());
64 - }
65 -
66 - @Override
67 - public long lastUpdated() {
68 - return lastUpdated;
69 - }
70 -}
...\ No newline at end of file ...\ No newline at end of file
...@@ -18,14 +18,17 @@ package org.onosproject.store.primitives.impl; ...@@ -18,14 +18,17 @@ package org.onosproject.store.primitives.impl;
18 18
19 import java.util.List; 19 import java.util.List;
20 import java.util.Map; 20 import java.util.Map;
21 +import java.util.concurrent.CompletableFuture;
22 +import java.util.function.Function;
21 import java.util.function.Supplier; 23 import java.util.function.Supplier;
22 24
23 import static com.google.common.base.Preconditions.*; 25 import static com.google.common.base.Preconditions.*;
24 26
27 +import org.onosproject.store.primitives.TransactionId;
28 +import org.onosproject.store.primitives.resources.impl.CommitResult;
29 +import org.onosproject.store.primitives.resources.impl.MapUpdate;
25 import org.onosproject.store.service.ConsistentMapBuilder; 30 import org.onosproject.store.service.ConsistentMapBuilder;
26 -import org.onosproject.store.service.DatabaseUpdate;
27 import org.onosproject.store.service.Serializer; 31 import org.onosproject.store.service.Serializer;
28 -import org.onosproject.store.service.Transaction;
29 import org.onosproject.store.service.TransactionContext; 32 import org.onosproject.store.service.TransactionContext;
30 import org.onosproject.store.service.TransactionalMap; 33 import org.onosproject.store.service.TransactionalMap;
31 34
...@@ -44,20 +47,20 @@ public class DefaultTransactionContext implements TransactionContext { ...@@ -44,20 +47,20 @@ public class DefaultTransactionContext implements TransactionContext {
44 @SuppressWarnings("rawtypes") 47 @SuppressWarnings("rawtypes")
45 private final Map<String, DefaultTransactionalMap> txMaps = Maps.newConcurrentMap(); 48 private final Map<String, DefaultTransactionalMap> txMaps = Maps.newConcurrentMap();
46 private boolean isOpen = false; 49 private boolean isOpen = false;
47 - private final Database database; 50 + private final Function<Transaction, CompletableFuture<CommitResult>> transactionCommitter;
48 - private final long transactionId; 51 + private final TransactionId transactionId;
49 private final Supplier<ConsistentMapBuilder> mapBuilderSupplier; 52 private final Supplier<ConsistentMapBuilder> mapBuilderSupplier;
50 53
51 - public DefaultTransactionContext(long transactionId, 54 + public DefaultTransactionContext(TransactionId transactionId,
52 - Database database, 55 + Function<Transaction, CompletableFuture<CommitResult>> transactionCommitter,
53 Supplier<ConsistentMapBuilder> mapBuilderSupplier) { 56 Supplier<ConsistentMapBuilder> mapBuilderSupplier) {
54 this.transactionId = transactionId; 57 this.transactionId = transactionId;
55 - this.database = checkNotNull(database); 58 + this.transactionCommitter = checkNotNull(transactionCommitter);
56 this.mapBuilderSupplier = checkNotNull(mapBuilderSupplier); 59 this.mapBuilderSupplier = checkNotNull(mapBuilderSupplier);
57 } 60 }
58 61
59 @Override 62 @Override
60 - public long transactionId() { 63 + public TransactionId transactionId() {
61 return transactionId; 64 return transactionId;
62 } 65 }
63 66
...@@ -91,13 +94,13 @@ public class DefaultTransactionContext implements TransactionContext { ...@@ -91,13 +94,13 @@ public class DefaultTransactionContext implements TransactionContext {
91 public boolean commit() { 94 public boolean commit() {
92 // TODO: rework commit implementation to be more intuitive 95 // TODO: rework commit implementation to be more intuitive
93 checkState(isOpen, TX_NOT_OPEN_ERROR); 96 checkState(isOpen, TX_NOT_OPEN_ERROR);
94 - CommitResponse response = null; 97 + CommitResult result = null;
95 try { 98 try {
96 - List<DatabaseUpdate> updates = Lists.newLinkedList(); 99 + List<MapUpdate<String, byte[]>> updates = Lists.newLinkedList();
97 - txMaps.values().forEach(m -> updates.addAll(m.prepareDatabaseUpdates())); 100 + txMaps.values().forEach(m -> updates.addAll(m.toMapUpdates()));
98 - Transaction transaction = new DefaultTransaction(transactionId, updates); 101 + Transaction transaction = new Transaction(transactionId, updates);
99 - response = Futures.getUnchecked(database.prepareAndCommit(transaction)); 102 + result = Futures.getUnchecked(transactionCommitter.apply(transaction));
100 - return response.success(); 103 + return result == CommitResult.OK;
101 } catch (Exception e) { 104 } catch (Exception e) {
102 abort(); 105 abort();
103 return false; 106 return false;
...@@ -128,4 +131,9 @@ public class DefaultTransactionContext implements TransactionContext { ...@@ -128,4 +131,9 @@ public class DefaultTransactionContext implements TransactionContext {
128 }); 131 });
129 return s.toString(); 132 return s.toString();
130 } 133 }
134 +
135 + @Override
136 + public String name() {
137 + return transactionId.toString();
138 + }
131 } 139 }
......
...@@ -15,6 +15,13 @@ ...@@ -15,6 +15,13 @@
15 */ 15 */
16 package org.onosproject.store.primitives.impl; 16 package org.onosproject.store.primitives.impl;
17 17
18 +import java.util.concurrent.CompletableFuture;
19 +import java.util.function.Function;
20 +import java.util.function.Supplier;
21 +
22 +import org.onosproject.store.primitives.TransactionId;
23 +import org.onosproject.store.primitives.resources.impl.CommitResult;
24 +import org.onosproject.store.service.ConsistentMapBuilder;
18 import org.onosproject.store.service.TransactionContext; 25 import org.onosproject.store.service.TransactionContext;
19 import org.onosproject.store.service.TransactionContextBuilder; 26 import org.onosproject.store.service.TransactionContextBuilder;
20 27
...@@ -22,29 +29,28 @@ import org.onosproject.store.service.TransactionContextBuilder; ...@@ -22,29 +29,28 @@ import org.onosproject.store.service.TransactionContextBuilder;
22 * The default implementation of a transaction context builder. This builder 29 * The default implementation of a transaction context builder. This builder
23 * generates a {@link DefaultTransactionContext}. 30 * generates a {@link DefaultTransactionContext}.
24 */ 31 */
25 -public class DefaultTransactionContextBuilder implements TransactionContextBuilder { 32 +public class DefaultTransactionContextBuilder extends TransactionContextBuilder {
26 33
27 - private boolean partitionsEnabled = true; 34 + private final Supplier<ConsistentMapBuilder> mapBuilderSupplier;
28 - private final DatabaseManager manager; 35 + private final Function<Transaction, CompletableFuture<CommitResult>> transactionCommitter;
29 - private final long transactionId; 36 + private final TransactionId transactionId;
30 37
31 - public DefaultTransactionContextBuilder(DatabaseManager manager, long transactionId) { 38 + public DefaultTransactionContextBuilder(Supplier<ConsistentMapBuilder> mapBuilderSupplier,
32 - this.manager = manager; 39 + Function<Transaction, CompletableFuture<CommitResult>> transactionCommiter,
40 + TransactionId transactionId) {
41 + this.mapBuilderSupplier = mapBuilderSupplier;
42 + this.transactionCommitter = transactionCommiter;
33 this.transactionId = transactionId; 43 this.transactionId = transactionId;
34 } 44 }
35 45
36 @Override 46 @Override
37 - public TransactionContextBuilder withPartitionsDisabled() {
38 - partitionsEnabled = false;
39 - return this;
40 - }
41 -
42 - @Override
43 public TransactionContext build() { 47 public TransactionContext build() {
44 - return new DefaultTransactionContext( 48 + return new DefaultTransactionContext(transactionId, transactionCommitter, () -> {
45 - transactionId, 49 + ConsistentMapBuilder mapBuilder = mapBuilderSupplier.get();
46 - partitionsEnabled ? manager.partitionedDatabase : manager.inMemoryDatabase, 50 + if (partitionsDisabled()) {
47 - () -> partitionsEnabled ? manager.consistentMapBuilder() 51 + mapBuilder = mapBuilder.withPartitionsDisabled();
48 - : manager.consistentMapBuilder().withPartitionsDisabled()); 52 + }
53 + return mapBuilder;
54 + });
49 } 55 }
50 } 56 }
......
...@@ -21,8 +21,8 @@ import java.util.Map; ...@@ -21,8 +21,8 @@ import java.util.Map;
21 import java.util.Set; 21 import java.util.Set;
22 22
23 import org.onlab.util.HexString; 23 import org.onlab.util.HexString;
24 +import org.onosproject.store.primitives.resources.impl.MapUpdate;
24 import org.onosproject.store.service.ConsistentMap; 25 import org.onosproject.store.service.ConsistentMap;
25 -import org.onosproject.store.service.DatabaseUpdate;
26 import org.onosproject.store.service.Serializer; 26 import org.onosproject.store.service.Serializer;
27 import org.onosproject.store.service.TransactionContext; 27 import org.onosproject.store.service.TransactionContext;
28 import org.onosproject.store.service.TransactionalMap; 28 import org.onosproject.store.service.TransactionalMap;
...@@ -159,14 +159,14 @@ public class DefaultTransactionalMap<K, V> implements TransactionalMap<K, V> { ...@@ -159,14 +159,14 @@ public class DefaultTransactionalMap<K, V> implements TransactionalMap<K, V> {
159 return latest; 159 return latest;
160 } 160 }
161 161
162 - protected List<DatabaseUpdate> prepareDatabaseUpdates() { 162 + protected List<MapUpdate<String, byte[]>> toMapUpdates() {
163 - List<DatabaseUpdate> updates = Lists.newLinkedList(); 163 + List<MapUpdate<String, byte[]>> updates = Lists.newLinkedList();
164 deleteSet.forEach(key -> { 164 deleteSet.forEach(key -> {
165 Versioned<V> original = readCache.get(key); 165 Versioned<V> original = readCache.get(key);
166 if (original != null) { 166 if (original != null) {
167 - updates.add(DatabaseUpdate.newBuilder() 167 + updates.add(MapUpdate.<String, byte[]>newBuilder()
168 .withMapName(name) 168 .withMapName(name)
169 - .withType(DatabaseUpdate.Type.REMOVE_IF_VERSION_MATCH) 169 + .withType(MapUpdate.Type.REMOVE_IF_VERSION_MATCH)
170 .withKey(keyCache.getUnchecked(key)) 170 .withKey(keyCache.getUnchecked(key))
171 .withCurrentVersion(original.version()) 171 .withCurrentVersion(original.version())
172 .build()); 172 .build());
...@@ -175,16 +175,16 @@ public class DefaultTransactionalMap<K, V> implements TransactionalMap<K, V> { ...@@ -175,16 +175,16 @@ public class DefaultTransactionalMap<K, V> implements TransactionalMap<K, V> {
175 writeCache.forEach((key, value) -> { 175 writeCache.forEach((key, value) -> {
176 Versioned<V> original = readCache.get(key); 176 Versioned<V> original = readCache.get(key);
177 if (original == null) { 177 if (original == null) {
178 - updates.add(DatabaseUpdate.newBuilder() 178 + updates.add(MapUpdate.<String, byte[]>newBuilder()
179 .withMapName(name) 179 .withMapName(name)
180 - .withType(DatabaseUpdate.Type.PUT_IF_ABSENT) 180 + .withType(MapUpdate.Type.PUT_IF_ABSENT)
181 .withKey(keyCache.getUnchecked(key)) 181 .withKey(keyCache.getUnchecked(key))
182 .withValue(serializer.encode(value)) 182 .withValue(serializer.encode(value))
183 .build()); 183 .build());
184 } else { 184 } else {
185 - updates.add(DatabaseUpdate.newBuilder() 185 + updates.add(MapUpdate.<String, byte[]>newBuilder()
186 .withMapName(name) 186 .withMapName(name)
187 - .withType(DatabaseUpdate.Type.PUT_IF_VERSION_MATCH) 187 + .withType(MapUpdate.Type.PUT_IF_VERSION_MATCH)
188 .withKey(keyCache.getUnchecked(key)) 188 .withKey(keyCache.getUnchecked(key))
189 .withCurrentVersion(original.version()) 189 .withCurrentVersion(original.version())
190 .withValue(serializer.encode(value)) 190 .withValue(serializer.encode(value))
...@@ -199,7 +199,7 @@ public class DefaultTransactionalMap<K, V> implements TransactionalMap<K, V> { ...@@ -199,7 +199,7 @@ public class DefaultTransactionalMap<K, V> implements TransactionalMap<K, V> {
199 public String toString() { 199 public String toString() {
200 return MoreObjects.toStringHelper(this) 200 return MoreObjects.toStringHelper(this)
201 .add("backingMap", backingMap) 201 .add("backingMap", backingMap)
202 - .add("updates", prepareDatabaseUpdates()) 202 + .add("updates", toMapUpdates())
203 .toString(); 203 .toString();
204 } 204 }
205 205
......
...@@ -26,8 +26,8 @@ import net.kuujo.copycat.cluster.Cluster; ...@@ -26,8 +26,8 @@ import net.kuujo.copycat.cluster.Cluster;
26 import net.kuujo.copycat.resource.ResourceState; 26 import net.kuujo.copycat.resource.ResourceState;
27 27
28 import org.onlab.util.Match; 28 import org.onlab.util.Match;
29 -import org.onosproject.store.service.DatabaseUpdate; 29 +import org.onosproject.store.primitives.resources.impl.CommitResult;
30 -import org.onosproject.store.service.Transaction; 30 +import org.onosproject.store.primitives.resources.impl.MapUpdate;
31 import org.onosproject.store.service.Versioned; 31 import org.onosproject.store.service.Versioned;
32 32
33 import java.util.Collection; 33 import java.util.Collection;
...@@ -273,7 +273,9 @@ public class PartitionedDatabase implements Database { ...@@ -273,7 +273,9 @@ public class PartitionedDatabase implements Database {
273 if (transactionManager == null) { 273 if (transactionManager == null) {
274 throw new IllegalStateException("TransactionManager is not initialized"); 274 throw new IllegalStateException("TransactionManager is not initialized");
275 } 275 }
276 - return transactionManager.execute(transaction); 276 + return transactionManager.execute(transaction)
277 + .thenApply(r -> r == CommitResult.OK
278 + ? CommitResponse.success(ImmutableList.of()) : CommitResponse.failure());
277 } 279 }
278 } 280 }
279 281
...@@ -373,15 +375,15 @@ public class PartitionedDatabase implements Database { ...@@ -373,15 +375,15 @@ public class PartitionedDatabase implements Database {
373 375
374 private Map<Database, Transaction> createSubTransactions( 376 private Map<Database, Transaction> createSubTransactions(
375 Transaction transaction) { 377 Transaction transaction) {
376 - Map<Database, List<DatabaseUpdate>> perPartitionUpdates = Maps.newHashMap(); 378 + Map<Database, List<MapUpdate<String, byte[]>>> perPartitionUpdates = Maps.newHashMap();
377 - for (DatabaseUpdate update : transaction.updates()) { 379 + for (MapUpdate<String, byte[]> update : transaction.updates()) {
378 Database partition = partitioner.getPartition(update.mapName(), update.key()); 380 Database partition = partitioner.getPartition(update.mapName(), update.key());
379 - List<DatabaseUpdate> partitionUpdates = 381 + List<MapUpdate<String, byte[]>> partitionUpdates =
380 perPartitionUpdates.computeIfAbsent(partition, k -> Lists.newLinkedList()); 382 perPartitionUpdates.computeIfAbsent(partition, k -> Lists.newLinkedList());
381 partitionUpdates.add(update); 383 partitionUpdates.add(update);
382 } 384 }
383 Map<Database, Transaction> subTransactions = Maps.newHashMap(); 385 Map<Database, Transaction> subTransactions = Maps.newHashMap();
384 - perPartitionUpdates.forEach((k, v) -> subTransactions.put(k, new DefaultTransaction(transaction.id(), v))); 386 + perPartitionUpdates.forEach((k, v) -> subTransactions.put(k, new Transaction(transaction.id(), v)));
385 return subTransactions; 387 return subTransactions;
386 } 388 }
387 389
......
...@@ -13,14 +13,20 @@ ...@@ -13,14 +13,20 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.store.service; 16 +package org.onosproject.store.primitives.impl;
17 17
18 import java.util.List; 18 import java.util.List;
19 19
20 +import org.onosproject.store.primitives.TransactionId;
21 +import org.onosproject.store.primitives.resources.impl.MapUpdate;
22 +
23 +import com.google.common.base.MoreObjects;
24 +import com.google.common.collect.ImmutableList;
25 +
20 /** 26 /**
21 * An immutable transaction object. 27 * An immutable transaction object.
22 */ 28 */
23 -public interface Transaction { 29 +public class Transaction {
24 30
25 enum State { 31 enum State {
26 /** 32 /**
...@@ -55,48 +61,44 @@ public interface Transaction { ...@@ -55,48 +61,44 @@ public interface Transaction {
55 ROLLEDBACK 61 ROLLEDBACK
56 } 62 }
57 63
58 - /** 64 + private final TransactionId transactionId;
59 - * Returns the transaction Id. 65 + private final List<MapUpdate<String, byte[]>> updates;
60 - * 66 + private final State state;
61 - * @return transaction id
62 - */
63 - long id();
64 67
65 - /** 68 + public Transaction(TransactionId transactionId, List<MapUpdate<String, byte[]>> updates) {
66 - * Returns the list of updates that are part of this transaction. 69 + this(transactionId, updates, State.PREPARING);
67 - * 70 + }
68 - * @return list of database updates
69 - */
70 - List<DatabaseUpdate> updates();
71 71
72 - /** 72 + private Transaction(TransactionId transactionId,
73 - * Returns the current state of this transaction. 73 + List<MapUpdate<String, byte[]>> updates,
74 - * 74 + State state) {
75 - * @return transaction state 75 + this.transactionId = transactionId;
76 - */ 76 + this.updates = ImmutableList.copyOf(updates);
77 - State state(); 77 + this.state = state;
78 + }
78 79
79 - /** 80 + public TransactionId id() {
80 - * Returns true if this transaction has completed execution. 81 + return transactionId;
81 - *
82 - * @return true is yes, false otherwise
83 - */
84 - default boolean isDone() {
85 - return state() == State.COMMITTED || state() == State.ROLLEDBACK;
86 } 82 }
87 83
88 - /** 84 + public List<MapUpdate<String, byte[]>> updates() {
89 - * Returns a new transaction that is created by transitioning this one to the specified state. 85 + return updates;
90 - * 86 + }
91 - * @param newState destination state
92 - * @return a new transaction instance similar to the current one but its state set to specified state
93 - */
94 - Transaction transition(State newState);
95 87
96 - /** 88 + public State state() {
97 - * Returns the system time when the transaction was last updated. 89 + return state;
98 - * 90 + }
99 - * @return last update time 91 +
100 - */ 92 + public Transaction transition(State newState) {
101 - long lastUpdated(); 93 + return new Transaction(transactionId, updates, newState);
94 + }
95 +
96 + @Override
97 + public String toString() {
98 + return MoreObjects.toStringHelper(getClass())
99 + .add("transactionId", transactionId)
100 + .add("updates", updates)
101 + .add("state", state)
102 + .toString();
103 + }
102 } 104 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -17,87 +17,62 @@ package org.onosproject.store.primitives.impl; ...@@ -17,87 +17,62 @@ package org.onosproject.store.primitives.impl;
17 17
18 import static com.google.common.base.Preconditions.checkNotNull; 18 import static com.google.common.base.Preconditions.checkNotNull;
19 19
20 -import java.util.Arrays;
21 import java.util.Collection; 20 import java.util.Collection;
22 import java.util.concurrent.CompletableFuture; 21 import java.util.concurrent.CompletableFuture;
23 import java.util.stream.Collectors; 22 import java.util.stream.Collectors;
24 23
25 -import org.onlab.util.KryoNamespace; 24 +import org.onosproject.store.primitives.TransactionId;
26 -import org.onosproject.store.serializers.KryoNamespaces; 25 +import org.onosproject.store.primitives.resources.impl.CommitResult;
27 import org.onosproject.store.service.AsyncConsistentMap; 26 import org.onosproject.store.service.AsyncConsistentMap;
28 -import org.onosproject.store.service.ConsistentMapBuilder;
29 -import org.onosproject.store.service.DatabaseUpdate;
30 -import org.onosproject.store.service.Serializer;
31 -import org.onosproject.store.service.Transaction;
32 -import org.onosproject.store.service.Versioned;
33 -import org.onosproject.store.service.Transaction.State;
34 27
35 -import com.google.common.collect.ImmutableList; 28 +import static org.onosproject.store.primitives.impl.Transaction.State.COMMITTED;
29 +import static org.onosproject.store.primitives.impl.Transaction.State.COMMITTING;
30 +import static org.onosproject.store.primitives.impl.Transaction.State.ROLLEDBACK;
31 +import static org.onosproject.store.primitives.impl.Transaction.State.ROLLINGBACK;
36 32
37 /** 33 /**
38 * Agent that runs the two phase commit protocol. 34 * Agent that runs the two phase commit protocol.
39 */ 35 */
40 public class TransactionManager { 36 public class TransactionManager {
41 37
42 - private static final KryoNamespace KRYO_NAMESPACE = KryoNamespace.newBuilder()
43 - .register(KryoNamespaces.BASIC)
44 - .nextId(KryoNamespace.FLOATING_ID)
45 - .register(Versioned.class)
46 - .register(DatabaseUpdate.class)
47 - .register(DatabaseUpdate.Type.class)
48 - .register(DefaultTransaction.class)
49 - .register(Transaction.State.class)
50 - .build();
51 -
52 - private final Serializer serializer = Serializer.using(Arrays.asList(KRYO_NAMESPACE));
53 private final Database database; 38 private final Database database;
54 - private final AsyncConsistentMap<Long, Transaction> transactions; 39 + private final AsyncConsistentMap<TransactionId, Transaction> transactions;
55 40
56 - /** 41 + public TransactionManager(Database database, AsyncConsistentMap<TransactionId, Transaction> transactions) {
57 - * Constructs a new TransactionManager for the specified database instance.
58 - *
59 - * @param database database
60 - * @param mapBuilder builder for ConsistentMap instances
61 - */
62 - public TransactionManager(Database database, ConsistentMapBuilder<Long, Transaction> mapBuilder) {
63 this.database = checkNotNull(database, "database cannot be null"); 42 this.database = checkNotNull(database, "database cannot be null");
64 - this.transactions = mapBuilder.withName("onos-transactions") 43 + this.transactions = transactions;
65 - .withSerializer(serializer)
66 - .buildAsyncMap();
67 } 44 }
68 45
69 /** 46 /**
70 * Executes the specified transaction by employing a two phase commit protocol. 47 * Executes the specified transaction by employing a two phase commit protocol.
71 * 48 *
72 * @param transaction transaction to commit 49 * @param transaction transaction to commit
73 - * @return transaction result. Result value true indicates a successful commit, false 50 + * @return transaction commit result
74 - * indicates abort
75 */ 51 */
76 - public CompletableFuture<CommitResponse> execute(Transaction transaction) { 52 + public CompletableFuture<CommitResult> execute(Transaction transaction) {
77 // clean up if this transaction in already in a terminal state. 53 // clean up if this transaction in already in a terminal state.
78 - if (transaction.state() == Transaction.State.COMMITTED || 54 + if (transaction.state() == COMMITTED || transaction.state() == ROLLEDBACK) {
79 - transaction.state() == Transaction.State.ROLLEDBACK) { 55 + return transactions.remove(transaction.id()).thenApply(v -> CommitResult.OK);
80 - return transactions.remove(transaction.id()).thenApply(v -> CommitResponse.success(ImmutableList.of())); 56 + } else if (transaction.state() == COMMITTING) {
81 - } else if (transaction.state() == Transaction.State.COMMITTING) {
82 return commit(transaction); 57 return commit(transaction);
83 - } else if (transaction.state() == Transaction.State.ROLLINGBACK) { 58 + } else if (transaction.state() == ROLLINGBACK) {
84 - return rollback(transaction).thenApply(v -> CommitResponse.success(ImmutableList.of())); 59 + return rollback(transaction).thenApply(v -> CommitResult.FAILURE_TO_PREPARE);
85 } else { 60 } else {
86 return prepare(transaction).thenCompose(v -> v ? commit(transaction) : rollback(transaction)); 61 return prepare(transaction).thenCompose(v -> v ? commit(transaction) : rollback(transaction));
87 } 62 }
88 } 63 }
89 64
90 -
91 /** 65 /**
92 - * Returns all transactions in the system. 66 + * Returns all pending transaction identifiers.
93 * 67 *
94 - * @return future for a collection of transactions 68 + * @return future for a collection of transaction identifiers.
95 */ 69 */
96 - public CompletableFuture<Collection<Transaction>> getTransactions() { 70 + public CompletableFuture<Collection<TransactionId>> getPendingTransactionIds() {
97 - return transactions.values().thenApply(c -> { 71 + return transactions.values().thenApply(c -> c.stream()
98 - Collection<Transaction> txns = c.stream().map(v -> v.value()).collect(Collectors.toList()); 72 + .map(v -> v.value())
99 - return txns; 73 + .filter(v -> v.state() != COMMITTED && v.state() != ROLLEDBACK)
100 - }); 74 + .map(Transaction::id)
75 + .collect(Collectors.toList()));
101 } 76 }
102 77
103 private CompletableFuture<Boolean> prepare(Transaction transaction) { 78 private CompletableFuture<Boolean> prepare(Transaction transaction) {
...@@ -105,22 +80,25 @@ public class TransactionManager { ...@@ -105,22 +80,25 @@ public class TransactionManager {
105 .thenCompose(v -> database.prepare(transaction)) 80 .thenCompose(v -> database.prepare(transaction))
106 .thenCompose(status -> transactions.put( 81 .thenCompose(status -> transactions.put(
107 transaction.id(), 82 transaction.id(),
108 - transaction.transition(status ? State.COMMITTING : State.ROLLINGBACK)) 83 + transaction.transition(status ? COMMITTING : ROLLINGBACK))
109 .thenApply(v -> status)); 84 .thenApply(v -> status));
110 } 85 }
111 86
112 - private CompletableFuture<CommitResponse> commit(Transaction transaction) { 87 + private CompletableFuture<CommitResult> commit(Transaction transaction) {
113 return database.commit(transaction) 88 return database.commit(transaction)
114 - .whenComplete((r, e) -> transactions.put( 89 + .thenCompose(r -> {
115 - transaction.id(), 90 + if (r.success()) {
116 - transaction.transition(Transaction.State.COMMITTED))); 91 + return transactions.put(transaction.id(), transaction.transition(COMMITTED))
92 + .thenApply(v -> CommitResult.OK);
93 + } else {
94 + return CompletableFuture.completedFuture(CommitResult.FAILURE_DURING_COMMIT);
95 + }
96 + });
117 } 97 }
118 98
119 - private CompletableFuture<CommitResponse> rollback(Transaction transaction) { 99 + private CompletableFuture<CommitResult> rollback(Transaction transaction) {
120 return database.rollback(transaction) 100 return database.rollback(transaction)
121 - .thenCompose(v -> transactions.put( 101 + .thenCompose(v -> transactions.put(transaction.id(), transaction.transition(ROLLEDBACK)))
122 - transaction.id(), 102 + .thenApply(v -> CommitResult.FAILURE_TO_PREPARE);
123 - transaction.transition(Transaction.State.ROLLEDBACK)))
124 - .thenApply(v -> CommitResponse.failure());
125 } 103 }
126 } 104 }
......
1 +/*
2 + * Copyright 2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.store.primitives.impl;
17 +
18 +import java.util.concurrent.CompletableFuture;
19 +
20 +import org.onosproject.store.primitives.TransactionId;
21 +import org.onosproject.store.primitives.resources.impl.CommitResult;
22 +import org.onosproject.store.primitives.resources.impl.PrepareResult;
23 +import org.onosproject.store.primitives.resources.impl.RollbackResult;
24 +
25 +/**
26 + * Participant in a two-phase commit protocol.
27 + */
28 +public interface TransactionParticipant {
29 +
30 + /**
31 + * Attempts to execute the prepare phase for the specified {@link Transaction transaction}.
32 + * @param transaction transaction
33 + * @return future for prepare result
34 + */
35 + CompletableFuture<PrepareResult> prepare(Transaction transaction);
36 +
37 + /**
38 + * Attempts to execute the commit phase for previously prepared transaction.
39 + * @param transactionId transaction identifier
40 + * @return future for commit result
41 + */
42 + CompletableFuture<CommitResult> commit(TransactionId transactionId);
43 +
44 + /**
45 + * Attempts to execute the rollback phase for previously prepared transaction.
46 + * @param transactionId transaction identifier
47 + * @return future for rollback result
48 + */
49 + CompletableFuture<RollbackResult> rollback(TransactionId transactionId);
50 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -31,6 +31,9 @@ import java.util.function.BiFunction; ...@@ -31,6 +31,9 @@ import java.util.function.BiFunction;
31 import java.util.function.Predicate; 31 import java.util.function.Predicate;
32 32
33 import org.onlab.util.Match; 33 import org.onlab.util.Match;
34 +import org.onosproject.store.primitives.TransactionId;
35 +import org.onosproject.store.primitives.impl.Transaction;
36 +import org.onosproject.store.primitives.impl.TransactionParticipant;
34 import org.onosproject.store.service.AsyncConsistentMap; 37 import org.onosproject.store.service.AsyncConsistentMap;
35 import org.onosproject.store.service.MapEvent; 38 import org.onosproject.store.service.MapEvent;
36 import org.onosproject.store.service.MapEventListener; 39 import org.onosproject.store.service.MapEventListener;
...@@ -43,7 +46,7 @@ import com.google.common.collect.Sets; ...@@ -43,7 +46,7 @@ import com.google.common.collect.Sets;
43 */ 46 */
44 @ResourceTypeInfo(id = -151, stateMachine = AtomixConsistentMapState.class) 47 @ResourceTypeInfo(id = -151, stateMachine = AtomixConsistentMapState.class)
45 public class AtomixConsistentMap extends Resource<AtomixConsistentMap, Resource.Options> 48 public class AtomixConsistentMap extends Resource<AtomixConsistentMap, Resource.Options>
46 - implements AsyncConsistentMap<String, byte[]> { 49 + implements AsyncConsistentMap<String, byte[]>, TransactionParticipant {
47 50
48 private final Set<MapEventListener<String, byte[]>> mapEventListeners = Sets.newCopyOnWriteArraySet(); 51 private final Set<MapEventListener<String, byte[]>> mapEventListeners = Sets.newCopyOnWriteArraySet();
49 52
...@@ -235,18 +238,6 @@ public class AtomixConsistentMap extends Resource<AtomixConsistentMap, Resource. ...@@ -235,18 +238,6 @@ public class AtomixConsistentMap extends Resource<AtomixConsistentMap, Resource.
235 }); 238 });
236 } 239 }
237 240
238 - public CompletableFuture<PrepareResult> prepare(TransactionalMapUpdate<String, byte[]> update) {
239 - return submit(new AtomixConsistentMapCommands.TransactionPrepare(update));
240 - }
241 -
242 - public CompletableFuture<CommitResult> commit(TransactionId transactionId) {
243 - return submit(new AtomixConsistentMapCommands.TransactionCommit(transactionId));
244 - }
245 -
246 - public CompletableFuture<RollbackResult> rollback(TransactionId transactionId) {
247 - return submit(new AtomixConsistentMapCommands.TransactionRollback(transactionId));
248 - }
249 -
250 @Override 241 @Override
251 public synchronized CompletableFuture<Void> addListener(MapEventListener<String, byte[]> listener) { 242 public synchronized CompletableFuture<Void> addListener(MapEventListener<String, byte[]> listener) {
252 if (!mapEventListeners.isEmpty()) { 243 if (!mapEventListeners.isEmpty()) {
...@@ -274,6 +265,21 @@ public class AtomixConsistentMap extends Resource<AtomixConsistentMap, Resource. ...@@ -274,6 +265,21 @@ public class AtomixConsistentMap extends Resource<AtomixConsistentMap, Resource.
274 } 265 }
275 } 266 }
276 267
268 + @Override
269 + public CompletableFuture<PrepareResult> prepare(Transaction transaction) {
270 + return submit(new AtomixConsistentMapCommands.TransactionPrepare(transaction));
271 + }
272 +
273 + @Override
274 + public CompletableFuture<CommitResult> commit(TransactionId transactionId) {
275 + return submit(new AtomixConsistentMapCommands.TransactionCommit(transactionId));
276 + }
277 +
278 + @Override
279 + public CompletableFuture<RollbackResult> rollback(TransactionId transactionId) {
280 + return submit(new AtomixConsistentMapCommands.TransactionRollback(transactionId));
281 + }
282 +
277 /** 283 /**
278 * Change listener context. 284 * Change listener context.
279 */ 285 */
......
...@@ -28,6 +28,8 @@ import java.util.Map; ...@@ -28,6 +28,8 @@ import java.util.Map;
28 import java.util.Set; 28 import java.util.Set;
29 29
30 import org.onlab.util.Match; 30 import org.onlab.util.Match;
31 +import org.onosproject.store.primitives.TransactionId;
32 +import org.onosproject.store.primitives.impl.Transaction;
31 import org.onosproject.store.service.Versioned; 33 import org.onosproject.store.service.Versioned;
32 34
33 import com.google.common.base.MoreObjects; 35 import com.google.common.base.MoreObjects;
...@@ -207,35 +209,35 @@ public final class AtomixConsistentMapCommands { ...@@ -207,35 +209,35 @@ public final class AtomixConsistentMapCommands {
207 */ 209 */
208 @SuppressWarnings("serial") 210 @SuppressWarnings("serial")
209 public static class TransactionPrepare extends MapCommand<PrepareResult> { 211 public static class TransactionPrepare extends MapCommand<PrepareResult> {
210 - private TransactionalMapUpdate<String, byte[]> update; 212 + private Transaction transaction;
211 213
212 public TransactionPrepare() { 214 public TransactionPrepare() {
213 } 215 }
214 216
215 - public TransactionPrepare(TransactionalMapUpdate<String, byte[]> update) { 217 + public TransactionPrepare(Transaction transaction) {
216 - this.update = update; 218 + this.transaction = transaction;
217 } 219 }
218 220
219 - public TransactionalMapUpdate<String, byte[]> transactionUpdate() { 221 + public Transaction transaction() {
220 - return update; 222 + return transaction;
221 } 223 }
222 224
223 @Override 225 @Override
224 public void writeObject(BufferOutput<?> buffer, Serializer serializer) { 226 public void writeObject(BufferOutput<?> buffer, Serializer serializer) {
225 super.writeObject(buffer, serializer); 227 super.writeObject(buffer, serializer);
226 - serializer.writeObject(update, buffer); 228 + serializer.writeObject(transaction, buffer);
227 } 229 }
228 230
229 @Override 231 @Override
230 public void readObject(BufferInput<?> buffer, Serializer serializer) { 232 public void readObject(BufferInput<?> buffer, Serializer serializer) {
231 super.readObject(buffer, serializer); 233 super.readObject(buffer, serializer);
232 - update = serializer.readObject(buffer); 234 + transaction = serializer.readObject(buffer);
233 } 235 }
234 236
235 @Override 237 @Override
236 public String toString() { 238 public String toString() {
237 return MoreObjects.toStringHelper(getClass()) 239 return MoreObjects.toStringHelper(getClass())
238 - .add("update", update) 240 + .add("transaction", transaction)
239 .toString(); 241 .toString();
240 } 242 }
241 } 243 }
......
...@@ -37,6 +37,8 @@ import java.util.stream.Collectors; ...@@ -37,6 +37,8 @@ import java.util.stream.Collectors;
37 37
38 import org.onlab.util.CountDownCompleter; 38 import org.onlab.util.CountDownCompleter;
39 import org.onlab.util.Match; 39 import org.onlab.util.Match;
40 +import org.onosproject.store.primitives.TransactionId;
41 +import org.onosproject.store.primitives.impl.Transaction;
40 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMapCommands.TransactionPrepare; 42 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMapCommands.TransactionPrepare;
41 import org.onosproject.store.service.MapEvent; 43 import org.onosproject.store.service.MapEvent;
42 import org.onosproject.store.service.Versioned; 44 import org.onosproject.store.service.Versioned;
...@@ -382,9 +384,8 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements ...@@ -382,9 +384,8 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements
382 Commit<? extends AtomixConsistentMapCommands.TransactionPrepare> commit) { 384 Commit<? extends AtomixConsistentMapCommands.TransactionPrepare> commit) {
383 boolean ok = false; 385 boolean ok = false;
384 try { 386 try {
385 - TransactionalMapUpdate<String, byte[]> transactionUpdate = commit 387 + Transaction transaction = commit.operation().transaction();
386 - .operation().transactionUpdate(); 388 + for (MapUpdate<String, byte[]> update : transaction.updates()) {
387 - for (MapUpdate<String, byte[]> update : transactionUpdate.batch()) {
388 String key = update.key(); 389 String key = update.key();
389 if (preparedKeys.contains(key)) { 390 if (preparedKeys.contains(key)) {
390 return PrepareResult.CONCURRENT_TRANSACTION; 391 return PrepareResult.CONCURRENT_TRANSACTION;
...@@ -403,8 +404,8 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements ...@@ -403,8 +404,8 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements
403 // No violations detected. Add to pendingTranctions and mark 404 // No violations detected. Add to pendingTranctions and mark
404 // modified keys as 405 // modified keys as
405 // currently locked to updates. 406 // currently locked to updates.
406 - pendingTransactions.put(transactionUpdate.transactionId(), commit); 407 + pendingTransactions.put(transaction.id(), commit);
407 - transactionUpdate.batch().forEach(u -> preparedKeys.add(u.key())); 408 + transaction.updates().forEach(u -> preparedKeys.add(u.key()));
408 ok = true; 409 ok = true;
409 return PrepareResult.OK; 410 return PrepareResult.OK;
410 } finally { 411 } finally {
...@@ -429,16 +430,15 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements ...@@ -429,16 +430,15 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements
429 if (prepareCommit == null) { 430 if (prepareCommit == null) {
430 return CommitResult.UNKNOWN_TRANSACTION_ID; 431 return CommitResult.UNKNOWN_TRANSACTION_ID;
431 } 432 }
432 - TransactionalMapUpdate<String, byte[]> transactionalUpdate = prepareCommit 433 + Transaction transaction = prepareCommit.operation().transaction();
433 - .operation().transactionUpdate(); 434 + long totalReferencesToCommit = transaction
434 - long totalReferencesToCommit = transactionalUpdate 435 + .updates()
435 - .batch()
436 .stream() 436 .stream()
437 .filter(update -> update.type() != MapUpdate.Type.REMOVE_IF_VERSION_MATCH) 437 .filter(update -> update.type() != MapUpdate.Type.REMOVE_IF_VERSION_MATCH)
438 .count(); 438 .count();
439 CountDownCompleter<Commit<? extends AtomixConsistentMapCommands.TransactionPrepare>> completer = 439 CountDownCompleter<Commit<? extends AtomixConsistentMapCommands.TransactionPrepare>> completer =
440 new CountDownCompleter<>(prepareCommit, totalReferencesToCommit, Commit::close); 440 new CountDownCompleter<>(prepareCommit, totalReferencesToCommit, Commit::close);
441 - for (MapUpdate<String, byte[]> update : transactionalUpdate.batch()) { 441 + for (MapUpdate<String, byte[]> update : transaction.updates()) {
442 String key = update.key(); 442 String key = update.key();
443 MapEntryValue previousValue = mapEntries.remove(key); 443 MapEntryValue previousValue = mapEntries.remove(key);
444 MapEntryValue newValue = null; 444 MapEntryValue newValue = null;
...@@ -473,7 +473,9 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements ...@@ -473,7 +473,9 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements
473 if (prepareCommit == null) { 473 if (prepareCommit == null) {
474 return RollbackResult.UNKNOWN_TRANSACTION_ID; 474 return RollbackResult.UNKNOWN_TRANSACTION_ID;
475 } else { 475 } else {
476 - prepareCommit.operation().transactionUpdate().batch() 476 + prepareCommit.operation()
477 + .transaction()
478 + .updates()
477 .forEach(u -> preparedKeys.remove(u.key())); 479 .forEach(u -> preparedKeys.remove(u.key()));
478 prepareCommit.close(); 480 prepareCommit.close();
479 return RollbackResult.OK; 481 return RollbackResult.OK;
...@@ -608,9 +610,8 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements ...@@ -608,9 +610,8 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements
608 610
609 @Override 611 @Override
610 public byte[] value() { 612 public byte[] value() {
611 - TransactionalMapUpdate<String, byte[]> update = completer.object() 613 + Transaction transaction = completer.object().operation().transaction();
612 - .operation().transactionUpdate(); 614 + return valueForKey(key, transaction);
613 - return update.valueForKey(key);
614 } 615 }
615 616
616 @Override 617 @Override
...@@ -622,5 +623,14 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements ...@@ -622,5 +623,14 @@ public class AtomixConsistentMapState extends ResourceStateMachine implements
622 public void discard() { 623 public void discard() {
623 completer.countDown(); 624 completer.countDown();
624 } 625 }
626 +
627 + private byte[] valueForKey(String key, Transaction transaction) {
628 + MapUpdate<String, byte[]> update = transaction.updates()
629 + .stream()
630 + .filter(u -> u.key().equals(key))
631 + .findFirst()
632 + .orElse(null);
633 + return update == null ? null : update.value();
634 + }
625 } 635 }
626 } 636 }
......
...@@ -28,4 +28,14 @@ public enum CommitResult { ...@@ -28,4 +28,14 @@ public enum CommitResult {
28 * Signifies a failure due to unrecognized transaction identifier. 28 * Signifies a failure due to unrecognized transaction identifier.
29 */ 29 */
30 UNKNOWN_TRANSACTION_ID, 30 UNKNOWN_TRANSACTION_ID,
31 +
32 + /**
33 + * Signifies a failure to get participants to agree to commit (during prepare stage).
34 + */
35 + FAILURE_TO_PREPARE,
36 +
37 + /**
38 + * Failure during commit phase.
39 + */
40 + FAILURE_DURING_COMMIT
31 } 41 }
......
...@@ -29,6 +29,8 @@ import com.google.common.base.MoreObjects; ...@@ -29,6 +29,8 @@ import com.google.common.base.MoreObjects;
29 * Both old and new values are accessible along with a flag that indicates if the 29 * Both old and new values are accessible along with a flag that indicates if the
30 * the value was updated. If flag is false, oldValue and newValue both 30 * the value was updated. If flag is false, oldValue and newValue both
31 * point to the same unmodified value. 31 * point to the same unmodified value.
32 + *
33 + * @param <K> key type
32 * @param <V> result type 34 * @param <V> result type
33 */ 35 */
34 public class MapEntryUpdateResult<K, V> { 36 public class MapEntryUpdateResult<K, V> {
...@@ -123,6 +125,8 @@ public class MapEntryUpdateResult<K, V> { ...@@ -123,6 +125,8 @@ public class MapEntryUpdateResult<K, V> {
123 * @param keyTransform transformer to use for transcoding keys 125 * @param keyTransform transformer to use for transcoding keys
124 * @param valueMapper mapper to use for transcoding values 126 * @param valueMapper mapper to use for transcoding values
125 * @return new instance 127 * @return new instance
128 + * @param <K1> key type of returned {@code MapEntryUpdateResult}
129 + * @param <V1> value type of returned {@code MapEntryUpdateResult}
126 */ 130 */
127 public <K1, V1> MapEntryUpdateResult<K1, V1> map(Function<K, K1> keyTransform, Function<V, V1> valueMapper) { 131 public <K1, V1> MapEntryUpdateResult<K1, V1> map(Function<K, K1> keyTransform, Function<V, V1> valueMapper) {
128 return new MapEntryUpdateResult<>(status, 132 return new MapEntryUpdateResult<>(status,
......
...@@ -70,6 +70,7 @@ public final class MapUpdate<K, V> { ...@@ -70,6 +70,7 @@ public final class MapUpdate<K, V> {
70 REMOVE_IF_VALUE_MATCH, 70 REMOVE_IF_VALUE_MATCH,
71 } 71 }
72 72
73 + private String mapName;
73 private Type type; 74 private Type type;
74 private K key; 75 private K key;
75 private V value; 76 private V value;
...@@ -77,6 +78,15 @@ public final class MapUpdate<K, V> { ...@@ -77,6 +78,15 @@ public final class MapUpdate<K, V> {
77 private long currentVersion = -1; 78 private long currentVersion = -1;
78 79
79 /** 80 /**
81 + * Returns the name of the map.
82 + *
83 + * @return map name
84 + */
85 + public String mapName() {
86 + return mapName;
87 + }
88 +
89 + /**
80 * Returns the type of update operation. 90 * Returns the type of update operation.
81 * @return type of update. 91 * @return type of update.
82 */ 92 */
...@@ -119,6 +129,7 @@ public final class MapUpdate<K, V> { ...@@ -119,6 +129,7 @@ public final class MapUpdate<K, V> {
119 @Override 129 @Override
120 public String toString() { 130 public String toString() {
121 return MoreObjects.toStringHelper(this) 131 return MoreObjects.toStringHelper(this)
132 + .add("mapName", mapName)
122 .add("type", type) 133 .add("type", type)
123 .add("key", key) 134 .add("key", key)
124 .add("value", value) 135 .add("value", value)
...@@ -153,6 +164,11 @@ public final class MapUpdate<K, V> { ...@@ -153,6 +164,11 @@ public final class MapUpdate<K, V> {
153 return update; 164 return update;
154 } 165 }
155 166
167 + public Builder<K, V> withMapName(String name) {
168 + update.mapName = checkNotNull(name, "name cannot be null");
169 + return this;
170 + }
171 +
156 public Builder<K, V> withType(Type type) { 172 public Builder<K, V> withType(Type type) {
157 update.type = checkNotNull(type, "type cannot be null"); 173 update.type = checkNotNull(type, "type cannot be null");
158 return this; 174 return this;
......
...@@ -25,6 +25,11 @@ public enum PrepareResult { ...@@ -25,6 +25,11 @@ public enum PrepareResult {
25 OK, 25 OK,
26 26
27 /** 27 /**
28 + * Signifies some participants in a distributed prepare operation failed.
29 + */
30 + PARTIAL_FAILURE,
31 +
32 + /**
28 * Signifies a failure to another transaction locking the underlying state. 33 * Signifies a failure to another transaction locking the underlying state.
29 */ 34 */
30 CONCURRENT_TRANSACTION, 35 CONCURRENT_TRANSACTION,
......
1 -/*
2 - * Copyright 2016 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.store.primitives.resources.impl;
17 -
18 -import java.util.Collection;
19 -import java.util.Map;
20 -
21 -import com.google.common.collect.ImmutableList;
22 -import com.google.common.collect.Maps;
23 -
24 -/**
25 - * A batch updates to an {@code AsyncConsistentMap} be committed as a transaction.
26 - *
27 - * @param <K> key type
28 - * @param <V> value type
29 - */
30 -public class TransactionalMapUpdate<K, V> {
31 - private final TransactionId transactionId;
32 - private final Collection<MapUpdate<K, V>> updates;
33 - private boolean indexPopulated = false;
34 - private final Map<K, V> keyValueIndex = Maps.newHashMap();
35 -
36 - public TransactionalMapUpdate(TransactionId transactionId, Collection<MapUpdate<K, V>> updates) {
37 - this.transactionId = transactionId;
38 - this.updates = ImmutableList.copyOf(updates);
39 - populateIndex();
40 - }
41 -
42 - /**
43 - * Returns the transaction identifier.
44 - * @return transaction id
45 - */
46 - public TransactionId transactionId() {
47 - return transactionId;
48 - }
49 -
50 - /**
51 - * Returns the collection of map updates.
52 - * @return map updates
53 - */
54 - public Collection<MapUpdate<K, V>> batch() {
55 - return updates;
56 - }
57 -
58 - /**
59 - * Returns the value that will be associated with the key after this transaction commits.
60 - * @param key key
61 - * @return value that will be associated with the value once this transaction commits
62 - */
63 - public V valueForKey(K key) {
64 - if (!indexPopulated) {
65 - // We do not synchronize as we don't expect this called to be made from multiple threads.
66 - populateIndex();
67 - }
68 - return keyValueIndex.get(key);
69 - }
70 -
71 - /**
72 - * Populates the internal key -> value mapping.
73 - */
74 - private synchronized void populateIndex() {
75 - updates.forEach(mapUpdate -> {
76 - if (mapUpdate.value() != null) {
77 - keyValueIndex.put(mapUpdate.key(), mapUpdate.value());
78 - }
79 - });
80 - indexPopulated = true;
81 - }
82 -}
...@@ -41,7 +41,6 @@ import org.onlab.util.Match; ...@@ -41,7 +41,6 @@ import org.onlab.util.Match;
41 import org.onosproject.core.ApplicationId; 41 import org.onosproject.core.ApplicationId;
42 import org.onosproject.core.DefaultApplicationId; 42 import org.onosproject.core.DefaultApplicationId;
43 import org.onosproject.store.service.Serializer; 43 import org.onosproject.store.service.Serializer;
44 -import org.onosproject.store.service.Transaction;
45 import org.onosproject.store.service.Versioned; 44 import org.onosproject.store.service.Versioned;
46 45
47 import com.google.common.base.MoreObjects; 46 import com.google.common.base.MoreObjects;
......
...@@ -27,6 +27,8 @@ import java.util.stream.Collectors; ...@@ -27,6 +27,8 @@ import java.util.stream.Collectors;
27 import org.junit.Ignore; 27 import org.junit.Ignore;
28 import org.junit.Test; 28 import org.junit.Test;
29 import org.onlab.util.Tools; 29 import org.onlab.util.Tools;
30 +import org.onosproject.store.primitives.TransactionId;
31 +import org.onosproject.store.primitives.impl.Transaction;
30 import org.onosproject.store.service.MapEvent; 32 import org.onosproject.store.service.MapEvent;
31 import org.onosproject.store.service.MapEventListener; 33 import org.onosproject.store.service.MapEventListener;
32 import org.onosproject.store.service.Versioned; 34 import org.onosproject.store.service.Versioned;
...@@ -351,10 +353,9 @@ public class AtomixConsistentMapTest extends AtomixTestBase { ...@@ -351,10 +353,9 @@ public class AtomixConsistentMapTest extends AtomixTestBase {
351 .withValue(value1) 353 .withValue(value1)
352 .build(); 354 .build();
353 355
354 - TransactionalMapUpdate<String, byte[]> txMapUpdate = 356 + Transaction tx = new Transaction(TransactionId.from("tx1"), Arrays.asList(update1));
355 - new TransactionalMapUpdate<>(TransactionId.from("tx1"), Arrays.asList(update1));
356 357
357 - map.prepare(txMapUpdate).thenAccept(result -> { 358 + map.prepare(tx).thenAccept(result -> {
358 assertEquals(PrepareResult.OK, result); 359 assertEquals(PrepareResult.OK, result);
359 }).join(); 360 }).join();
360 assertNull(listener.event()); 361 assertNull(listener.event());
...@@ -376,7 +377,7 @@ public class AtomixConsistentMapTest extends AtomixTestBase { ...@@ -376,7 +377,7 @@ public class AtomixConsistentMapTest extends AtomixTestBase {
376 377
377 assertNull(listener.event()); 378 assertNull(listener.event());
378 379
379 - map.commit(txMapUpdate.transactionId()).join(); 380 + map.commit(tx.id()).join();
380 assertNotNull(listener.event()); 381 assertNotNull(listener.event());
381 assertEquals(MapEvent.Type.INSERT, listener.event().type()); 382 assertEquals(MapEvent.Type.INSERT, listener.event().type());
382 assertTrue(Arrays.equals(value1, listener.event().newValue().value())); 383 assertTrue(Arrays.equals(value1, listener.event().newValue().value()));
...@@ -406,14 +407,13 @@ public class AtomixConsistentMapTest extends AtomixTestBase { ...@@ -406,14 +407,13 @@ public class AtomixConsistentMapTest extends AtomixTestBase {
406 .withKey("foo") 407 .withKey("foo")
407 .withValue(value1) 408 .withValue(value1)
408 .build(); 409 .build();
409 - TransactionalMapUpdate<String, byte[]> txMapUpdate = 410 + Transaction tx = new Transaction(TransactionId.from("tx1"), Arrays.asList(update1));
410 - new TransactionalMapUpdate<>(TransactionId.from("tx1"), Arrays.asList(update1)); 411 + map.prepare(tx).thenAccept(result -> {
411 - map.prepare(txMapUpdate).thenAccept(result -> {
412 assertEquals(PrepareResult.OK, result); 412 assertEquals(PrepareResult.OK, result);
413 }).join(); 413 }).join();
414 assertNull(listener.event()); 414 assertNull(listener.event());
415 415
416 - map.rollback(txMapUpdate.transactionId()).join(); 416 + map.rollback(tx.id()).join();
417 assertNull(listener.event()); 417 assertNull(listener.event());
418 418
419 map.get("foo").thenAccept(result -> { 419 map.get("foo").thenAccept(result -> {
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.store.service; 16 +package org.onosproject.store.primitives.resources.impl;
17 17
18 import com.google.common.testing.EqualsTester; 18 import com.google.common.testing.EqualsTester;
19 import org.junit.Test; 19 import org.junit.Test;
...@@ -22,63 +22,63 @@ import static org.hamcrest.MatcherAssert.assertThat; ...@@ -22,63 +22,63 @@ import static org.hamcrest.MatcherAssert.assertThat;
22 import static org.hamcrest.Matchers.is; 22 import static org.hamcrest.Matchers.is;
23 23
24 /** 24 /**
25 - * Unit Tests for DatabseUpdate class. 25 + * Unit Tests for MapUpdate class.
26 */ 26 */
27 27
28 -public class DatabaseUpdateTest { 28 +public class MapUpdateTest {
29 29
30 - private final DatabaseUpdate stats1 = DatabaseUpdate.newBuilder() 30 + private final MapUpdate<String, byte[]> stats1 = MapUpdate.<String, byte[]>newBuilder()
31 .withCurrentValue("1".getBytes()) 31 .withCurrentValue("1".getBytes())
32 .withValue("2".getBytes()) 32 .withValue("2".getBytes())
33 .withCurrentVersion(3) 33 .withCurrentVersion(3)
34 .withKey("4") 34 .withKey("4")
35 .withMapName("5") 35 .withMapName("5")
36 - .withType(DatabaseUpdate.Type.PUT) 36 + .withType(MapUpdate.Type.PUT)
37 .build(); 37 .build();
38 38
39 - private final DatabaseUpdate stats2 = DatabaseUpdate.newBuilder() 39 + private final MapUpdate<String, byte[]> stats2 = MapUpdate.<String, byte[]>newBuilder()
40 .withCurrentValue("1".getBytes()) 40 .withCurrentValue("1".getBytes())
41 .withValue("2".getBytes()) 41 .withValue("2".getBytes())
42 .withCurrentVersion(3) 42 .withCurrentVersion(3)
43 .withKey("4") 43 .withKey("4")
44 .withMapName("5") 44 .withMapName("5")
45 - .withType(DatabaseUpdate.Type.REMOVE) 45 + .withType(MapUpdate.Type.REMOVE)
46 .build(); 46 .build();
47 47
48 - private final DatabaseUpdate stats3 = DatabaseUpdate.newBuilder() 48 + private final MapUpdate<String, byte[]> stats3 = MapUpdate.<String, byte[]>newBuilder()
49 .withCurrentValue("1".getBytes()) 49 .withCurrentValue("1".getBytes())
50 .withValue("2".getBytes()) 50 .withValue("2".getBytes())
51 .withCurrentVersion(3) 51 .withCurrentVersion(3)
52 .withKey("4") 52 .withKey("4")
53 .withMapName("5") 53 .withMapName("5")
54 - .withType(DatabaseUpdate.Type.REMOVE_IF_VALUE_MATCH) 54 + .withType(MapUpdate.Type.REMOVE_IF_VALUE_MATCH)
55 .build(); 55 .build();
56 56
57 - private final DatabaseUpdate stats4 = DatabaseUpdate.newBuilder() 57 + private final MapUpdate<String, byte[]> stats4 = MapUpdate.<String, byte[]>newBuilder()
58 .withCurrentValue("1".getBytes()) 58 .withCurrentValue("1".getBytes())
59 .withValue("2".getBytes()) 59 .withValue("2".getBytes())
60 .withCurrentVersion(3) 60 .withCurrentVersion(3)
61 .withKey("4") 61 .withKey("4")
62 .withMapName("5") 62 .withMapName("5")
63 - .withType(DatabaseUpdate.Type.REMOVE_IF_VERSION_MATCH) 63 + .withType(MapUpdate.Type.REMOVE_IF_VERSION_MATCH)
64 .build(); 64 .build();
65 65
66 - private final DatabaseUpdate stats5 = DatabaseUpdate.newBuilder() 66 + private final MapUpdate<String, byte[]> stats5 = MapUpdate.<String, byte[]>newBuilder()
67 .withCurrentValue("1".getBytes()) 67 .withCurrentValue("1".getBytes())
68 .withValue("2".getBytes()) 68 .withValue("2".getBytes())
69 .withCurrentVersion(3) 69 .withCurrentVersion(3)
70 .withKey("4") 70 .withKey("4")
71 .withMapName("5") 71 .withMapName("5")
72 - .withType(DatabaseUpdate.Type.PUT_IF_VALUE_MATCH) 72 + .withType(MapUpdate.Type.PUT_IF_VALUE_MATCH)
73 .build(); 73 .build();
74 74
75 - private final DatabaseUpdate stats6 = DatabaseUpdate.newBuilder() 75 + private final MapUpdate<String, byte[]> stats6 = MapUpdate.<String, byte[]>newBuilder()
76 .withCurrentValue("1".getBytes()) 76 .withCurrentValue("1".getBytes())
77 .withValue("2".getBytes()) 77 .withValue("2".getBytes())
78 .withCurrentVersion(3) 78 .withCurrentVersion(3)
79 .withKey("4") 79 .withKey("4")
80 .withMapName("5") 80 .withMapName("5")
81 - .withType(DatabaseUpdate.Type.PUT_IF_VERSION_MATCH) 81 + .withType(MapUpdate.Type.PUT_IF_VERSION_MATCH)
82 .build(); 82 .build();
83 83
84 /** 84 /**
...@@ -91,7 +91,7 @@ public class DatabaseUpdateTest { ...@@ -91,7 +91,7 @@ public class DatabaseUpdateTest {
91 assertThat(stats1.currentVersion(), is(3L)); 91 assertThat(stats1.currentVersion(), is(3L));
92 assertThat(stats1.key(), is("4")); 92 assertThat(stats1.key(), is("4"));
93 assertThat(stats1.mapName(), is("5")); 93 assertThat(stats1.mapName(), is("5"));
94 - assertThat(stats1.type(), is(DatabaseUpdate.Type.PUT)); 94 + assertThat(stats1.type(), is(MapUpdate.Type.PUT));
95 } 95 }
96 96
97 /** 97 /**
......
...@@ -199,6 +199,7 @@ import org.onosproject.net.resource.link.MplsLabelResourceAllocation; ...@@ -199,6 +199,7 @@ import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
199 import org.onosproject.net.resource.link.MplsLabelResourceRequest; 199 import org.onosproject.net.resource.link.MplsLabelResourceRequest;
200 import org.onosproject.security.Permission; 200 import org.onosproject.security.Permission;
201 import org.onosproject.store.Timestamp; 201 import org.onosproject.store.Timestamp;
202 +import org.onosproject.store.primitives.TransactionId;
202 import org.onosproject.store.service.MapEvent; 203 import org.onosproject.store.service.MapEvent;
203 import org.onosproject.store.service.SetEvent; 204 import org.onosproject.store.service.SetEvent;
204 import org.onosproject.store.service.Versioned; 205 import org.onosproject.store.service.Versioned;
...@@ -483,6 +484,7 @@ public final class KryoNamespaces { ...@@ -483,6 +484,7 @@ public final class KryoNamespaces {
483 .register(new ExtensionCriterionSerializer(), ExtensionCriterion.class) 484 .register(new ExtensionCriterionSerializer(), ExtensionCriterion.class)
484 .register(ExtensionSelectorType.class) 485 .register(ExtensionSelectorType.class)
485 .register(ExtensionTreatmentType.class) 486 .register(ExtensionTreatmentType.class)
487 + .register(TransactionId.class)
486 .register(Versioned.class) 488 .register(Versioned.class)
487 .register(MapEvent.class) 489 .register(MapEvent.class)
488 .register(MapEvent.Type.class) 490 .register(MapEvent.Type.class)
......