use of com.github.ambry.clustermap.HelixFactory in project ambry by linkedin.
the class BlobStoreTest method storeErrorTriggerDisableReplicaTest.
/**
* Test that replica is correctly disabled when store is shut down due to disk I/O error.
* @throws Exception
*/
@Test
public void storeErrorTriggerDisableReplicaTest() throws Exception {
final String RESOURCE_NAME = "0";
final String CLUSTER_NAME = "BlobStoreTest";
// setup testing environment
store.shutdown();
List<TestUtils.ZkInfo> zkInfoList = new ArrayList<>();
zkInfoList.add(new TestUtils.ZkInfo(null, "DC1", (byte) 0, 2199, false));
JSONObject zkJson = constructZkLayoutJSON(zkInfoList);
properties.setProperty("clustermap.cluster.name", CLUSTER_NAME);
properties.setProperty("clustermap.datacenter.name", "DC1");
properties.setProperty("clustermap.host.name", "localhost");
properties.setProperty("clustermap.dcs.zk.connect.strings", zkJson.toString(2));
properties.setProperty("store.io.error.count.to.trigger.shutdown", "1");
properties.setProperty("store.replica.status.delegate.enable", "true");
properties.setProperty("store.set.local.partition.state.enabled", "true");
ClusterMapConfig clusterMapConfig = new ClusterMapConfig(new VerifiableProperties(properties));
AtomicReference<InstanceConfig> instanceConfig = new AtomicReference<>(new InstanceConfig("localhost"));
instanceConfig.get().setPort("2222");
Map<String, List<String>> listMap = new HashMap<>();
listMap.put(storeId, null);
ZNRecord znRecord = new ZNRecord("localhost");
znRecord.setListFields(listMap);
IdealState idealState = new IdealState(znRecord);
idealState.setRebalanceMode(IdealState.RebalanceMode.SEMI_AUTO);
// mock helix related components
HelixAdmin mockHelixAdmin = mock(HelixAdmin.class);
when(mockHelixAdmin.getInstanceConfig(eq(CLUSTER_NAME), anyString())).then(invocation -> instanceConfig.get());
when(mockHelixAdmin.getResourcesInCluster(eq(CLUSTER_NAME))).thenReturn(Collections.singletonList(RESOURCE_NAME));
when(mockHelixAdmin.getResourceIdealState(eq(CLUSTER_NAME), eq(RESOURCE_NAME))).thenReturn(idealState);
when(mockHelixAdmin.setInstanceConfig(any(), any(), any())).then(invocation -> {
instanceConfig.set(invocation.getArgument(2));
return true;
});
HelixManager mockHelixManager = mock(HelixManager.class);
when(mockHelixManager.getClusterManagmentTool()).thenReturn(mockHelixAdmin);
HelixFactory mockHelixFactory = new HelixFactory() {
@Override
public HelixManager getZKHelixManager(String clusterName, String instanceName, InstanceType instanceType, String zkAddr) {
return mockHelixManager;
}
};
MockHelixParticipant.metricRegistry = new MetricRegistry();
MockHelixParticipant mockParticipant = new MockHelixParticipant(clusterMapConfig, mockHelixFactory);
mockParticipant.overrideDisableReplicaMethod = false;
ReplicaStatusDelegate replicaStatusDelegate = new ReplicaStatusDelegate(mockParticipant);
BlobStore testStore = createBlobStore(getMockAmbryReplica(clusterMapConfig, tempDirStr), new StoreConfig(new VerifiableProperties(properties)), Collections.singletonList(replicaStatusDelegate));
testStore.start();
assertTrue("Store should start successfully", testStore.isStarted());
// create corrupted write set
MessageInfo corruptedInfo = new MessageInfo(getUniqueId(), PUT_RECORD_SIZE, Utils.getRandomShort(TestUtils.RANDOM), Utils.getRandomShort(TestUtils.RANDOM), Utils.Infinite_Time);
MessageWriteSet corruptedWriteSet = new MockMessageWriteSet(Collections.singletonList(corruptedInfo), Collections.singletonList(ByteBuffer.allocate(PUT_RECORD_SIZE)), new StoreException(StoreException.IO_ERROR_STR, StoreErrorCodes.IOError));
// 1. mock failure case
when(mockHelixAdmin.getInstanceConfig(eq(CLUSTER_NAME), anyString())).thenReturn(null);
// trigger store exception when calling store.put()
try {
testStore.put(corruptedWriteSet);
fail("should throw exception");
} catch (StoreException e) {
assertEquals("Mismatch in error code", StoreErrorCodes.IOError, e.getErrorCode());
}
assertNull("Disabled partition list should be null as disabling replica didn't succeed", instanceConfig.get().getDisabledPartitions(RESOURCE_NAME));
// 2. mock success case
when(mockHelixAdmin.getInstanceConfig(eq(CLUSTER_NAME), anyString())).then(invocation -> instanceConfig.get());
testStore.start();
assertTrue("Store should start successfully", testStore.isStarted());
try {
testStore.put(corruptedWriteSet);
fail("should throw exception");
} catch (StoreException e) {
assertEquals("Mismatch in error code", StoreErrorCodes.IOError, e.getErrorCode());
}
assertEquals("Disabled partition name is not expected", storeId, instanceConfig.get().getDisabledPartitions(RESOURCE_NAME).get(0));
// verify "DISABLED" list in InstanceConfig has correct partition id.
assertEquals("Disabled replica list is not expected", Collections.singletonList(storeId), getDisabledReplicas(instanceConfig.get()));
// 3. mock disk is replaced case, restart should succeed
testStore.start();
assertNull("Disabled partition list should be null as restart will enable same replica", instanceConfig.get().getDisabledPartitions(RESOURCE_NAME));
assertTrue("Disabled replica list should be empty", getDisabledReplicas(instanceConfig.get()).isEmpty());
testStore.shutdown();
reloadStore();
}
use of com.github.ambry.clustermap.HelixFactory in project ambry by linkedin.
the class HelixVcrClusterSpectator method spectate.
@Override
public void spectate() throws Exception {
HelixFactory helixFactory = new HelixFactory();
String selfInstanceName = ClusterMapUtils.getInstanceName(clusterMapConfig.clusterMapHostName, clusterMapConfig.clusterMapPort);
// Should we fail here if even one of the remote zk connection fails? If we have just one datacenter, then this will not be a problem.
// If we have two data centers, then its not clear if we should pass the startup with one remote zk connection failure. Because if remote
// zk connection fails on both data centers, then things like replication between data centers might just stop.
// For now, since we have only one fabric in cloud, and the spectator is being used for only cloud to store replication, this will work.
// Once we add more fabrics, we should revisit this.
HelixManager helixManager = helixFactory.getZkHelixManagerAndConnect(cloudConfig.vcrClusterName, selfInstanceName, InstanceType.SPECTATOR, cloudConfig.vcrClusterZkConnectString);
helixManager.addInstanceConfigChangeListener(this);
helixManager.addLiveInstanceChangeListener(this);
}
Aggregations