From d3d2323ad9ad332d71dc6b956e4a3d3daa525902 Mon Sep 17 00:00:00 2001 From: Moiz Raja Date: Tue, 17 Jun 2014 15:27:44 -0700 Subject: [PATCH] Initial implementation of ShardTransactionChain Change-Id: Ia7fea4502f5e35837d43c404dc14e3a17480051d Signed-off-by: Moiz Raja --- .../controller/cluster/datastore/Shard.java | 2 +- .../cluster/datastore/ShardTransaction.java | 49 ++++++++++++++++ .../datastore/ShardTransactionChain.java | 49 ++++++++++++++++ .../cluster/datastore/TransactionChain.java | 38 ------------- .../datastore/messages/CreateTransaction.java | 13 +++++ .../messages/CreateTransactionReply.java | 23 ++++++++ .../cluster/datastore/ShardTest.java | 6 +- .../datastore/ShardTransactionChainTest.java | 56 +++++++++++++++++++ .../impl/tree/data/InMemoryDataTree.java | 11 ++-- 9 files changed, 199 insertions(+), 48 deletions(-) create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java delete mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionChain.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java index dbb25b9bf4..f59e05ae99 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java @@ -61,7 +61,7 @@ public class Shard extends UntypedProcessor { private void createTransactionChain() { DOMStoreTransactionChain chain = store.createTransactionChain(); - ActorRef transactionChain = getContext().actorOf(TransactionChain.props(chain)); + ActorRef transactionChain = getContext().actorOf(ShardTransactionChain.props(chain)); getSender().tell(new CreateTransactionChainReply(transactionChain.path()), getSelf()); } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java new file mode 100644 index 0000000000..ef9b66a1bc --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.cluster.datastore; + +import akka.actor.Props; +import akka.actor.UntypedActor; +import akka.japi.Creator; +import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction; + +/** + * The ShardTransaction Actor represents a remote transaction + * + * The ShardTransaction Actor delegates all actions to DOMDataReadWriteTransaction + * + * Even though the DOMStore and the DOMStoreTransactionChain implement multiple types of transactions + * the ShardTransaction Actor only works with read-write transactions. This is just to keep the logic simple. At this + * time there are no known advantages for creating a read-only or write-only transaction which may change over time + * at which point we can optimize things in the distributed store as well. + */ +public class ShardTransaction extends UntypedActor { + + private final DOMStoreReadWriteTransaction transaction; + + public ShardTransaction(DOMStoreReadWriteTransaction transaction) { + this.transaction = transaction; + } + + + public static Props props(final DOMStoreReadWriteTransaction transaction){ + return Props.create(new Creator(){ + + @Override + public ShardTransaction create() throws Exception { + return new ShardTransaction(transaction); + } + }); + } + + @Override + public void onReceive(Object message) throws Exception { + throw new UnsupportedOperationException("onReceive"); + } +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java new file mode 100644 index 0000000000..a42b51338b --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.cluster.datastore; + +import akka.actor.ActorRef; +import akka.actor.Props; +import akka.actor.UntypedActor; +import akka.japi.Creator; +import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction; +import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply; +import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction; +import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain; + +/** + * The ShardTransactionChain Actor represents a remote TransactionChain + */ +public class ShardTransactionChain extends UntypedActor{ + + private final DOMStoreTransactionChain chain; + + public ShardTransactionChain(DOMStoreTransactionChain chain) { + this.chain = chain; + } + + @Override + public void onReceive(Object message) throws Exception { + if(message instanceof CreateTransaction){ + DOMStoreReadWriteTransaction transaction = chain.newReadWriteTransaction(); + ActorRef transactionActor = getContext().actorOf(ShardTransaction.props(transaction)); + getSender().tell(new CreateTransactionReply(transactionActor.path()), getSelf()); + } + } + + public static Props props(final DOMStoreTransactionChain chain){ + return Props.create(new Creator(){ + + @Override + public ShardTransactionChain create() throws Exception { + return new ShardTransactionChain(chain); + } + }); + } +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionChain.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionChain.java deleted file mode 100644 index 1cce09fb33..0000000000 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionChain.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.controller.cluster.datastore; - -import akka.actor.Props; -import akka.actor.UntypedActor; -import akka.japi.Creator; -import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain; - -public class TransactionChain extends UntypedActor{ - - private final DOMStoreTransactionChain chain; - - public TransactionChain(DOMStoreTransactionChain chain) { - this.chain = chain; - } - - @Override - public void onReceive(Object message) throws Exception { - throw new UnsupportedOperationException("onReceive"); - } - - public static Props props(final DOMStoreTransactionChain chain){ - return Props.create(new Creator(){ - - @Override - public TransactionChain create() throws Exception { - return new TransactionChain(chain); - } - }); - } -} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java new file mode 100644 index 0000000000..e0cdd3cc2b --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.cluster.datastore.messages; + +public class CreateTransaction { + +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java new file mode 100644 index 0000000000..4faf9d370d --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.cluster.datastore.messages; + +import akka.actor.ActorPath; + +public class CreateTransactionReply { + private final ActorPath transactionPath; + + public CreateTransactionReply(ActorPath transactionPath) { + this.transactionPath = transactionPath; + } + + public ActorPath getTransactionPath() { + return transactionPath; + } +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java index 775b881b60..b5a341d95c 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java @@ -20,10 +20,10 @@ import static org.junit.Assert.assertTrue; public class ShardTest extends AbstractActorTest{ @Test - public void testOnReceiveCreateTransaction() throws Exception { + public void testOnReceiveCreateTransactionChain() throws Exception { new JavaTestKit(getSystem()) {{ final Props props = Props.create(Shard.class); - final ActorRef subject = getSystem().actorOf(props, "testCreateTransaction"); + final ActorRef subject = getSystem().actorOf(props, "testCreateTransactionChain"); new Within(duration("1 seconds")) { protected void run() { @@ -42,7 +42,7 @@ public class ShardTest extends AbstractActorTest{ } }.get(); // this extracts the received message - assertTrue(out.matches("akka:\\/\\/test\\/user\\/testCreateTransaction\\/\\$.*")); + assertTrue(out.matches("akka:\\/\\/test\\/user\\/testCreateTransactionChain\\/\\$.*")); // Will wait for the rest of the 3 seconds expectNoMsg(); } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java new file mode 100644 index 0000000000..d8cb53d083 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java @@ -0,0 +1,56 @@ +package org.opendaylight.controller.cluster.datastore; + +import akka.actor.ActorRef; +import akka.actor.Props; +import akka.testkit.JavaTestKit; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import org.junit.Test; +import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction; +import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply; +import org.opendaylight.controller.md.cluster.datastore.model.TestModel; +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore; + +import static org.junit.Assert.assertTrue; + +public class ShardTransactionChainTest extends AbstractActorTest { + + private static ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor()); + + private static final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor); + + static { + store.onGlobalContextUpdated(TestModel.createTestContext()); + } + @Test + public void testOnReceiveCreateTransaction() throws Exception { + new JavaTestKit(getSystem()) {{ + final Props props = ShardTransactionChain.props(store.createTransactionChain()); + final ActorRef subject = getSystem().actorOf(props, "testCreateTransaction"); + + new Within(duration("1 seconds")) { + protected void run() { + + subject.tell(new CreateTransaction(), getRef()); + + final String out = new ExpectMsg("match hint") { + // do not put code outside this method, will run afterwards + protected String match(Object in) { + if (in instanceof CreateTransactionReply) { + return ((CreateTransactionReply) in).getTransactionPath().toString(); + } else { + throw noMatch(); + } + } + }.get(); // this extracts the received message + + assertTrue(out.matches("akka:\\/\\/test\\/user\\/testCreateTransaction\\/\\$.*")); + // Will wait for the rest of the 3 seconds + expectNoMsg(); + } + + + }; + }}; + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java index 4ffa6f91b0..803105f264 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java @@ -7,13 +7,12 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException; import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils; import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; @@ -22,8 +21,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Read-only snapshot of the data tree. -- 2.36.6