[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14090934#comment-14090934 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-51625311 Oops, will fix. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Cameron McKenzie > Fix For: 2.7.0 > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14090744#comment-14090744 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-51598892 A Java 7ism go into the code. Please fix: https://issues.apache.org/jira/browse/CURATOR-137 > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Cameron McKenzie > Fix For: 2.7.0 > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14090457#comment-14090457 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-51574445 Thanks! I'll follow up with the event unification we talked about. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Cameron McKenzie > Fix For: 2.7.0 > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14090192#comment-14090192 ] ASF GitHub Bot commented on CURATOR-33: --- Github user asfgit closed the pull request at: https://github.com/apache/curator/pull/17 > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: 2.7.0 > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14090130#comment-14090130 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15974091 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14090020#comment-14090020 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15970735 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14089913#comment-14089913 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15966979 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14089711#comment-14089711 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15959752 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14089708#comment-14089708 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15959716 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088813#comment-14088813 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15917910 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088805#comment-14088805 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15917752 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088782#comment-14088782 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15917583 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088781#comment-14088781 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15917546 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088780#comment-14088780 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15917501 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088693#comment-14088693 ] Jordan Zimmerman commented on CURATOR-33: - At some point in the future, we might consider deprecating PathChildrenCache or replacing it's implementation with a contained TreeCache. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088662#comment-14088662 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15915401 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088658#comment-14088658 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15915346 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCacheEvent.java --- @@ -0,0 +1,126 @@ +/** --- End diff -- Ok. What do you think if I rename these to CacheEvent / CacheListener for now, and then after this lands, go back separately and add the new listener APIs to NodeCache and PathChildrenCache? Or does it need to be 100% done in one shot? > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088661#comment-14088661 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15915372 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14088656#comment-14088656 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15915313 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java --- @@ -0,0 +1,335 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.collect.ImmutableSet; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.test.KillSession; +import org.apache.curator.utils.CloseableUtils; +import org.apache.zookeeper.CreateMode; +import org.testng.Assert; +import org.testng.annotations.Test; +import java.util.concurrent.Semaphore; + +public class TestTreeCache extends BaseTestTreeCache +{ +@Test +public void testStartup() throws Exception +{ +client.create().forPath("/test"); +client.create().forPath("/test/1", "one".getBytes()); +client.create().forPath("/test/2", "two".getBytes()); +client.create().forPath("/test/3", "three".getBytes()); +client.create().forPath("/test/2/sub", "two-sub".getBytes()); + +cache.start(); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/1", "one".getBytes()); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/2", "two".getBytes()); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/3", "three".getBytes()); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/2/sub", "two-sub".getBytes()); +assertEvent(TreeCacheEvent.Type.INITIALIZED); +assertNoMoreEvents(); + +Assert.assertEquals(cache.getCurrentChildren("/test").keySet(), ImmutableSet.of("1", "2", "3")); +Assert.assertEquals(cache.getCurrentChildren("/test/1").keySet(), ImmutableSet.of()); +Assert.assertEquals(cache.getCurrentChildren("/test/2").keySet(), ImmutableSet.of("sub")); +Assert.assertNull(cache.getCurrentChildren("/test/non_exist")); +} + +@Test +public void testStartEmpty() throws Exception +{ +cache.start(); +assertEvent(TreeCacheEvent.Type.INITIALIZED); + +client.create().forPath("/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertNoMoreEvents(); +} + +@Test +public void testAsyncInitialPopulation() throws Exception +{ +client.create().forPath("/test"); +client.create().forPath("/test/one", "hey there".getBytes()); + +cache.start(); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/one"); +assertEvent(TreeCacheEvent.Type.INITIALIZED); +assertNoMoreEvents(); +} + +@Test +public void testFromRoot() throws Exception +{ +client.create().forPath("/test"); +client.create().forPath("/test/one", "hey there".getBytes()); + +cache = new TreeCache(client, "/", true); +cache.start(); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/one"); +assertEvent(TreeCacheEvent.Type.INITIALIZED); +assertNoMoreEvents(); + + Assert.assertTrue(cache.getCurrentChildren("/").keySet().contains("test")); +Assert.assertEquals(cache.getCurrentChildren("/test").keySet(), ImmutableSet.of("one")); + Assert.assertEquals(cache.getCurrentChildren("/t
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14086891#comment-14086891 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15845904 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,648 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +private final class TreeNode implements Watcher, BackgroundCallback +{ +final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +final TreeNode parent; +final String path; +final AtomicReference stat = new AtomicReference(); +final AtomicReference data = new AtomicReference(); +final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refresh() throws Exception +{ +outstandingOps.addAndGet(2); +doRefreshData(); +doRefreshChildren(); +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshChildren(); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +doRefreshData(); +}
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14086357#comment-14086357 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15819107 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/BaseTestTreeCache.java --- @@ -0,0 +1,173 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.api.UnhandledErrorListener; +import org.apache.curator.retry.RetryOneTime; +import org.apache.curator.test.BaseClassForTests; +import org.apache.curator.test.Timing; +import org.apache.curator.utils.CloseableUtils; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class BaseTestTreeCache extends BaseClassForTests +{ +private final Timing timing = new Timing(); +CuratorFramework client; +TreeCache cache; +private List exceptions; +private BlockingQueue events; +TreeCacheListener eventListener; + +/** + * A TreeCache that records exceptions and automatically adds a listener. + */ +class TreeCache extends org.apache.curator.framework.recipes.cache.TreeCache --- End diff -- I'd rename it. It confused me. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14086362#comment-14086362 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15819222 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/BaseTestTreeCache.java --- @@ -0,0 +1,173 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.api.UnhandledErrorListener; +import org.apache.curator.retry.RetryOneTime; +import org.apache.curator.test.BaseClassForTests; +import org.apache.curator.test.Timing; +import org.apache.curator.utils.CloseableUtils; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class BaseTestTreeCache extends BaseClassForTests +{ +private final Timing timing = new Timing(); +CuratorFramework client; +TreeCache cache; +private List exceptions; +private BlockingQueue events; +TreeCacheListener eventListener; + +/** + * A TreeCache that records exceptions and automatically adds a listener. + */ +class TreeCache extends org.apache.curator.framework.recipes.cache.TreeCache --- End diff -- K. Originally I was going to name it "TestTreeCache" but then realized it conflicted with the test of the same name. I'll figure something out. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14086358#comment-14086358 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15819163 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java --- @@ -0,0 +1,335 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.collect.ImmutableSet; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.test.KillSession; +import org.apache.curator.utils.CloseableUtils; +import org.apache.zookeeper.CreateMode; +import org.testng.Assert; +import org.testng.annotations.Test; +import java.util.concurrent.Semaphore; + +public class TestTreeCache extends BaseTestTreeCache +{ +@Test +public void testStartup() throws Exception +{ +client.create().forPath("/test"); +client.create().forPath("/test/1", "one".getBytes()); +client.create().forPath("/test/2", "two".getBytes()); +client.create().forPath("/test/3", "three".getBytes()); +client.create().forPath("/test/2/sub", "two-sub".getBytes()); + +cache.start(); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/1", "one".getBytes()); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/2", "two".getBytes()); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/3", "three".getBytes()); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/2/sub", "two-sub".getBytes()); +assertEvent(TreeCacheEvent.Type.INITIALIZED); +assertNoMoreEvents(); + +Assert.assertEquals(cache.getCurrentChildren("/test").keySet(), ImmutableSet.of("1", "2", "3")); +Assert.assertEquals(cache.getCurrentChildren("/test/1").keySet(), ImmutableSet.of()); +Assert.assertEquals(cache.getCurrentChildren("/test/2").keySet(), ImmutableSet.of("sub")); +Assert.assertNull(cache.getCurrentChildren("/test/non_exist")); +} + +@Test +public void testStartEmpty() throws Exception +{ +cache.start(); +assertEvent(TreeCacheEvent.Type.INITIALIZED); + +client.create().forPath("/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertNoMoreEvents(); +} + +@Test +public void testAsyncInitialPopulation() throws Exception +{ +client.create().forPath("/test"); +client.create().forPath("/test/one", "hey there".getBytes()); + +cache.start(); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/one"); +assertEvent(TreeCacheEvent.Type.INITIALIZED); +assertNoMoreEvents(); +} + +@Test +public void testFromRoot() throws Exception +{ +client.create().forPath("/test"); +client.create().forPath("/test/one", "hey there".getBytes()); + +cache = new TreeCache(client, "/", true); +cache.start(); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/one"); +assertEvent(TreeCacheEvent.Type.INITIALIZED); +assertNoMoreEvents(); + + Assert.assertTrue(cache.getCurrentChildren("/").keySet().contains("test")); +Assert.assertEquals(cache.getCurrentChildren("/test").keySet(), ImmutableSet.of("one")); + Assert.assertEquals(cache.getCurrentChildren("/t
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14086354#comment-14086354 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15819016 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/BaseTestTreeCache.java --- @@ -0,0 +1,173 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.api.UnhandledErrorListener; +import org.apache.curator.retry.RetryOneTime; +import org.apache.curator.test.BaseClassForTests; +import org.apache.curator.test.Timing; +import org.apache.curator.utils.CloseableUtils; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class BaseTestTreeCache extends BaseClassForTests +{ +private final Timing timing = new Timing(); +CuratorFramework client; +TreeCache cache; +private List exceptions; +private BlockingQueue events; +TreeCacheListener eventListener; + +/** + * A TreeCache that records exceptions and automatically adds a listener. + */ +class TreeCache extends org.apache.curator.framework.recipes.cache.TreeCache --- End diff -- Because the local class shadows it. `class TreeCache extends TreeCache` would extend itself. Arguably, I could rename the local class to "MyTreeCache" or something, if you guys think that's the better style. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14086290#comment-14086290 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15813477 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java --- @@ -0,0 +1,335 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.collect.ImmutableSet; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.test.KillSession; +import org.apache.curator.utils.CloseableUtils; +import org.apache.zookeeper.CreateMode; +import org.testng.Assert; +import org.testng.annotations.Test; +import java.util.concurrent.Semaphore; + +public class TestTreeCache extends BaseTestTreeCache +{ +@Test +public void testStartup() throws Exception +{ +client.create().forPath("/test"); +client.create().forPath("/test/1", "one".getBytes()); +client.create().forPath("/test/2", "two".getBytes()); +client.create().forPath("/test/3", "three".getBytes()); +client.create().forPath("/test/2/sub", "two-sub".getBytes()); + +cache.start(); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/1", "one".getBytes()); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/2", "two".getBytes()); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/3", "three".getBytes()); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/2/sub", "two-sub".getBytes()); +assertEvent(TreeCacheEvent.Type.INITIALIZED); +assertNoMoreEvents(); + +Assert.assertEquals(cache.getCurrentChildren("/test").keySet(), ImmutableSet.of("1", "2", "3")); +Assert.assertEquals(cache.getCurrentChildren("/test/1").keySet(), ImmutableSet.of()); +Assert.assertEquals(cache.getCurrentChildren("/test/2").keySet(), ImmutableSet.of("sub")); +Assert.assertNull(cache.getCurrentChildren("/test/non_exist")); +} + +@Test +public void testStartEmpty() throws Exception +{ +cache.start(); +assertEvent(TreeCacheEvent.Type.INITIALIZED); + +client.create().forPath("/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertNoMoreEvents(); +} + +@Test +public void testAsyncInitialPopulation() throws Exception +{ +client.create().forPath("/test"); +client.create().forPath("/test/one", "hey there".getBytes()); + +cache.start(); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/one"); +assertEvent(TreeCacheEvent.Type.INITIALIZED); +assertNoMoreEvents(); +} + +@Test +public void testFromRoot() throws Exception +{ +client.create().forPath("/test"); +client.create().forPath("/test/one", "hey there".getBytes()); + +cache = new TreeCache(client, "/", true); +cache.start(); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test"); +assertEvent(TreeCacheEvent.Type.NODE_ADDED, "/test/one"); +assertEvent(TreeCacheEvent.Type.INITIALIZED); +assertNoMoreEvents(); + + Assert.assertTrue(cache.getCurrentChildren("/").keySet().contains("test")); +Assert.assertEquals(cache.getCurrentChildren("/test").keySet(), ImmutableSet.of("one")); + Assert.assertEquals(cache.getCurrentChildren("/test
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14086287#comment-14086287 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15813324 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/BaseTestTreeCache.java --- @@ -0,0 +1,173 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.api.UnhandledErrorListener; +import org.apache.curator.retry.RetryOneTime; +import org.apache.curator.test.BaseClassForTests; +import org.apache.curator.test.Timing; +import org.apache.curator.utils.CloseableUtils; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class BaseTestTreeCache extends BaseClassForTests +{ +private final Timing timing = new Timing(); +CuratorFramework client; +TreeCache cache; +private List exceptions; +private BlockingQueue events; +TreeCacheListener eventListener; + +/** + * A TreeCache that records exceptions and automatically adds a listener. + */ +class TreeCache extends org.apache.curator.framework.recipes.cache.TreeCache --- End diff -- Why is the base class spelled out with a FQPN? > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082740#comment-14082740 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50921130 Just to be sure, I went back and instrumented the entire refresh() section like this: ``` private void refresh() throws Exception { for ( int i = 0; i < 20; ++i ) { executorService.submit(new Callable() { @Override public Void call() throws Exception { outstandingOps.addAndGet(2); Thread.sleep(random.nextInt(30)); doRefreshData(); Thread.sleep(random.nextInt(30)); doRefreshChildren(); return null; } }); } } private void doRefreshChildren() throws Exception { GetChildrenBuilder children1 = client.getChildren(); Thread.sleep(random.nextInt(30)); BackgroundPathable> listBackgroundPathable = children1.usingWatcher(this); Thread.sleep(random.nextInt(30)); Pathable> listPathable = listBackgroundPathable.inBackground(this); Thread.sleep(random.nextInt(30)); listPathable.forPath(path); } ``` All the test still pass (just way more slowly) despite there being 20 threads racing each other on every op. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082735#comment-14082735 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50920900 wasDeleted() can only be called from the watch event / background result thread, not the connection state listener. It is true it can be called concurrently from TreeCache.close(), but I believe wasDeleted() is completely idempotent / concurrency safe. The first several operations are completely idempotent, it's harmless to run them multiple times. After that, there's an escape hatch if the tree is closing (which will have already been set in the TreeCache.close() case). After THAT, there's a an atomic compare-and-set to publish a delete event, which only one thread can win. And the remainder of the method is also idempotent. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082697#comment-14082697 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50919247 Yes, and I think that's okay. refreshData() should be concurrency safe. All it does is atomically increment the outstanding ops (so no race there), then queue up a curator background operation, e.g. `client.getData().usingWatcher(this).inBackground(this).forPath(path);` There's no reason this would be a problem, right? path is final so it won't change, CuratorFramework itself should be thread safe, and if the same operation happens twice at the same time, the callbacks will still come back in serial, and the second (duplicate) result should be the same and not produce an event. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082714#comment-14082714 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50919952 What about wasDeleted()? > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082688#comment-14082688 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50918629 Imagine a scenario where there is a temporary connection problem. Curator will send SUSPENDED. If the connect gets repaired and the session survives, Curator will send RECONNECTED. At nearly the same time, some of the watchers might get called due to watched changes. Thus, a method like refreshData() might get called simultaneously by two threads. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082683#comment-14082683 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50918370 Good call, will do. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082681#comment-14082681 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50918169 So I looked through the issue you described with respect to wasReconnected() being called concurrently with refreshData / refreshChildren. I can't actually see any potential problems with this. None of the code paths from wasReconnected()/wasCreated()/wasDeleted() perform any mutations, all they ultimately do is queue up ZK operations which fire on the serialized background response thread. The background response thread is the only thread that mutates the tree. Do you see something I'm missing? > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082678#comment-14082678 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50917549 I think that introduces a new problem. What if the background callback executes before the finally block. The initial event notification won't get sent until there's a change in the tree. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082672#comment-14082672 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50917378 Okay, the outstandingOps race was easy to resolve, I'm changing refresh() to do this: ``` private void refresh() throws Exception { // Push an extra op so that a race between refreshData() response and // refreshChildren() can't cause the outstanding ops to drop to zero. try { outstandingOps.incrementAndGet(); refreshData(); refreshChildren(); } finally { outstandingOps.decrementAndGet(); } } ``` With this I can add a Thread.sleep() at that start of refreshChildren() and there's no problem. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082603#comment-14082603 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50913980 Good find! I'll look at the race conditions today. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082597#comment-14082597 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15708789 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082246#comment-14082246 ] ASF GitHub Bot commented on CURATOR-33: --- Github user jhump commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15696190 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback --- End diff -- The class can still be private. The synthetic methods are only added for private methods, fields, and constructors. So you can mark the class as private, leave its members as package-private, and there shouldn't be any synthetic accessors. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14082216#comment-14082216 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50882098 OK - please reply to the race issues mentioned above. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081954#comment-14081954 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50851793 Updates based on feedback; getCurrentChildren() returns a map, added more extensive testing and polish. The one thing still missing is an accessor to get an entire subtree. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081716#comment-14081716 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15677537 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081713#comment-14081713 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15677507 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081712#comment-14081712 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15677498 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCacheEvent.java --- @@ -0,0 +1,126 @@ +/** --- End diff -- I think that would be better for users of the recipes. The downside is a lot of coupling. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081652#comment-14081652 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15675713 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCacheEvent.java --- @@ -0,0 +1,126 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +/** + * POJO that abstracts a change to a path + */ +public class TreeCacheEvent +{ +private final Type type; +private final ChildData data; + +/** + * Type of change + */ +public enum Type +{ +/** + * A node was added. + */ +NODE_ADDED, + +/** + * A node's data was changed + */ +NODE_UPDATED, + +/** + * A node was removed from the tree + */ +NODE_REMOVED, + +/** + * Called when the connection has changed to {@link org.apache.curator.framework.state.ConnectionState#SUSPENDED} + * + * This is exposed so that users of the class can be notified of issues that *might* affect normal operation. + * The TreeCache is written such that listeners are not expected to do anything special on this + * event, except for those people who want to cause some application-specific logic to fire when this occurs. + * While the connection is down, the TreeCache will continue to have its state from before it lost + * the connection and after the connection is restored, the TreeCache will emit normal child events + * for all of the adds, deletes and updates that happened during the time that it was disconnected. + */ +CONNECTION_SUSPENDED, + +/** + * Called when the connection has changed to {@link org.apache.curator.framework.state.ConnectionState#RECONNECTED} + * + * This is exposed so that users of the class can be notified of issues that *might* affect normal operation. + * The TreeCache is written such that listeners are not expected to do anything special on this + * event, except for those people who want to cause some application-specific logic to fire when this occurs. + * While the connection is down, the TreeCache will continue to have its state from before it lost + * the connection and after the connection is restored, the TreeCache will emit normal child events + * for all of the adds, deletes and updates that happened during the time that it was disconnected. + */ +CONNECTION_RECONNECTED, + +/** + * Called when the connection has changed to {@link org.apache.curator.framework.state.ConnectionState#LOST} + * + * This is exposed so that users of the class can be notified of issues that *might* affect normal operation. + * The TreeCache is written such that listeners are not expected to do anything special on this + * event, except for those people who want to cause some application-specific logic to fire when this occurs. + * While the connection is down, the TreeCache will continue to have its state from before it lost + * the connection and after the connection is restored, the TreeCache will emit normal child events + * for all of the adds, deletes and updates that happened during the time that it was disconnected. + */ +CONNECTION_LOST, + +/** + * Posted when the initial cache has been populated. --- End diff -- update doc > Recursive Node Cache > -
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081639#comment-14081639 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15675387 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCacheEvent.java --- @@ -0,0 +1,126 @@ +/** --- End diff -- Glad you brought this up; it's a straight copy, I think the only changes are renaming things like CHILD_ADDED -> NODE_ADDED. I tried to consistently switch to "node" terminology since nodes in the tree cache can be both parents and children (as opposed to PathChildrenCache). Also, I wasn't sure how weird it would be to have a TreeCache emitting PathChildrenCacheEvents. I do kind of like the idea of deprecating the old event interfaces and creating a new one that can consistently surface events for all 3 caches. Perhaps we could call it "CacheEvent" and it would essentially look like TreeCacheEvent. I think NodeCache would be especially improved by this, since at the moment all it offers is a "nodeChanged" event. The caches could simply keep two lists of listeners and publish both new and old style events. What do you think? > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081632#comment-14081632 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15675036 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081629#comment-14081629 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15674624 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081614#comment-14081614 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15674181 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081604#comment-14081604 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15674042 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081599#comment-14081599 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15673959 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081602#comment-14081602 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15674008 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081595#comment-14081595 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15673864 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback --- End diff -- sure thing, my personal style is typically not to bother marking inner classes private since it makes javac emit package-access bridge methods to allow the outer class to access the inner class, but i'm sure it makes little actual difference so happy to add if that's the preferred style > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081233#comment-14081233 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50798327 I need to spend more time on this, but I'm suspecting that the refresh*() and was*() methods of TreeNode need to be synchronized. These methods can be called from the watcher/async callbacks as well as Curator's connection state listener callback. The watcher/async are from a single thread in ZK, but Curator's connection state listener callback is a different thread. Thus, these methods could be called at the same time from two threads (via wasReconnected()). > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081224#comment-14081224 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50797741 There is a tiny potential for a race with outstandingOps for refreshData()'s background result to succeed before refreshChildren() resulting in a false INITIALIZED event. I was able to simulate this by forcing refreshChildren() to block indefinitely. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines >Assignee: Jordan Zimmerman > Fix For: TBD > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14081190#comment-14081190 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15658282 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080890#comment-14080890 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15642588 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080882#comment-14080882 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15642130 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080871#comment-14080871 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15641822 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080868#comment-14080868 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15641775 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback --- End diff -- can be private > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080865#comment-14080865 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15641748 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080870#comment-14080870 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15641784 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) --- End diff -- can be private > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was se
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080862#comment-14080862 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15641543 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080860#comment-14080860 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15641489 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080856#comment-14080856 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15641326 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCacheEvent.java --- @@ -0,0 +1,126 @@ +/** --- End diff -- This is just a copy of TreeCacheEvent with some naming changes right? Can't PathChildrenCacheEvent be used instead? Or, maybe we should introduce a new common class and deprecate PathChildrenCacheEvent? > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14080823#comment-14080823 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15640127 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,605 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14075470#comment-14075470 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50246127 Great! I'll remove the prints, add a getSubtree(), and add more tests. Wanted to be sure the basic approach was good before I added too much more. :) > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14074128#comment-14074128 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50111927 Overall, looks really good. I've made a few minor comments. My only other comment would be that it would be nice to see some more unit tests specific to a multi level cache. It's good that the TreeCache works against all of the PathChildrenCache tests, but I could only see 1 test that specifically deals with data with a depth > 2. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14074120#comment-14074120 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15387439 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14074111#comment-14074111 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15387221 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,608 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14074110#comment-14074110 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15387199 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,608 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14074105#comment-14074105 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15387161 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,608 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14074101#comment-14074101 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-50110235 Tests are all good for me now, will have a look at the code now. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14073064#comment-14073064 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-49991637 Thanks guys, I was able to repro under 1.7 (I don't have 1.6 on OSX to test against). Interestingly, it looks like the order in which `event.getChildren()` names appear during `CuratorEventType.CHILDREN` differs between JDK versions. So now I'm sorting the names of added children to increase test determinism. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14072801#comment-14072801 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-49967763 They're failing for me both in eclipse and via Maven. I'm running on Java 1.7.0 on OSX > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14072791#comment-14072791 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-49967308 testChildrenInitialized, testIssue27 and testStartup fail for me as well. Note: I run under Java 6 (i modified this PR to work under Java 6). > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14072789#comment-14072789 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-49967202 Hmm, that's weird. Yeah, they're all passing for me, both in intellij and maven with a clean build. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14072748#comment-14072748 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-49963530 The testChildrenInitialized, testIssue27 and testStartup are all failing for me? Are they passing for you? > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14072658#comment-14072658 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15325624 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java --- @@ -0,0 +1,421 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.collect.ImmutableSortedSet; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.api.UnhandledErrorListener; +import org.apache.curator.retry.RetryOneTime; +import org.apache.curator.test.BaseClassForTests; +import org.apache.curator.test.KillSession; +import org.apache.curator.test.Timing; +import org.apache.curator.utils.CloseableUtils; +import org.apache.zookeeper.CreateMode; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +public class TestTreeCache extends BaseClassForTests +{ +private final Timing timing = new Timing(); +private CuratorFramework client; +private TreeCache cache; +private List exceptions; +private BlockingQueue events; +private TreeCacheListener eventListener; + +/** + * A TreeCache that records exceptions. + */ +private TreeCache newTreeCache(String path, boolean cacheData) +{ +return new TreeCache(client, path, cacheData) +{ +@Override +protected void handleException(Throwable e) +{ +exceptions.add(e); +} +}; +} + +@Override +@BeforeMethod +public void setup() throws Exception +{ +super.setup(); + +exceptions = new ArrayList(); +events = new LinkedBlockingQueue(); +eventListener = new TreeCacheListener() +{ +@Override +public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception +{ +events.add(event); +} +}; + +client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1)); +client.start(); +client.getUnhandledErrorListenable().addListener(new UnhandledErrorListener() + { + @Override + public void unhandledError(String message, Throwable e) + { + exceptions.add(e); + } + } +); +cache = newTreeCache("/test", true); +cache.getListenable().addListener(eventListener); +} + +@Override +@AfterMethod +public void teardown() throws Exception +{ +try +{ +try +{ +for ( Thr
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14072560#comment-14072560 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15323038 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14072561#comment-14072561 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15323058 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java --- @@ -0,0 +1,421 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.collect.ImmutableSortedSet; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.api.UnhandledErrorListener; +import org.apache.curator.retry.RetryOneTime; +import org.apache.curator.test.BaseClassForTests; +import org.apache.curator.test.KillSession; +import org.apache.curator.test.Timing; +import org.apache.curator.utils.CloseableUtils; +import org.apache.zookeeper.CreateMode; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +public class TestTreeCache extends BaseClassForTests +{ +private final Timing timing = new Timing(); +private CuratorFramework client; +private TreeCache cache; +private List exceptions; +private BlockingQueue events; +private TreeCacheListener eventListener; + +/** + * A TreeCache that records exceptions. + */ +private TreeCache newTreeCache(String path, boolean cacheData) +{ +return new TreeCache(client, path, cacheData) +{ +@Override +protected void handleException(Throwable e) +{ +exceptions.add(e); +} +}; +} + +@Override +@BeforeMethod +public void setup() throws Exception +{ +super.setup(); + +exceptions = new ArrayList(); +events = new LinkedBlockingQueue(); +eventListener = new TreeCacheListener() +{ +@Override +public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception +{ +events.add(event); +} +}; + +client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1)); +client.start(); +client.getUnhandledErrorListenable().addListener(new UnhandledErrorListener() + { + @Override + public void unhandledError(String message, Throwable e) + { + exceptions.add(e); + } + } +); +cache = newTreeCache("/test", true); +cache.getListenable().addListener(eventListener); +} + +@Override +@AfterMethod +public void teardown() throws Exception +{ +try +{ +try +{ +for ( Thr
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14072562#comment-14072562 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cammckenzie commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15323064 --- Diff: curator-recipes/src/test/java/org/apache/curator/framework/recipes/cache/TestTreeCache.java --- @@ -0,0 +1,421 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.collect.ImmutableSortedSet; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.api.UnhandledErrorListener; +import org.apache.curator.retry.RetryOneTime; +import org.apache.curator.test.BaseClassForTests; +import org.apache.curator.test.KillSession; +import org.apache.curator.test.Timing; +import org.apache.curator.utils.CloseableUtils; +import org.apache.zookeeper.CreateMode; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +public class TestTreeCache extends BaseClassForTests +{ +private final Timing timing = new Timing(); +private CuratorFramework client; +private TreeCache cache; +private List exceptions; +private BlockingQueue events; +private TreeCacheListener eventListener; + +/** + * A TreeCache that records exceptions. + */ +private TreeCache newTreeCache(String path, boolean cacheData) +{ +return new TreeCache(client, path, cacheData) +{ +@Override +protected void handleException(Throwable e) +{ +exceptions.add(e); +} +}; +} + +@Override +@BeforeMethod +public void setup() throws Exception +{ +super.setup(); + +exceptions = new ArrayList(); +events = new LinkedBlockingQueue(); +eventListener = new TreeCacheListener() +{ +@Override +public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception +{ +events.add(event); +} +}; + +client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1)); +client.start(); +client.getUnhandledErrorListenable().addListener(new UnhandledErrorListener() + { + @Override + public void unhandledError(String message, Throwable e) + { + exceptions.add(e); + } + } +); +cache = newTreeCache("/test", true); +cache.getListenable().addListener(eventListener); +} + +@Override +@AfterMethod +public void teardown() throws Exception +{ +try +{ +try +{ +for ( Thr
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14068642#comment-14068642 ] ASF GitHub Bot commented on CURATOR-33: --- Github user jhump commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15175830 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +{
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14068099#comment-14068099 ] ASF GitHub Bot commented on CURATOR-33: --- Github user Randgalt commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-49566348 Thanks for this. I'll review when I can. Hopefully cameron can look too. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066814#comment-14066814 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cconroy commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15131069 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066749#comment-14066749 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15128271 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066744#comment-14066744 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15128164 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066737#comment-14066737 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15127735 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must --- End diff -- I haven't looked into zxid order at all; I wish that all event callbacks including a zxid but they don't. I had consider that perhaps the UPDATE case should compare the mzxid of the incoming event to the mzxid recorded on the existing node, but in practice I don't think events can come in such an out of order fashion. Given that PathChildren doesn't utilize mzxid's at all, it seems like it'd be more of an assertion than actually useful. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066730#comment-14066730 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15127479 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCacheEvent.java --- @@ -0,0 +1,126 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +/** + * POJO that abstracts a change to a path + */ +public class TreeCacheEvent +{ +private final Type type; +private final ChildData data; + +/** + * Type of change + */ +public enum Type +{ +/** + * A node was added. + */ +NODE_ADDED, + +/** + * A node's data was changed + */ +NODE_UPDATED, + +/** + * A node was removed from the tree + */ +NODE_REMOVED, + +/** + * Called when the connection has changed to {@link org.apache.curator.framework.state.ConnectionState#SUSPENDED} + * + * This is exposed so that users of the class can be notified of issues that *might* affect normal operation. + * The TreeCache is written such that listeners are not expected to do anything special on this + * event, except for those people who want to cause some application-specific logic to fire when this occurs. + * While the connection is down, the TreeCache will continue to have its state from before it lost + * the connection and after the connection is restored, the TreeCache will emit normal child events + * for all of the adds, deletes and updates that happened during the time that it was disconnected. + */ +CONNECTION_SUSPENDED, + +/** + * Called when the connection has changed to {@link org.apache.curator.framework.state.ConnectionState#RECONNECTED} + * + * This is exposed so that users of the class can be notified of issues that *might* affect normal operation. + * The TreeCache is written such that listeners are not expected to do anything special on this + * event, except for those people who want to cause some application-specific logic to fire when this occurs. + * While the connection is down, the TreeCache will continue to have its state from before it lost + * the connection and after the connection is restored, the TreeCache will emit normal child events + * for all of the adds, deletes and updates that happened during the time that it was disconnected. + */ +CONNECTION_RECONNECTED, + +/** + * Called when the connection has changed to {@link org.apache.curator.framework.state.ConnectionState#LOST} + * + * This is exposed so that users of the class can be notified of issues that *might* affect normal operation. + * The TreeCache is written such that listeners are not expected to do anything special on this + * event, except for those people who want to cause some application-specific logic to fire when this occurs. + * While the connection is down, the TreeCache will continue to have its state from before it lost + * the connection and after the connection is restored, the TreeCache will emit normal child events + * for all of the adds, deletes and updates that happened during the time that it was disconnected. + */ +CONNECTION_LOST, + +/** + * Posted when the initial cache has been populated. --- End diff -- Yeah, exactly the same. It fires events as
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066729#comment-14066729 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cconroy commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15127457 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066725#comment-14066725 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cconroy commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15127380 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must --- End diff -- Worth doing more than just tree-order on re-sync but also giving zkId order? Probably not since I can think of edge cases where interleaved creations and deletions would cause pure mzkid ordering to conflict with tree order... > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066611#comment-14066611 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15124193 --- Diff: curator-client/src/main/java/org/apache/curator/utils/ZKPaths.java --- @@ -112,6 +113,34 @@ public static PathAndNode getPathAndNode(String path) } /** + * Given a full path, return the the individual parts, without slashes. + * The root path will return an empty list. + * + * @param path the path + * @return an array of parts + */ +public static List split(String path) --- End diff -- will look at that > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066609#comment-14066609 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15124118 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must --- End diff -- They actually do wind up in correct up-to-down order on a re-sync. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066606#comment-14066606 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15124056 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066605#comment-14066605 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cconroy commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15124028 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCacheEvent.java --- @@ -0,0 +1,126 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +/** + * POJO that abstracts a change to a path + */ +public class TreeCacheEvent +{ +private final Type type; +private final ChildData data; + +/** + * Type of change + */ +public enum Type +{ +/** + * A node was added. + */ +NODE_ADDED, + +/** + * A node's data was changed + */ +NODE_UPDATED, + +/** + * A node was removed from the tree + */ +NODE_REMOVED, + +/** + * Called when the connection has changed to {@link org.apache.curator.framework.state.ConnectionState#SUSPENDED} + * + * This is exposed so that users of the class can be notified of issues that *might* affect normal operation. + * The TreeCache is written such that listeners are not expected to do anything special on this + * event, except for those people who want to cause some application-specific logic to fire when this occurs. + * While the connection is down, the TreeCache will continue to have its state from before it lost + * the connection and after the connection is restored, the TreeCache will emit normal child events + * for all of the adds, deletes and updates that happened during the time that it was disconnected. + */ +CONNECTION_SUSPENDED, + +/** + * Called when the connection has changed to {@link org.apache.curator.framework.state.ConnectionState#RECONNECTED} + * + * This is exposed so that users of the class can be notified of issues that *might* affect normal operation. + * The TreeCache is written such that listeners are not expected to do anything special on this + * event, except for those people who want to cause some application-specific logic to fire when this occurs. + * While the connection is down, the TreeCache will continue to have its state from before it lost + * the connection and after the connection is restored, the TreeCache will emit normal child events + * for all of the adds, deletes and updates that happened during the time that it was disconnected. + */ +CONNECTION_RECONNECTED, + +/** + * Called when the connection has changed to {@link org.apache.curator.framework.state.ConnectionState#LOST} + * + * This is exposed so that users of the class can be notified of issues that *might* affect normal operation. + * The TreeCache is written such that listeners are not expected to do anything special on this + * event, except for those people who want to cause some application-specific logic to fire when this occurs. + * While the connection is down, the TreeCache will continue to have its state from before it lost + * the connection and after the connection is restored, the TreeCache will emit normal child events + * for all of the adds, deletes and updates that happened during the time that it was disconnected. + */ +CONNECTION_LOST, + +/** + * Posted when the initial cache has been populated. --- End diff -- is this the same behavior as the `PathChildrenC
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066601#comment-14066601 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-49459230 https://issues.apache.org/jira/browse/CURATOR-33 > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066594#comment-14066594 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cconroy commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15123789 --- Diff: curator-client/src/main/java/org/apache/curator/utils/ZKPaths.java --- @@ -112,6 +113,34 @@ public static PathAndNode getPathAndNode(String path) } /** + * Given a full path, return the the individual parts, without slashes. + * The root path will return an empty list. + * + * @param path the path + * @return an array of parts + */ +public static List split(String path) --- End diff -- this looks fine, but use a guava splitter instead? > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066585#comment-14066585 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cconroy commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15123604 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must + * be prepared for false-positives and false-negatives. Additionally, always use the version number + * when updating data to avoid overwriting another process' change. + */ +public class TreeCache implements Closeable +{ +private static final Logger LOG = LoggerFactory.getLogger(TreeCache.class); + +private enum NodeState +{ +PENDING, LIVE, DEAD +} + +final class TreeNode implements Watcher, BackgroundCallback +{ +private final AtomicReference nodeState = new AtomicReference(NodeState.PENDING); +private final String path; +private final TreeNode parent; +private final AtomicReference stat = new AtomicReference(); +private final AtomicReference data = new AtomicReference(); +private final AtomicReference> children = new AtomicReference>(); + +TreeNode(String path, TreeNode parent) +{ +this.path = path; +this.parent = parent; +} + +private void refreshChildren() throws Exception +{ +outstandingOps.incrementAndGet(); + client.getChildren().usingWatcher(this).inBackground(this).forPath(path); +} + +private void refreshData() throws Exception +{ +outstandingOps.incrementAndGet(); +if ( dataIsCompressed ) +{ + client.getData().decompressed().usingWatcher(this).inBackground(this).forPath(path); +} +else +
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066569#comment-14066569 ] ASF GitHub Bot commented on CURATOR-33: --- Github user cconroy commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15123089 --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/TreeCache.java --- @@ -0,0 +1,600 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.curator.framework.recipes.cache; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.api.BackgroundCallback; +import org.apache.curator.framework.api.CuratorEvent; +import org.apache.curator.framework.listen.ListenerContainer; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.utils.CloseableExecutorService; +import org.apache.curator.utils.ThreadUtils; +import org.apache.curator.utils.ZKPaths; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A utility that attempts to keep all data from all children of a ZK path locally cached. This class + * will watch the ZK path, respond to update/create/delete events, pull down the data, etc. You can + * register a listener that will get notified when changes occur. + * + * IMPORTANT - it's not possible to stay transactionally in sync. Users of this class must --- End diff -- I know this comment comes form path and node cache, but I find it very unhelpful. I think it would be more clear to note that a sequence of updates to any two nodes may be delivered in any sequence by the cache. But, it also seems like we should be able to offer a much stronger consistency guarantee. Watches are guaranteed to fire in order from the ZK protocol level, and therefore we should be able to give consistent delivery of e.g. a recursive delete bottom up, tree creation top-down, etc. TreeCache is potentially in a much better position to do this since it need not segment the listener for each path into its own single threaded executor. The only major caveat I see here is on a disconnect/reconnect case where we have to re-read the tree, but the events could still be synthesized in correct tree order for add/remove. > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066233#comment-14066233 ] ASF GitHub Bot commented on CURATOR-33: --- Github user ericzundel commented on a diff in the pull request: https://github.com/apache/curator/pull/17#discussion_r15104749 --- Diff: curator-client/src/main/java/org/apache/curator/utils/ZKPaths.java --- @@ -112,6 +113,34 @@ public static PathAndNode getPathAndNode(String path) } /** + * Given a full path, return the the individual parts, without slashes. + * The root path will return an empty list. + * + * @param path the path + * @return an array of parts + */ +public static List split(String path) +{ +PathUtils.validatePath(path); +if (path.length() == 1) { +return Collections.emptyList(); +} +int lastPos = 1; +List parts = new ArrayList(); +while (true) +{ +int nextPos = path.indexOf('/', lastPos); --- End diff -- Do you want to use file.separator system property (or File.separatorChar) > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)
[jira] [Commented] (CURATOR-33) Recursive Node Cache
[ https://issues.apache.org/jira/browse/CURATOR-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14066129#comment-14066129 ] ASF GitHub Bot commented on CURATOR-33: --- Github user dragonsinth commented on the pull request: https://github.com/apache/curator/pull/17#issuecomment-49401772 CC: @cconroy @jhump > Recursive Node Cache > > > Key: CURATOR-33 > URL: https://issues.apache.org/jira/browse/CURATOR-33 > Project: Apache Curator > Issue Type: Improvement > Components: Recipes >Reporter: John Vines > Fix For: awaiting-response > > Attachments: CURATOR-33.2.patch, CURATOR-33.patch > > > Currently the PathChildrenCache will trigger listen events for all children > at the given node. However, it would be useful to have a cache that would > trigger listen events for the entire hierarchy below the given node. -- This message was sent by Atlassian JIRA (v6.2#6252)