use of com.github.ambry.clustermap.PartitionStateChangeListener in project ambry by linkedin.
the class StorageManagerTest method replicaFromStandbyToInactiveTest.
/**
* test both success and failure cases during STANDBY -> INACTIVE transition
*/
@Test
public void replicaFromStandbyToInactiveTest() throws Exception {
generateConfigs(true, false);
MockDataNodeId localNode = clusterMap.getDataNodes().get(0);
List<ReplicaId> localReplicas = clusterMap.getReplicaIds(localNode);
MockClusterParticipant mockHelixParticipant = new MockClusterParticipant();
StorageManager storageManager = createStorageManager(localNode, metricRegistry, Collections.singletonList(mockHelixParticipant));
storageManager.start();
// 1. get listeners from Helix participant and verify there is a storageManager listener.
Map<StateModelListenerType, PartitionStateChangeListener> listeners = mockHelixParticipant.getPartitionStateChangeListeners();
assertTrue("Should contain storage manager listener", listeners.containsKey(StateModelListenerType.StorageManagerListener));
// 2. not found replica should encounter exception
try {
mockHelixParticipant.onPartitionBecomeInactiveFromStandby("-1");
fail("should fail because replica is not found");
} catch (StateTransitionException e) {
assertEquals("Error code doesn't match", ReplicaNotFound, e.getErrorCode());
}
// 3. not found store should throw exception (induced by removing the store)
ReplicaId replicaToRemove = localReplicas.get(localReplicas.size() - 1);
storageManager.controlCompactionForBlobStore(replicaToRemove.getPartitionId(), false);
storageManager.shutdownBlobStore(replicaToRemove.getPartitionId());
storageManager.getDiskManager(replicaToRemove.getPartitionId()).removeBlobStore(replicaToRemove.getPartitionId());
try {
mockHelixParticipant.onPartitionBecomeInactiveFromStandby(replicaToRemove.getPartitionId().toPathString());
fail("should fail because store is not found");
} catch (StateTransitionException e) {
assertEquals("Error code doesn't match", ReplicaNotFound, e.getErrorCode());
}
// 4. store not started exception
ReplicaId localReplica = localReplicas.get(0);
storageManager.shutdownBlobStore(localReplica.getPartitionId());
try {
mockHelixParticipant.onPartitionBecomeInactiveFromStandby(localReplica.getPartitionId().toPathString());
fail("should fail because store is not started");
} catch (StateTransitionException e) {
assertEquals("Error code doesn't match", StoreNotStarted, e.getErrorCode());
}
storageManager.startBlobStore(localReplica.getPartitionId());
// 5. store is disabled due to disk I/O error
BlobStore localStore = (BlobStore) storageManager.getStore(localReplica.getPartitionId());
localStore.setDisableState(true);
try {
mockHelixParticipant.onPartitionBecomeInactiveFromStandby(localReplica.getPartitionId().toPathString());
fail("should fail because store is disabled");
} catch (StateTransitionException e) {
assertEquals("Error code doesn't match", ReplicaOperationFailure, e.getErrorCode());
}
localStore.setDisableState(false);
// 6. success case (verify both replica's state and decommission file)
mockHelixParticipant.onPartitionBecomeInactiveFromStandby(localReplica.getPartitionId().toPathString());
assertEquals("local store state should be set to INACTIVE", ReplicaState.INACTIVE, storageManager.getStore(localReplica.getPartitionId()).getCurrentState());
File decommissionFile = new File(localReplica.getReplicaPath(), BlobStore.DECOMMISSION_FILE_NAME);
assertTrue("Decommission file is not found in local replica's dir", decommissionFile.exists());
shutdownAndAssertStoresInaccessible(storageManager, localReplicas);
// 7. mock disable compaction failure
mockHelixParticipant = new MockClusterParticipant();
MockStorageManager mockStorageManager = new MockStorageManager(localNode, Collections.singletonList(mockHelixParticipant));
mockStorageManager.start();
try {
mockHelixParticipant.onPartitionBecomeInactiveFromStandby(localReplica.getPartitionId().toPathString());
} catch (StateTransitionException e) {
assertEquals("Error code doesn't match", ReplicaNotFound, e.getErrorCode());
} finally {
shutdownAndAssertStoresInaccessible(mockStorageManager, localReplicas);
}
}
use of com.github.ambry.clustermap.PartitionStateChangeListener in project ambry by linkedin.
the class StorageManagerTest method replicaFromOfflineToBootstrapTest.
/**
* test that both success and failure in storage manager when replica becomes BOOTSTRAP from OFFLINE (update
* InstanceConfig in Helix is turned off in this test)
* @throws Exception
*/
@Test
public void replicaFromOfflineToBootstrapTest() throws Exception {
generateConfigs(true, false);
MockDataNodeId localNode = clusterMap.getDataNodes().get(0);
List<PartitionId> partitionIds = clusterMap.getAllPartitionIds(null);
List<ReplicaId> localReplicas = clusterMap.getReplicaIds(localNode);
MockClusterParticipant mockHelixParticipant = new MockClusterParticipant();
StorageManager storageManager = createStorageManager(localNode, metricRegistry, Collections.singletonList(mockHelixParticipant));
storageManager.start();
// 1. get listeners from Helix participant and verify there is a storageManager listener.
Map<StateModelListenerType, PartitionStateChangeListener> listeners = mockHelixParticipant.getPartitionStateChangeListeners();
assertTrue("Should contain storage manager listener", listeners.containsKey(StateModelListenerType.StorageManagerListener));
// 2. if new bootstrap replica is not found, there should be an exception
try {
mockHelixParticipant.onPartitionBecomeBootstrapFromOffline(String.valueOf(partitionIds.size() + 1));
fail("should fail due to bootstrap replica not found");
} catch (StateTransitionException e) {
assertEquals("Error code doesn't match", ReplicaNotFound, e.getErrorCode());
}
// 3. test regular store didn't start up (which triggers StoreNotStarted exception)
ReplicaId replicaId = localReplicas.get(0);
Store localStore = storageManager.getStore(replicaId.getPartitionId(), true);
localStore.shutdown();
try {
mockHelixParticipant.onPartitionBecomeBootstrapFromOffline(replicaId.getPartitionId().toPathString());
fail("should fail due to store not started");
} catch (StateTransitionException e) {
assertEquals("Error code doesn't match", StoreNotStarted, e.getErrorCode());
}
localStore.start();
// 4. test both failure and success cases regarding new replica addition
PartitionId newPartition = clusterMap.createNewPartition(Collections.singletonList(localNode));
assertNull("There should not be any store associated with new partition", storageManager.getStore(newPartition, true));
// find an existing replica that shares disk with new replica
ReplicaId newReplica = newPartition.getReplicaIds().get(0);
ReplicaId replicaOnSameDisk = localReplicas.stream().filter(r -> r.getDiskId().equals(newReplica.getDiskId())).findFirst().get();
// test add new store failure by shutting down target diskManager
storageManager.getDiskManager(replicaOnSameDisk.getPartitionId()).shutdown();
try {
mockHelixParticipant.onPartitionBecomeBootstrapFromOffline(newPartition.toPathString());
} catch (StateTransitionException e) {
assertEquals("Error code doesn't match", ReplicaOperationFailure, e.getErrorCode());
}
// restart disk manager to test case where new replica(store) is successfully added into StorageManager
storageManager.getDiskManager(replicaOnSameDisk.getPartitionId()).start();
mockHelixParticipant.onPartitionBecomeBootstrapFromOffline(newPartition.toPathString());
BlobStore newAddedStore = (BlobStore) storageManager.getStore(newPartition);
assertNotNull("There should be a started store associated with new partition", newAddedStore);
// 5. verify that new added store has bootstrap file
assertTrue("There should be a bootstrap file indicating store is in BOOTSTRAP state", newAddedStore.isBootstrapInProgress());
assertEquals("The store's current state should be BOOTSTRAP", ReplicaState.BOOTSTRAP, newAddedStore.getCurrentState());
// 6. test that state transition should succeed for existing non-empty replicas (we write some data into store beforehand)
MockId id = new MockId(TestUtils.getRandomString(MOCK_ID_STRING_LENGTH), Utils.getRandomShort(TestUtils.RANDOM), Utils.getRandomShort(TestUtils.RANDOM));
MessageInfo info = new MessageInfo(id, PUT_RECORD_SIZE, id.getAccountId(), id.getContainerId(), Utils.Infinite_Time);
MessageWriteSet writeSet = new MockMessageWriteSet(Collections.singletonList(info), Collections.singletonList(ByteBuffer.allocate(PUT_RECORD_SIZE)));
Store storeToWrite = storageManager.getStore(localReplicas.get(1).getPartitionId());
storeToWrite.put(writeSet);
mockHelixParticipant.onPartitionBecomeBootstrapFromOffline(localReplicas.get(1).getPartitionId().toPathString());
assertFalse("There should not be any bootstrap file for existing non-empty store", storeToWrite.isBootstrapInProgress());
assertEquals("The store's current state should be BOOTSTRAP", ReplicaState.BOOTSTRAP, storeToWrite.getCurrentState());
// 7. test that for new created (empty) store, state transition puts it into BOOTSTRAP state
mockHelixParticipant.onPartitionBecomeBootstrapFromOffline(localReplicas.get(0).getPartitionId().toPathString());
assertTrue("There should be a bootstrap file because store is empty and probably recreated", localStore.isBootstrapInProgress());
assertEquals("The store's current state should be BOOTSTRAP", ReplicaState.BOOTSTRAP, localStore.getCurrentState());
shutdownAndAssertStoresInaccessible(storageManager, localReplicas);
}
Aggregations