Search in sources :

Example 11 with PathChildrenCacheEvent

use of org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent in project druid by druid-io.

the class Announcer method announce.

/**
   * Announces the provided bytes at the given path.  Announcement means that it will create an ephemeral node
   * and monitor it to make sure that it always exists until it is unannounced or this object is closed.
   *
   * @param path                  The path to announce at
   * @param bytes                 The payload to announce
   * @param removeParentIfCreated remove parent of "path" if we had created that parent
   */
public void announce(String path, byte[] bytes, boolean removeParentIfCreated) {
    synchronized (toAnnounce) {
        if (!started) {
            toAnnounce.add(new Announceable(path, bytes, removeParentIfCreated));
            return;
        }
    }
    final ZKPaths.PathAndNode pathAndNode = ZKPaths.getPathAndNode(path);
    final String parentPath = pathAndNode.getPath();
    boolean buildParentPath = false;
    ConcurrentMap<String, byte[]> subPaths = announcements.get(parentPath);
    if (subPaths == null) {
        try {
            if (curator.checkExists().forPath(parentPath) == null) {
                buildParentPath = true;
            }
        } catch (Exception e) {
            log.debug(e, "Problem checking if the parent existed, ignoring.");
        }
        // I don't have a watcher on this path yet, create a Map and start watching.
        announcements.putIfAbsent(parentPath, new MapMaker().<String, byte[]>makeMap());
        // Guaranteed to be non-null, but might be a map put in there by another thread.
        final ConcurrentMap<String, byte[]> finalSubPaths = announcements.get(parentPath);
        // Synchronize to make sure that I only create a listener once.
        synchronized (finalSubPaths) {
            if (!listeners.containsKey(parentPath)) {
                final PathChildrenCache cache = factory.make(curator, parentPath);
                cache.getListenable().addListener(new PathChildrenCacheListener() {

                    private final AtomicReference<Set<String>> pathsLost = new AtomicReference<Set<String>>(null);

                    @Override
                    public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                        log.debug("Path[%s] got event[%s]", parentPath, event);
                        switch(event.getType()) {
                            case CHILD_REMOVED:
                                final ChildData child = event.getData();
                                final ZKPaths.PathAndNode childPath = ZKPaths.getPathAndNode(child.getPath());
                                final byte[] value = finalSubPaths.get(childPath.getNode());
                                if (value != null) {
                                    log.info("Node[%s] dropped, reinstating.", child.getPath());
                                    createAnnouncement(child.getPath(), value);
                                }
                                break;
                            case CONNECTION_LOST:
                                // Lost connection, which means session is broken, take inventory of what has been seen.
                                // This is to protect from a race condition in which the ephemeral node could have been
                                // created but not actually seen by the PathChildrenCache, which means that it won't know
                                // that it disappeared and thus will not generate a CHILD_REMOVED event for us.  Under normal
                                // circumstances, this can only happen upon connection loss; but technically if you have
                                // an adversary in the system, they could also delete the ephemeral node before the cache sees
                                // it.  This does not protect from that case, so don't have adversaries.
                                Set<String> pathsToReinstate = Sets.newHashSet();
                                for (String node : finalSubPaths.keySet()) {
                                    String path = ZKPaths.makePath(parentPath, node);
                                    log.info("Node[%s] is added to reinstate.", path);
                                    pathsToReinstate.add(path);
                                }
                                if (!pathsToReinstate.isEmpty() && !pathsLost.compareAndSet(null, pathsToReinstate)) {
                                    log.info("Already had a pathsLost set!?[%s]", parentPath);
                                }
                                break;
                            case CONNECTION_RECONNECTED:
                                final Set<String> thePathsLost = pathsLost.getAndSet(null);
                                if (thePathsLost != null) {
                                    for (String path : thePathsLost) {
                                        log.info("Reinstating [%s]", path);
                                        final ZKPaths.PathAndNode split = ZKPaths.getPathAndNode(path);
                                        createAnnouncement(path, announcements.get(split.getPath()).get(split.getNode()));
                                    }
                                }
                                break;
                        }
                    }
                });
                synchronized (toAnnounce) {
                    if (started) {
                        if (buildParentPath) {
                            createPath(parentPath, removeParentIfCreated);
                        }
                        startCache(cache);
                        listeners.put(parentPath, cache);
                    }
                }
            }
        }
        subPaths = finalSubPaths;
    }
    boolean created = false;
    synchronized (toAnnounce) {
        if (started) {
            byte[] oldBytes = subPaths.putIfAbsent(pathAndNode.getNode(), bytes);
            if (oldBytes == null) {
                created = true;
            } else if (!Arrays.equals(oldBytes, bytes)) {
                throw new IAE("Cannot reannounce different values under the same path");
            }
        }
    }
    if (created) {
        try {
            createAnnouncement(path, bytes);
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
    }
}
Also used : Set(java.util.Set) PathChildrenCacheListener(org.apache.curator.framework.recipes.cache.PathChildrenCacheListener) PathChildrenCacheEvent(org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent) MapMaker(com.google.common.collect.MapMaker) AtomicReference(java.util.concurrent.atomic.AtomicReference) IAE(io.druid.java.util.common.IAE) KeeperException(org.apache.zookeeper.KeeperException) CuratorFramework(org.apache.curator.framework.CuratorFramework) PathChildrenCache(org.apache.curator.framework.recipes.cache.PathChildrenCache) ChildData(org.apache.curator.framework.recipes.cache.ChildData) ZKPaths(org.apache.curator.utils.ZKPaths)

Example 12 with PathChildrenCacheEvent

use of org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent in project chassis by Kixeye.

the class DynamicZookeeperConfigurationSource method initializePathChildrenCache.

private void initializePathChildrenCache() {
    pathChildrenCache = new PathChildrenCache(curatorFramework, configPathRoot, true);
    pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {

        @Override
        public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
            LOGGER.debug("Got event {}", event);
            if (event.getType() == PathChildrenCacheEvent.Type.CHILD_ADDED && event.getData().getPath().equals(instanceConfigPath)) {
                //do stuff
                LOGGER.info("Detected creation of node {}. Initializing zookeeper configuration source...", instanceConfigPath);
                try {
                    initializeZookeeperConfigurationSource();
                } catch (BootstrapException e) {
                    LOGGER.error("Failed to initialized zookeeper configuration source for path " + instanceConfigPath, e);
                    throw e;
                }
                return;
            }
            if (event.getType() == PathChildrenCacheEvent.Type.CHILD_REMOVED && event.getData().getPath().equals(instanceConfigPath)) {
                if (running) {
                    LOGGER.info("Detected deletion of node {}, destroying zookeeper configuration source...", instanceConfigPath);
                    destroyZookeeperCofigurationSource();
                    return;
                }
                LOGGER.warn("Detected deletion of node {}, but zookeeper configuration source not currently running. This should not happen. Ignoring event...", instanceConfigPath);
                return;
            }
            LOGGER.debug("Ignoring event {}", event);
        }
    });
    try {
        pathChildrenCache.start(StartMode.BUILD_INITIAL_CACHE);
    } catch (Exception e) {
        throw new BootstrapException("Failed to initialize zookeeper configuration path cache" + configPathRoot, e);
    }
}
Also used : CuratorFramework(org.apache.curator.framework.CuratorFramework) PathChildrenCacheListener(org.apache.curator.framework.recipes.cache.PathChildrenCacheListener) PathChildrenCacheEvent(org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent) PathChildrenCache(org.apache.curator.framework.recipes.cache.PathChildrenCache) BootstrapException(com.kixeye.chassis.bootstrap.BootstrapException) BootstrapException(com.kixeye.chassis.bootstrap.BootstrapException) IOException(java.io.IOException)

Example 13 with PathChildrenCacheEvent

use of org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent in project drill by apache.

the class TestEventDispatcher method testDispatcherPropagatesEvents.

@Test
public void testDispatcherPropagatesEvents() throws Exception {
    final PathChildrenCacheEvent.Type[] types = new PathChildrenCacheEvent.Type[] { PathChildrenCacheEvent.Type.CHILD_ADDED, PathChildrenCacheEvent.Type.CHILD_REMOVED, PathChildrenCacheEvent.Type.CHILD_UPDATED };
    for (final PathChildrenCacheEvent.Type type : types) {
        dispatcher.childEvent(null, new PathChildrenCacheEvent(type, child));
        final TransientStoreEvent event = TransientStoreEvent.of(EventDispatcher.MAPPINGS.get(type), key, value);
        Mockito.verify(store).fireListeners(event);
    }
    Assert.assertEquals("Number of event types that dispatcher can handle is different", types.length, EventDispatcher.MAPPINGS.size());
}
Also used : TransientStoreEvent(org.apache.drill.exec.coord.store.TransientStoreEvent) PathChildrenCacheEvent(org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent) Test(org.junit.Test)

Aggregations

PathChildrenCacheEvent (org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent)13 CuratorFramework (org.apache.curator.framework.CuratorFramework)11 PathChildrenCacheListener (org.apache.curator.framework.recipes.cache.PathChildrenCacheListener)11 IOException (java.io.IOException)6 PathChildrenCache (org.apache.curator.framework.recipes.cache.PathChildrenCache)5 KeeperException (org.apache.zookeeper.KeeperException)4 Test (org.junit.Test)4 DataSegment (io.druid.timeline.DataSegment)3 CountDownLatch (java.util.concurrent.CountDownLatch)3 ExecutionException (java.util.concurrent.ExecutionException)3 ChildData (org.apache.curator.framework.recipes.cache.ChildData)3 LifecycleStart (io.druid.java.util.common.lifecycle.LifecycleStart)2 MalformedURLException (java.net.MalformedURLException)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 NoNodeException (org.apache.zookeeper.KeeperException.NoNodeException)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 MapMaker (com.google.common.collect.MapMaker)1 FutureCallback (com.google.common.util.concurrent.FutureCallback)1