[ 
https://issues.apache.org/jira/browse/COUCHDB-902?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Klaus Trainer updated COUCHDB-902:
----------------------------------

    Attachment: 0001-Fix-COUCHDB-902.patch

First of all, thank you, Adam! Your rewrite of couch_key_tree made it way more 
readable.


I think that I got to the point where I understand how the merging logic works. 

To me, the merging logic in couch_key_tree looks absolutely correct. Given the 
fact that I now understand what's going on there, I don't see any reasonable 
change we can make in couch_key_tree in order to solve this issue. We rather 
have to make a change somewhere else.

To anticipate my conclusion: Pruning the revs tree of a #doc{} is necessary for 
updates that cannot introduce new conflicts.

In the following, I'd like to explain why. I've attached a new patch, which 
fixes the issue in a more reasonable way.


couch_key_tree:merge/3 returns an atom (`conflicts | no_conflicts`) that tells 
us whether an update creates a conflict or not. The returned atom is ignored as 
long as a certain flag `MergeConflicts` is set. More precisely, conflict 
checking is only active for normal interactive edits, but not for replication 
or bulk insertions with `all_or_nothing: true`.

Currently, the only case where an interactive edit is done with the #doc{} 
containing the full revision history (instead of just the current and the new 
rev) is when there's an attachment (see couch_httpd_db:db_attachment_req/4).

couch_key_tree:merge/3 is called with a list of paths and a path, whereupon the 
latter is the return value of couch_doc:to_path/1. Looking at 
couch_doc:to_path/1, one can see that the start sequence number that is 
computed there depends on the length of the revision history. Also, the 
revisions list `RevIds` is reversed. That means that for interactive edits the 
computed paths may be different (namely when length(RevIds) > 2), depending on 
whether it's an update with an attachment or not.

To summarize my above explanation:

1) The result of the conflict detection algorithm is only relevant for 
interactive edits with `MergeConflicts =:= false`. Otherwise, the result may be 
not correct and it's ignored anyway.

2) The correctness of the conflict detections in couch_key_tree (namely 
merge_at/2 and merge_simple/2) relies on the fact that no more than two 
revision ids, namely the new and the current one (if available), are contained 
in the revs tree.


Although my previous patch was somehow correct, and pruning the revs tree seems 
to be the way to go indeed, Filipe is right when saying that the fix should be 
applied in couch_db_updater:merge_rev_trees/7 (as opposed to in 
couch_httpd_db), which is what I've done now.

> Attachments that have recovered from conflict do not accept attachments.
> ------------------------------------------------------------------------
>
>                 Key: COUCHDB-902
>                 URL: https://issues.apache.org/jira/browse/COUCHDB-902
>             Project: CouchDB
>          Issue Type: Bug
>          Components: Database Core
>         Environment: trunk
>            Reporter: Paul Joseph Davis
>            Priority: Critical
>         Attachments: 0001-Fix-COUCHDB-902.patch, couchdb-902-test-case.py
>
>
> Apparently if a document has been in a conflict, they will reject requests to 
> add an attachment with a conflict error.
> I've tracked this down to couch_db_updater.erl line 501, but I'm not too 
> familiar with this part of the code so I figured I'd fill out a ticket in 
> case anyone else can go through this more quickly than me.
> Sure would be nice if I could attach a file when I create an issue...

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to