use of com.github.ambry.utils.MockTime in project ambry by linkedin.
the class MockSelector method poll.
/**
* Mocks sending and polling. Creates a response for every send to be returned after the next poll,
* with the correlation id in the Send, unless beBad state is on. If beBad is on,
* all sends will result in disconnections.
* @param timeoutMs Ignored.
* @param sends The list of new sends.
*/
@Override
public void poll(long timeoutMs, List<NetworkSend> sends) throws IOException {
if (state == MockSelectorState.ThrowExceptionOnPoll) {
throw new IOException("Mock exception on poll");
}
disconnected = new ArrayList<>();
if (state == MockSelectorState.FailConnectionInitiationOnPoll) {
disconnected.addAll(nextConnected);
connected = new ArrayList<>();
nextConnected = new ArrayList<>();
} else if (state != MockSelectorState.IdlePoll) {
connected = nextConnected;
nextConnected = new ArrayList<>();
}
disconnected.addAll(delayedFailPassedList);
delayedFailPassedList.clear();
delayedFailPassedList.addAll(delayedFailFreshList);
delayedFailFreshList.clear();
disconnected.addAll(closedConnections);
this.sends = sends;
if (sends != null) {
for (NetworkSend send : sends) {
MockSend mockSend = (MockSend) send.getPayload();
if (state == MockSelectorState.DisconnectOnSend) {
disconnected.add(send.getConnectionId());
} else if (!closedConnections.contains(send.getConnectionId())) {
receives.add(new NetworkReceive(send.getConnectionId(), new MockBoundedNettyByteBufReceive(mockSend.getCorrelationId()), new MockTime()));
mockSend.writeTo(new ByteBufferChannel(ByteBuffer.allocate(MockSend.SEND_SIZE)));
if (mockSend.isSendComplete()) {
mockSend.release();
}
}
}
}
closedConnections.clear();
}
use of com.github.ambry.utils.MockTime in project ambry by linkedin.
the class ConnectionTrackerTest method initialize.
@Before
public void initialize() {
Properties props = new Properties();
props.setProperty("router.hostname", "localhost");
props.setProperty("router.datacenter.name", "DC1");
props.setProperty("router.scaling.unit.max.connections.per.port.plain.text", "3");
props.setProperty("router.scaling.unit.max.connections.per.port.ssl", "2");
verifiableProperties = new VerifiableProperties((props));
routerConfig = new RouterConfig(verifiableProperties);
networkConfig = new NetworkConfig(verifiableProperties);
time = new MockTime();
plainTextPort = new Port(100, PortType.PLAINTEXT);
sslPort = new Port(200, PortType.SSL);
}
use of com.github.ambry.utils.MockTime in project ambry by linkedin.
the class CloudToStoreReplicationManagerTest method cloudReplicaRemovalTest.
/**
* Test both success and failure cases when removing cloud replica.
* @throws Exception
*/
@Test
public void cloudReplicaRemovalTest() throws Exception {
StorageManager storageManager = new StorageManager(storeConfig, new DiskManagerConfig(verifiableProperties), Utils.newScheduler(1, true), clusterMap.getMetricRegistry(), null, clusterMap, currentNode, null, Collections.singletonList(mockHelixParticipant), new MockTime(), null, new InMemAccountService(false, false));
CloudToStoreReplicationManager cloudToStoreReplicationManager = new CloudToStoreReplicationManager(replicationConfig, clusterMapConfig, storeConfig, storageManager, storeKeyFactory, clusterMap, mockScheduler, currentNode, null, clusterMap.getMetricRegistry(), null, storeKeyConverterFactory, serverConfig.serverMessageTransformer, mockClusterSpectator, mockHelixParticipant);
storageManager.start();
cloudToStoreReplicationManager.start();
mockClusterSpectator.spectate();
PartitionId localPartition = storageManager.getLocalPartitions().iterator().next();
// 1. add cloud replica first for subsequent removal test
mockHelixParticipant.onPartitionBecomeLeaderFromStandby(localPartition.toPathString());
String replicaPath = Cloud_Replica_Keyword + File.separator + localPartition.toPathString() + File.separator + localPartition.toPathString();
RemoteReplicaInfo remoteReplicaInfo = cloudToStoreReplicationManager.getRemoteReplicaInfo(localPartition, vcrNode.getHostname(), replicaPath);
assertNotNull("Remote replica info should not be null", remoteReplicaInfo);
assertEquals("There should be only one cloud replica thread created", 1, TestUtils.getAllThreadsByThisName(REPLICA_THREAD_PREFIX).size());
// 2. before removing cloud replica of local partition let's remove a non-existent partition first
mockHelixParticipant.onPartitionBecomeStandbyFromLeader(NEW_PARTITION_NAME);
// ensure there is no change in replica thread
assertEquals("There should be only one cloud replica thread created", 1, TestUtils.getAllThreadsByThisName(REPLICA_THREAD_PREFIX).size());
// 3. remove the cloud replica by calling Leader-To-Standby transition on local partition
mockHelixParticipant.onPartitionBecomeStandbyFromLeader(localPartition.toPathString());
// ensure that the remote replica info has been successfully removed from replica thread
assertNull("Cloud replica should be removed and no thread is assigned to it", remoteReplicaInfo.getReplicaThread());
cloudToStoreReplicationManager.shutdown();
storageManager.shutdown();
}
use of com.github.ambry.utils.MockTime in project ambry by linkedin.
the class ReplicationTest method replicaTokenTest.
/**
* Tests that replica tokens are set correctly and go through different stages correctly.
* @throws InterruptedException
*/
@Test
public void replicaTokenTest() throws InterruptedException {
final long tokenPersistInterval = 100;
Time time = new MockTime();
MockFindToken token1 = new MockFindToken(0, 0);
RemoteReplicaInfo remoteReplicaInfo = new RemoteReplicaInfo(new MockReplicaId(ReplicaType.DISK_BACKED), new MockReplicaId(ReplicaType.DISK_BACKED), new InMemoryStore(null, Collections.emptyList(), Collections.emptyList(), null), token1, tokenPersistInterval, time, new Port(5000, PortType.PLAINTEXT));
// The equality check is for the reference, which is fine.
// Initially, the current token and the token to persist are the same.
assertEquals(token1, remoteReplicaInfo.getToken());
assertEquals(token1, remoteReplicaInfo.getTokenToPersist());
MockFindToken token2 = new MockFindToken(100, 100);
remoteReplicaInfo.initializeTokens(token2);
// Both tokens should be the newly initialized token.
assertEquals(token2, remoteReplicaInfo.getToken());
assertEquals(token2, remoteReplicaInfo.getTokenToPersist());
remoteReplicaInfo.onTokenPersisted();
MockFindToken token3 = new MockFindToken(200, 200);
remoteReplicaInfo.setToken(token3);
// Token to persist should still be the old token.
assertEquals(token3, remoteReplicaInfo.getToken());
assertEquals(token2, remoteReplicaInfo.getTokenToPersist());
remoteReplicaInfo.onTokenPersisted();
// Sleep for shorter than token persist interval.
time.sleep(tokenPersistInterval - 1);
// Token to persist should still be the old token.
assertEquals(token3, remoteReplicaInfo.getToken());
assertEquals(token2, remoteReplicaInfo.getTokenToPersist());
remoteReplicaInfo.onTokenPersisted();
MockFindToken token4 = new MockFindToken(200, 200);
remoteReplicaInfo.setToken(token4);
time.sleep(2);
// Token to persist should be the most recent token as of currentTime - tokenToPersistInterval
// which is token3 at this time.
assertEquals(token4, remoteReplicaInfo.getToken());
assertEquals(token3, remoteReplicaInfo.getTokenToPersist());
remoteReplicaInfo.onTokenPersisted();
time.sleep(tokenPersistInterval + 1);
// The most recently set token as of currentTime - tokenToPersistInterval is token4
assertEquals(token4, remoteReplicaInfo.getToken());
assertEquals(token4, remoteReplicaInfo.getTokenToPersist());
remoteReplicaInfo.onTokenPersisted();
}
use of com.github.ambry.utils.MockTime in project ambry by linkedin.
the class ReplicationTest method onReplicaAddedOrRemovedCallbackTest.
/**
* Test cluster map change callback in {@link ReplicationManager} when any remote replicas are added or removed.
* Test setup: attempt to add 3 replicas and remove 3 replicas respectively. The three replicas are picked as follows:
* (1) 1st replica on current node (should skip)
* (2) 2nd replica on remote node sharing partition with current one (should be added or removed)
* (3) 3rd replica on remote node but doesn't share partition with current one (should skip)
* @throws Exception
*/
@Test
public void onReplicaAddedOrRemovedCallbackTest() throws Exception {
MockClusterMap clusterMap = new MockClusterMap();
ClusterMapConfig clusterMapConfig = new ClusterMapConfig(verifiableProperties);
StoreConfig storeConfig = new StoreConfig(verifiableProperties);
// pick a node with no special partition as current node
Set<DataNodeId> specialPartitionNodes = clusterMap.getSpecialPartition().getReplicaIds().stream().map(ReplicaId::getDataNodeId).collect(Collectors.toSet());
DataNodeId currentNode = clusterMap.getDataNodes().stream().filter(d -> !specialPartitionNodes.contains(d)).findFirst().get();
MockStoreKeyConverterFactory storeKeyConverterFactory = new MockStoreKeyConverterFactory(null, null);
storeKeyConverterFactory.setConversionMap(new HashMap<>());
StorageManager storageManager = new StorageManager(storeConfig, new DiskManagerConfig(verifiableProperties), Utils.newScheduler(1, true), new MetricRegistry(), null, clusterMap, currentNode, null, null, new MockTime(), null, new InMemAccountService(false, false));
storageManager.start();
MockReplicationManager replicationManager = new MockReplicationManager(replicationConfig, clusterMapConfig, storeConfig, storageManager, clusterMap, currentNode, storeKeyConverterFactory, null);
ClusterMapChangeListener clusterMapChangeListener = clusterMap.getClusterMapChangeListener();
// find the special partition (not on current node) and get an irrelevant replica from it
PartitionId absentPartition = clusterMap.getSpecialPartition();
ReplicaId irrelevantReplica = absentPartition.getReplicaIds().get(0);
// find an existing replica on current node and one of its peer replicas on remote node
ReplicaId existingReplica = clusterMap.getReplicaIds(currentNode).get(0);
ReplicaId peerReplicaToRemove = existingReplica.getPartitionId().getReplicaIds().stream().filter(r -> r != existingReplica).findFirst().get();
// create a new node and place a peer of existing replica on it.
MockDataNodeId remoteNode = createDataNode(getListOfPorts(PLAIN_TEXT_PORT_START_NUMBER + 10, SSL_PORT_START_NUMBER + 10, HTTP2_PORT_START_NUMBER + 10), clusterMap.getDatacenterName((byte) 0), 3);
ReplicaId addedReplica = new MockReplicaId(remoteNode.getPort(), (MockPartitionId) existingReplica.getPartitionId(), remoteNode, 0);
// populate added replica and removed replica lists
List<ReplicaId> replicasToAdd = new ArrayList<>(Arrays.asList(existingReplica, addedReplica, irrelevantReplica));
List<ReplicaId> replicasToRemove = new ArrayList<>(Arrays.asList(existingReplica, peerReplicaToRemove, irrelevantReplica));
PartitionInfo partitionInfo = replicationManager.getPartitionToPartitionInfoMap().get(existingReplica.getPartitionId());
assertNotNull("PartitionInfo is not found", partitionInfo);
RemoteReplicaInfo peerReplicaInfo = partitionInfo.getRemoteReplicaInfos().stream().filter(info -> info.getReplicaId() == peerReplicaToRemove).findFirst().get();
// get the replica-thread for this peer replica
ReplicaThread peerReplicaThread = peerReplicaInfo.getReplicaThread();
// Test Case 1: replication manager encountered exception during startup (remote replica addition/removal will be skipped)
replicationManager.startWithException();
clusterMapChangeListener.onReplicaAddedOrRemoved(replicasToAdd, replicasToRemove);
// verify that PartitionInfo stays unchanged
verifyRemoteReplicaInfo(partitionInfo, addedReplica, false);
verifyRemoteReplicaInfo(partitionInfo, peerReplicaToRemove, true);
// Test Case 2: startup latch is interrupted
CountDownLatch initialLatch = replicationManager.startupLatch;
CountDownLatch mockLatch = Mockito.mock(CountDownLatch.class);
doThrow(new InterruptedException()).when(mockLatch).await();
replicationManager.startupLatch = mockLatch;
try {
clusterMapChangeListener.onReplicaAddedOrRemoved(replicasToAdd, replicasToRemove);
fail("should fail because startup latch is interrupted");
} catch (IllegalStateException e) {
// expected
}
replicationManager.startupLatch = initialLatch;
// Test Case 3: replication manager is successfully started
replicationManager.start();
clusterMapChangeListener.onReplicaAddedOrRemoved(replicasToAdd, replicasToRemove);
// verify that PartitionInfo has latest remote replica infos
verifyRemoteReplicaInfo(partitionInfo, addedReplica, true);
verifyRemoteReplicaInfo(partitionInfo, peerReplicaToRemove, false);
verifyRemoteReplicaInfo(partitionInfo, irrelevantReplica, false);
// verify new added replica is assigned to a certain thread
ReplicaThread replicaThread = replicationManager.getDataNodeIdToReplicaThreadMap().get(addedReplica.getDataNodeId());
assertNotNull("There is no ReplicaThread assocated with new replica", replicaThread);
Optional<RemoteReplicaInfo> findResult = replicaThread.getRemoteReplicaInfos().get(remoteNode).stream().filter(info -> info.getReplicaId() == addedReplica).findAny();
assertTrue("New added remote replica info should exist in corresponding thread", findResult.isPresent());
// verify the removed replica info's thread is null
assertNull("Thread in removed replica info should be null", peerReplicaInfo.getReplicaThread());
findResult = peerReplicaThread.getRemoteReplicaInfos().get(peerReplicaToRemove.getDataNodeId()).stream().filter(info -> info.getReplicaId() == peerReplicaToRemove).findAny();
assertFalse("Previous replica thread should not contain RemoteReplicaInfo that is already removed", findResult.isPresent());
storageManager.shutdown();
}
Aggregations