Subject: [Simple] XCAP proposal on conditional inserts

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 29 Dec 2005 16:37:36 -0500

At the last IETF meeting, I raised the possibility of fixing the current
conditional insert problem as another change to make to the spec while
we are editing it. The problem, to refresh everyones memory, is that
HTTP (and thus XCAP) allows for conditional operations on a resource
only if the resource being operated on exists. Thats because if it
doesn't exist, it doesn't have an etag. So, you can't insert an element
conditioned on the etag of the entire document and all of its components.

So, if you really mean to insert this thing ONLY if the document is
unchanged, you'll need to do the insert "blindly", and then after its
done, you'll find out whether or not the insert was done against the
version you intended. If so, great. If not, you need to somehow undo the
change you just made.

This is far from ideal, but a known issue, and documented in the spec
today. I've been increasingly concerned that this is just not going to
work well, as it substantially raises the bar for getting the system to
work reliably.

I made a proposal at IETF to fix it, and some good comments were
provided. Based on that, here is my modified proposal for how to fix
this issue.

An XCAP resource representing an XML element in a document is said to
exist if the element appears in the document, OR its parent appears in
the document. If the XCAP resource exists but doesn't appear in the
document, it is said to be empty. So, for example:

<test>
   <el1/>
</test>

test/el1 exists and isn't empty. test/el1/el2 exists but is empty.
test/el1/blah-blah exists but is empty. In fact, every single potential
child element of el1 exists - they're just all empty. Because they exist,
they all have etags, which are all equal to the document etag. Based on
this definition, I can now go and insert a new element, which isn't
technically an insertion, but rather a modification: I'm modifying the
element to change it from empty to a specific value.

This does not apply to attributes, however. An attribute exists only if
its physically present in the document (the difficulty in getting this
mechanism to work with attributes was one of the issues raised at ietf).

Now, there are some actual consequences to this change in definition:

* A GET against one of these empty resources will not return a 404 as it
does today. Rather, it would return a 200 OK, with a Content-Type of
application/xcap-el+xml and a Content-Length of zero. This indicates
that the resource is empty.

So, based on the above example, GET test/el1/foobar would return a 200
OK with Content-Length zero.

* A GET against an element which doesnt exist WOULD return a 404. So,
for example, a GET of test/el1/foobar/nothere would return 404.

* A DELETE of an element would be forbidden, and always return a 405. To
delete an element, you need to modify it to be empty. So, you'd do a PUT
with a Content-Length of 0.

* We would no longer have a way to say, "insert this element into the
document if the element is not currently present in the document". In
the current spec, this is done by a PUT with If-None-Match: *. However,
with the proposed change, this condition would always fail, since the
element will now always exist. What we gain instead is the ability to
insert conditionally based on whether the document on the server matches
the one cached by the client.

* There would no longer be a need for the xcap-diff document that is
returned in a 202 Created response. The reason this xcap-diff document
gets sent is to let the client know what the etag was prior to
insertion, so if it didn't match the cached copy, the client could try
to repair the error. Eliminating the need for this would remove the
dependency on xcap-diff, xml-patch-ops, and so on.

It is tempting to take a slightly different approach. Call the approach 
above "approach 1". The idea with approach 2 is to declare that, even 
though a resource doesn't exist, it has an etag, and that etag is equal 
to the document's etag, assuming the document does exist. Approach 2 
would work much like approach 1, except that:

* A GET against a non-existent resource would be a 404, rather than a 
200 OK with CL of zero

* A DELETE would be allowed

Note however, that with approach 2, you still cannot support the 
operation that says, "insert this but only if this element doesn't 
already exist in the document". Approach 2 has the problem that it 
seriously bends (and possibly breaks), an underlying http assumption 
about the scope and meaning of etags. That might have odd and 
unpredicatable interactions with caching systems and other http 
intermediaries. For this reason, I wouldn't recommend it.

So, I would like to make the concrete proposal of moving to approach 1. 
The main drawback I see is the loss of the ability to insert an element 
if an element with that same name/attribute already exist.

Comments?

-Jonathan R.

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

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

---

From: "Schmidt, Christian" <[email-masked]>
Date: Fri, 30 Dec 2005 10:03:54 +0100

Hi Jonathan,

> for example, a GET of test/el1/foobar/nothere would return 404.

This mean, there are still elements, empty elements and not existing elements.

> the one cached by the client.

Perhaps we should use conditional insertion:
- If the element exists and is not empty: return 404
- If the element exists and is empty: insert
- If the element do not exist: create and insert
This would clarify the meaning of "matches".

Shouldn´t it still be allowed, to delete an element: element > not existing element?
Perhaps in deleting an empty branch: test/el1/foobar/? This could remove garbage.

Example:
<test>
   <el1>
      <foobar>
         <last-one>
      </foobar>
	<silvester/>
   </el1>
</test>

Delete: test/el1/foobar/last-one would lead to
<test>
   <el1>
	<silvester/>
   </el1>
</test>

What do you think about?

Regards
Christian Schmidt, Siemens COM 

	Phone: 	+49 89 636-75192
	Mobile: 	+49 178 7700363
	Fax: 		+49 89 636-75577
	E-Mail: 	[email-masked]

-----Ursprüngliche Nachricht-----
Von: [email-masked] [mailto:[email-masked]] Im Auftrag von Jonathan Rosenberg
Gesendet: Donnerstag, 29. Dezember 2005 22:38
An: Simple WG
Betreff: [Simple] XCAP proposal on conditional inserts

<test>
   <el1/>
</test>

Comments?

-Jonathan R.