You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ei...@apache.org on 2020/02/11 16:32:18 UTC

[couchdb] 03/04: Use flattened JSON for store doc in fdb

This is an automated email from the ASF dual-hosted git repository.

eiri pushed a commit to branch prototype/flattened-doc-storage
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 999686e76b924c8a9f44bdcc528b6252c914ff92
Author: Eric Avdey <ei...@eiri.ca>
AuthorDate: Mon Feb 10 17:39:07 2020 -0400

    Use flattened JSON for store doc in fdb
---
 src/fabric/src/fabric2_fdb.erl | 74 ++++++++++++++++++++++++++++++------------
 1 file changed, 53 insertions(+), 21 deletions(-)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index 6abe1f6..cdd1b60 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -508,18 +508,15 @@ get_doc_body_future(#{} = Db, DocId, RevInfo) ->
         db_prefix := DbPrefix
     } = ensure_current(Db),
 
-    #{
-        rev_id := {RevPos, Rev}
-    } = RevInfo,
-
-    Key = {?DB_DOCS, DocId, RevPos, Rev},
+    Key = {?DB_DOCS, DocId},
     {StartKey, EndKey} = erlfdb_tuple:range(Key, DbPrefix),
     erlfdb:fold_range_future(Tx, StartKey, EndKey, []).
 
 
 get_doc_body_wait(#{} = Db0, DocId, RevInfo, Future) ->
     #{
-        tx := Tx
+        tx := Tx,
+        db_prefix := DbPrefix
     } = Db = ensure_current(Db0),
 
     #{
@@ -527,12 +524,22 @@ get_doc_body_wait(#{} = Db0, DocId, RevInfo, Future) ->
         rev_path := RevPath
     } = RevInfo,
 
-    RevBodyRows = erlfdb:fold_range_wait(Tx, Future, fun({_K, V}, Acc) ->
-        [V | Acc]
+    DocPrefix = erlfdb_tuple:pack({?DB_DOCS, DocId}, DbPrefix),
+
+    MetaBodyAcc = erlfdb:fold_range_wait(Tx, Future, fun({K, V}, Acc) ->
+        Tuple = erlfdb_tuple:unpack(K, DocPrefix),
+        case tuple_to_list(Tuple) of
+            [Deleted, RevPos, Rev] ->
+                {[], V, Deleted};
+            [_Deleted, RevPos, Rev | KeyPath] ->
+                {Body, DiskAtts, Deleted} = Acc,
+                {[{KeyPath, V} | Body], DiskAtts, Deleted};
+            _ ->
+                Acc
+        end
     end, []),
-    BodyRows = lists:reverse(RevBodyRows),
 
-    fdb_to_doc(Db, DocId, RevPos, [Rev | RevPath], BodyRows).
+    fdb_to_doc(Db, DocId, RevPos, [Rev | RevPath], MetaBodyAcc).
 
 
 get_local_doc(#{} = Db0, <<?LOCAL_DOC_PREFIX, _/binary>> = DocId) ->
@@ -1041,10 +1048,11 @@ clear_doc_body(#{} = Db, DocId, #{} = RevInfo) ->
     } = Db,
 
     #{
-        rev_id := {RevPos, Rev}
+        rev_id := {RevPos, Rev},
+        deleted := Deleted
     } = RevInfo,
 
-    BaseKey = {?DB_DOCS, DocId, RevPos, Rev},
+    BaseKey = {?DB_DOCS, DocId, Deleted, RevPos, Rev},
     {StartKey, EndKey} = erlfdb_tuple:range(BaseKey, DbPrefix),
     ok = erlfdb:clear_range(Tx, StartKey, EndKey).
 
@@ -1182,21 +1190,33 @@ doc_to_fdb(Db, #doc{} = Doc) ->
 
     DiskAtts = lists:map(fun couch_att:to_disk_term/1, Atts),
 
-    Value = term_to_binary({Body, DiskAtts, Deleted}, [{minor_version, 1}]),
+    DocKey = {?DB_DOCS, Id, Deleted, Start, Rev},
+    DocPrefix = erlfdb_tuple:pack(DocKey, DbPrefix),
+    Meta = term_to_binary(DiskAtts, [{minor_version, 1}]),
+    Rows0 = [{DocPrefix, Meta}],
 
-    {Rows, _} = lists:mapfoldl(fun(Chunk, ChunkId) ->
-        Key = erlfdb_tuple:pack({?DB_DOCS, Id, Start, Rev, ChunkId}, DbPrefix),
-        {{Key, Chunk}, ChunkId + 1}
-    end, 0, chunkify_binary(Value)),
-    Rows.
+    Body1 = case Body of
+        {[]} -> [];
+        _ -> couch_util:json_explode(Body)
+    end,
+    lists:foldl(fun({K, V}, Acc) ->
+        Key = erlfdb_tuple:pack(list_to_tuple(K), DocPrefix),
+        Value = encode_body_value(V),
+        [{Key, Value} | Acc]
+    end, Rows0, Body1).
 
 
 fdb_to_doc(_Db, _DocId, _Pos, _Path, []) ->
     {not_found, missing};
 
-fdb_to_doc(Db, DocId, Pos, Path, BinRows) when is_list(BinRows) ->
-    Bin = iolist_to_binary(BinRows),
-    {Body, DiskAtts, Deleted} = binary_to_term(Bin, [safe]),
+fdb_to_doc(Db, DocId, Pos, Path, MetaBodyAcc) ->
+    {Body0, DiskAtts0, Deleted} = MetaBodyAcc,
+    BodyRows = [{K, decode_body_value(V)} || {K, V} <- lists:reverse(Body0)],
+    Body = case BodyRows of
+        [] -> {[]};
+        _ -> couch_util:json_implode(BodyRows)
+    end,
+    DiskAtts = binary_to_term(DiskAtts0, [safe]),
     Atts = lists:map(fun(Att) ->
         couch_att:from_disk_term(Db, DocId, Att)
     end, DiskAtts),
@@ -1214,6 +1234,18 @@ fdb_to_doc(Db, DocId, Pos, Path, BinRows) when is_list(BinRows) ->
     end.
 
 
+encode_body_value(V) when is_list(V); is_tuple(V) ->
+    term_to_binary(V, [{minor_version, 1}]);
+encode_body_value(V) ->
+    erlfdb_tuple:pack({V}).
+
+decode_body_value(<<131, _/binary>> = V) ->
+    binary_to_term(V, [safe]);
+decode_body_value(V) ->
+    {V1} = erlfdb_tuple:unpack(V),
+    V1.
+
+
 local_doc_to_fdb(Db, #doc{} = Doc) ->
     #{
         db_prefix := DbPrefix