use of org.apache.helix.api.exceptions.HelixMetaDataAccessException in project helix by apache.
the class ZkBaseDataAccessor method get.
/**
* async get
*/
List<T> get(List<String> paths, List<Stat> stats, boolean[] needRead, boolean throwException) throws HelixException {
if (paths == null || paths.size() == 0) {
return Collections.emptyList();
}
// init stats
if (stats != null) {
stats.clear();
stats.addAll(Collections.<Stat>nCopies(paths.size(), null));
}
long startT = System.nanoTime();
try {
// issue asyn get requests
GetDataCallbackHandler[] cbList = new GetDataCallbackHandler[paths.size()];
for (int i = 0; i < paths.size(); i++) {
if (!needRead[i])
continue;
String path = paths.get(i);
cbList[i] = new GetDataCallbackHandler();
_zkClient.asyncGetData(path, cbList[i]);
}
// wait for completion
for (int i = 0; i < cbList.length; i++) {
if (!needRead[i])
continue;
GetDataCallbackHandler cb = cbList[i];
cb.waitForSuccess();
}
// construct return results
List<T> records = new ArrayList<T>(Collections.<T>nCopies(paths.size(), null));
Map<String, Integer> pathFailToRead = new HashMap<>();
for (int i = 0; i < paths.size(); i++) {
if (!needRead[i])
continue;
GetDataCallbackHandler cb = cbList[i];
if (Code.get(cb.getRc()) == Code.OK) {
@SuppressWarnings("unchecked") T record = (T) _zkClient.deserialize(cb._data, paths.get(i));
records.set(i, record);
if (stats != null) {
stats.set(i, cb._stat);
}
} else if (Code.get(cb.getRc()) != Code.NONODE && throwException) {
throw new HelixMetaDataAccessException(String.format("Failed to read node %s", paths.get(i)));
} else {
pathFailToRead.put(paths.get(i), cb.getRc());
}
}
if (pathFailToRead.size() > 0) {
LOG.warn("Fail to read record for paths: " + pathFailToRead);
}
return records;
} catch (Exception e) {
throw new HelixMetaDataAccessException(String.format("Fail to read nodes for %s", paths));
} finally {
long endT = System.nanoTime();
if (LOG.isTraceEnabled()) {
LOG.trace("getData_async, size: " + paths.size() + ", paths: " + paths.get(0) + ",... time: " + (endT - startT) + " ns");
}
}
}
use of org.apache.helix.api.exceptions.HelixMetaDataAccessException in project helix by apache.
the class TestHelixDataAccessor method testHelixDataAccessorReadData.
@Test
public void testHelixDataAccessorReadData() {
accessor.getProperty(new ArrayList<>(propertyKeys), false);
try {
accessor.getProperty(new ArrayList<>(propertyKeys), true);
Assert.fail();
} catch (HelixMetaDataAccessException ex) {
}
PropertyKey idealStates = accessor.keyBuilder().idealStates();
accessor.getChildValues(idealStates, false);
try {
accessor.getChildValues(idealStates, true);
Assert.fail();
} catch (HelixMetaDataAccessException ex) {
}
accessor.getChildValuesMap(idealStates, false);
try {
accessor.getChildValuesMap(idealStates, true);
Assert.fail();
} catch (HelixMetaDataAccessException ex) {
}
}
use of org.apache.helix.api.exceptions.HelixMetaDataAccessException in project helix by apache.
the class ZKHelixDataAccessor method setProperty.
@Override
public <T extends HelixProperty> boolean setProperty(PropertyKey key, T value) {
PropertyType type = key.getType();
if (!value.isValid()) {
throw new HelixMetaDataAccessException("The ZNRecord for " + type + " is not valid.");
}
String path = key.getPath();
int options = constructOptions(type);
boolean success = false;
switch(type) {
case IDEALSTATES:
case EXTERNALVIEW:
// check if bucketized
if (value.getBucketSize() > 0) {
// set parent node
ZNRecord metaRecord = new ZNRecord(value.getId());
metaRecord.setSimpleFields(value.getRecord().getSimpleFields());
success = _baseDataAccessor.set(path, metaRecord, options);
if (success) {
ZNRecordBucketizer bucketizer = new ZNRecordBucketizer(value.getBucketSize());
Map<String, ZNRecord> map = bucketizer.bucketize(value.getRecord());
List<String> paths = new ArrayList<String>();
List<ZNRecord> bucketizedRecords = new ArrayList<ZNRecord>();
for (String bucketName : map.keySet()) {
paths.add(path + "/" + bucketName);
bucketizedRecords.add(map.get(bucketName));
}
// TODO: set success accordingly
_baseDataAccessor.setChildren(paths, bucketizedRecords, options);
}
} else {
success = _baseDataAccessor.set(path, value.getRecord(), options);
}
break;
default:
success = _baseDataAccessor.set(path, value.getRecord(), options);
break;
}
return success;
}
use of org.apache.helix.api.exceptions.HelixMetaDataAccessException in project helix by apache.
the class ZkBaseDataAccessor method getChildren.
@Override
public List<T> getChildren(String parentPath, List<Stat> stats, int options, int retryCount, int retryInterval) throws HelixException {
int readCount = retryCount + 1;
while (readCount > 0) {
try {
readCount--;
List<T> records = getChildren(parentPath, stats, options, true);
return records;
} catch (HelixMetaDataAccessException e) {
if (readCount == 0) {
throw new HelixMetaDataAccessException(String.format("Failed to get full list of %s", parentPath), e);
}
try {
Thread.sleep(retryInterval);
} catch (InterruptedException interruptedException) {
throw new HelixMetaDataAccessException("Fail to interrupt the sleep", interruptedException);
}
}
}
// Impossible to reach end
return null;
}
use of org.apache.helix.api.exceptions.HelixMetaDataAccessException in project helix by apache.
the class GenericHelixController method handleEvent.
/**
* lock-always: caller always needs to obtain an external lock before call, calls to handleEvent()
* should be serialized
* @param event
*/
protected void handleEvent(ClusterEvent event, ClusterDataCache cache) {
HelixManager manager = event.getAttribute(AttributeName.helixmanager.name());
if (manager == null) {
logger.error("No cluster manager in event:" + event.getEventType());
return;
}
if (!manager.isLeader()) {
logger.error("Cluster manager: " + manager.getInstanceName() + " is not leader for " + manager.getClusterName() + ". Pipeline will not be invoked");
return;
}
// will be excuting in un-paused mode. Which might not be the config in ZK.
if (_paused) {
logger.info("Cluster " + manager.getClusterName() + " is paused. Ignoring the event:" + event.getEventType());
return;
}
NotificationContext context = null;
if (event.getAttribute(AttributeName.changeContext.name()) != null) {
context = event.getAttribute(AttributeName.changeContext.name());
}
if (context != null) {
if (context.getType() == Type.FINALIZE) {
stopRebalancingTimers();
logger.info("Get FINALIZE notification, skip the pipeline. Event :" + event.getEventType());
return;
} else {
// TODO: should be in the initialization of controller.
if (_cache != null) {
checkRebalancingTimer(manager, Collections.EMPTY_LIST, _cache.getClusterConfig());
}
if (_isMonitoring) {
event.addAttribute(AttributeName.clusterStatusMonitor.name(), _clusterStatusMonitor);
}
}
}
// add the cache
event.addAttribute(AttributeName.ClusterDataCache.name(), cache);
List<Pipeline> pipelines = cache.isTaskCache() ? _taskRegistry.getPipelinesForEvent(event.getEventType()) : _registry.getPipelinesForEvent(event.getEventType());
if (pipelines == null || pipelines.size() == 0) {
logger.info("No " + getPipelineType(cache.isTaskCache()) + " pipeline to run for event:" + event.getEventType());
return;
}
logger.info(String.format("START: Invoking %s controller pipeline for cluster %s event: %s", manager.getClusterName(), getPipelineType(cache.isTaskCache()), event.getEventType()));
long startTime = System.currentTimeMillis();
boolean rebalanceFail = false;
for (Pipeline pipeline : pipelines) {
try {
pipeline.handle(event);
pipeline.finish();
} catch (Exception e) {
logger.error("Exception while executing " + getPipelineType(cache.isTaskCache()) + "pipeline: " + pipeline + "for cluster ." + _clusterName + ". Will not continue to next pipeline", e);
if (e instanceof HelixMetaDataAccessException) {
rebalanceFail = true;
// If pipeline failed due to read/write fails to zookeeper, retry the pipeline.
cache.requireFullRefresh();
logger.warn("Rebalance pipeline failed due to read failure from zookeeper, cluster: " + _clusterName);
// only push a retry event when there is no pending event in the corresponding event queue.
if (isEventQueueEmpty(cache.isTaskCache())) {
_continousRebalanceFailureCount++;
long delay = getRetryDelay(_continousRebalanceFailureCount);
if (delay == 0) {
forceRebalance(manager, ClusterEventType.RetryRebalance);
} else {
_asyncTasksThreadPool.schedule(new RebalanceTask(manager, ClusterEventType.RetryRebalance), delay, TimeUnit.MILLISECONDS);
}
logger.info("Retry rebalance pipeline with delay " + delay + "ms for cluster: " + _clusterName);
}
}
_clusterStatusMonitor.reportRebalanceFailure();
break;
}
}
if (!rebalanceFail) {
_continousRebalanceFailureCount = 0;
}
long endTime = System.currentTimeMillis();
logger.info(String.format("END: Invoking %s controller pipeline for event: %s for cluster %s, took %d ms", getPipelineType(cache.isTaskCache()), event.getEventType(), manager.getClusterName(), (endTime - startTime)));
if (!cache.isTaskCache()) {
// report event process durations
NotificationContext notificationContext = event.getAttribute(AttributeName.changeContext.name());
long enqueueTime = event.getCreationTime();
long zkCallbackTime;
StringBuilder sb = new StringBuilder();
if (notificationContext != null) {
zkCallbackTime = notificationContext.getCreationTime();
if (_isMonitoring) {
_clusterStatusMonitor.updateClusterEventDuration(ClusterEventMonitor.PhaseName.Callback.name(), enqueueTime - zkCallbackTime);
}
sb.append(String.format("Callback time for event: " + event.getEventType() + " took: " + (enqueueTime - zkCallbackTime) + " ms\n"));
}
if (_isMonitoring) {
_clusterStatusMonitor.updateClusterEventDuration(ClusterEventMonitor.PhaseName.InQueue.name(), startTime - enqueueTime);
_clusterStatusMonitor.updateClusterEventDuration(ClusterEventMonitor.PhaseName.TotalProcessed.name(), endTime - startTime);
}
sb.append(String.format("InQueue time for event: " + event.getEventType() + " took: " + (startTime - enqueueTime) + " ms\n"));
sb.append(String.format("TotalProcessed time for event: " + event.getEventType() + " took: " + (endTime - startTime) + " ms"));
logger.info(sb.toString());
} else if (_isMonitoring) {
// report workflow status
TaskDriver driver = new TaskDriver(manager);
_clusterStatusMonitor.refreshWorkflowsStatus(driver);
_clusterStatusMonitor.refreshJobsStatus(driver);
}
// If event handling happens before controller deactivate, the process may write unnecessary
// MBeans to monitoring after the monitor is disabled.
// So reset ClusterStatusMonitor according to it's status after all event handling.
// TODO remove this once clusterStatusMonitor blocks any MBean register on isMonitoring = false.
resetClusterStatusMonitor();
}
Aggregations