Search in sources :

Example 1 with ConnectionEntry

use of org.opendaylight.controller.cluster.access.client.ConnectionEntry in project controller by opendaylight.

the class AbstractProxyTransactionTest method testReplayMessages.

@Test
public void testReplayMessages() throws Exception {
    final TestProbe probe = new TestProbe(system);
    final List<ConnectionEntry> entries = new ArrayList<>();
    final Consumer<Response<?, ?>> callback = createCallbackMock();
    final ReadTransactionRequest request1 = new ReadTransactionRequest(TRANSACTION_ID, 2L, probe.ref(), PATH_2, true);
    final ExistsTransactionRequest request2 = new ExistsTransactionRequest(TRANSACTION_ID, 3L, probe.ref(), PATH_3, true);
    entries.add(AccessClientUtil.createConnectionEntry(request1, callback, 0L));
    entries.add(AccessClientUtil.createConnectionEntry(request2, callback, 0L));
    final TransactionTester<RemoteProxyTransaction> successor = createRemoteProxyTransactionTester();
    final AbortLocalTransactionRequest successful1 = new AbortLocalTransactionRequest(TRANSACTION_ID, probe.ref());
    transaction.recordSuccessfulRequest(successful1);
    final ReadTransactionRequest successful2 = new ReadTransactionRequest(TRANSACTION_ID, 1L, probe.ref(), PATH_1, true);
    transaction.recordSuccessfulRequest(successful2);
    transaction.startReconnect();
    final ProxyHistory mockSuccessor = mock(ProxyHistory.class);
    when(mockSuccessor.createTransactionProxy(TRANSACTION_ID, transaction.isSnapshotOnly(), false)).thenReturn(successor.getTransaction());
    transaction.replayMessages(mockSuccessor, entries);
    final ModifyTransactionRequest transformed = successor.expectTransactionRequest(ModifyTransactionRequest.class);
    Assert.assertNotNull(transformed);
    Assert.assertEquals(successful1.getSequence(), transformed.getSequence());
    Assert.assertTrue(transformed.getPersistenceProtocol().isPresent());
    Assert.assertEquals(PersistenceProtocol.ABORT, transformed.getPersistenceProtocol().get());
    ReadTransactionRequest tmpRead = successor.expectTransactionRequest(ReadTransactionRequest.class);
    Assert.assertNotNull(tmpRead);
    Assert.assertEquals(successful2.getTarget(), tmpRead.getTarget());
    Assert.assertEquals(successful2.getSequence(), tmpRead.getSequence());
    Assert.assertEquals(successful2.getPath(), tmpRead.getPath());
    Assert.assertEquals(successor.localActor(), tmpRead.getReplyTo());
    tmpRead = successor.expectTransactionRequest(ReadTransactionRequest.class);
    Assert.assertNotNull(tmpRead);
    Assert.assertEquals(request1.getTarget(), tmpRead.getTarget());
    Assert.assertEquals(request1.getSequence(), tmpRead.getSequence());
    Assert.assertEquals(request1.getPath(), tmpRead.getPath());
    Assert.assertEquals(successor.localActor(), tmpRead.getReplyTo());
    final ExistsTransactionRequest tmpExist = successor.expectTransactionRequest(ExistsTransactionRequest.class);
    Assert.assertNotNull(tmpExist);
    Assert.assertEquals(request2.getTarget(), tmpExist.getTarget());
    Assert.assertEquals(request2.getSequence(), tmpExist.getSequence());
    Assert.assertEquals(request2.getPath(), tmpExist.getPath());
    Assert.assertEquals(successor.localActor(), tmpExist.getReplyTo());
}
Also used : ArrayList(java.util.ArrayList) ReadTransactionRequest(org.opendaylight.controller.cluster.access.commands.ReadTransactionRequest) Response(org.opendaylight.controller.cluster.access.concepts.Response) AbortLocalTransactionRequest(org.opendaylight.controller.cluster.access.commands.AbortLocalTransactionRequest) ConnectionEntry(org.opendaylight.controller.cluster.access.client.ConnectionEntry) ExistsTransactionRequest(org.opendaylight.controller.cluster.access.commands.ExistsTransactionRequest) TestProbe(akka.testkit.TestProbe) ModifyTransactionRequest(org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequest) Test(org.junit.Test)

Example 2 with ConnectionEntry

use of org.opendaylight.controller.cluster.access.client.ConnectionEntry in project controller by opendaylight.

the class AbstractProxyTransaction method replayMessages.

// Called with the connection locked
final void replayMessages(final ProxyHistory successorHistory, final Iterable<ConnectionEntry> enqueuedEntries) {
    final SuccessorState local = getSuccessorState();
    final State prevState = local.getPrevState();
    final AbstractProxyTransaction successor = successorHistory.createTransactionProxy(getIdentifier(), isSnapshotOnly(), local.isDone());
    LOG.debug("{} created successor {}", this, successor);
    local.setSuccessor(successor);
    // Replay successful requests first
    if (!successfulRequests.isEmpty()) {
        // We need to find a good timestamp to use for successful requests, as we do not want to time them out
        // nor create timing inconsistencies in the queue -- requests are expected to be ordered by their enqueue
        // time. We will pick the time of the first entry available. If there is none, we will just use current
        // time, as all other requests will get enqueued afterwards.
        final ConnectionEntry firstInQueue = Iterables.getFirst(enqueuedEntries, null);
        final long now = firstInQueue != null ? firstInQueue.getEnqueuedTicks() : parent.currentTime();
        for (Object obj : successfulRequests) {
            if (obj instanceof TransactionRequest) {
                LOG.debug("Forwarding successful request {} to successor {}", obj, successor);
                successor.doReplayRequest((TransactionRequest<?>) obj, resp -> {
                /*NOOP*/
                }, now);
            } else {
                Verify.verify(obj instanceof IncrementSequence);
                final IncrementSequence increment = (IncrementSequence) obj;
                successor.doReplayRequest(new IncrementTransactionSequenceRequest(getIdentifier(), increment.getSequence(), localActor(), isSnapshotOnly(), increment.getDelta()), resp -> {
                /*NOOP*/
                }, now);
                LOG.debug("Incrementing sequence {} to successor {}", obj, successor);
            }
        }
        LOG.debug("{} replayed {} successful requests", getIdentifier(), successfulRequests.size());
        successfulRequests.clear();
    }
    // Now replay whatever is in the connection
    final Iterator<ConnectionEntry> it = enqueuedEntries.iterator();
    while (it.hasNext()) {
        final ConnectionEntry e = it.next();
        final Request<?, ?> req = e.getRequest();
        if (getIdentifier().equals(req.getTarget())) {
            Verify.verify(req instanceof TransactionRequest, "Unhandled request %s", req);
            LOG.debug("Replaying queued request {} to successor {}", req, successor);
            successor.doReplayRequest((TransactionRequest<?>) req, e.getCallback(), e.getEnqueuedTicks());
            it.remove();
        }
    }
    /*
         * Check the state at which we have started the reconnect attempt. State transitions triggered while we were
         * reconnecting have been forced to slow paths, which will be unlocked once we unblock the state latch
         * at the end of this method.
         */
    if (SEALED.equals(prevState)) {
        LOG.debug("Proxy {} reconnected while being sealed, propagating state to successor {}", this, successor);
        final long enqueuedTicks = parent.currentTime();
        final java.util.Optional<ModifyTransactionRequest> optState = flushState();
        if (optState.isPresent()) {
            successor.handleReplayedRemoteRequest(optState.get(), null, enqueuedTicks);
        }
        if (successor.markSealed()) {
            successor.sealAndSend(Optional.of(enqueuedTicks));
        }
    }
}
Also used : TransactionRequest(org.opendaylight.controller.cluster.access.commands.TransactionRequest) AbstractLocalTransactionRequest(org.opendaylight.controller.cluster.access.commands.AbstractLocalTransactionRequest) ModifyTransactionRequest(org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequest) ConnectionEntry(org.opendaylight.controller.cluster.access.client.ConnectionEntry) IncrementTransactionSequenceRequest(org.opendaylight.controller.cluster.access.commands.IncrementTransactionSequenceRequest) ModifyTransactionRequest(org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequest)

Aggregations

ConnectionEntry (org.opendaylight.controller.cluster.access.client.ConnectionEntry)2 ModifyTransactionRequest (org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequest)2 TestProbe (akka.testkit.TestProbe)1 ArrayList (java.util.ArrayList)1 Test (org.junit.Test)1 AbortLocalTransactionRequest (org.opendaylight.controller.cluster.access.commands.AbortLocalTransactionRequest)1 AbstractLocalTransactionRequest (org.opendaylight.controller.cluster.access.commands.AbstractLocalTransactionRequest)1 ExistsTransactionRequest (org.opendaylight.controller.cluster.access.commands.ExistsTransactionRequest)1 IncrementTransactionSequenceRequest (org.opendaylight.controller.cluster.access.commands.IncrementTransactionSequenceRequest)1 ReadTransactionRequest (org.opendaylight.controller.cluster.access.commands.ReadTransactionRequest)1 TransactionRequest (org.opendaylight.controller.cluster.access.commands.TransactionRequest)1 Response (org.opendaylight.controller.cluster.access.concepts.Response)1