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());
}
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));
}
}
}
Aggregations