diff options
author | Paul J. Davis <paul.joseph.davis@gmail.com> | 2019-03-11 14:37:17 -0500 |
---|---|---|
committer | Paul J. Davis <paul.joseph.davis@gmail.com> | 2019-03-11 14:37:17 -0500 |
commit | 6a82373396e9a0fd00919d527fbe8bc74421c2d8 (patch) | |
tree | 9c9f1dd9b3e28bd2b0fc09b485e080b2966fa3aa | |
parent | 41d82c781381cc709062bbb608c327aefb6ca351 (diff) | |
download | couchdb-6a82373396e9a0fd00919d527fbe8bc74421c2d8.tar.gz |
Fix versionstamp handling
-rw-r--r-- | src/fabric/src/fabric2_db.erl | 11 | ||||
-rw-r--r-- | src/fabric/src/fabric2_doc.erl | 45 |
2 files changed, 38 insertions, 18 deletions
diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl index ebdb4283a..9f1a06e3e 100644 --- a/src/fabric/src/fabric2_db.erl +++ b/src/fabric/src/fabric2_db.erl @@ -23,6 +23,7 @@ with_tx/2, pack/2, + pack_vs/2, unpack/2, range_bounds/2, @@ -101,6 +102,16 @@ pack(Db, Tuple) -> erlfdb_directory:pack(Dir, Tuple). +pack_vs(#{dir := undefined} = Db, _Tuple) -> + erlang:error({no_directory, Db}); + +pack_vs(Db, Tuple) -> + #{ + dir := Dir + } = Db, + erlfdb_directory:pack_vs(Dir, Tuple). + + unpack(#{dir := undefined} = Db, _Key) -> erlang:error({no_directory, Db}); diff --git a/src/fabric/src/fabric2_doc.erl b/src/fabric/src/fabric2_doc.erl index dabf183f8..f014e094b 100644 --- a/src/fabric/src/fabric2_doc.erl +++ b/src/fabric/src/fabric2_doc.erl @@ -28,13 +28,13 @@ get_fdi(TxDb, DocId) -> Future = fabric2_db:get(TxDb, {<<"revs">>, DocId}), - fdb_to_fdi(DocId, erlfdb:wait(Future)). + fdb_to_fdi(TxDb, DocId, erlfdb:wait(Future)). open(TxDb, DocId, {Pos, [Rev | _] = Path}) -> Key = {<<"docs">>, DocId, Pos, Rev}, Future = fabric2_db:get(TxDb, Key), - fdb_to_doc(DocId, Pos, Path, erlfdb:wait(Future)). + fdb_to_doc(TxDb, DocId, Pos, Path, erlfdb:wait(Future)). % TODO: Handle _local docs separately. @@ -51,17 +51,20 @@ update(TxDb, #doc{} = Doc0, Options) -> interactive_edit -> new_revid(Doc1); replicated_changes -> Doc1 end, - {FDI2, Doc3} = merge_rev_tree(FDI1, Doc2, UpdateType), + FDI2 = if FDI1 /= not_found -> FDI1; true -> + #full_doc_info{id = Doc2#doc.id} + end, + {FDI3, Doc3} = merge_rev_tree(FDI2, Doc2, UpdateType), #{tx := Tx} = TxDb, % Delete old entry in changes feed - OldSeqKey = {<<"changes">>, FDI1#full_doc_info.update_seq}, + OldSeqKey = {<<"changes">>, FDI3#full_doc_info.update_seq}, OldSeqKeyBin = fabric2_db:pack(TxDb, OldSeqKey), erlfdb:clear(Tx, OldSeqKeyBin), % Add new entry to changes feed - NewSeqKey = {<<"changes">>, <<16#FFFFFFFFFFFFFFFFFFFF:80>>}, + NewSeqKey = {<<"changes">>, {versionstamp, 16#FFFFFFFFFFFFFFFF, 16#FFFF}}, NewSeqKeyBin = fabric2_db:pack_vs(TxDb, NewSeqKey), erlfdb:set_versionstamped_key(Tx, NewSeqKeyBin, Doc3#doc.id), @@ -72,10 +75,10 @@ update(TxDb, #doc{} = Doc0, Options) -> erlfdb:set(Tx, NewDocKey, NewDocVal), % Update revision tree entry - {NewFDIKey, NewFDIVal} = fdi_to_fdb(TxDb, FDI2), - erlfdb:set_versionstampled_value(Tx, NewFDIKey, NewFDIVal), + {NewFDIKey, NewFDIVal} = fdi_to_fdb(TxDb, FDI3), + erlfdb:set_versionstamped_value(Tx, NewFDIKey, NewFDIVal), - {DocIncr, DocDelIncr} = case {FDI1, FDI2} of + {DocIncr, DocDelIncr} = case {FDI1, FDI3} of {not_found, _} -> {1, 0}; {#full_doc_info{deleted = true}, #full_doc_info{deleted = false}} -> @@ -110,10 +113,12 @@ update(TxDb, #doc{} = Doc0, Options) -> prep_and_validate(TxDb, not_found, Doc, UpdateType) -> case Doc#doc.revs of - {0, []} when UpdateType == interactive_edit -> - ?RETURN({error, conflict}); + {0, []} -> + ok; + _ when UpdateType == replicated_changes -> + ok; _ -> - ok + ?RETURN({error, conflict}) end, prep_and_validate(TxDb, Doc, fun() -> nil end); @@ -397,7 +402,7 @@ doc_to_fdb(TxDb, #doc{} = Doc) -> {KeyBin, term_to_binary(Val, [{minor_version, 1}])}. -fdb_to_doc(DocId, Pos, Path, Bin) when is_binary(Bin) -> +fdb_to_doc(_TxDb, DocId, Pos, Path, Bin) when is_binary(Bin) -> {Body, Atts, Deleted} = binary_to_term(Bin, [safe]), #doc{ id = DocId, @@ -406,7 +411,7 @@ fdb_to_doc(DocId, Pos, Path, Bin) when is_binary(Bin) -> atts = Atts, deleted = Deleted }; -fdb_to_doc(_DocId, _Pos, _Path, not_found) -> +fdb_to_doc(_TxDb, _DocId, _Pos, _Path, not_found) -> {not_found, missing}. @@ -419,19 +424,23 @@ fdi_to_fdb(TxDb, #full_doc_info{} = FDI) -> Key = {<<"revs">>, Id}, KeyBin = fabric2_db:pack(TxDb, Key), - Val = {Deleted, RevTree, <<16#FFFFFFFFFFFFFFFFFFFF:80>>}, - {KeyBin, term_to_binary(Val, [{minor_version, 1}])}. + RevTreeBin = term_to_binary(RevTree, [{minor_version, 1}]), + ValTuple = {Deleted, RevTreeBin, {versionstamp, 16#FFFFFFFFFFFFFFFF, 16#FFFF}}, + Val = fabric2_db:pack_vs(TxDb, ValTuple), + {KeyBin, Val}. -fdb_to_fdi(Id, Bin) when is_binary(Bin) -> - {Deleted, RevTree, UpdateSeq} = binary_to_term(Bin, [safe]), +fdb_to_fdi(TxDb, Id, Bin) when is_binary(Bin) -> + {Deleted, RevTreeBin, {versionstamp, V, B}} = fabric2_db:unpack(TxDb, Bin), + RevTree = binary_to_term(RevTreeBin, [safe]), + UpdateSeq = <<V:64/big, B:16/big>>, #full_doc_info{ id = Id, deleted = Deleted, rev_tree = RevTree, update_seq = UpdateSeq }; -fdb_to_fdi(_Id, not_found) -> +fdb_to_fdi(_TxDb, _Id, not_found) -> not_found. |