Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3c05c67
basic work done. Needs more testing, tuning, etc.
Randgalt Dec 25, 2016
ca4a000
working on persistent watcher removal
Randgalt Dec 26, 2016
bf13ded
Support resetting persistent watches
Randgalt Dec 26, 2016
27d8d6c
docs
Randgalt Dec 26, 2016
2766fb1
containsWatcher() was broken for STANDARD watchers
Randgalt Dec 26, 2016
86fa1fb
removed unused import
Randgalt Dec 26, 2016
b490c84
Updated doc for persistent watches
Randgalt Dec 26, 2016
e00b7a9
Fixed some Jenkins issues
Randgalt Dec 26, 2016
d60fde7
Fix a few nits:
Randgalt Dec 26, 2016
0b50826
Based on suggestion from eribeiro make PathIterator usable in for eac…
Randgalt Dec 26, 2016
073d693
fixed bad newline
Randgalt Dec 26, 2016
1272e4f
spacing
Randgalt Dec 26, 2016
99a0088
fixed a few nits
Randgalt Dec 27, 2016
84410e1
Inlcude deletions in persistent watcher tests
Randgalt Dec 27, 2016
48d7f64
Don't trigger NodeChildrenChanged for persistent watches. It's redundant
Randgalt Dec 27, 2016
8332eb4
PathIterator.next() should throw NoSuchElementException if no next el…
Randgalt Dec 27, 2016
23756a1
add root watcher test
Randgalt Dec 28, 2016
692db2d
doc updates
Randgalt Dec 28, 2016
29d3c6c
more doc
Randgalt Dec 28, 2016
61c2211
fixed misspelling
Randgalt Dec 28, 2016
3354369
doc clarification
Randgalt Dec 28, 2016
2e4fcbb
Merge branch 'master' into ZOOKEEPER-1416
Randgalt Aug 3, 2017
088dfb9
Renamed PathIterator to PathParentIterator for better clarity
Randgalt Aug 9, 2017
9a11ee5
Optimization: don't iterate through to parent paths unless the system…
Randgalt Aug 9, 2017
51ef9be
Use try-with-resources for cleaner code
Randgalt Aug 9, 2017
4c9f24b
added javadoc
Randgalt Aug 9, 2017
4fcbe4f
Merge branch 'master' into ZOOKEEPER-1416
Randgalt Aug 10, 2017
072df53
1. made the recursion feature of persistent watches optional. i.e. yo…
Randgalt Aug 20, 2017
97a9f3e
doc updates for recursive watches
Randgalt Aug 20, 2017
19fc766
doc updates for recursive watches
Randgalt Aug 20, 2017
30ef7af
doc updates for recursive watches
Randgalt Aug 20, 2017
6345881
Cleaner method of checking for recursive watches
Randgalt Aug 21, 2017
cb45e56
Merge branch 'master' into ZOOKEEPER-1416
Randgalt Sep 25, 2017
15e0a1d
Needed license header
Randgalt Sep 25, 2017
5a43ef8
Merge branch 'master' into ZOOKEEPER-1416
Randgalt Oct 3, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/docs/src/documentation/content/xdocs/zookeeperOver.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@
connection between the client and one of the Zoo Keeper servers is
broken, the client will receive a local notification. These can be used
to <emphasis>[tbd]</emphasis>.</para>

<para><emphasis role="bold">New in 3.6.0: </emphasis>Clients can also set
permanent, recursive watches on a znode that are not removed when triggered
and that trigger for changes on the registered znode as well as any children
znodes recursively.</para>
</section>

<section>
Expand Down
32 changes: 30 additions & 2 deletions src/docs/src/documentation/content/xdocs/zookeeperProgrammers.xml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
sends the client a notification. More information about watches can be
found in the section
<ulink url="#ch_zkWatches">ZooKeeper Watches</ulink>.</para>

<para><emphasis role="bold">New in 3.6.0: </emphasis>Clients can also set
permanent, recursive watches on a znode that are not removed when triggered
and that trigger for changes on the registered znode as well as any children
znodes recursively.</para>
</section>

<section>
Expand Down Expand Up @@ -712,6 +717,24 @@
</itemizedlist>
</section>

<section id="sc_PersistentWatches">
<title>Persistent Watches</title>
<para><emphasis role="bold">New in 3.6.0: </emphasis> There is now a variation on the standard
watch described above whereby you can set a watch that does not get removed when triggered.
Additionally, these watches trigger the event types <emphasis role="bold">NodeCreated</emphasis>,
<emphasis role="bold">NodeDeleted</emphasis>, and <emphasis role="bold">NodeDataChanged</emphasis>
and, optionally, recursively for all znodes starting at the znode that the watch is registered for. Note that
<emphasis role="bold">NodeChildrenChanged</emphasis> are not triggered for persistent recursive watches as
it is redundant.</para>

<para>Persistent watches are set using the method <emphasis
role="bold">addPersistentWatch()</emphasis>. The triggering semantics and guarantees
(other than one-time triggering) are the same as standard watches. The only exception regarding events is that
recursive persistent watchers never trigger child changed events as they are redundant.
Persistent watches are removed using <emphasis role="bold">removeWatches()</emphasis> with watcher type
<emphasis role="bold">WatcherType.Any</emphasis>.</para>
</section>

<section id="sc_WatchRemoval">
<title>Remove Watches</title>
<para>We can remove the watches registered on a znode with a call to
Expand All @@ -730,6 +753,11 @@
<para><emphasis role="bold">Data Remove event:</emphasis></para>
<para>Watcher which was added with a call to exists or getData.</para>
</listitem>

<listitem>
<para><emphasis role="bold">Persistent Remove event:</emphasis></para>
<para>Watcher which was added with a call to add a persistent watch.</para>
</listitem>
</itemizedlist>
</section>

Expand Down Expand Up @@ -767,15 +795,15 @@

<itemizedlist>
<listitem>
<para>Watches are one time triggers; if you get a watch event and
<para>Standard watches are one time triggers; if you get a watch event and
you want to get notified of future changes, you must set another
watch.</para>
</listitem>
</itemizedlist>

<itemizedlist>
<listitem>
<para>Because watches are one time triggers and there is latency
<para>Because standard watches are one time triggers and there is latency
between getting the event and sending a new request to get a watch
you cannot reliably see every change that happens to a node in
ZooKeeper. Be prepared to handle the case where the znode changes
Expand Down
27 changes: 22 additions & 5 deletions src/java/main/org/apache/zookeeper/ClientCnxn.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
import org.apache.zookeeper.proto.SetACLResponse;
import org.apache.zookeeper.proto.SetDataResponse;
import org.apache.zookeeper.proto.SetWatches;
import org.apache.zookeeper.proto.SetWatches2;
import org.apache.zookeeper.proto.WatcherEvent;
import org.apache.zookeeper.server.ByteBufferInputStream;
import org.apache.zookeeper.server.ZooKeeperThread;
Expand Down Expand Up @@ -958,18 +959,26 @@ void primeConnection() throws IOException {
List<String> dataWatches = zooKeeper.getDataWatches();
List<String> existWatches = zooKeeper.getExistWatches();
List<String> childWatches = zooKeeper.getChildWatches();
List<String> persistentWatches = zooKeeper.getPersistentWatches();
List<String> persistentRecursiveWatches = zooKeeper.getPersistentRecursiveWatches();
if (!dataWatches.isEmpty()
|| !existWatches.isEmpty() || !childWatches.isEmpty()) {
|| !existWatches.isEmpty() || !childWatches.isEmpty()
|| !persistentWatches.isEmpty() || !persistentRecursiveWatches.isEmpty()) {
Iterator<String> dataWatchesIter = prependChroot(dataWatches).iterator();
Iterator<String> existWatchesIter = prependChroot(existWatches).iterator();
Iterator<String> childWatchesIter = prependChroot(childWatches).iterator();
Iterator<String> persistentWatchesIter = prependChroot(persistentWatches).iterator();
Iterator<String> persistentRecursiveWatchesIter = prependChroot(persistentRecursiveWatches).iterator();
long setWatchesLastZxid = lastZxid;

while (dataWatchesIter.hasNext()
|| existWatchesIter.hasNext() || childWatchesIter.hasNext()) {
|| existWatchesIter.hasNext() || childWatchesIter.hasNext()
|| persistentWatchesIter.hasNext() || persistentRecursiveWatchesIter.hasNext()) {
List<String> dataWatchesBatch = new ArrayList<String>();
List<String> existWatchesBatch = new ArrayList<String>();
List<String> childWatchesBatch = new ArrayList<String>();
List<String> persistentWatchesBatch = new ArrayList<String>();
List<String> persistentRecursiveWatchesBatch = new ArrayList<String>();
int batchLength = 0;

// Note, we may exceed our max length by a bit when we add the last
Expand All @@ -985,17 +994,25 @@ void primeConnection() throws IOException {
} else if (childWatchesIter.hasNext()) {
watch = childWatchesIter.next();
childWatchesBatch.add(watch);
} else if (persistentWatchesIter.hasNext()) {
watch = persistentWatchesIter.next();
persistentWatchesBatch.add(watch);
} else if (persistentRecursiveWatchesIter.hasNext()) {
watch = persistentRecursiveWatchesIter.next();
persistentRecursiveWatchesBatch.add(watch);
} else {
break;
}
batchLength += watch.length();
}

SetWatches sw = new SetWatches(setWatchesLastZxid,
SetWatches2 sw = new SetWatches2(setWatchesLastZxid,
dataWatchesBatch,
existWatchesBatch,
childWatchesBatch);
RequestHeader header = new RequestHeader(-8, OpCode.setWatches);
childWatchesBatch,
persistentWatchesBatch,
persistentRecursiveWatchesBatch);
RequestHeader header = new RequestHeader(-8, OpCode.setWatches2);
Packet packet = new Packet(header, new ReplyHeader(), sw, null, null);
outgoingQueue.addFirst(packet);
}
Expand Down
4 changes: 3 additions & 1 deletion src/java/main/org/apache/zookeeper/Watcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ public enum EventType {
NodeDataChanged (3),
NodeChildrenChanged (4),
DataWatchRemoved (5),
ChildWatchRemoved (6);
ChildWatchRemoved (6),
PersistentWatchRemoved (7);

private final int intValue; // Integer representation of value
// for sending over wire
Expand All @@ -147,6 +148,7 @@ public static EventType fromInt(int intValue) {
case 4: return EventType.NodeChildrenChanged;
case 5: return EventType.DataWatchRemoved;
case 6: return EventType.ChildWatchRemoved;
case 7: return EventType.PersistentWatchRemoved;

default:
throw new RuntimeException("Invalid integer value for conversion to EventType");
Expand Down
4 changes: 4 additions & 0 deletions src/java/main/org/apache/zookeeper/ZooDefs.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,16 @@ public interface OpCode {

public final int createTTL = 21;

public final int addPersistentWatch = 22;

public final int auth = 100;

public final int setWatches = 101;

public final int sasl = 102;

public final int setWatches2 = 103;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are targeting a new major release with this change, can we just make changes to the preexisting setWatches?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I plan on backporting this to 3.5.x so I'd vote against that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think just because we are backporting this we need to keep this the same between the branches. I feel we should take advantage of the new version and keep the code as clean as possible. @hanm do you have an opinion on the matter?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Randgalt im guessing you meant to put "The problem is that it makes 3.5.4 clients incompatible with 3.5.3 servers. That might make sense for 3.6.0 but it's unreasonable for .x.N release." here. I agree totally. This code should stay the same in the 3.5 line but there is no reason it needs to be identical to the 3.6 line which is why i think it should be changed "here".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see - sure that's OK with me. Frankly, anything to get this PR moving. It's been almost impossible to get a ZK committer interested in this and I see this as a vital addition to ZK.


public final int createSession = -10;

public final int closeSession = -11;
Expand Down
Loading