use of com.github.ambry.clustermap.ClusterParticipant in project ambry by linkedin.
the class StorageManagerTest method setBlobStoreStoppedStateWithMultiDelegatesTest.
/**
* Test setting blob stop state in two clusters (if server participates into two Helix clusters)
* @throws Exception
*/
@Test
public void setBlobStoreStoppedStateWithMultiDelegatesTest() throws Exception {
MockDataNodeId dataNode = clusterMap.getDataNodes().get(0);
List<ReplicaId> replicas = clusterMap.getReplicaIds(dataNode);
MockClusterParticipant mockClusterParticipant1 = new MockClusterParticipant();
MockClusterParticipant mockClusterParticipant2 = new MockClusterParticipant(null, false);
List<ClusterParticipant> participants = Arrays.asList(mockClusterParticipant1, mockClusterParticipant2);
StorageManager storageManager = createStorageManager(dataNode, metricRegistry, participants);
storageManager.start();
PartitionId id = replicas.get(0).getPartitionId();
// test that any delegate fails to update stop state, then the whole operation fails
List<PartitionId> failToUpdateList = storageManager.setBlobStoreStoppedState(Collections.singletonList(id), true);
assertEquals("Set store stopped state should fail because one of delegates returns false", id, failToUpdateList.get(0));
// test the success case, both delegates succeed in updating stop state of replica
mockClusterParticipant2.setStopStateReturnVal = null;
failToUpdateList = storageManager.setBlobStoreStoppedState(Collections.singletonList(id), true);
assertTrue("Set store stopped state should succeed", failToUpdateList.isEmpty());
// verify both delegates have the correct stopped replica list.
List<String> expectedStoppedReplicas = Collections.singletonList(id.toPathString());
assertEquals("Stopped replica list from participant 1 is not expected", expectedStoppedReplicas, mockClusterParticipant1.getStoppedReplicas());
assertEquals("Stopped replica list from participant 2 is not expected", expectedStoppedReplicas, mockClusterParticipant2.getStoppedReplicas());
shutdownAndAssertStoresInaccessible(storageManager, replicas);
}
use of com.github.ambry.clustermap.ClusterParticipant in project ambry by linkedin.
the class StorageManagerTest method multiParticipantsMarkStoreInErrorStateTest.
/**
* Test that, if store is not started, all participants on this node are able to mark it in ERROR state during
* OFFLINE -> BOOTSTRAP transition.
* @throws Exception
*/
@Test
public void multiParticipantsMarkStoreInErrorStateTest() throws Exception {
MockDataNodeId dataNode = clusterMap.getDataNodes().get(0);
List<ReplicaId> replicas = clusterMap.getReplicaIds(dataNode);
List<ClusterParticipant> participants = Arrays.asList(new MockClusterParticipant(), new MockClusterParticipant());
StorageManager storageManager = createStorageManager(dataNode, metricRegistry, participants);
storageManager.start();
// stop one of the stores to induce transition failure
PartitionId id = replicas.get(0).getPartitionId();
storageManager.shutdownBlobStore(id);
// verify that both participants throw exception during OFFLINE -> BOOTSTRAP transition
for (ClusterParticipant participant : participants) {
try {
((MockClusterParticipant) participant).onPartitionBecomeBootstrapFromOffline(id.toPathString());
fail("should fail because store is not started");
} catch (StateTransitionException e) {
assertEquals("Error code doesn't match", StoreNotStarted, e.getErrorCode());
}
}
shutdownAndAssertStoresInaccessible(storageManager, replicas);
}
use of com.github.ambry.clustermap.ClusterParticipant in project ambry by linkedin.
the class StorageManagerTest method setBlobStoreStoppedStateSuccessTest.
/**
* Test successfully set stopped state of blobstore with given list of {@link PartitionId}.
*/
@Test
public void setBlobStoreStoppedStateSuccessTest() throws Exception {
MockDataNodeId dataNode = clusterMap.getDataNodes().get(0);
List<ReplicaId> replicas = clusterMap.getReplicaIds(dataNode);
List<PartitionId> partitionIds = new ArrayList<>();
Map<DiskId, List<ReplicaId>> diskToReplicas = new HashMap<>();
// test setting the state of store via instantiated MockClusterParticipant
ClusterParticipant participant = new MockClusterParticipant();
ClusterParticipant participantSpy = Mockito.spy(participant);
StorageManager storageManager = createStorageManager(dataNode, metricRegistry, Collections.singletonList(participantSpy));
storageManager.start();
assertEquals("There should be no unexpected partitions reported", 0, getNumUnrecognizedPartitionsReported());
for (ReplicaId replica : replicas) {
partitionIds.add(replica.getPartitionId());
diskToReplicas.computeIfAbsent(replica.getDiskId(), disk -> new ArrayList<>()).add(replica);
}
List<PartitionId> failToUpdateList;
// add a list of stores to STOPPED list. Note that the stores are residing on 3 disks.
failToUpdateList = storageManager.setBlobStoreStoppedState(partitionIds, true);
// make sure the update operation succeeds
assertTrue("Add stores to stopped list should succeed, failToUpdateList should be empty", failToUpdateList.isEmpty());
// make sure the stopped list contains all the added stores
Set<String> stoppedReplicasCopy = new HashSet<>(participantSpy.getStoppedReplicas());
for (ReplicaId replica : replicas) {
assertTrue("The stopped list should contain the replica: " + replica.getPartitionId().toPathString(), stoppedReplicasCopy.contains(replica.getPartitionId().toPathString()));
}
// make sure replicaStatusDelegate is invoked 3 times and each time the input replica list conforms with stores on particular disk
for (List<ReplicaId> replicasPerDisk : diskToReplicas.values()) {
verify(participantSpy, times(1)).setReplicaStoppedState(replicasPerDisk, true);
}
// remove a list of stores from STOPPED list. Note that the stores are residing on 3 disks.
storageManager.setBlobStoreStoppedState(partitionIds, false);
// make sure the update operation succeeds
assertTrue("Remove stores from stopped list should succeed, failToUpdateList should be empty", failToUpdateList.isEmpty());
// make sure the stopped list is empty because all the stores are successfully removed.
assertTrue("The stopped list should be empty after removing all stores", participantSpy.getStoppedReplicas().isEmpty());
// make sure replicaStatusDelegate is invoked 3 times and each time the input replica list conforms with stores on particular disk
for (List<ReplicaId> replicasPerDisk : diskToReplicas.values()) {
verify(participantSpy, times(1)).setReplicaStoppedState(replicasPerDisk, false);
}
shutdownAndAssertStoresInaccessible(storageManager, replicas);
}
use of com.github.ambry.clustermap.ClusterParticipant in project ambry by linkedin.
the class BlobStoreTest method resolveStoreInitialStateTest.
/**
* Test that if {@link HelixParticipant} is adopted, store state is set to OFFLINE after startup (which will be updated
* by Helix state transition later)
* @throws Exception
*/
@Test
public void resolveStoreInitialStateTest() throws Exception {
store.shutdown();
properties.setProperty(StoreConfig.storeReplicaStatusDelegateEnableName, "true");
File storeDir = StoreTestUtils.createTempDirectory("store-" + storeId);
File reserveDir = StoreTestUtils.createTempDirectory("reserve-pool");
reserveDir.deleteOnExit();
DiskSpaceAllocator diskAllocator = new DiskSpaceAllocator(true, reserveDir, 0, new StorageManagerMetrics(new MetricRegistry()));
StoreConfig config = new StoreConfig(new VerifiableProperties(properties));
MetricRegistry registry = new MetricRegistry();
StoreMetrics metrics = new StoreMetrics(registry);
ClusterParticipant dynamicParticipant = Mockito.mock(ClusterParticipant.class);
when(dynamicParticipant.supportsStateChanges()).thenReturn(true);
ReplicaStatusDelegate delegate = new ReplicaStatusDelegate(dynamicParticipant);
BlobStore testStore = new BlobStore(getMockReplicaId(storeDir.getAbsolutePath()), config, scheduler, storeStatsScheduler, diskIOScheduler, diskAllocator, metrics, metrics, STORE_KEY_FACTORY, recovery, hardDelete, Collections.singletonList(delegate), time, new InMemAccountService(false, false), null);
testStore.start();
assertEquals("Store current state should be OFFLINE if dynamic participant is adopted", OFFLINE, testStore.getCurrentState());
testStore.shutdown();
}
use of com.github.ambry.clustermap.ClusterParticipant in project ambry by linkedin.
the class AmbryServer method startup.
public void startup() throws InstantiationException {
try {
logger.info("starting");
clusterParticipants = clusterAgentsFactory.getClusterParticipants();
logger.info("Setting up JMX.");
long startTime = SystemTime.getInstance().milliseconds();
reporter = reporterFactory != null ? reporterFactory.apply(registry) : JmxReporter.forRegistry(registry).build();
reporter.start();
logger.info("creating configs");
NetworkConfig networkConfig = new NetworkConfig(properties);
StoreConfig storeConfig = new StoreConfig(properties);
DiskManagerConfig diskManagerConfig = new DiskManagerConfig(properties);
ServerConfig serverConfig = new ServerConfig(properties);
ReplicationConfig replicationConfig = new ReplicationConfig(properties);
ConnectionPoolConfig connectionPoolConfig = new ConnectionPoolConfig(properties);
SSLConfig sslConfig = new SSLConfig(properties);
ClusterMapConfig clusterMapConfig = new ClusterMapConfig(properties);
StatsManagerConfig statsConfig = new StatsManagerConfig(properties);
CloudConfig cloudConfig = new CloudConfig(properties);
// verify the configs
properties.verify();
scheduler = Utils.newScheduler(serverConfig.serverSchedulerNumOfthreads, false);
// mismatch in sealed/stopped replica lists that maintained by each participant.
if (clusterParticipants != null && clusterParticipants.size() > 1 && serverConfig.serverParticipantsConsistencyCheckerPeriodSec > 0) {
consistencyChecker = new ParticipantsConsistencyChecker(clusterParticipants, metrics);
logger.info("Scheduling participants consistency checker with a period of {} secs", serverConfig.serverParticipantsConsistencyCheckerPeriodSec);
consistencyCheckerScheduler = Utils.newScheduler(1, "consistency-checker-", false);
consistencyCheckerTask = consistencyCheckerScheduler.scheduleAtFixedRate(consistencyChecker, 0, serverConfig.serverParticipantsConsistencyCheckerPeriodSec, TimeUnit.SECONDS);
}
logger.info("checking if node exists in clustermap host {} port {}", networkConfig.hostName, networkConfig.port);
DataNodeId nodeId = clusterMap.getDataNodeId(networkConfig.hostName, networkConfig.port);
if (nodeId == null) {
throw new IllegalArgumentException("The node " + networkConfig.hostName + ":" + networkConfig.port + "is not present in the clustermap. Failing to start the datanode");
}
AccountServiceFactory accountServiceFactory = Utils.getObj(serverConfig.serverAccountServiceFactory, properties, registry);
AccountService accountService = accountServiceFactory.getAccountService();
StoreKeyFactory storeKeyFactory = Utils.getObj(storeConfig.storeKeyFactory, clusterMap);
// In most cases, there should be only one participant in the clusterParticipants list. If there are more than one
// and some components require sole participant, the first one in the list will be primary participant.
storageManager = new StorageManager(storeConfig, diskManagerConfig, scheduler, registry, storeKeyFactory, clusterMap, nodeId, new BlobStoreHardDelete(), clusterParticipants, time, new BlobStoreRecovery(), accountService);
storageManager.start();
SSLFactory sslFactory = new NettySslHttp2Factory(sslConfig);
if (clusterMapConfig.clusterMapEnableHttp2Replication) {
connectionPool = new Http2BlockingChannelPool(sslFactory, new Http2ClientConfig(properties), new Http2ClientMetrics(registry));
} else {
connectionPool = new BlockingChannelConnectionPool(connectionPoolConfig, sslConfig, clusterMapConfig, registry);
}
connectionPool.start();
StoreKeyConverterFactory storeKeyConverterFactory = Utils.getObj(serverConfig.serverStoreKeyConverterFactory, properties, registry);
Predicate<MessageInfo> skipPredicate = new ReplicationSkipPredicate(accountService, replicationConfig);
replicationManager = new ReplicationManager(replicationConfig, clusterMapConfig, storeConfig, storageManager, storeKeyFactory, clusterMap, scheduler, nodeId, connectionPool, registry, notificationSystem, storeKeyConverterFactory, serverConfig.serverMessageTransformer, clusterParticipants.get(0), skipPredicate);
replicationManager.start();
if (replicationConfig.replicationEnabledWithVcrCluster) {
logger.info("Creating Helix cluster spectator for cloud to store replication.");
vcrClusterSpectator = _vcrClusterAgentsFactory.getVcrClusterSpectator(cloudConfig, clusterMapConfig);
cloudToStoreReplicationManager = new CloudToStoreReplicationManager(replicationConfig, clusterMapConfig, storeConfig, storageManager, storeKeyFactory, clusterMap, scheduler, nodeId, connectionPool, registry, notificationSystem, storeKeyConverterFactory, serverConfig.serverMessageTransformer, vcrClusterSpectator, clusterParticipants.get(0));
cloudToStoreReplicationManager.start();
}
logger.info("Creating StatsManager to publish stats");
accountStatsMySqlStore = statsConfig.enableMysqlReport ? (AccountStatsMySqlStore) new AccountStatsMySqlStoreFactory(properties, clusterMapConfig, registry).getAccountStatsStore() : null;
statsManager = new StatsManager(storageManager, clusterMap.getReplicaIds(nodeId), registry, statsConfig, time, clusterParticipants.get(0), accountStatsMySqlStore, accountService);
if (serverConfig.serverStatsPublishLocalEnabled) {
statsManager.start();
}
ArrayList<Port> ports = new ArrayList<Port>();
ports.add(new Port(networkConfig.port, PortType.PLAINTEXT));
if (nodeId.hasSSLPort()) {
ports.add(new Port(nodeId.getSSLPort(), PortType.SSL));
}
networkServer = new SocketServer(networkConfig, sslConfig, registry, ports);
FindTokenHelper findTokenHelper = new FindTokenHelper(storeKeyFactory, replicationConfig);
requests = new AmbryServerRequests(storageManager, networkServer.getRequestResponseChannel(), clusterMap, nodeId, registry, metrics, findTokenHelper, notificationSystem, replicationManager, storeKeyFactory, serverConfig, storeKeyConverterFactory, statsManager, clusterParticipants.get(0));
requestHandlerPool = new RequestHandlerPool(serverConfig.serverRequestHandlerNumOfThreads, networkServer.getRequestResponseChannel(), requests);
networkServer.start();
// Start netty http2 server
if (nodeId.hasHttp2Port()) {
NettyConfig nettyConfig = new NettyConfig(properties);
NettyMetrics nettyMetrics = new NettyMetrics(registry);
Http2ServerMetrics http2ServerMetrics = new Http2ServerMetrics(registry);
Http2ClientConfig http2ClientConfig = new Http2ClientConfig(properties);
logger.info("Http2 port {} is enabled. Starting HTTP/2 service.", nodeId.getHttp2Port());
NettyServerRequestResponseChannel requestResponseChannel = new NettyServerRequestResponseChannel(networkConfig.queuedMaxRequests, http2ServerMetrics);
AmbryServerRequests ambryServerRequestsForHttp2 = new AmbryServerRequests(storageManager, requestResponseChannel, clusterMap, nodeId, registry, metrics, findTokenHelper, notificationSystem, replicationManager, storeKeyFactory, serverConfig, storeKeyConverterFactory, statsManager, clusterParticipants.get(0));
requestHandlerPoolForHttp2 = new RequestHandlerPool(serverConfig.serverRequestHandlerNumOfThreads, requestResponseChannel, ambryServerRequestsForHttp2);
NioServerFactory nioServerFactory = new StorageServerNettyFactory(nodeId.getHttp2Port(), requestResponseChannel, sslFactory, nettyConfig, http2ClientConfig, metrics, nettyMetrics, http2ServerMetrics, serverSecurityService);
nettyHttp2Server = nioServerFactory.getNioServer();
nettyHttp2Server.start();
}
// Other code
List<AmbryStatsReport> ambryStatsReports = new ArrayList<>();
Set<String> validStatsTypes = new HashSet<>();
for (StatsReportType type : StatsReportType.values()) {
validStatsTypes.add(type.toString());
}
if (serverConfig.serverStatsPublishReportEnabled) {
serverConfig.serverStatsReportsToPublish.forEach(e -> {
if (validStatsTypes.contains(e)) {
ambryStatsReports.add(new AmbryStatsReportImpl(serverConfig.serverQuotaStatsAggregateIntervalInMinutes, StatsReportType.valueOf(e)));
}
});
}
if (vcrClusterSpectator != null) {
vcrClusterSpectator.spectate();
}
Callback<StatsSnapshot> accountServiceCallback = new AccountServiceCallback(accountService);
for (ClusterParticipant clusterParticipant : clusterParticipants) {
clusterParticipant.participate(ambryStatsReports, accountStatsMySqlStore, accountServiceCallback);
}
if (nettyInternalMetrics != null) {
nettyInternalMetrics.start();
logger.info("NettyInternalMetric starts");
}
logger.info("started");
long processingTime = SystemTime.getInstance().milliseconds() - startTime;
metrics.serverStartTimeInMs.update(processingTime);
logger.info("Server startup time in Ms {}", processingTime);
} catch (Exception e) {
logger.error("Error during startup", e);
throw new InstantiationException("failure during startup " + e);
}
}
Aggregations