|
|
Shelley, Ryan 2012-03-01, 00:08
Is it possible to create all nodes in a path in one step?
For example, my ZK is empty of any nodes. I want to create: /lorem/ipsum/foo/bar
Do I have to create each segment with iterative calls to ZK, or is there an easier way to build this?
+
Shelley, Ryan 2012-03-01, 00:08
-
Re: Create nested paths
Ted Dunning 2012-03-01, 00:23
Well, in 3.4, you can use multi to do this.
On Wed, Feb 29, 2012 at 4:08 PM, Shelley, Ryan <[EMAIL PROTECTED]>wrote:
> Is it possible to create all nodes in a path in one step? > > For example, my ZK is empty of any nodes. I want to create: > /lorem/ipsum/foo/bar > > Do I have to create each segment with iterative calls to ZK, or is there > an easier way to build this? >
+
Ted Dunning 2012-03-01, 00:23
-
Re: Create nested paths
Shelley, Ryan 2012-03-01, 00:26
Can you reference some docs? I looked but couldn't find anything regarding multi.
On 2/29/12 4:23 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote:
>Well, in 3.4, you can use multi to do this. > >On Wed, Feb 29, 2012 at 4:08 PM, Shelley, Ryan ><[EMAIL PROTECTED]>wrote: > >> Is it possible to create all nodes in a path in one step? >> >> For example, my ZK is empty of any nodes. I want to create: >> /lorem/ipsum/foo/bar >> >> Do I have to create each segment with iterative calls to ZK, or is there >> an easier way to build this? >>
+
Shelley, Ryan 2012-03-01, 00:26
-
Re: Create nested paths
Ted Dunning 2012-03-01, 00:46
http://zookeeper.apache.org/doc/r3.4.2/api/org/apache/zookeeper/ZooKeeper.html#multi(java.lang.Iterable)The javadoc for Op does not appear for an unknown (to me) reason. Here it is from org.apache.zookeeper.Op: /** * Represents a single operation in a multi-operation transaction. Each operation can be a create, update * or delete or can just be a version check. * * Sub-classes of Op each represent each detailed type but should not normally be referenced except via * the provided factory methods. * * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode) * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode, org.apache.zookeeper.AsyncCallback.StringCallback, Object) * @see ZooKeeper#delete(String, int) * @see ZooKeeper#setData(String, byte[], int) */ Sample usage can be found in org.apache.zookeeper.test.MultiTransactionTest On Wed, Feb 29, 2012 at 4:26 PM, Shelley, Ryan <[EMAIL PROTECTED]>wrote: > Can you reference some docs? I looked but couldn't find anything regarding > multi. > > On 2/29/12 4:23 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > > >Well, in 3.4, you can use multi to do this. > > > >On Wed, Feb 29, 2012 at 4:08 PM, Shelley, Ryan > ><[EMAIL PROTECTED]>wrote: > > > >> Is it possible to create all nodes in a path in one step? > >> > >> For example, my ZK is empty of any nodes. I want to create: > >> /lorem/ipsum/foo/bar > >> > >> Do I have to create each segment with iterative calls to ZK, or is there > >> an easier way to build this? > >> > >
+
Ted Dunning 2012-03-01, 00:46
-
Re: Create nested paths
Shelley, Ryan 2012-03-01, 00:52
Thanks for that. Out of curiosity, in my prior example of creating a node at /lorem/ipsum/foo/bar, if I'm building the multi operation list and at the same time some other client creates /lorem before I execute the multi operation, will the entire multi fail because /lorem already exists? On 2/29/12 4:46 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > http://zookeeper.apache.org/doc/r3.4.2/api/org/apache/zookeeper/ZooKeeper. >html#multi(java.lang.Iterable) > >The javadoc for Op does not appear for an unknown (to me) reason. Here it >is from org.apache.zookeeper.Op: > >/** > * Represents a single operation in a multi-operation transaction. Each >operation can be a create, update > * or delete or can just be a version check. > * > * Sub-classes of Op each represent each detailed type but should not >normally be referenced except via > * the provided factory methods. > * > * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode) > * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode, >org.apache.zookeeper.AsyncCallback.StringCallback, Object) > * @see ZooKeeper#delete(String, int) > * @see ZooKeeper#setData(String, byte[], int) > */ > >Sample usage can be found in >org.apache.zookeeper.test.MultiTransactionTest > >On Wed, Feb 29, 2012 at 4:26 PM, Shelley, Ryan ><[EMAIL PROTECTED]>wrote: > >> Can you reference some docs? I looked but couldn't find anything >>regarding >> multi. >> >> On 2/29/12 4:23 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: >> >> >Well, in 3.4, you can use multi to do this. >> > >> >On Wed, Feb 29, 2012 at 4:08 PM, Shelley, Ryan >> ><[EMAIL PROTECTED]>wrote: >> > >> >> Is it possible to create all nodes in a path in one step? >> >> >> >> For example, my ZK is empty of any nodes. I want to create: >> >> /lorem/ipsum/foo/bar >> >> >> >> Do I have to create each segment with iterative calls to ZK, or is >>there >> >> an easier way to build this? >> >> >> >>
+
Shelley, Ryan 2012-03-01, 00:52
-
Re: Create nested paths
Ted Dunning 2012-03-01, 02:59
Yes. I don't know of a good race-free solution involving a single multi-request. On Wed, Feb 29, 2012 at 4:52 PM, Shelley, Ryan <[EMAIL PROTECTED]>wrote: > Thanks for that. Out of curiosity, in my prior example of creating a node > at /lorem/ipsum/foo/bar, if I'm building the multi operation list and at > the same time some other client creates /lorem before I execute the multi > operation, will the entire multi fail because /lorem already exists? > > On 2/29/12 4:46 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > > > http://zookeeper.apache.org/doc/r3.4.2/api/org/apache/zookeeper/ZooKeeper> . > >html#multi(java.lang.Iterable) > > > >The javadoc for Op does not appear for an unknown (to me) reason. Here it > >is from org.apache.zookeeper.Op: > > > >/** > > * Represents a single operation in a multi-operation transaction. Each > >operation can be a create, update > > * or delete or can just be a version check. > > * > > * Sub-classes of Op each represent each detailed type but should not > >normally be referenced except via > > * the provided factory methods. > > * > > * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode) > > * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode, > >org.apache.zookeeper.AsyncCallback.StringCallback, Object) > > * @see ZooKeeper#delete(String, int) > > * @see ZooKeeper#setData(String, byte[], int) > > */ > > > >Sample usage can be found in > >org.apache.zookeeper.test.MultiTransactionTest > > > >On Wed, Feb 29, 2012 at 4:26 PM, Shelley, Ryan > ><[EMAIL PROTECTED]>wrote: > > > >> Can you reference some docs? I looked but couldn't find anything > >>regarding > >> multi. > >> > >> On 2/29/12 4:23 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > >> > >> >Well, in 3.4, you can use multi to do this. > >> > > >> >On Wed, Feb 29, 2012 at 4:08 PM, Shelley, Ryan > >> ><[EMAIL PROTECTED]>wrote: > >> > > >> >> Is it possible to create all nodes in a path in one step? > >> >> > >> >> For example, my ZK is empty of any nodes. I want to create: > >> >> /lorem/ipsum/foo/bar > >> >> > >> >> Do I have to create each segment with iterative calls to ZK, or is > >>there > >> >> an easier way to build this? > >> >> > >> > >> > >
+
Ted Dunning 2012-03-01, 02:59
-
Re: Create nested paths
Marshall McMullen 2012-03-01, 03:04
Yes, Ted's right. The multi has to fail as that's part of the contract it guarantees. The only thing you could do, which will significantly narrow the race condition, is as you're *building *the multi, check if the path already exists. If so, then don't add the create op for that path into the multi. Of course this may not work in every situation, but we use that approach in many code paths and it works well. On Wed, Feb 29, 2012 at 7:59 PM, Ted Dunning <[EMAIL PROTECTED]> wrote: > Yes. I don't know of a good race-free solution involving a single > multi-request. > > On Wed, Feb 29, 2012 at 4:52 PM, Shelley, Ryan <[EMAIL PROTECTED] > >wrote: > > > Thanks for that. Out of curiosity, in my prior example of creating a node > > at /lorem/ipsum/foo/bar, if I'm building the multi operation list and at > > the same time some other client creates /lorem before I execute the multi > > operation, will the entire multi fail because /lorem already exists? > > > > On 2/29/12 4:46 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > > > > > > http://zookeeper.apache.org/doc/r3.4.2/api/org/apache/zookeeper/ZooKeeper> > . > > >html#multi(java.lang.Iterable) > > > > > >The javadoc for Op does not appear for an unknown (to me) reason. Here > it > > >is from org.apache.zookeeper.Op: > > > > > >/** > > > * Represents a single operation in a multi-operation transaction. Each > > >operation can be a create, update > > > * or delete or can just be a version check. > > > * > > > * Sub-classes of Op each represent each detailed type but should not > > >normally be referenced except via > > > * the provided factory methods. > > > * > > > * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode) > > > * @see ZooKeeper#create(String, byte[], java.util.List, CreateMode, > > >org.apache.zookeeper.AsyncCallback.StringCallback, Object) > > > * @see ZooKeeper#delete(String, int) > > > * @see ZooKeeper#setData(String, byte[], int) > > > */ > > > > > >Sample usage can be found in > > >org.apache.zookeeper.test.MultiTransactionTest > > > > > >On Wed, Feb 29, 2012 at 4:26 PM, Shelley, Ryan > > ><[EMAIL PROTECTED]>wrote: > > > > > >> Can you reference some docs? I looked but couldn't find anything > > >>regarding > > >> multi. > > >> > > >> On 2/29/12 4:23 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > > >> > > >> >Well, in 3.4, you can use multi to do this. > > >> > > > >> >On Wed, Feb 29, 2012 at 4:08 PM, Shelley, Ryan > > >> ><[EMAIL PROTECTED]>wrote: > > >> > > > >> >> Is it possible to create all nodes in a path in one step? > > >> >> > > >> >> For example, my ZK is empty of any nodes. I want to create: > > >> >> /lorem/ipsum/foo/bar > > >> >> > > >> >> Do I have to create each segment with iterative calls to ZK, or is > > >>there > > >> >> an easier way to build this? > > >> >> > > >> > > >> > > > > >
+
Marshall McMullen 2012-03-01, 03:04
-
Re: Create nested paths
Ted Dunning 2012-03-01, 03:16
On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < [EMAIL PROTECTED]> wrote:
> Yes, Ted's right. The multi has to fail as that's part of the contract it > guarantees. > > The only thing you could do, which will significantly narrow the race > condition, is as you're *building *the multi, check if the path already > exists. If so, then don't add the create op for that path into the multi. > Of course this may not work in every situation, but we use that approach in > many code paths and it works well. >
Another approach is to compose one multi with Op.exists() for each level so that you find everything you need, then create another with the correct Op.create() operations. That gets the problem down to two server round-trips but still has the race condition.
+
Ted Dunning 2012-03-01, 03:16
-
Re: Create nested paths
Shelley, Ryan 2012-03-01, 19:17
Ok, I tried this with the Op.create and found that it will throw a KeeperException on the first path that doesn't exist. It doesn't return back an OpResult with an "error" type. I can still use this, and just catch the exception and create the node in the exception, but I was under the impression that I could do this in two trips. One trip to get back a list of OpResults from the check that would inform me if the path existed or not, and a second trip to create all the paths that don't exist (and as a note, the CheckResult object doesn't include the path, so I have to infer it from the order of my original list of paths used to create the multi-check).
-Ryan
On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote:
>On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < >[EMAIL PROTECTED]> wrote: > >> Yes, Ted's right. The multi has to fail as that's part of the contract >>it >> guarantees. >> >> The only thing you could do, which will significantly narrow the race >> condition, is as you're *building *the multi, check if the path already >> exists. If so, then don't add the create op for that path into the >>multi. >> Of course this may not work in every situation, but we use that >>approach in >> many code paths and it works well. >> > >Another approach is to compose one multi with Op.exists() for each level >so >that you find everything you need, then create another with the correct >Op.create() operations. That gets the problem down to two server >round-trips but still has the race condition.
+
Shelley, Ryan 2012-03-01, 19:17
-
Re: Create nested paths
Ted Dunning 2012-03-01, 23:05
No. I meant one call full of checks and a second call with any necessary creates.
Sent from my iPhone
On Mar 1, 2012, at 11:17 AM, "Shelley, Ryan" <[EMAIL PROTECTED]> wrote:
> Ok, I tried this with the Op.create and found that it will throw a > KeeperException on the first path that doesn't exist. It doesn't return > back an OpResult with an "error" type. I can still use this, and just > catch the exception and create the node in the exception, but I was under > the impression that I could do this in two trips. One trip to get back a > list of OpResults from the check that would inform me if the path existed > or not, and a second trip to create all the paths that don't exist (and as > a note, the CheckResult object doesn't include the path, so I have to > infer it from the order of my original list of paths used to create the > multi-check). > > -Ryan > > On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > >> On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < >> [EMAIL PROTECTED]> wrote: >> >>> Yes, Ted's right. The multi has to fail as that's part of the contract >>> it >>> guarantees. >>> >>> The only thing you could do, which will significantly narrow the race >>> condition, is as you're *building *the multi, check if the path already >>> exists. If so, then don't add the create op for that path into the >>> multi. >>> Of course this may not work in every situation, but we use that >>> approach in >>> many code paths and it works well. >>> >> >> Another approach is to compose one multi with Op.exists() for each level >> so >> that you find everything you need, then create another with the correct >> Op.create() operations. That gets the problem down to two server >> round-trips but still has the race condition. >
+
Ted Dunning 2012-03-01, 23:05
-
Re: Create nested paths
Shelley, Ryan 2012-03-01, 23:14
Right, I did this:
(psuedo-code) List<Ops> ops For(path in paths) ops.add( Op.check(path, -1) ) EndFor
List<OpResult> Results = Zk.multi(ops)
This causes an exception to be thrown on the first path that doesn't exist. It doesn't return back a list with one OpResult flagged with an error. I was under the impression I'd get back a bunch of OpResult objects with flags of error, or otherwise, and then I could build another list of operations to create what's needed (which, even if it did work, the CheckResult object doesn't include the path, so I'm just hoping the results are in the same order as the operations were listed in, as I have to infer the path I'll need to build from the position of the OpResult in the list).
On 3/1/12 3:05 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote:
>No. I meant one call full of checks and a second call with any necessary >creates. > >Sent from my iPhone > >On Mar 1, 2012, at 11:17 AM, "Shelley, Ryan" <[EMAIL PROTECTED]> >wrote: > >> Ok, I tried this with the Op.create and found that it will throw a >> KeeperException on the first path that doesn't exist. It doesn't return >> back an OpResult with an "error" type. I can still use this, and just >> catch the exception and create the node in the exception, but I was >>under >> the impression that I could do this in two trips. One trip to get back a >> list of OpResults from the check that would inform me if the path >>existed >> or not, and a second trip to create all the paths that don't exist (and >>as >> a note, the CheckResult object doesn't include the path, so I have to >> infer it from the order of my original list of paths used to create the >> multi-check). >> >> -Ryan >> >> On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: >> >>> On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < >>> [EMAIL PROTECTED]> wrote: >>> >>>> Yes, Ted's right. The multi has to fail as that's part of the contract >>>> it >>>> guarantees. >>>> >>>> The only thing you could do, which will significantly narrow the race >>>> condition, is as you're *building *the multi, check if the path >>>>already >>>> exists. If so, then don't add the create op for that path into the >>>> multi. >>>> Of course this may not work in every situation, but we use that >>>> approach in >>>> many code paths and it works well. >>>> >>> >>> Another approach is to compose one multi with Op.exists() for each >>>level >>> so >>> that you find everything you need, then create another with the correct >>> Op.create() operations. That gets the problem down to two server >>> round-trips but still has the race condition. >>
+
Shelley, Ryan 2012-03-01, 23:14
-
Re: Create nested paths
Marshall McMullen 2012-03-01, 23:27
Yes, the results are guaranteed to be the same order of the requests.
However, the first one that fails will cause the entire multi to be aborted. So, if say the first one fails, then you won't know if the others after that would have failed.
I'd suggest doing something entire different, such as (pseudo-code):
List<Ops> ops for(path in paths) if (!Exists(path)) { ops.add(Op.Create(path)); }
Does that make sense? I'm suggesting you use the non-multi code to check if it exists or not. If not, you can append any ops related to that path into your ops list. On Thu, Mar 1, 2012 at 11:14 PM, Shelley, Ryan <[EMAIL PROTECTED]>wrote:
> Right, I did this: > > (psuedo-code) > List<Ops> ops > For(path in paths) > ops.add( Op.check(path, -1) ) > EndFor > > List<OpResult> Results = Zk.multi(ops) > > This causes an exception to be thrown on the first path that doesn't > exist. It doesn't return back a list with one OpResult flagged with an > error. I was under the impression I'd get back a bunch of OpResult objects > with flags of error, or otherwise, and then I could build another list of > operations to create what's needed (which, even if it did work, the > CheckResult object doesn't include the path, so I'm just hoping the > results are in the same order as the operations were listed in, as I have > to infer the path I'll need to build from the position of the OpResult in > the list). > > > > On 3/1/12 3:05 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > > >No. I meant one call full of checks and a second call with any necessary > >creates. > > > >Sent from my iPhone > > > >On Mar 1, 2012, at 11:17 AM, "Shelley, Ryan" <[EMAIL PROTECTED]> > >wrote: > > > >> Ok, I tried this with the Op.create and found that it will throw a > >> KeeperException on the first path that doesn't exist. It doesn't return > >> back an OpResult with an "error" type. I can still use this, and just > >> catch the exception and create the node in the exception, but I was > >>under > >> the impression that I could do this in two trips. One trip to get back a > >> list of OpResults from the check that would inform me if the path > >>existed > >> or not, and a second trip to create all the paths that don't exist (and > >>as > >> a note, the CheckResult object doesn't include the path, so I have to > >> infer it from the order of my original list of paths used to create the > >> multi-check). > >> > >> -Ryan > >> > >> On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > >> > >>> On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < > >>> [EMAIL PROTECTED]> wrote: > >>> > >>>> Yes, Ted's right. The multi has to fail as that's part of the contract > >>>> it > >>>> guarantees. > >>>> > >>>> The only thing you could do, which will significantly narrow the race > >>>> condition, is as you're *building *the multi, check if the path > >>>>already > >>>> exists. If so, then don't add the create op for that path into the > >>>> multi. > >>>> Of course this may not work in every situation, but we use that > >>>> approach in > >>>> many code paths and it works well. > >>>> > >>> > >>> Another approach is to compose one multi with Op.exists() for each > >>>level > >>> so > >>> that you find everything you need, then create another with the correct > >>> Op.create() operations. That gets the problem down to two server > >>> round-trips but still has the race condition. > >> > >
+
Marshall McMullen 2012-03-01, 23:27
-
Re: Create nested paths
Shelley, Ryan 2012-03-01, 23:30
Yeah, that's what I had coded previously. Sorry for all the back-and-forth guys, I was trying to be lazy and reduce round-trips. I'll switch back to this code. I appreciate the feedback!
On 3/1/12 3:27 PM, "Marshall McMullen" <[EMAIL PROTECTED]> wrote:
>Yes, the results are guaranteed to be the same order of the requests. > >However, the first one that fails will cause the entire multi to be >aborted. So, if say the first one fails, then you won't know if the others >after that would have failed. > >I'd suggest doing something entire different, such as (pseudo-code): > >List<Ops> ops >for(path in paths) > if (!Exists(path)) { > ops.add(Op.Create(path)); > } > >Does that make sense? I'm suggesting you use the non-multi code to check >if >it exists or not. If not, you can append any ops related to that path into >your ops list. > > >On Thu, Mar 1, 2012 at 11:14 PM, Shelley, Ryan ><[EMAIL PROTECTED]>wrote: > >> Right, I did this: >> >> (psuedo-code) >> List<Ops> ops >> For(path in paths) >> ops.add( Op.check(path, -1) ) >> EndFor >> >> List<OpResult> Results = Zk.multi(ops) >> >> This causes an exception to be thrown on the first path that doesn't >> exist. It doesn't return back a list with one OpResult flagged with an >> error. I was under the impression I'd get back a bunch of OpResult >>objects >> with flags of error, or otherwise, and then I could build another list >>of >> operations to create what's needed (which, even if it did work, the >> CheckResult object doesn't include the path, so I'm just hoping the >> results are in the same order as the operations were listed in, as I >>have >> to infer the path I'll need to build from the position of the OpResult >>in >> the list). >> >> >> >> On 3/1/12 3:05 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: >> >> >No. I meant one call full of checks and a second call with any >>necessary >> >creates. >> > >> >Sent from my iPhone >> > >> >On Mar 1, 2012, at 11:17 AM, "Shelley, Ryan" <[EMAIL PROTECTED]> >> >wrote: >> > >> >> Ok, I tried this with the Op.create and found that it will throw a >> >> KeeperException on the first path that doesn't exist. It doesn't >>return >> >> back an OpResult with an "error" type. I can still use this, and just >> >> catch the exception and create the node in the exception, but I was >> >>under >> >> the impression that I could do this in two trips. One trip to get >>back a >> >> list of OpResults from the check that would inform me if the path >> >>existed >> >> or not, and a second trip to create all the paths that don't exist >>(and >> >>as >> >> a note, the CheckResult object doesn't include the path, so I have to >> >> infer it from the order of my original list of paths used to create >>the >> >> multi-check). >> >> >> >> -Ryan >> >> >> >> On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: >> >> >> >>> On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < >> >>> [EMAIL PROTECTED]> wrote: >> >>> >> >>>> Yes, Ted's right. The multi has to fail as that's part of the >>contract >> >>>> it >> >>>> guarantees. >> >>>> >> >>>> The only thing you could do, which will significantly narrow the >>race >> >>>> condition, is as you're *building *the multi, check if the path >> >>>>already >> >>>> exists. If so, then don't add the create op for that path into the >> >>>> multi. >> >>>> Of course this may not work in every situation, but we use that >> >>>> approach in >> >>>> many code paths and it works well. >> >>>> >> >>> >> >>> Another approach is to compose one multi with Op.exists() for each >> >>>level >> >>> so >> >>> that you find everything you need, then create another with the >>correct >> >>> Op.create() operations. That gets the problem down to two server >> >>> round-trips but still has the race condition. >> >> >> >>
+
Shelley, Ryan 2012-03-01, 23:30
-
Re: Create nested paths
Ted Dunning 2012-03-01, 23:25
Harrumph.
The only good thing to say here is that, yes, there is a one to one correspondence between arguments and results in the returned list.
I will have to check the documentation to see if throwing an exception is the correct thing to do for check. It surprises me a bit that you are seeing this result.
Sent from my iPhone
On Mar 1, 2012, at 3:14 PM, "Shelley, Ryan" <[EMAIL PROTECTED]> wrote:
> Right, I did this: > > (psuedo-code) > List<Ops> ops > For(path in paths) > ops.add( Op.check(path, -1) ) > EndFor > > List<OpResult> Results = Zk.multi(ops) > > This causes an exception to be thrown on the first path that doesn't > exist. It doesn't return back a list with one OpResult flagged with an > error. I was under the impression I'd get back a bunch of OpResult objects > with flags of error, or otherwise, and then I could build another list of > operations to create what's needed (which, even if it did work, the > CheckResult object doesn't include the path, so I'm just hoping the > results are in the same order as the operations were listed in, as I have > to infer the path I'll need to build from the position of the OpResult in > the list). > > > > On 3/1/12 3:05 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > >> No. I meant one call full of checks and a second call with any necessary >> creates. >> >> Sent from my iPhone >> >> On Mar 1, 2012, at 11:17 AM, "Shelley, Ryan" <[EMAIL PROTECTED]> >> wrote: >> >>> Ok, I tried this with the Op.create and found that it will throw a >>> KeeperException on the first path that doesn't exist. It doesn't return >>> back an OpResult with an "error" type. I can still use this, and just >>> catch the exception and create the node in the exception, but I was >>> under >>> the impression that I could do this in two trips. One trip to get back a >>> list of OpResults from the check that would inform me if the path >>> existed >>> or not, and a second trip to create all the paths that don't exist (and >>> as >>> a note, the CheckResult object doesn't include the path, so I have to >>> infer it from the order of my original list of paths used to create the >>> multi-check). >>> >>> -Ryan >>> >>> On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: >>> >>>> On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < >>>> [EMAIL PROTECTED]> wrote: >>>> >>>>> Yes, Ted's right. The multi has to fail as that's part of the contract >>>>> it >>>>> guarantees. >>>>> >>>>> The only thing you could do, which will significantly narrow the race >>>>> condition, is as you're *building *the multi, check if the path >>>>> already >>>>> exists. If so, then don't add the create op for that path into the >>>>> multi. >>>>> Of course this may not work in every situation, but we use that >>>>> approach in >>>>> many code paths and it works well. >>>>> >>>> >>>> Another approach is to compose one multi with Op.exists() for each >>>> level >>>> so >>>> that you find everything you need, then create another with the correct >>>> Op.create() operations. That gets the problem down to two server >>>> round-trips but still has the race condition. >>> >
+
Ted Dunning 2012-03-01, 23:25
-
Re: Create nested paths
Marshall McMullen 2012-03-01, 23:28
Check is just handled the same as the other ops. In the PrepRequestProcessor stage if the requested path doesn't exist, then it aborts the multi with an error.
On Thu, Mar 1, 2012 at 11:25 PM, Ted Dunning <[EMAIL PROTECTED]> wrote:
> Harrumph. > > The only good thing to say here is that, yes, there is a one to one > correspondence between arguments and results in the returned list. > > I will have to check the documentation to see if throwing an exception is > the correct thing to do for check. It surprises me a bit that you are > seeing this result. > > Sent from my iPhone > > On Mar 1, 2012, at 3:14 PM, "Shelley, Ryan" <[EMAIL PROTECTED]> > wrote: > > > Right, I did this: > > > > (psuedo-code) > > List<Ops> ops > > For(path in paths) > > ops.add( Op.check(path, -1) ) > > EndFor > > > > List<OpResult> Results = Zk.multi(ops) > > > > This causes an exception to be thrown on the first path that doesn't > > exist. It doesn't return back a list with one OpResult flagged with an > > error. I was under the impression I'd get back a bunch of OpResult > objects > > with flags of error, or otherwise, and then I could build another list of > > operations to create what's needed (which, even if it did work, the > > CheckResult object doesn't include the path, so I'm just hoping the > > results are in the same order as the operations were listed in, as I have > > to infer the path I'll need to build from the position of the OpResult in > > the list). > > > > > > > > On 3/1/12 3:05 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > > > >> No. I meant one call full of checks and a second call with any necessary > >> creates. > >> > >> Sent from my iPhone > >> > >> On Mar 1, 2012, at 11:17 AM, "Shelley, Ryan" <[EMAIL PROTECTED]> > >> wrote: > >> > >>> Ok, I tried this with the Op.create and found that it will throw a > >>> KeeperException on the first path that doesn't exist. It doesn't return > >>> back an OpResult with an "error" type. I can still use this, and just > >>> catch the exception and create the node in the exception, but I was > >>> under > >>> the impression that I could do this in two trips. One trip to get back > a > >>> list of OpResults from the check that would inform me if the path > >>> existed > >>> or not, and a second trip to create all the paths that don't exist (and > >>> as > >>> a note, the CheckResult object doesn't include the path, so I have to > >>> infer it from the order of my original list of paths used to create the > >>> multi-check). > >>> > >>> -Ryan > >>> > >>> On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > >>> > >>>> On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < > >>>> [EMAIL PROTECTED]> wrote: > >>>> > >>>>> Yes, Ted's right. The multi has to fail as that's part of the > contract > >>>>> it > >>>>> guarantees. > >>>>> > >>>>> The only thing you could do, which will significantly narrow the race > >>>>> condition, is as you're *building *the multi, check if the path > >>>>> already > >>>>> exists. If so, then don't add the create op for that path into the > >>>>> multi. > >>>>> Of course this may not work in every situation, but we use that > >>>>> approach in > >>>>> many code paths and it works well. > >>>>> > >>>> > >>>> Another approach is to compose one multi with Op.exists() for each > >>>> level > >>>> so > >>>> that you find everything you need, then create another with the > correct > >>>> Op.create() operations. That gets the problem down to two server > >>>> round-trips but still has the race condition. > >>> > > >
+
Marshall McMullen 2012-03-01, 23:28
-
Re: Create nested paths
Shelley, Ryan 2012-03-01, 18:13
I don't see an Op.exists() method. Check, Create, Delete and SetData. I'm on 3.4.3, if that makes a difference.
On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote:
>On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < >[EMAIL PROTECTED]> wrote: > >> Yes, Ted's right. The multi has to fail as that's part of the contract >>it >> guarantees. >> >> The only thing you could do, which will significantly narrow the race >> condition, is as you're *building *the multi, check if the path already >> exists. If so, then don't add the create op for that path into the >>multi. >> Of course this may not work in every situation, but we use that >>approach in >> many code paths and it works well. >> > >Another approach is to compose one multi with Op.exists() for each level >so >that you find everything you need, then create another with the correct >Op.create() operations. That gets the problem down to two server >round-trips but still has the race condition.
+
Shelley, Ryan 2012-03-01, 18:13
-
Re: Create nested paths
Ted Dunning 2012-03-01, 23:02
No. Version number won't change the fact that I am spacy.
I meant the check op.
Sent from my iPhone
On Mar 1, 2012, at 10:13 AM, "Shelley, Ryan" <[EMAIL PROTECTED]> wrote:
> I don't see an Op.exists() method. Check, Create, Delete and SetData. I'm > on 3.4.3, if that makes a difference. > > On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > >> On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < >> [EMAIL PROTECTED]> wrote: >> >>> Yes, Ted's right. The multi has to fail as that's part of the contract >>> it >>> guarantees. >>> >>> The only thing you could do, which will significantly narrow the race >>> condition, is as you're *building *the multi, check if the path already >>> exists. If so, then don't add the create op for that path into the >>> multi. >>> Of course this may not work in every situation, but we use that >>> approach in >>> many code paths and it works well. >>> >> >> Another approach is to compose one multi with Op.exists() for each level >> so >> that you find everything you need, then create another with the correct >> Op.create() operations. That gets the problem down to two server >> round-trips but still has the race condition. >
+
Ted Dunning 2012-03-01, 23:02
-
Re: Create nested paths
Marshall McMullen 2012-03-01, 18:15
Check() will check if it exists with the specified version number. If you give it -1 it won't compare the version number. So that's a basic Exists() call. Does that make sense?
On Thu, Mar 1, 2012 at 6:13 PM, Shelley, Ryan <[EMAIL PROTECTED]>wrote:
> I don't see an Op.exists() method. Check, Create, Delete and SetData. I'm > on 3.4.3, if that makes a difference. > > On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: > > >On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < > >[EMAIL PROTECTED]> wrote: > > > >> Yes, Ted's right. The multi has to fail as that's part of the contract > >>it > >> guarantees. > >> > >> The only thing you could do, which will significantly narrow the race > >> condition, is as you're *building *the multi, check if the path already > >> exists. If so, then don't add the create op for that path into the > >>multi. > >> Of course this may not work in every situation, but we use that > >>approach in > >> many code paths and it works well. > >> > > > >Another approach is to compose one multi with Op.exists() for each level > >so > >that you find everything you need, then create another with the correct > >Op.create() operations. That gets the problem down to two server > >round-trips but still has the race condition. > >
+
Marshall McMullen 2012-03-01, 18:15
-
Re: Create nested paths
Shelley, Ryan 2012-03-01, 18:46
Perfect. Thanks so much!
On 3/1/12 10:15 AM, "Marshall McMullen" <[EMAIL PROTECTED]> wrote:
>Check() will check if it exists with the specified version number. If you >give it -1 it won't compare the version number. So that's a basic Exists() >call. Does that make sense? > >On Thu, Mar 1, 2012 at 6:13 PM, Shelley, Ryan ><[EMAIL PROTECTED]>wrote: > >> I don't see an Op.exists() method. Check, Create, Delete and SetData. >>I'm >> on 3.4.3, if that makes a difference. >> >> On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote: >> >> >On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < >> >[EMAIL PROTECTED]> wrote: >> > >> >> Yes, Ted's right. The multi has to fail as that's part of the >>contract >> >>it >> >> guarantees. >> >> >> >> The only thing you could do, which will significantly narrow the race >> >> condition, is as you're *building *the multi, check if the path >>already >> >> exists. If so, then don't add the create op for that path into the >> >>multi. >> >> Of course this may not work in every situation, but we use that >> >>approach in >> >> many code paths and it works well. >> >> >> > >> >Another approach is to compose one multi with Op.exists() for each >>level >> >so >> >that you find everything you need, then create another with the correct >> >Op.create() operations. That gets the problem down to two server >> >round-trips but still has the race condition. >> >>
+
Shelley, Ryan 2012-03-01, 18:46
-
Re: Create nested paths
Shelley, Ryan 2012-03-01, 05:29
I think what I was getting at was a flag that simply says "It's ok to already exists, just ignore it and continue." However, I'm doing the approach you already suggested and checking each sub-path before adding the Op to the list, and it works fine. I just wanted to make sure I wasn't missing a better approach. Thanks!
On 2/29/12 7:16 PM, "Ted Dunning" <[EMAIL PROTECTED]> wrote:
>On Wed, Feb 29, 2012 at 7:04 PM, Marshall McMullen < >[EMAIL PROTECTED]> wrote: > >> Yes, Ted's right. The multi has to fail as that's part of the contract >>it >> guarantees. >> >> The only thing you could do, which will significantly narrow the race >> condition, is as you're *building *the multi, check if the path already >> exists. If so, then don't add the create op for that path into the >>multi. >> Of course this may not work in every situation, but we use that >>approach in >> many code paths and it works well. >> > >Another approach is to compose one multi with Op.exists() for each level >so >that you find everything you need, then create another with the correct >Op.create() operations. That gets the problem down to two server >round-trips but still has the race condition.
+
Shelley, Ryan 2012-03-01, 05:29
|
|