com.hubspot.singularity.data.CuratorAsyncManager Maven / Gradle / Ivy
package com.hubspot.singularity.data;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.utils.ZKPaths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.hubspot.mesos.JavaUtils;
import com.hubspot.singularity.SingularityId;
import com.hubspot.singularity.data.transcoders.IdTranscoder;
import com.hubspot.singularity.data.transcoders.Transcoder;
import com.hubspot.singularity.data.transcoders.Transcoders;
public abstract class CuratorAsyncManager extends CuratorManager {
private static final Logger LOG = LoggerFactory.getLogger(CuratorAsyncManager.class);
private final long zkAsyncTimeout;
public CuratorAsyncManager(CuratorFramework curator, long zkAsyncTimeout) {
super(curator);
this.zkAsyncTimeout = zkAsyncTimeout;
}
private List getAsyncChildrenThrows(final String parent, final Transcoder transcoder) throws Exception {
final List children = getChildren(parent);
LOG.trace("Fetched {} children from path {}", children.size(), parent);
final List paths = Lists.newArrayListWithCapacity(children.size());
for (String child : children) {
paths.add(ZKPaths.makePath(parent, child));
}
return getAsyncThrows(parent, paths, transcoder);
}
private List getAsyncThrows(final String pathNameForLogs, final Collection paths, final Transcoder transcoder) throws Exception {
final List objects = Lists.newArrayListWithCapacity(paths.size());
if (paths.isEmpty()) {
return objects;
}
final CountDownLatch latch = new CountDownLatch(paths.size());
final AtomicInteger missing = new AtomicInteger();
final BackgroundCallback callback = new BackgroundCallback() {
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
if (event.getData() == null || event.getData().length == 0) {
LOG.trace("Expected active node {} but it wasn't there", event.getPath());
missing.incrementAndGet();
latch.countDown();
return;
}
objects.add(transcoder.fromBytes(event.getData()));
latch.countDown();
}
};
final long start = System.currentTimeMillis();
for (String path : paths) {
curator.getData().inBackground(callback).forPath(path);
}
checkLatch(latch, pathNameForLogs);
LOG.trace("Fetched {} objects from {} (missing {}) in {}", objects.size(), pathNameForLogs, missing.intValue(), JavaUtils.duration(start));
return objects;
}
private void checkLatch(CountDownLatch latch, String path) throws InterruptedException {
if (!latch.await(zkAsyncTimeout, TimeUnit.MILLISECONDS)) {
throw new IllegalStateException(String.format("Timed out waiting response for objects from %s, waited %s millis", path, zkAsyncTimeout));
}
}
private List getChildrenAsIdsForParentsThrows(final String pathNameforLogs, final Collection parents, final IdTranscoder idTranscoder) throws Exception {
if (parents.isEmpty()) {
return Collections.emptyList();
}
final List objects = Lists.newArrayListWithExpectedSize(parents.size());
final CountDownLatch latch = new CountDownLatch(parents.size());
final AtomicInteger missing = new AtomicInteger();
final BackgroundCallback callback = new BackgroundCallback() {
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
if (event.getChildren() == null || event.getChildren().size() == 0) {
LOG.trace("Expected children for node {} - but found none", event.getPath());
missing.incrementAndGet();
latch.countDown();
return;
}
objects.addAll(Lists.transform(event.getChildren(), Transcoders.getFromStringFunction(idTranscoder)));
latch.countDown();
}
};
final long start = System.currentTimeMillis();
for (String parent : parents) {
curator.getChildren().inBackground(callback).forPath(parent);
}
checkLatch(latch, pathNameforLogs);
LOG.trace("Fetched {} objects from {} (missing {}) in {}", objects.size(), pathNameforLogs, missing.intValue(), JavaUtils.duration(start));
return objects;
}
protected List getChildrenAsIdsForParents(final String pathNameforLogs, final Collection parents, final IdTranscoder idTranscoder) {
try {
return getChildrenAsIdsForParentsThrows(pathNameforLogs, parents, idTranscoder);
} catch (Throwable t) {
throw Throwables.propagate(t);
}
}
protected List getChildrenAsIds(final String rootPath, final IdTranscoder idTranscoder) {
return Lists.transform(getChildren(rootPath), Transcoders.getFromStringFunction(idTranscoder));
}
private List existsThrows(final String pathNameforLogs, final Collection paths, final IdTranscoder idTranscoder) throws Exception {
if (paths.isEmpty()) {
return Collections.emptyList();
}
final List objects = Lists.newArrayListWithCapacity(paths.size());
final CountDownLatch latch = new CountDownLatch(paths.size());
final BackgroundCallback callback = new BackgroundCallback() {
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
if (event.getStat() == null) {
latch.countDown();
return;
}
objects.add(Transcoders.getFromStringFunction(idTranscoder).apply(ZKPaths.getNodeFromPath(event.getPath())));
latch.countDown();
}
};
final long start = System.currentTimeMillis();
for (String path : paths) {
curator.checkExists().inBackground(callback).forPath(path);
}
checkLatch(latch, pathNameforLogs);
LOG.trace("Found {} objects out of {} from {} in {}", objects.size(), paths.size(), pathNameforLogs, JavaUtils.duration(start));
return objects;
}
protected List exists(final String pathNameForLogs, final Collection paths, final IdTranscoder idTranscoder) {
try {
return existsThrows(pathNameForLogs, paths, idTranscoder);
} catch (Throwable t) {
throw Throwables.propagate(t);
}
}
protected List getAsync(final String pathNameForLogs, final Collection paths, final Transcoder transcoder) {
try {
return getAsyncThrows(pathNameForLogs, paths, transcoder);
} catch (Throwable t) {
throw Throwables.propagate(t);
}
}
protected List getAsyncChildren(final String parent, final Transcoder transcoder) {
try {
return getAsyncChildrenThrows(parent, transcoder);
} catch (Throwable t) {
throw Throwables.propagate(t);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy