use of org.apache.helix.model.IdealState in project helix by apache.
the class ZKHelixAdmin method rebalance.
void rebalance(String clusterName, String resourceName, int replica, String keyPrefix, List<String> instanceNames, String groupId) {
// ensure we get the same idealState with the same set of instances
Collections.sort(instanceNames);
IdealState idealState = getResourceIdealState(clusterName, resourceName);
if (idealState == null) {
throw new HelixException("Resource: " + resourceName + " has NOT been added yet");
}
if (groupId != null && groupId.length() > 0) {
idealState.setInstanceGroupTag(groupId);
}
idealState.setReplicas(Integer.toString(replica));
int partitions = idealState.getNumPartitions();
String stateModelName = idealState.getStateModelDefRef();
StateModelDefinition stateModDef = getStateModelDef(clusterName, stateModelName);
if (stateModDef == null) {
throw new HelixException("cannot find state model: " + stateModelName);
}
// StateModelDefinition def = new StateModelDefinition(stateModDef);
List<String> statePriorityList = stateModDef.getStatesPriorityList();
String masterStateValue = null;
String slaveStateValue = null;
replica--;
for (String state : statePriorityList) {
String count = stateModDef.getNumInstancesPerState(state);
if (count.equals("1")) {
if (masterStateValue != null) {
throw new HelixException("Invalid or unsupported state model definition");
}
masterStateValue = state;
} else if (count.equalsIgnoreCase("R")) {
if (slaveStateValue != null) {
throw new HelixException("Invalid or unsupported state model definition");
}
slaveStateValue = state;
} else if (count.equalsIgnoreCase("N")) {
if (!(masterStateValue == null && slaveStateValue == null)) {
throw new HelixException("Invalid or unsupported state model definition");
}
replica = instanceNames.size() - 1;
masterStateValue = slaveStateValue = state;
}
}
if (masterStateValue == null && slaveStateValue == null) {
throw new HelixException("Invalid or unsupported state model definition");
}
if (masterStateValue == null) {
masterStateValue = slaveStateValue;
}
if (idealState.getRebalanceMode() != RebalanceMode.FULL_AUTO && idealState.getRebalanceMode() != RebalanceMode.USER_DEFINED) {
ZNRecord newIdealState = DefaultIdealStateCalculator.calculateIdealState(instanceNames, partitions, replica, keyPrefix, masterStateValue, slaveStateValue);
// for now keep mapField in SEMI_AUTO mode and remove listField in CUSTOMIZED mode
if (idealState.getRebalanceMode() == RebalanceMode.SEMI_AUTO) {
idealState.getRecord().setListFields(newIdealState.getListFields());
// TODO: need consider to remove this.
idealState.getRecord().setMapFields(newIdealState.getMapFields());
}
if (idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED) {
idealState.getRecord().setMapFields(newIdealState.getMapFields());
}
} else {
for (int i = 0; i < partitions; i++) {
String partitionName = keyPrefix + "_" + i;
idealState.getRecord().setMapField(partitionName, new HashMap<String, String>());
idealState.getRecord().setListField(partitionName, new ArrayList<String>());
}
}
setResourceIdealState(clusterName, resourceName, idealState);
}
use of org.apache.helix.model.IdealState in project helix by apache.
the class ZKHelixAdmin method resetPartition.
@Override
public void resetPartition(String clusterName, String instanceName, String resourceName, List<String> partitionNames) {
HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<ZNRecord>(_zkClient));
Builder keyBuilder = accessor.keyBuilder();
// check the instance is alive
LiveInstance liveInstance = accessor.getProperty(keyBuilder.liveInstance(instanceName));
if (liveInstance == null) {
throw new HelixException("Can't reset state for " + resourceName + "/" + partitionNames + " on " + instanceName + ", because " + instanceName + " is not alive");
}
// check resource group exists
IdealState idealState = accessor.getProperty(keyBuilder.idealStates(resourceName));
if (idealState == null) {
throw new HelixException("Can't reset state for " + resourceName + "/" + partitionNames + " on " + instanceName + ", because " + resourceName + " is not added");
}
// check partition exists in resource group
Set<String> resetPartitionNames = new HashSet<String>(partitionNames);
if (idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED) {
Set<String> partitions = new HashSet<String>(idealState.getRecord().getMapFields().keySet());
if (!partitions.containsAll(resetPartitionNames)) {
throw new HelixException("Can't reset state for " + resourceName + "/" + partitionNames + " on " + instanceName + ", because not all " + partitionNames + " exist");
}
} else {
Set<String> partitions = new HashSet<String>(idealState.getRecord().getListFields().keySet());
if (!partitions.containsAll(resetPartitionNames)) {
throw new HelixException("Can't reset state for " + resourceName + "/" + partitionNames + " on " + instanceName + ", because not all " + partitionNames + " exist");
}
}
// check partition is in ERROR state
String sessionId = liveInstance.getSessionId();
CurrentState curState = accessor.getProperty(keyBuilder.currentState(instanceName, sessionId, resourceName));
for (String partitionName : resetPartitionNames) {
if (!curState.getState(partitionName).equals(HelixDefinedState.ERROR.toString())) {
throw new HelixException("Can't reset state for " + resourceName + "/" + partitionNames + " on " + instanceName + ", because not all " + partitionNames + " are in ERROR state");
}
}
// check stateModelDef exists and get initial state
String stateModelDef = idealState.getStateModelDefRef();
StateModelDefinition stateModel = accessor.getProperty(keyBuilder.stateModelDef(stateModelDef));
if (stateModel == null) {
throw new HelixException("Can't reset state for " + resourceName + "/" + partitionNames + " on " + instanceName + ", because " + stateModelDef + " is NOT found");
}
// check there is no pending messages for the partitions exist
List<Message> messages = accessor.getChildValues(keyBuilder.messages(instanceName));
for (Message message : messages) {
if (!MessageType.STATE_TRANSITION.name().equalsIgnoreCase(message.getMsgType()) || !sessionId.equals(message.getTgtSessionId()) || !resourceName.equals(message.getResourceName()) || !resetPartitionNames.contains(message.getPartitionName())) {
continue;
}
throw new HelixException("Can't reset state for " + resourceName + "/" + partitionNames + " on " + instanceName + ", because a pending message exists: " + message);
}
String adminName = null;
try {
adminName = InetAddress.getLocalHost().getCanonicalHostName() + "-ADMIN";
} catch (UnknownHostException e) {
// can ignore it
logger.info("Unable to get host name. Will set it to UNKNOWN, mostly ignorable", e);
adminName = "UNKNOWN";
}
List<Message> resetMessages = new ArrayList<Message>();
List<PropertyKey> messageKeys = new ArrayList<PropertyKey>();
for (String partitionName : resetPartitionNames) {
// send ERROR to initialState message
String msgId = UUID.randomUUID().toString();
Message message = new Message(MessageType.STATE_TRANSITION, msgId);
message.setSrcName(adminName);
message.setTgtName(instanceName);
message.setMsgState(MessageState.NEW);
message.setPartitionName(partitionName);
message.setResourceName(resourceName);
message.setTgtSessionId(sessionId);
message.setStateModelDef(stateModelDef);
message.setFromState(HelixDefinedState.ERROR.toString());
message.setToState(stateModel.getInitialState());
message.setStateModelFactoryName(idealState.getStateModelFactoryName());
if (idealState.getResourceGroupName() != null) {
message.setResourceGroupName(idealState.getResourceGroupName());
}
if (idealState.getInstanceGroupTag() != null) {
message.setResourceTag(idealState.getInstanceGroupTag());
}
resetMessages.add(message);
messageKeys.add(keyBuilder.message(instanceName, message.getId()));
}
accessor.setChildren(messageKeys, resetMessages);
}
use of org.apache.helix.model.IdealState in project helix by apache.
the class ZKHelixAdmin method enableResource.
@Override
public void enableResource(final String clusterName, final String resourceName, final boolean enabled) {
String path = PropertyPathBuilder.idealState(clusterName, resourceName);
BaseDataAccessor<ZNRecord> baseAccessor = new ZkBaseDataAccessor<ZNRecord>(_zkClient);
if (!baseAccessor.exists(path, 0)) {
throw new HelixException("Cluster " + clusterName + ", resource: " + resourceName + ", ideal-state does not exist");
}
baseAccessor.update(path, new DataUpdater<ZNRecord>() {
@Override
public ZNRecord update(ZNRecord currentData) {
if (currentData == null) {
throw new HelixException("Cluster: " + clusterName + ", resource: " + resourceName + ", ideal-state is null");
}
IdealState idealState = new IdealState(currentData);
idealState.enable(enabled);
return idealState.getRecord();
}
}, AccessOption.PERSISTENT);
}
use of org.apache.helix.model.IdealState in project helix by apache.
the class ZKHelixAdmin method addResource.
@Override
public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, String rebalancerMode, String rebalanceStrategy, int bucketSize, int maxPartitionsPerInstance) {
if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) {
throw new HelixException("cluster " + clusterName + " is not setup yet");
}
IdealState idealState = new IdealState(resourceName);
idealState.setNumPartitions(partitions);
idealState.setStateModelDefRef(stateModelRef);
RebalanceMode mode = idealState.rebalanceModeFromString(rebalancerMode, RebalanceMode.SEMI_AUTO);
idealState.setRebalanceMode(mode);
idealState.setRebalanceStrategy(rebalanceStrategy);
idealState.setReplicas("" + 0);
idealState.setStateModelFactoryName(HelixConstants.DEFAULT_STATE_MODEL_FACTORY);
if (maxPartitionsPerInstance > 0 && maxPartitionsPerInstance < Integer.MAX_VALUE) {
idealState.setMaxPartitionsPerInstance(maxPartitionsPerInstance);
}
if (bucketSize > 0) {
idealState.setBucketSize(bucketSize);
}
addResource(clusterName, resourceName, idealState);
}
use of org.apache.helix.model.IdealState in project helix by apache.
the class CallbackHandler method invoke.
public void invoke(NotificationContext changeContext) throws Exception {
Type type = changeContext.getType();
long start = System.currentTimeMillis();
// This allows the listener to work with one change at a time
synchronized (_manager) {
if (logger.isInfoEnabled()) {
logger.info(Thread.currentThread().getId() + " START:INVOKE " + _path + " listener:" + _listener + " type: " + type);
}
if (!_expectTypes.contains(type)) {
logger.warn("Callback handler received event in wrong order. Listener: " + _listener + ", path: " + _path + ", expected types: " + _expectTypes + " but was " + type);
return;
}
_expectTypes = nextNotificationType.get(type);
if (type == Type.INIT || type == Type.FINALIZE) {
subscribeForChanges(changeContext.getType(), _path, _watchChild);
} else {
// put SubscribeForChange run in async thread to reduce the latency of zk callback handling.
subscribeForChangesAsyn(changeContext.getType(), _path, _watchChild);
}
_expectTypes = nextNotificationType.get(type);
if (_changeType == IDEAL_STATE) {
IdealStateChangeListener idealStateChangeListener = (IdealStateChangeListener) _listener;
List<IdealState> idealStates = preFetch(_propertyKey);
idealStateChangeListener.onIdealStateChange(idealStates, changeContext);
} else if (_changeType == INSTANCE_CONFIG) {
if (_listener instanceof ConfigChangeListener) {
ConfigChangeListener configChangeListener = (ConfigChangeListener) _listener;
List<InstanceConfig> configs = preFetch(_propertyKey);
configChangeListener.onConfigChange(configs, changeContext);
} else if (_listener instanceof InstanceConfigChangeListener) {
InstanceConfigChangeListener listener = (InstanceConfigChangeListener) _listener;
List<InstanceConfig> configs = preFetch(_propertyKey);
listener.onInstanceConfigChange(configs, changeContext);
}
} else if (_changeType == RESOURCE_CONFIG) {
ResourceConfigChangeListener listener = (ResourceConfigChangeListener) _listener;
List<ResourceConfig> configs = preFetch(_propertyKey);
listener.onResourceConfigChange(configs, changeContext);
} else if (_changeType == CLUSTER_CONFIG) {
ClusterConfigChangeListener listener = (ClusterConfigChangeListener) _listener;
ClusterConfig config = null;
if (_preFetchEnabled) {
config = _accessor.getProperty(_propertyKey);
}
listener.onClusterConfigChange(config, changeContext);
} else if (_changeType == CONFIG) {
ScopedConfigChangeListener listener = (ScopedConfigChangeListener) _listener;
List<HelixProperty> configs = preFetch(_propertyKey);
listener.onConfigChange(configs, changeContext);
} else if (_changeType == LIVE_INSTANCE) {
LiveInstanceChangeListener liveInstanceChangeListener = (LiveInstanceChangeListener) _listener;
List<LiveInstance> liveInstances = preFetch(_propertyKey);
liveInstanceChangeListener.onLiveInstanceChange(liveInstances, changeContext);
} else if (_changeType == CURRENT_STATE) {
CurrentStateChangeListener currentStateChangeListener = (CurrentStateChangeListener) _listener;
String instanceName = PropertyPathConfig.getInstanceNameFromPath(_path);
List<CurrentState> currentStates = preFetch(_propertyKey);
currentStateChangeListener.onStateChange(instanceName, currentStates, changeContext);
} else if (_changeType == MESSAGE) {
MessageListener messageListener = (MessageListener) _listener;
String instanceName = PropertyPathConfig.getInstanceNameFromPath(_path);
List<Message> messages = preFetch(_propertyKey);
messageListener.onMessage(instanceName, messages, changeContext);
} else if (_changeType == MESSAGES_CONTROLLER) {
MessageListener messageListener = (MessageListener) _listener;
List<Message> messages = preFetch(_propertyKey);
messageListener.onMessage(_manager.getInstanceName(), messages, changeContext);
} else if (_changeType == EXTERNAL_VIEW || _changeType == TARGET_EXTERNAL_VIEW) {
ExternalViewChangeListener externalViewListener = (ExternalViewChangeListener) _listener;
List<ExternalView> externalViewList = preFetch(_propertyKey);
externalViewListener.onExternalViewChange(externalViewList, changeContext);
} else if (_changeType == CONTROLLER) {
ControllerChangeListener controllerChangelistener = (ControllerChangeListener) _listener;
controllerChangelistener.onControllerChange(changeContext);
} else {
logger.warn("Unknown change type: " + _changeType);
}
long end = System.currentTimeMillis();
if (logger.isInfoEnabled()) {
logger.info(Thread.currentThread().getId() + " END:INVOKE " + _path + " listener:" + _listener + " type: " + type + " Took: " + (end - start) + "ms");
}
if (_monitor != null) {
_monitor.increaseCallbackCounters(end - start);
}
}
}
Aggregations