private void logSegmentsLoadingInfo() { InstanceDataManager instanceDataManager = _serverInstance.getInstanceDataManager(); if (instanceDataManager == null) { return; } HelixDataAccessor helixDataAccessor = _helixManager.getHelixDataAccessor(); Builder keyBuilder = helixDataAccessor.keyBuilder(); LiveInstance liveInstance = helixDataAccessor.getProperty(keyBuilder.liveInstance(_instanceId)); String sessionId = liveInstance.getSessionId(); List<String> tableNames = _helixAdmin.getResourcesInCluster(_helixClusterName); for (String tableName : tableNames) { PropertyKey currentStateKey = keyBuilder.currentState(_instanceId, sessionId, tableName); CurrentState currentState = helixDataAccessor.getProperty(currentStateKey); int numSegmentsLoaded = instanceDataManager.getAllSegmentsMetadata(tableName).size(); if (currentState != null && currentState.isValid()) { int numSegmentsToLoad = currentState.getPartitionStateMap().size(); LOGGER.info( "Segments are not fully loaded during server bootstrap, current progress: table: {}, segments loading progress [ {} / {} ]", tableName, numSegmentsLoaded, numSegmentsToLoad); } } }
private int getNumSegmentsToLoad() { InstanceDataManager instanceDataManager = _serverInstance.getInstanceDataManager(); if (instanceDataManager == null) { return -1; } HelixDataAccessor helixDataAccessor = _helixManager.getHelixDataAccessor(); Builder keyBuilder = helixDataAccessor.keyBuilder(); int numSegmentsToLoad = 0; List<String> tableNames = _helixAdmin.getResourcesInCluster(_helixClusterName); for (String tableName : tableNames) { LiveInstance liveInstance = helixDataAccessor.getProperty(keyBuilder.liveInstance(_instanceId)); String sessionId = liveInstance.getSessionId(); PropertyKey currentStateKey = keyBuilder.currentState(_instanceId, sessionId, tableName); CurrentState currentState = helixDataAccessor.getProperty(currentStateKey); if (currentState != null && currentState.isValid()) { numSegmentsToLoad += currentState.getPartitionStateMap().size(); } } return numSegmentsToLoad; }
private void refreshCurrentStatesCache(HelixDataAccessor accessor, Map<String, LiveInstance> liveInstanceMap) { long start = System.currentTimeMillis(); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); Set<PropertyKey> currentStateKeys = new HashSet<>(); for (String instanceName : liveInstanceMap.keySet()) { LiveInstance liveInstance = liveInstanceMap.get(instanceName); String sessionId = liveInstance.getSessionId(); List<String> currentStateNames = accessor.getChildNames(keyBuilder.currentStates(instanceName, sessionId)); for (String currentStateName : currentStateNames) { currentStateKeys.add(keyBuilder.currentState(instanceName, sessionId, currentStateName)); } } // All new entries from zk not cached locally yet should be read from ZK. Set<PropertyKey> reloadKeys = new HashSet<>(currentStateKeys); reloadKeys.removeAll(_currentStateCache.keySet()); Set<PropertyKey> cachedKeys = new HashSet<>(_currentStateCache.keySet()); cachedKeys.retainAll(currentStateKeys); _currentStateCache = Collections.unmodifiableMap( refreshProperties(accessor, new ArrayList<>(reloadKeys), new ArrayList<>(cachedKeys), _currentStateCache)); if (LOG.isDebugEnabled()) { LogUtil.logDebug(LOG, getEventId(), "# of CurrentStates reload: " + reloadKeys.size() + ", skipped:" + ( currentStateKeys.size() - reloadKeys.size()) + ". took " + (System.currentTimeMillis() - start) + " ms to reload new current states for cluster: " + _clusterName); } }
keyBuilder.currentState(instanceName, _message.getTgtSessionId(), resourceName), currentStateDelta)) { logger.error("Fails to persist ERROR current state to ZK for resource " + resourceName
keyBuilder.currentState(instanceName, _message.getTgtSessionId(), resourceName), currentStateDelta)) { logger.error("Fails to persist ERROR current state to ZK for resource " + resourceName
for (String sessionId : sessionIds) { CurrentState currentState = accessor.getProperty(keyBuilder.currentState(participant, sessionId, _resourceName)); Map<String, String> partitionStateMap = currentState.getPartitionStateMap(); if (partitionStateMap != null && !partitionStateMap.isEmpty()) {
public static boolean verifyEmptyCurStateAndExtView(String clusterName, String resourceName, Set<String> instanceNames, String zkAddr) { HelixZkClient zkClient = SharedZkClientFactory.getInstance() .buildZkClient(new HelixZkClient.ZkConnectionConfig(zkAddr)); zkClient.setZkSerializer(new ZNRecordSerializer()); try { ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<ZNRecord>(zkClient)); Builder keyBuilder = accessor.keyBuilder(); for (String instanceName : instanceNames) { List<String> sessionIds = accessor.getChildNames(keyBuilder.sessions(instanceName)); for (String sessionId : sessionIds) { CurrentState curState = accessor.getProperty(keyBuilder.currentState(instanceName, sessionId, resourceName)); if (curState != null && curState.getRecord().getMapFields().size() != 0) { return false; } } ExternalView extView = accessor.getProperty(keyBuilder.externalView(resourceName)); if (extView != null && extView.getRecord().getMapFields().size() != 0) { return false; } } return true; } finally { zkClient.close(); } }
private void callParticipantCode(NotificationContext context) { // since ZkClient.unsubscribe() does not immediately remove listeners // from zk, it is possible that two listeners exist when leadership transfers // therefore, double check to make sure only one participant invokes the code if (context.getType() == Type.CALLBACK) { HelixManager manager = context.getManager(); // DataAccessor accessor = manager.getDataAccessor(); HelixDataAccessor accessor = manager.getHelixDataAccessor(); Builder keyBuilder = accessor.keyBuilder(); String instance = manager.getInstanceName(); String sessionId = manager.getSessionId(); // get resource name from partition key: "PARTICIPANT_LEADER_XXX_0" String resourceName = _partitionKey.substring(0, _partitionKey.lastIndexOf('_')); CurrentState curState = accessor.getProperty(keyBuilder.currentState(instance, sessionId, resourceName)); if (curState == null) { return; } String state = curState.getState(_partitionKey); if (state == null || !state.equalsIgnoreCase("LEADER")) { return; } } try { _callback.onCallback(context); } catch (Exception e) { LOG.error("Error invoking callback:" + _callback, e); } }
private void callParticipantCode(NotificationContext context) { // since ZkClient.unsubscribe() does not immediately remove listeners // from zk, it is possible that two listeners exist when leadership transfers // therefore, double check to make sure only one participant invokes the code if (context.getType() == Type.CALLBACK) { HelixManager manager = context.getManager(); // DataAccessor accessor = manager.getDataAccessor(); HelixDataAccessor accessor = manager.getHelixDataAccessor(); Builder keyBuilder = accessor.keyBuilder(); String instance = manager.getInstanceName(); String sessionId = manager.getSessionId(); // get resource name from partition key: "PARTICIPANT_LEADER_XXX_0" String resourceName = _partitionKey.substring(0, _partitionKey.lastIndexOf('_')); CurrentState curState = accessor.getProperty(keyBuilder.currentState(instance, sessionId, resourceName)); if (curState == null) { return; } String state = curState.getState(_partitionKey); if (state == null || !state.equalsIgnoreCase("LEADER")) { return; } } try { _callback.onCallback(context); } catch (Exception e) { LOG.error("Error invoking callback:" + _callback, e); } }
/** * Request a state change for a specific task. * * @param accessor connected Helix data accessor * @param instance the instance serving the task * @param sessionId the current session of the instance * @param resource the job name * @param partition the task partition name * @param state the requested state * @return true if the request was persisted, false otherwise */ private static boolean setRequestedState(HelixDataAccessor accessor, String instance, String sessionId, String resource, String partition, TaskPartitionState state) { LOG.debug( String.format("Requesting a state transition to %s for partition %s.", state, partition)); try { PropertyKey.Builder keyBuilder = accessor.keyBuilder(); PropertyKey key = keyBuilder.currentState(instance, sessionId, resource); CurrentState currStateDelta = new CurrentState(resource); currStateDelta.setRequestedState(partition, state.name()); return accessor.updateProperty(key, currStateDelta); } catch (Exception e) { LOG.error(String .format("Error when requesting a state transition to %s for partition %s.", state, partition), e); return false; } } }
/** * Request a state change for a specific task. * * @param accessor connected Helix data accessor * @param instance the instance serving the task * @param sessionId the current session of the instance * @param resource the job name * @param partition the task partition name * @param state the requested state * @return true if the request was persisted, false otherwise */ private static boolean setRequestedState(HelixDataAccessor accessor, String instance, String sessionId, String resource, String partition, TaskPartitionState state) { LOG.debug( String.format("Requesting a state transition to %s for partition %s.", state, partition)); try { PropertyKey.Builder keyBuilder = accessor.keyBuilder(); PropertyKey key = keyBuilder.currentState(instance, sessionId, resource); CurrentState currStateDelta = new CurrentState(resource); currStateDelta.setRequestedState(partition, state.name()); return accessor.updateProperty(key, currStateDelta); } catch (Exception e) { LOG.error(String .format("Error when requesting a state transition to %s for partition %s.", state, partition), e); return false; } } }
@Test public void testGroupCommitAddCurrentStateBack() throws InterruptedException { HelixDataAccessor accessor = _manager.getHelixDataAccessor(); Message initMessage = generateMessage("OFFLINE", "ONLINE"); accessor.setProperty( accessor.keyBuilder().message(_participant.getInstanceName(), initMessage.getMsgId()), initMessage); Assert.assertTrue(waitForMessageProcessed(accessor, initMessage.getMsgId())); Message toOffline = generateMessage("ONLINE", "OFFLINE"); accessor.setProperty( accessor.keyBuilder().message(_participant.getInstanceName(), toOffline.getMsgId()), toOffline); Assert.assertTrue(waitForMessageProcessed(accessor, toOffline.getMsgId())); // Consequential 10 messages for (int i = 0; i < 10; i++) { Message dropped = generateMessage("OFFLINE", "DROPPED"); accessor.setProperty( accessor.keyBuilder().message(_participant.getInstanceName(), dropped.getMsgId()), dropped); Assert.assertTrue(waitForMessageProcessed(accessor, dropped.getMsgId())); Assert.assertFalse(accessor.getBaseDataAccessor().exists(accessor.keyBuilder() .currentState(_participant.getInstanceName(), _participant.getSessionId(), WorkflowGenerator.DEFAULT_TGT_DB).getPath(), 0)); } }
@Test public void testAddedFieldsInCurrentState() { String instanceName = PARTICIPANT_PREFIX + "_" + _startPort; HelixDataAccessor accessor = _manager.getHelixDataAccessor(); LiveInstance liveInstance = accessor.getProperty(accessor.keyBuilder().liveInstance(instanceName)); CurrentState currentState = accessor.getProperty(accessor.keyBuilder() .currentState(instanceName, liveInstance.getSessionId(), WorkflowGenerator.DEFAULT_TGT_DB)); // Test start time should happen after test start time Assert.assertTrue( currentState.getStartTime(WorkflowGenerator.DEFAULT_TGT_DB + "_0") >= _testStartTime); // Test end time is always larger than start time Assert.assertTrue( currentState.getEndTime(WorkflowGenerator.DEFAULT_TGT_DB + "_0") >= currentState .getStartTime(WorkflowGenerator.DEFAULT_TGT_DB + "_0")); // Final state is MASTER, so SLAVE will be the previous state Assert.assertEquals(currentState.getPreviousState(WorkflowGenerator.DEFAULT_TGT_DB + "_0"), "SLAVE"); } }
@GET @Path("{instanceName}/resources/{resourceName}") public Response getResourceOnInstance(@PathParam("clusterId") String clusterId, @PathParam("instanceName") String instanceName, @PathParam("resourceName") String resourceName) throws IOException { HelixDataAccessor accessor = getDataAccssor(clusterId); List<String> sessionIds = accessor.getChildNames(accessor.keyBuilder().sessions(instanceName)); if (sessionIds == null || sessionIds.size() == 0) { return notFound(); } // Only get resource list from current session id String currentSessionId = sessionIds.get(0); CurrentState resourceCurrentState = accessor .getProperty(accessor.keyBuilder().currentState(instanceName, currentSessionId, resourceName)); if (resourceCurrentState != null) { return JSONRepresentation(resourceCurrentState.getRecord()); } return notFound(); }
StringRepresentation getInstanceCurrentStateRepresentation(String clusterName, String instanceName, String resourceGroup) throws JsonGenerationException, JsonMappingException, IOException { ZkClient zkClient = (ZkClient) getRequest().getAttributes().get(RestAdminApplication.ZKCLIENT); String instanceSessionId = ClusterRepresentationUtil.getInstanceSessionId(zkClient, clusterName, instanceName); Builder keyBuilder = new PropertyKey.Builder(clusterName); String message = ClusterRepresentationUtil.getInstancePropertyAsString(zkClient, clusterName, keyBuilder.currentState(instanceName, instanceSessionId, resourceGroup), MediaType.APPLICATION_JSON); StringRepresentation representation = new StringRepresentation(message, MediaType.APPLICATION_JSON); return representation; } }
/** * Assert externalView and currentState for each participant are empty * @param clusterName * @param db * @param participants */ private void assertEmptyCSandEV(String clusterName, String db, MockParticipantManager[] participants) { HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<ZNRecord>(_gZkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); Assert.assertNull(accessor.getProperty(keyBuilder.externalView(db))); for (MockParticipantManager participant : participants) { String instanceName = participant.getInstanceName(); String sessionId = participant.getSessionId(); Assert.assertNull(accessor.getProperty(keyBuilder.currentState(instanceName, sessionId, db))); } }
private void setCurrentState(String clusterName, String instance, String resourceGroupName, String resourceKey, String sessionId, String state, boolean updateTimestamp) { ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<ZNRecord>(_gZkClient)); Builder keyBuilder = accessor.keyBuilder(); CurrentState curState = new CurrentState(resourceGroupName); curState.setState(resourceKey, state); curState.setSessionId(sessionId); curState.setStateModelDefRef("MasterSlave"); if (updateTimestamp) { curState.setEndTime(resourceKey, System.currentTimeMillis()); } accessor.setProperty(keyBuilder.currentState(instance, sessionId, resourceGroupName), curState); }
protected void setupCurrentStates(Map<String, CurrentState> currentStates) { Builder keyBuilder = accessor.keyBuilder(); for (String instanceName : currentStates.keySet()) { accessor.setProperty(keyBuilder .currentState(instanceName, currentStates.get(instanceName).getSessionId(), currentStates.get(instanceName).getResourceName()), currentStates.get(instanceName)); } }
@Override public boolean verify() throws Exception { PropertyKey.Builder keyBuilder = accessor.keyBuilder(); PropertyKey partitionStatusKey = keyBuilder.currentState(participant.getInstanceName(), participant.getSessionId(), resourceName); CurrentState currentState = accessor.getProperty(partitionStatusKey); return currentState != null && !currentState.getPartitionStateMap().isEmpty(); } }, timeout);
@Override protected CurrentState getState(String resourceName) { PropertyKey.Builder keyBuilder = _helixDataAccessor.keyBuilder(); LiveInstance liveInstance = _helixDataAccessor.getProperty(keyBuilder.liveInstance(_instanceName)); String sessionId = liveInstance.getSessionId(); return _helixDataAccessor.getProperty(keyBuilder.currentState(_instanceName, sessionId, resourceName)); }