Subject: Re: Simplifying RFC-2518 Locking: A proposal

From: [email-masked]
Date: Sat, 16 Oct 1999 21:13:20 -0400

I would resist the second extension. My server currently does not associate
  anything with the lock token except the locked resource. In particular, it
  doesn't remember the URL used to lock the resource,

Hey, it's just a little matter of coding. :-) It sounds like the server would
need to maintain a   lock + URI  ->  new URI mapping or something
like that.  There really wouldn't be any point in storing it with resource.
That mapping table would need to be global (at least to the workspace).  It
would need an entry for every URI locked by a depth lock if we plan to
remap each of those independently.

Issues...

i1) I suspect Geoff didn't mean it, but I think he said (by using the
 word "identify") that the server "tells" the client where the resource
 has moved to.  (If this is not what Geoff meant... skip to (i2).)
 This can be a bad thing.
 The server should internally redirect the request to the resource at it's new
location.
 The reason it's bad is that by the time the client accesses that new location
 it couild have moved again.  That means the client has to go back to the
 original URI to to ask where it has moved again.  So this means the
 client has to chase down the resource.  It's a potential race condition and
 the client can never safely use the second location/URI in a request.  It
 always has to remember the first location.  -- Now this could be improved
(client view) if
 Geoff says    that a resource doesn't just remember the original location of
 the resource... but also subsequent.  (This was what Geoff proposed a few
 weeks ago.)   We'd need to define this more clearly but it might work.  BTW
 this second alteration by itself doesn't save the client from chasing down
 the resource... but if we can define a useful deterministic behavior, it
 allows the client to only remember the most recent URI that he was given.
 This second change would also allow one to use a lock obtained via lock
 discovery.
i2) This proposal breaks our model whereby all webdav resources have parents
 at their analagous parent URI.  This would not be the case here unless
 URI protection were added.  That is... a whole tree of URI's could be
 locked, but if someone does a MOVE above the root of that URI at which
 the lock request was originally directed, then there will be a gap in the
 parentage tree.  --  I personally don't care about this, but a lot of folks
 went through a ton of time defining and refining how webdav resources must
 have a parent at their parent URI.  A ton.  They must feel this is a valuable
 feature.  -- Also a lesser namespace incongruity like this was also the reason
 that it was claimed that lock null resources are a pain for the client.  If
 that was to believed there... it should be a consideration here.
i3) Because this model doesn't protect a URI, it isn't just possible to move
 a locked resource from the namespace... it's also possible to delete it
 from the namespace and thus removing all apparent URI's for it.  Redirection
 won't work then.  Perhaps internal redirection would still though.
i4) For depth locks, we'd need to define behaivor.   Given /a/b/c and a
 depth lock placed on /a/b/.  It's pretty clear what the redirection does
 for an access to /a/b/.  But what about /a/b/c?  Does it refer to the
 resource that was originally at that location?  Or does it refer to the
 current "c" member of the collection that was orginally at /a/b/.
i5) We'd have to work out when the redirection is triggered.  It's probably
 not sufficient to say it's triggered when there is no resource at a
 URI.  It would need to also deal with the situation where a different
 resource is now at that location.  But that does create another
 ambiguity rlated to (i4).  Ah... it's a bit of a mess.  I'm not going to
 get into it here.

   and there is no special case
   URL mapping that would somehow add lock tokens to namespace resolution
   calculations, some of which happen outside my server's domain.

???  wakarimasen (I don't understand.)

  It seems like if
  we have to do this, we're still missing something. I think the solution is
that
  if the user is conserned about someone moving his locked resource, then he
  should lock the parent collection. That's what locking collections is for, to
  control the namespace.

Lacking URI protection, he'd also lock all the collections to the root.

  Alternatively, we can fail any move whose souce is
  locked, and the requesting principal either doesn't own the lock, or didn't
  specify the lock token.

This sounds like a version of URI protection.  The version where all URI's of
a lock are protected.
It actually sounds fine/benign the way you describe it, but in an earlier
thread Geoff and I determined that this can be expensive.  (It might have
been an offline thread between the AdvColl folks.) I have to
admit... it really does sound attractive here though.  :-)

  The confusion here is that PUT and DELETE are resource
  methods that effect their parent collection as a side effect. It would be
better
  to have some addMember/removeMember methods on a collection to do this. The
  problems result form the behavior being in the wrong place. But this is
  inherited from HTTP which didn't have collections, so we'll have to work
around
  it.

What PUT and DELETE problem are you refering to that is
related to this discussion?

  Now, while we're on a role, how about getting rid of those pesky lock tokens!
  The only thing they seem to do is let a particular principle who is running
  concurrent authoring applications that might be updating the same resources
  detect the possibility of overwrite conflicts by distinguishing which
  application got the lock token by doing the LOCK, and which one got it from
some
  other mechanism (like IPC or the user typed it in). The application that
  directly got the lock could proceed with its operation while the others could
  put up a warning indicating there might be some other application that could
be
  updating the resource at the same time, and you might want to think about
  whether you want to do this operation now or not. (Now there's a warning for
  you). It took me quite a while to figure this out, and I may not have it right
  yet, but that's my interpretation of the spec.

I think you got that right... the part about determining which application got
the token via the primary mechanism isn't right, but it doesn't affect what you
say below.

  Note that clients don't have to
  do anything with the lock token except hang on to them and send them back when
  needed.

I guess so.  I don't know else they might do that you are suggesting is avoided.

  The above is just a suggested convention.

You're losing me.  :-)

  Not also that having a lock
  token doesn't give any other principle any privilege as you must own a lock
  token to be able to use it.

Right.  You can't get past a lock by stealing a lock token... unless you appear
to be the principal that took out the lock in the first place.

  I submit the problem being solved is not worth the
  protocol complexity and client inconvence (having to retain all those lock
  tokens). Note also that other systems either associate the lock with the
process
  id (which we can't do in an HTTP server), or let the user be responsible for
  concurrent process he might have started up. I'd be happy that.

I think you're essentially saying that when one authenticates, there should be a
way to distinguish between the applications using the same ID... or perhaps that
they really should use different ID"s.  The use of distinct ID's or session ID's
has been discussed before.  (Yaron and I had an exchange on this about two years
ago... but I can't find the posting.)   Yaron shot down that proposal.

Reasons for tokens rather than just principles
  1)    Reduces the dependency on a clients
        generating unique and unpredictable session identifiers.
        (Puts control in the server's hands.)
  2)    Still allows the same principal to share a capability
        between his left and right hands if it deems it
        appropriate.  (puts some control in the lock owner's
        hands.)
   2.1) It's never stated, but I suspect they might have also
        envisioned using this as a the basis of capabilities
        passing system that wasn't dependent on authentication.
  3)    It allows for the possibility of multiple locks per
        resource by the same principal... without chaos.
   3.1) It's a convenient way for UNLOCK to specify the lock
        it is removing.
  4)    It allows for URI remapping schemes like Geoff's.
  5)    The original authors seemed to feel it was important
        that the client at times to provide verification that it
        knows what locks are located where.  This actually
        becomes essential if we don't protect URI's or remap
        them.  (if-match headers don't support guids yet.)

I think it's an interesting coincidence that you seem to have suggested the
possible removal of lock tokens.  I was actually mulling over another
possibility.  Removal of locks altogether.  It was inspired by recent arguments
against URI protection and lock null resources... which both are intended to
protect the namespace.  I eventually decided that locks are still a good thing
even without URI protection (which I still advocate) and LNRs.  Locks do more
than just prevent the lost update problem.

Later,

J.

---

From: "Geoffrey M. Clemm" <[email-masked]>
Date: Sat, 16 Oct 1999 23:04:49 -0400

From: [email-masked]

   <ja>
   </ja>

   Hey, it's just a little matter of coding. :-)

I was wondering the same thing.  It seems like a fairly easy thing to
compute.  If somebody tries to "MOVE" the resource outside of the
resources you control, you can just fail the MOVE.  Otherwise, when
someone comes at you with a URL and a Lock-Token header, just look the
pair up in your table, and perform the request on that resource.

   It sounds like the server would
   need to maintain a   lock + URI  ->  new URI mapping or something
   like that.

lock + URI -> resource.  No need for the server to indirect through
another URI mapping ... that would just make things hard.  The nice
thing about being a server is that you have real resource handles
and *don't* have to indirect through URI's.

   There really wouldn't be any point in storing it with resource.

You could just store it in the resource, and then search for it every
time you get a request, but that doesn't sound like the efficient way
to do it.

Which is reasonable with static depth locks, and quite the pain with
dynamic depth locks, but I digress ... (:-).

   Issues...

You are correct, that's not what I meant (:-).  By "identify", I mean
the server figures out what the locked resource was, and applies the
method to that resource.  Clients are not involved at all, so I'll
skip to i2 ...

   i2) This proposal breaks our model whereby all webdav
   resources have parents at their analagous parent URI.  This would not
   be the case here unless URI protection were added.

I believe that there is no more breakage in this regard than
is introduced by multiple bindings.  You have a new name for a resource
*other* than the name it used to have (just like adding a binding).

Unlike a normal binding, this new name (the <lock-token,URL> pair)
is stored off in some server maintained place where clients can't
mess with it.

Now it's true that this new name effectively exists in a non-WebDAV
namespace, but WebDAV was carefully designed to ensure that these
non-WebDAV namespaces can co-exist with the WebDAV ones.
The fact that this new name is bound to the same resource that
exists in WebDAV space should cause no confusion.

   That is... a whole
   tree of URI's could be locked, but if someone does a MOVE above the
   root of that URI at which the lock request was originally directed,
   then there will be a gap in the parentage tree.

The WebDAV resource space will have no gaps.  The <lock-token,URL> name
is still valid.  It's true that you can't treat the new name as forming
a tree of any interesting kind, but that's not what it is there for.
It's a way to guarantee that a client has a reliable handle on the
resource it locked (e.g. for a subsequent PUT/UNLOCK).

   I personally don't care about this,
   but a lot of folks went through a ton of time
   defining and refining how webdav resources must have a parent at their
   parent URI.  A ton.  They must feel this is a valuable feature.  --

As do I.  If I were violating it, I'd be concerned.  I believe we
are just "supplementing" it with some additional reliable names.

   Also a lesser namespace incongruity like this was also the reason that
   it was claimed that lock null resources are a pain for the client.  If
   that was to believed there... it should be a consideration here.

That was very different.  The case against a lock null resource is that
it was a URL masquerading as a resource.  A lock null resource is just
a sleight-of-mouth (:-) for locking a name while still pretending that
there was some resource being locked.  The complexities that resulted
stemed from the fact that there really *was* no resource to hold this
lock, and so the model would break down.

   i3)
   Because this model doesn't protect a URI, it isn't just possible to
   move a locked resource from the namespace... it's also possible to
   delete it from the namespace and thus removing all apparent URI's for
   it.

except for the special <lock-token,URI> name that will continue to
provide access to it.

   Redirection won't work then.  Perhaps internal redirection would
   still though.  

The server maps this special name to a resource, not to another URI.
(Life is good, when you're a server :-).

   i4) For depth locks, we'd need to define behaivor.
   Given /a/b/c and a depth lock placed on /a/b/.  It's pretty clear what
   the redirection does for an access to /a/b/.  But what about /a/b/c?
   Does it refer to the resource that was originally at that location?

If you use the Lock-Token header, it will be the resource that was at
/a/b/c when you applied the lock.

   Or does it refer to the current "c" member of the collection that was
   orginally at /a/b/.

No, the Lock-Token is just there to guarantee access to the original resource.
If you want to play with the current members of the collection, you'd
just BIND that collection into some working collection, and then
issue your requests against that new binding without the
Lock-Token header.

   i5) We'd have to work out when the redirection is
   triggered.  It's probably not sufficient to say it's triggered when
   there is no resource at a URI.  It would need to also deal with the
   situation where a different resource is now at that location.  But
   that does create another ambiguity rlated to (i4).  Ah... it's a bit
   of a mess.  I'm not going to get into it here.

I think you're still thinking of it as a "<lock-token,URL> -> new-URL"
mapping ... it's not.  It's "<lock-token,URL> -> resource".  The server
stores this information in its lock table at the time of the lock request,
and doesn't change it until the UNLOCK request is made.  The server
knows when to use the lock table when it gets a Lock-Token header.
Otherwise it just ignores the lock table.

   and there is no special case URL mapping that would somehow add lock
   tokens to namespace resolution calculations, some of which happen
   outside my server's domain.

As long as the same server handles the same segment of the URL space
(e.g. nobody messes with the Apache config file), all requests for
Lock-Token based URL's will go to the same server.  Sure, if the
client holds onto the lock token long enough for that to no longer
apply, then it won't find the resource.  The server just handles that
like a timeout, (probably it would have timed out anyway by then :-).

   <ja> It seems like if we have to do this, we're still missing something. I
   think the solution is that if the user is conserned about someone
   moving his locked resource, then he should lock the parent
   collection. That's what locking collections is for, to control the
   namespace. </ja>

   Lacking URI protection, he'd also lock all the collections to the
   root.

No, just the subtree being worked on.  If you ever "lose" the sub-tree
you were working on, you can use your "lock-token" and the original
subtree root URL to find your sub-tree, bind it somewhere so you can
keep working on it.  If somebody moves *that* away, heck, you've still
got your lock token, and you can rebind to it as often as you need to.

As for Jim's suggestion that we do away with lock tokens, as Jason
points out, it would require designing a session mechanism, which
is probably better but more complicated than lock tokens, so it
wouldn't fit into my current "simplify 2518" jihad (:-).

Cheers,
Geoff

---

From: Edgar Schwarz <[email-masked]>
Date: Mon, 18 Oct 1999 08:36:04 +0200

Geoffrey M. Clemm wrote:

> and *don't* have to indirect through URI's.
I would vote for a lock + URI  ->  new URI mapping. More below.

> method to that resource.  Clients are not involved at all, so I'll
My idea was that the server will tell the client in this case just the
new URI. Then he can forget the mapping because the client now knows
the new URI and can reaccess it. Also the client can signal his user
that the
resource has moved. If it is moved again before accessing
it (a rare event I think) the client will just get a new URI again.
Do you see any problems ?
BTW, I also don't want depth locks and lock null resources compicating
my client.

Regards, Edgar

-- 
[email-masked] ON/EUE1, 07191/13-3382         Niklaus Wirth:
Privat kann jeder soviel C programmieren oder Videos ansehen wie er mag.
Albert Einstein:  Mach es so einfach wie moeglich, aber nicht einfacher.

---

From: "Geoffrey M. Clemm" <[email-masked]>
Date: Mon, 18 Oct 1999 08:15:48 -0400

First, thanks to JimW for pointing out several areas of poor word
choice in the original proposal.  I didn't mean to eliminate the ability
to refresh a lock, and didn't mean to say that the live properties were
not part of the state of a resource ... just that they were not part
of the *lockable* state of the resource.

   From: Edgar Schwarz <[email-masked]>

   <jc>  I suspect Geoff didn't mean it, but I think he said (by using the
   word "identify") that the server "tells" the client where the resource
   has moved to. </jc>

   <es> My idea was that the server will tell the client in this case just the
   new URI. Then he can forget the mapping because the client now knows
   the new URI and can reaccess it. Also the client can signal his user
   that the resource has moved. If it is moved again before accessing it
   (a rare event I think) the client will just get a new URI again.  Do
   you see any problems ? </es>

<gmc>
I actually see any problem with this ... I just wasn't thinking
along those lines (even though after reviewing the mail archives, it's
something that both you and Jason have brought up).  And the more that
I (finally! :-) do think about it, the more I like it.

Returning a 302 is enshrined HTTP behavior (for good reason).  We're
even defining a new resource type (redirect references) just so that
we can give the client the ability to specify this useful functionality.
So clients in general will be designed to handle this case.

Jason raised the issue of a "race" condition (i.e. every time you try
to access your locked resource, you get back a new "302" because some
other client keeps moving it).  My response is that if your client
just updates it's location table (as opposed to trying to move it back),
there is no race condition.  The probability of someone trying to rapidly
move it around to a different locations is so low that I really don't
think that we need to be concerned with that possibility.

Finally, I think that the 302 approach gives us the best of both
worlds.  An implementation can chose to just fail any DELETE or MOVE
that would make a locked resource no longer appear at the locking URL.
Clients need to handle DELETE's and MOVE's failing anyway (e.g. the
collection containing the resource is locked).  Alternatively, an
implementation can chose to allow the DELETE or MOVE, as long as it
is tracking an alternative URL that it can give back to the client for
the 302 response.  Again, clients need to handle 302's anyway, so this
is again straightforward for a client to deal with.  Flexibility for server
implementors with little/no additional cost to clients.

   <es> BTW, I also don't want depth locks and lock null resources complicating
   my client. </es>

<gmc> In my earlier proposal, I included static depth locking as a
"compromise" for the depth locking advocates.  But as JimW (as depth
locking spokesman :-) points out, that's not what depth locking advocates
want ... they want dynamic depth locking.

So it's time to rev the lock simplification proposal: Add in the 302
behavior that Edgar advocates, and take out depth locking altogether.
A couple of notes about depth locking:

(1) I don't see client writers clamoring for it ... the only strong
voices in its support appear to be the 2518 authors.  It would be great
if the client writers on this list would weigh in here with some
opinions/guidance.

(2) The reality is that depth locking is not provided in one of the
key WebDAV platforms (Office 2000).  As fun as it is to bash
Microsoft, the Microsoft file system guys probably know as much or
more than anyone about the proper use of file locks for concurrent
access management.  The fact that they chose not to support them is in
my opinion significant.  If nothing else, it is significant in that
any client that wants to work against the Office 2000 server had
better not expect a depth lock request to succeed.  Obviously this
can't be our sole reason for taking them out, but if it seems like a
50/50 call, it is a factor.

So without more ado, here's the modified simplified locking proposal.

Cheers,
Geoff

***** Simplified RFC-2518 Locking, Version-2 *****

A LOCK/UNLOCK request places/removes a lock on exactly one resource
(the resource identified by the request-URL).  A LOCK/UNLOCK request
on a URL that is not mapped to a resource will fail with a 404.

Only an explicit LOCK request ever adds a lock to a resource, and only
an explicit UNLOCK request ever removes a lock from a resource.  In
particular, locks are not deleted as a side effect of a MOVE or a
DELETE, and locks are not added as a side effect of a MOVE due to
"inheriting a lock" from a collection.

A request fails with a 423 if the request would modify the state of a
write-locked resource for which you don't hold (and specify) the lock
token.  The state of a basic resource that is affected by a lock is
its body and its dead properties.  The state of a collection that is
affected by a lock is its set of bindings, its body, and its dead
properties.  A write-lock request on a resource that is already
write-locked will fail with a 423 unless it is an explicit "refresh"
of an existing lock.

When a Lock-Token header is included in any request, if the locked
resource is no longer available at that URL, the server MUST return a
302 indicating a new URL at which the locked resource is available.  A
server MAY refuse to perform a MOVE/DELETE that would cause a locked
resource to no longer be available at the locked URL.

***** End: Simplified RFC-2518 Locking, Version-2 *****