Search in sources :

Example 1 with Creator

use of akka.japi.Creator in project controller by opendaylight.

the class ShardTest method testOnBatchedModificationsWhenNotLeader.

@Test
public void testOnBatchedModificationsWhenNotLeader() {
    final AtomicBoolean overrideLeaderCalls = new AtomicBoolean();
    new ShardTestKit(getSystem()) {

        {
            final Creator<Shard> creator = new Creator<Shard>() {

                private static final long serialVersionUID = 1L;

                @Override
                public Shard create() throws Exception {
                    return new Shard(newShardBuilder()) {

                        @Override
                        protected boolean isLeader() {
                            return overrideLeaderCalls.get() ? false : super.isLeader();
                        }

                        @Override
                        public ActorSelection getLeader() {
                            return overrideLeaderCalls.get() ? getSystem().actorSelection(getRef().path()) : super.getLeader();
                        }
                    };
                }
            };
            final TestActorRef<Shard> shard = actorFactory.createTestActor(Props.create(new DelegatingShardCreator(creator)).withDispatcher(Dispatchers.DefaultDispatcherId()), "testOnBatchedModificationsWhenNotLeader");
            waitUntilLeader(shard);
            overrideLeaderCalls.set(true);
            final BatchedModifications batched = new BatchedModifications(nextTransactionId(), DataStoreVersions.CURRENT_VERSION);
            shard.tell(batched, ActorRef.noSender());
            expectMsgEquals(batched);
        }
    };
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Creator(akka.japi.Creator) BatchedModifications(org.opendaylight.controller.cluster.datastore.messages.BatchedModifications) Test(org.junit.Test)

Example 2 with Creator

use of akka.japi.Creator in project controller by opendaylight.

the class ShardManagerTest method testPerShardDatastoreContext.

@Test
public void testPerShardDatastoreContext() throws Exception {
    LOG.info("testPerShardDatastoreContext starting");
    final DatastoreContextFactory mockFactory = newDatastoreContextFactory(datastoreContextBuilder.shardElectionTimeoutFactor(5).build());
    Mockito.doReturn(DatastoreContext.newBuilderFrom(datastoreContextBuilder.build()).shardElectionTimeoutFactor(6).build()).when(mockFactory).getShardDatastoreContext("default");
    Mockito.doReturn(DatastoreContext.newBuilderFrom(datastoreContextBuilder.build()).shardElectionTimeoutFactor(7).build()).when(mockFactory).getShardDatastoreContext("topology");
    final MockConfiguration mockConfig = new MockConfiguration() {

        @Override
        public Collection<String> getMemberShardNames(final MemberName memberName) {
            return Arrays.asList("default", "topology");
        }

        @Override
        public Collection<MemberName> getMembersFromShardName(final String shardName) {
            return members("member-1");
        }
    };
    final ActorRef defaultShardActor = actorFactory.createActor(MessageCollectorActor.props(), actorFactory.generateActorId("default"));
    final ActorRef topologyShardActor = actorFactory.createActor(MessageCollectorActor.props(), actorFactory.generateActorId("topology"));
    final Map<String, Entry<ActorRef, DatastoreContext>> shardInfoMap = Collections.synchronizedMap(new HashMap<String, Entry<ActorRef, DatastoreContext>>());
    shardInfoMap.put("default", new AbstractMap.SimpleEntry<>(defaultShardActor, null));
    shardInfoMap.put("topology", new AbstractMap.SimpleEntry<>(topologyShardActor, null));
    final PrimaryShardInfoFutureCache primaryShardInfoCache = new PrimaryShardInfoFutureCache();
    final CountDownLatch newShardActorLatch = new CountDownLatch(2);
    class LocalShardManager extends ShardManager {

        LocalShardManager(final AbstractShardManagerCreator<?> creator) {
            super(creator);
        }

        @Override
        protected ActorRef newShardActor(final ShardInformation info) {
            Entry<ActorRef, DatastoreContext> entry = shardInfoMap.get(info.getShardName());
            ActorRef ref = null;
            if (entry != null) {
                ref = entry.getKey();
                entry.setValue(info.getDatastoreContext());
            }
            newShardActorLatch.countDown();
            return ref;
        }
    }
    final Creator<ShardManager> creator = new Creator<ShardManager>() {

        private static final long serialVersionUID = 1L;

        @Override
        public ShardManager create() throws Exception {
            return new LocalShardManager(new GenericCreator<>(LocalShardManager.class).datastoreContextFactory(mockFactory).primaryShardInfoCache(primaryShardInfoCache).configuration(mockConfig));
        }
    };
    TestKit kit = new TestKit(getSystem());
    final ActorRef shardManager = actorFactory.createActor(Props.create(new DelegatingShardManagerCreator(creator)).withDispatcher(Dispatchers.DefaultDispatcherId()));
    shardManager.tell(new UpdateSchemaContext(TestModel.createTestContext()), kit.getRef());
    assertEquals("Shard actors created", true, newShardActorLatch.await(5, TimeUnit.SECONDS));
    assertEquals("getShardElectionTimeoutFactor", 6, shardInfoMap.get("default").getValue().getShardElectionTimeoutFactor());
    assertEquals("getShardElectionTimeoutFactor", 7, shardInfoMap.get("topology").getValue().getShardElectionTimeoutFactor());
    DatastoreContextFactory newMockFactory = newDatastoreContextFactory(datastoreContextBuilder.shardElectionTimeoutFactor(5).build());
    Mockito.doReturn(DatastoreContext.newBuilderFrom(datastoreContextBuilder.build()).shardElectionTimeoutFactor(66).build()).when(newMockFactory).getShardDatastoreContext("default");
    Mockito.doReturn(DatastoreContext.newBuilderFrom(datastoreContextBuilder.build()).shardElectionTimeoutFactor(77).build()).when(newMockFactory).getShardDatastoreContext("topology");
    shardManager.tell(newMockFactory, kit.getRef());
    DatastoreContext newContext = MessageCollectorActor.expectFirstMatching(defaultShardActor, DatastoreContext.class);
    assertEquals("getShardElectionTimeoutFactor", 66, newContext.getShardElectionTimeoutFactor());
    newContext = MessageCollectorActor.expectFirstMatching(topologyShardActor, DatastoreContext.class);
    assertEquals("getShardElectionTimeoutFactor", 77, newContext.getShardElectionTimeoutFactor());
    LOG.info("testPerShardDatastoreContext ending");
}
Also used : UpdateSchemaContext(org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext) DatastoreContextFactory(org.opendaylight.controller.cluster.datastore.DatastoreContextFactory) ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) AddressFromURIString(akka.actor.AddressFromURIString) Creator(akka.japi.Creator) TestKit(akka.testkit.javadsl.TestKit) CountDownLatch(java.util.concurrent.CountDownLatch) AbstractMap(java.util.AbstractMap) Entry(java.util.Map.Entry) DatastoreContext(org.opendaylight.controller.cluster.datastore.DatastoreContext) PrimaryShardInfoFutureCache(org.opendaylight.controller.cluster.datastore.utils.PrimaryShardInfoFutureCache) MockConfiguration(org.opendaylight.controller.cluster.datastore.utils.MockConfiguration) MemberName(org.opendaylight.controller.cluster.access.concepts.MemberName) Test(org.junit.Test) AbstractShardManagerTest(org.opendaylight.controller.cluster.datastore.AbstractShardManagerTest)

Example 3 with Creator

use of akka.japi.Creator in project controller by opendaylight.

the class ShardTest method testChangeListenerNotifiedWhenNotTheLeaderOnRegistration.

@SuppressWarnings("serial")
@Test
public void testChangeListenerNotifiedWhenNotTheLeaderOnRegistration() throws Exception {
    // This test tests the timing window in which a change listener is registered before the
    // shard becomes the leader. We verify that the listener is registered and notified of the
    // existing data when the shard becomes the leader.
    // For this test, we want to send the RegisterChangeListener message after the shard
    // has recovered from persistence and before it becomes the leader. So we subclass
    // Shard to override onReceiveCommand and, when the first ElectionTimeout is received,
    // we know that the shard has been initialized to a follower and has started the
    // election process. The following 2 CountDownLatches are used to coordinate the
    // ElectionTimeout with the sending of the RegisterChangeListener message.
    final CountDownLatch onFirstElectionTimeout = new CountDownLatch(1);
    final CountDownLatch onChangeListenerRegistered = new CountDownLatch(1);
    final Creator<Shard> creator = new Creator<Shard>() {

        boolean firstElectionTimeout = true;

        @Override
        public Shard create() throws Exception {
            // it does do a persist)
            return new Shard(newShardBuilder()) {

                @Override
                public void handleCommand(final Object message) {
                    if (message instanceof ElectionTimeout && firstElectionTimeout) {
                        // Got the first ElectionTimeout. We don't forward it to the
                        // base Shard yet until we've sent the RegisterChangeListener
                        // message. So we signal the onFirstElectionTimeout latch to tell
                        // the main thread to send the RegisterChangeListener message and
                        // start a thread to wait on the onChangeListenerRegistered latch,
                        // which the main thread signals after it has sent the message.
                        // After the onChangeListenerRegistered is triggered, we send the
                        // original ElectionTimeout message to proceed with the election.
                        firstElectionTimeout = false;
                        final ActorRef self = getSelf();
                        new Thread(() -> {
                            Uninterruptibles.awaitUninterruptibly(onChangeListenerRegistered, 5, TimeUnit.SECONDS);
                            self.tell(message, self);
                        }).start();
                        onFirstElectionTimeout.countDown();
                    } else {
                        super.handleCommand(message);
                    }
                }
            };
        }
    };
    setupInMemorySnapshotStore();
    final YangInstanceIdentifier path = TestModel.TEST_PATH;
    final MockDataChangeListener listener = new MockDataChangeListener(1);
    final ActorRef dclActor = actorFactory.createActor(DataChangeListener.props(listener, path), "testRegisterChangeListenerWhenNotLeaderInitially-DataChangeListener");
    final TestActorRef<Shard> shard = actorFactory.createTestActor(Props.create(new DelegatingShardCreator(creator)).withDispatcher(Dispatchers.DefaultDispatcherId()), "testRegisterChangeListenerWhenNotLeaderInitially");
    new ShardTestKit(getSystem()) {

        {
            // Wait until the shard receives the first ElectionTimeout
            // message.
            assertEquals("Got first ElectionTimeout", true, onFirstElectionTimeout.await(5, TimeUnit.SECONDS));
            // Now send the RegisterChangeListener and wait for the reply.
            shard.tell(new RegisterChangeListener(path, dclActor, AsyncDataBroker.DataChangeScope.SUBTREE, false), getRef());
            final RegisterDataTreeNotificationListenerReply reply = expectMsgClass(duration("5 seconds"), RegisterDataTreeNotificationListenerReply.class);
            assertNotNull("getListenerRegistrationPath", reply.getListenerRegistrationPath());
            // Sanity check - verify the shard is not the leader yet.
            shard.tell(FindLeader.INSTANCE, getRef());
            final FindLeaderReply findLeadeReply = expectMsgClass(duration("5 seconds"), FindLeaderReply.class);
            assertFalse("Expected the shard not to be the leader", findLeadeReply.getLeaderActor().isPresent());
            // Signal the onChangeListenerRegistered latch to tell the
            // thread above to proceed
            // with the election process.
            onChangeListenerRegistered.countDown();
            // Wait for the shard to become the leader and notify our
            // listener with the existing
            // data in the store.
            listener.waitForChangeEvents(path);
        }
    };
}
Also used : RegisterDataTreeNotificationListenerReply(org.opendaylight.controller.cluster.datastore.messages.RegisterDataTreeNotificationListenerReply) ElectionTimeout(org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout) ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) RegisterChangeListener(org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener) Creator(akka.japi.Creator) CountDownLatch(java.util.concurrent.CountDownLatch) YangInstanceIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier) FindLeaderReply(org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply) MockDataChangeListener(org.opendaylight.controller.cluster.datastore.utils.MockDataChangeListener) Test(org.junit.Test)

Example 4 with Creator

use of akka.japi.Creator in project controller by opendaylight.

the class ShardTest method testDataTreeChangeListenerNotifiedWhenNotTheLeaderOnRegistration.

@SuppressWarnings("serial")
@Test
public void testDataTreeChangeListenerNotifiedWhenNotTheLeaderOnRegistration() throws Exception {
    final CountDownLatch onFirstElectionTimeout = new CountDownLatch(1);
    final CountDownLatch onChangeListenerRegistered = new CountDownLatch(1);
    final Creator<Shard> creator = new Creator<Shard>() {

        boolean firstElectionTimeout = true;

        @Override
        public Shard create() throws Exception {
            return new Shard(newShardBuilder()) {

                @Override
                public void handleCommand(final Object message) {
                    if (message instanceof ElectionTimeout && firstElectionTimeout) {
                        firstElectionTimeout = false;
                        final ActorRef self = getSelf();
                        new Thread(() -> {
                            Uninterruptibles.awaitUninterruptibly(onChangeListenerRegistered, 5, TimeUnit.SECONDS);
                            self.tell(message, self);
                        }).start();
                        onFirstElectionTimeout.countDown();
                    } else {
                        super.handleCommand(message);
                    }
                }
            };
        }
    };
    setupInMemorySnapshotStore();
    final YangInstanceIdentifier path = TestModel.TEST_PATH;
    final MockDataTreeChangeListener listener = new MockDataTreeChangeListener(1);
    final ActorRef dclActor = actorFactory.createActor(DataTreeChangeListenerActor.props(listener, path), "testDataTreeChangeListenerNotifiedWhenNotTheLeaderOnRegistration-DataChangeListener");
    final TestActorRef<Shard> shard = actorFactory.createTestActor(Props.create(new DelegatingShardCreator(creator)).withDispatcher(Dispatchers.DefaultDispatcherId()), "testDataTreeChangeListenerNotifiedWhenNotTheLeaderOnRegistration");
    new ShardTestKit(getSystem()) {

        {
            assertEquals("Got first ElectionTimeout", true, onFirstElectionTimeout.await(5, TimeUnit.SECONDS));
            shard.tell(new RegisterDataTreeChangeListener(path, dclActor, false), getRef());
            final RegisterDataTreeNotificationListenerReply reply = expectMsgClass(duration("5 seconds"), RegisterDataTreeNotificationListenerReply.class);
            assertNotNull("getListenerRegistratioznPath", reply.getListenerRegistrationPath());
            shard.tell(FindLeader.INSTANCE, getRef());
            final FindLeaderReply findLeadeReply = expectMsgClass(duration("5 seconds"), FindLeaderReply.class);
            assertFalse("Expected the shard not to be the leader", findLeadeReply.getLeaderActor().isPresent());
            onChangeListenerRegistered.countDown();
            // TODO: investigate why we do not receive data chage events
            listener.waitForChangeEvents();
        }
    };
}
Also used : RegisterDataTreeNotificationListenerReply(org.opendaylight.controller.cluster.datastore.messages.RegisterDataTreeNotificationListenerReply) ElectionTimeout(org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout) ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) Creator(akka.japi.Creator) CountDownLatch(java.util.concurrent.CountDownLatch) YangInstanceIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier) RegisterDataTreeChangeListener(org.opendaylight.controller.cluster.datastore.messages.RegisterDataTreeChangeListener) FindLeaderReply(org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply) MockDataTreeChangeListener(org.opendaylight.controller.cluster.datastore.utils.MockDataTreeChangeListener) Test(org.junit.Test)

Aggregations

Creator (akka.japi.Creator)4 Test (org.junit.Test)4 ActorRef (akka.actor.ActorRef)3 TestActorRef (akka.testkit.TestActorRef)3 CountDownLatch (java.util.concurrent.CountDownLatch)3 RegisterDataTreeNotificationListenerReply (org.opendaylight.controller.cluster.datastore.messages.RegisterDataTreeNotificationListenerReply)2 ElectionTimeout (org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout)2 FindLeaderReply (org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply)2 YangInstanceIdentifier (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)2 AddressFromURIString (akka.actor.AddressFromURIString)1 TestKit (akka.testkit.javadsl.TestKit)1 AbstractMap (java.util.AbstractMap)1 Entry (java.util.Map.Entry)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 MemberName (org.opendaylight.controller.cluster.access.concepts.MemberName)1 AbstractShardManagerTest (org.opendaylight.controller.cluster.datastore.AbstractShardManagerTest)1 DatastoreContext (org.opendaylight.controller.cluster.datastore.DatastoreContext)1 DatastoreContextFactory (org.opendaylight.controller.cluster.datastore.DatastoreContextFactory)1 BatchedModifications (org.opendaylight.controller.cluster.datastore.messages.BatchedModifications)1 RegisterChangeListener (org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener)1