Skip to content

Instantly share code, notes, and snippets.

@jhs
Created January 8, 2012 04:08
Show Gist options
  • Save jhs/1577159 to your computer and use it in GitHub Desktop.
Save jhs/1577159 to your computer and use it in GitHub Desktop.
Log the conflict winner comparison

Conflict winners are chosen dynamically, every time a request for the document arrives. The revision tree is sort of like a git repository: most updates are based on a parent update. In general, you have a tree of changes, but usually it works out to a linear linked list.

Anyway, the winner is the version with the longest revision history. (That is arbitrary but deterministic, so two couches with the same revision trees will pick the same winner.)

couch_doc:to_doc_info_path does the main job: converting the revision tree into an array of paths from root to leaf. It returns this array sorted, with the longest path first. The diff here will print a log message every time the comparison function is called by lists:sort().

The execution path basically goes:

  1. couch_http_db:db_doc_req()
  2. couch_db:open_doc()
  3. couch_db:open_doc_int(Db, Id, []) (a kind of convenience function)
  4. couch_db:get_full_doc_info(Db, Id)
  5. dig it out of the id index (btree)
  6. Rerun couch_db:open_doc_int(Db, FullDocInfo, []) (this time with feeling)
  7. couch_doc:to_doc_info(FullDocInfo) which basically wraps couch_doc:to_doc_info_path(FullDocInfo)
  8. This is where revisions are sorted: longest history first (as long as it is not deleted)
  9. Pop back up the execution stack to step 4, where the code grabs the first array element--the one with the longest history and that will be the revision and document you get over HTTP
diff --git a/src/couchdb/couch_doc.erl b/src/couchdb/couch_doc.erl
index 7b7233e..7830a4e 100644
--- a/src/couchdb/couch_doc.erl
+++ b/src/couchdb/couch_doc.erl
@@ -350,6 +350,7 @@ to_doc_info_path(#full_doc_info{id=Id,rev_tree=Tree,update_seq=Seq}) ->
fun({#rev_info{deleted=DeletedA,rev=RevA}, _PathA},
{#rev_info{deleted=DeletedB,rev=RevB}, _PathB}) ->
% sort descending by {not deleted, rev}
+ ?LOG_INFO("Compare ~s:\nA: ~p\nB: ~p", [Id, {not DeletedA, RevA}, {not DeletedB, RevB}]),
{not DeletedA, RevA} > {not DeletedB, RevB}
end, RevInfosAndPath),
[{_RevInfo, WinPath}|_] = SortedRevInfosAndPath,
@snej
Copy link

snej commented Sep 5, 2013

the winner is the version with the longest revision history

And in case of a tie, the winner is the revision with the lexicographically highest revision ID; e.g. "12-F4B2..." beats "12-42AA..."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment