Subject: [Simple] XCAP Issue 9: Etags mostly useless for insert

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 24 Jun 2004 06:49:57 -0400

[resend]

While working through the text on etags, I ran into an interesting
issue. Its not clear its a problem, but its something that needs to be
documented if we decide its not.

The issue is that, when you do a conditional PUT (that is, a PUT with an
If-Match containing an etag), the conditioning is based on the etag for
*that* resource. There is no way to say, "perform this PUT on resource
X, but only if the etag for resource Y has not changed". Why is this an
issue? Well, let me give a concrete example.

Lets say I have a basic buddy list that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<resource-lists xmlns="urn:ietf:params:xml:ns:resource-lists"
xmlns:xcap="urn:ietf:params:xml:ns:xcap-must-understand"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <list name="friends" uri="sip:[email-masked]" subscribeable="true">
     <entry name="Bill" uri="sip:[email-masked]">
       <display-name>Bill Doe</display-name>
     </entry>
     <list name="close-friends" uri="sip:[email-masked]"
           subscribeable="true">
       <entry name="Joe" uri="sip:[email-masked]">
         <display-name>Joe Smith</display-name>
       </entry>
       <entry name="Nancy" uri="sip:[email-masked]">
         <display-name>Nancy Gross</display-name>
       </entry>
       <external>http://www.example.org/xcap/resource-lists/users/a/foo
          </external>
     </list>
   </list>
</resource-lists>

and lets consider the simplest etag scope (this issue doesnt matter what
we decide to do for etag scopes per issue 8), where every resource in
the document has the same value for its etag. Its important to
understand that etags are associated with a resource. Even if we decide
that all resources will share the same value for their etags, they still
each have their own etags.

Lets say that the current etag for this document (and all resources
within it) is 2. I decide to insert a new entry, and so I do this:

PUT http://server.com/xcap-root/resource-lists/users/bob/mylist/~/
   resource-lists/list[@name="friends"]/entry[@name="Mikko"]
If-Match: 1

<entry name="Mikko" uri="sip:[email-masked]"/>

You would think that this insertion would be done if the document had
not been modified (i.e., its etag was still 1), but that is NOT what
this request will do. The conditioning here means that the PUT is only
done if the etag for the resource in the request URI has an etag of 1.
Of course, the resource in the request URI doesnt yet exist (thats why
its an insert), so this request will be rejected with a 412.

Basically, there is no way to do an insert, and say, "don't do this
insertion if the document hasn't changed since etag 1". You can say,
"don't do this insert if this resource exists", by using an
If-Not-Match: *. So, you can at least guarantee that what you think is
an insertion, really is an insertion.

So, the question is, is this a problem? I don't think so. Or, more
concretely, I couldn't think of a use case where this was a problem.

Consider the following example. Once again, we have the document above,
and client A has a copy of it locally, in memory, with etag 1. Client 2
makes a change, and the change it makes is to delete the close-friends
list. Client 1 then tries to do an insert into this list, and so it does:

PUT http://server.com/xcap-root/resource-lists/users/bob/mylist/~/
   resource-lists/list[@name="friends"]/
   list[@name="close-friends"]/entry[@name="Paul"]

<entry name="Paul" uri="[email-masked]"/>

Fortunately, this will request will fail with a 409, since the parent of
entry[@name="Paul"] doesnt exist anymore. The client could then refetch
the document and figure out why this error happened.

So, no problem here.

COnsider a different case. Client 1 has this list locally. Client 2
changes the name of "close-friends" to "really-close-friends". Same
thing happens as the previous example.

In yet another case, client 2 changes the subscribeable flag for
close-friends from true to false. In this case, the insert done by
client 1 will succeed. THe problem is that the client no longer has a
correct copy of the document cached. If this is a problem, the client
can refetch the document.

I'll also note that, if you use the xcap package, this problem pretty
much goes away.

As far as I can tell, we have three choices about what to do about this
"problem":

1. document the situation so its clear what etags do and don't do for you

2. instead of thinking about resources within a document as "not
existing" when they aren't there, we can think about them as existing,
but empty. If we stretch our imaginations a bit, we could think about
assigning etags to empty resources. In that case, you basically never
really do insertions; you only ever do modifications, and you might
modify something from being empty to having actual value. In that case,
  you could usefully use etags to condition an "insertion" on whether or
not the entire document has changed since you cached a copy. I consider
this quite ugly.

3. Define an HTTP extension which allows you to condition a request
based on the etag of a different request on the server.

I think we should do 1. I think the costs of doing more complicated
locking and transaction mechanisms (which is what we are talking about)
are too high to pay for this functionality we want right now. If these
things prove really important, we can work them in through xcap extensions.

Comments and input are welcome.

Thanks,
Jonathan R.

-- 
Jonathan D. Rosenberg, Ph.D.                600 Lanidex Plaza
Chief Technology Officer                    Parsippany, NJ 07054-2711
dynamicsoft
[email-masked]                     FAX:   (973) 952-5050
http://www.jdrosen.net                      PHONE: (973) 952-5000
http://www.dynamicsoft.com

_______________________________________________
Simple mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/simple

---

From: Jari Urpalainen <[email-masked]>
Date: Wed, 30 Jun 2004 19:10:39 +0300

> concretely, I couldn't think of a use case where this was a problem.
If-None-Match: *  will certainly help (and make the request much safer)  
if  you want to insert with r-uri like
PUT http://server.com/xcap-root/resource-lists/users/bob/mylist/~/
  resource-lists/list[@name="friends"]/entry[5]
where this new entry is the last one in the "friends" list. 

Anyway, it would have been also much easier both for the client and the 
server if  it had been possible to use the only valid context for ETag 
in this case i.e. the parent node of  the inserted new node.

> 1. document the situation so its clear what etags do and don't do for you
I'll vote this 1. one too.

br,
Jari