You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2020/08/07 09:03:24 UTC

[couchdb] branch prototype/fdb-layer-ebtree-immutable updated (d959efb -> 5215aa3)

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

rnewson pushed a change to branch prototype/fdb-layer-ebtree-immutable
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard d959efb  add cache test
 discard 81e0704  convert node ids to uuids
 discard f21324e  pluggable caching of inner nodes
 discard be55a65  consolidate id mutation logic into one function
 discard 8190602  mutate node id of non-leaf, non-root nodes on delete
 discard 295e8c5  mutate node id of non-leaf, non-root nodes on insert
     add ebe62b2  Only call erlfdb:set if the node changes
     add f811f3f  Merge pull request #3033 from apache/prototype/fdb-layer-ebtree-spurious-conflicts
     add 90158ea  separate out collation wrapper to avoid spurious comparisons
     add 81a8db7  Merge pull request #3034 from apache/prototype/fdb-layer-collation-bugs
     add 0a44446  add get_active_job_ids and get_types
     add fd9557a  add support for active_tasks via fabric2
     add a447f07  add active_tasks for view builds using version stamps
     add 0c7c77e  Merge pull request #3003 from apache/add_active_tasks_fdb
     add 77e1c8c  Use _scheduler/jobs instead of _active_tasks in replication Elixir tests
     add 5a4da50  Replace the 'true' clauses in visit with more explicit ones
     add 79cb06c  Allow inclusive_start/end
     add 46cff24  Merge pull request #3045 from apache/prototype/fdb-layer-ebtree-enhancements
     add e1b4259  Strip last_msg from logs
     add 97e7a95  Add format_status/2 callback in gen_server implementations
     add 52d5327  Do not log sensitive data during _cluster_setup
     add 8360026  Do not log admin credentials
     add e4555a4  Update config app
     add 6ff2f41  Merge pull request #3031 from cloudant/clean-up-logs
     add f8fdf97  Call collate for group equality
     add 41d946b  Merge pull request #3046 from apache/prototype/fdb-layer-ebtree-group-reduce-fix
     add 8b49b0d  Allow interactive requests to reopen a re-created db instance
     add bd53678  Optionally add a key manager application as a dependency
     add 22d857d  Merge pull request #3053 from apache/aegis_key_manager_app
     add 683335c  Validate the result from collate_fun
     add e0bcb2a  Merge pull request #3055 from apache/prototype/fdb-layer-ebtree-collate-validate
     add 282e858  add local_seq option to views (#3043)
     add f925919  Export reduce/5
     add a32bc83  Handle empty reduce batches
     add 29d6498  Fix range scans over an empty tree
     add 31b467c  Speed up ebtree test suite without losing coverage
     add bf4265e  Merge pull request #3060 from apache/prototype/fdb-layer-ebtree-speedy-tests
     add 042347e  fixup: Build couch_js for redhat linux
     add dff8bc9  Merge pull request #3057 from apache/build-fdb-couchjs-for-redhat-linux
     add 51a131d  Tighten expectation of members format by level
     add 887e835  extra tests
     add 8ddcc22  Merge pull request #3062 from apache/prototype/fdb-layer-ebtree-enhance
     add a74675f  Pluggable persist_fun
     add 4d7149c  Merge pull request #3065 from apache/prototype/fdb-layer-ebtree-persist-fun
     new 9a0d67f  mutate node id of non-leaf, non-root nodes on insert
     new 4b9221f  mutate node id of non-leaf, non-root nodes on delete
     new 922c42c  consolidate id mutation logic into one function
     new f2a5343  pluggable caching of inner nodes
     new 4bf5e30  convert node ids to uuids
     new 5215aa3  add cache test

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (d959efb)
            \
             N -- N -- N   refs/heads/prototype/fdb-layer-ebtree-immutable (5215aa3)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 rebar.config.script                                |   4 +-
 .../src/{aegis.app.src => aegis.app.src.script}    |  33 +-
 src/chttpd/src/chttpd_db.erl                       |   3 +-
 src/chttpd/src/chttpd_misc.erl                     |   7 +-
 src/chttpd/src/chttpd_node.erl                     |   4 +-
 src/couch/include/couch_db.hrl                     |   3 +
 src/couch/rebar.config.script                      |   2 +-
 src/couch/src/couch_lru.erl                        |   5 +-
 src/couch/src/couch_multidb_changes.erl            |  14 +-
 src/couch/src/couch_native_process.erl             |  17 +-
 src/couch/src/couch_proc_manager.erl               |  16 +-
 src/couch/src/couch_server.erl                     |   6 +-
 src/couch/src/couch_stream.erl                     |  16 +-
 src/couch/src/couch_work_queue.erl                 |  25 +-
 src/couch_index/src/couch_index.erl                |  19 +-
 src/couch_jobs/src/couch_jobs.erl                  |  19 +
 src/couch_jobs/src/couch_jobs_notifier.erl         |  22 +-
 src/couch_js/src/couch_js_native_process.erl       |  18 +-
 src/couch_js/src/couch_js_proc_manager.erl         |  16 +-
 src/couch_log/src/couch_log_config.erl             |  11 +-
 src/couch_log/src/couch_log_config_dyn.erl         |   3 +-
 src/couch_log/src/couch_log_formatter.erl          |  24 +-
 src/couch_log/src/couch_log_sup.erl                |   2 +
 src/couch_log/test/eunit/couch_log_config_test.erl |  37 +-
 .../test/eunit/couch_log_formatter_test.erl        | 114 +++++-
 src/couch_mrview/src/couch_mrview_index.erl        |  12 +
 src/couch_peruser/src/couch_peruser.erl            |  13 +-
 .../src/couch_replicator_auth_session.erl          |   2 +-
 .../src/couch_replicator_httpc_pool.erl            |  14 +-
 src/couch_stats/src/couch_stats_aggregator.erl     |  17 +-
 src/couch_views/src/couch_views_indexer.erl        |  60 ++-
 src/couch_views/src/couch_views_server.erl         |  17 +-
 src/couch_views/src/couch_views_util.erl           |  27 +-
 .../test/couch_views_active_tasks_test.erl         | 155 +++++++
 src/couch_views/test/couch_views_map_test.erl      |  51 ++-
 src/ddoc_cache/src/ddoc_cache_entry.erl            |  21 +-
 src/dreyfus/src/dreyfus_index.erl                  |  26 +-
 src/ebtree/src/ebtree.erl                          | 451 +++++++++++++--------
 src/fabric/src/fabric2_active_tasks.erl            |  51 +++
 src/fabric/src/fabric2_db.erl                      |   8 +-
 src/fabric/src/fabric2_fdb.erl                     |  24 +-
 src/fabric/src/fabric2_server.erl                  |   3 +-
 src/fabric/src/fabric2_txids.erl                   |  15 +-
 src/fabric/test/fabric2_db_crud_tests.erl          |  28 ++
 src/fabric/test/fabric2_db_security_tests.erl      |  55 ++-
 src/global_changes/src/global_changes_server.erl   |  11 +-
 src/ken/src/ken_server.erl                         |  16 +-
 src/setup/src/setup.erl                            |   2 +-
 src/setup/src/setup_httpd.erl                      |  17 +-
 test/elixir/test/map_test.exs                      |  27 ++
 test/elixir/test/replication_test.exs              |  24 +-
 51 files changed, 1321 insertions(+), 266 deletions(-)
 rename src/aegis/src/{aegis.app.src => aegis.app.src.script} (62%)
 create mode 100644 src/couch_views/test/couch_views_active_tasks_test.erl
 create mode 100644 src/fabric/src/fabric2_active_tasks.erl


[couchdb] 04/06: pluggable caching of inner nodes

Posted by rn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rnewson pushed a commit to branch prototype/fdb-layer-ebtree-immutable
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit f2a5343577f40777718f9064155636a57a193352
Author: Robert Newson <rn...@apache.org>
AuthorDate: Thu Jul 23 19:10:04 2020 +0100

    pluggable caching of inner nodes
---
 src/ebtree/src/ebtree.erl | 53 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 48 insertions(+), 5 deletions(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index 34f42e6..7c36fa5 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -47,7 +47,8 @@
     collate_fun,
     reduce_fun,
     encode_fun,
-    persist_fun
+    persist_fun,
+    cache_fun
 }).
 
 -define(META, 0).
@@ -85,13 +86,15 @@ open(Db, Prefix, Order, Options) when is_binary(Prefix), is_integer(Order), Orde
     CollateFun = proplists:get_value(collate_fun, Options, fun collate_raw/2),
     EncodeFun = proplists:get_value(encode_fun, Options, fun encode_erlang/3),
     PersistFun = proplists:get_value(persist_fun, Options, fun simple_persist/3),
+    CacheFun = proplists:get_value(cache_fun, Options, fun cache_noop/2),
 
     Tree = #tree{
         prefix = Prefix,
         reduce_fun = ReduceFun,
         collate_fun = CollateFun,
         encode_fun = EncodeFun,
-        persist_fun = PersistFun
+        persist_fun = PersistFun,
+        cache_fun = CacheFun
     },
 
     erlfdb:transactional(Db, fun(Tx) ->
@@ -776,9 +779,16 @@ meta_key(Prefix, MetaKey) when is_binary(Prefix) ->
 %% node persistence functions
 
 get_node(Tx, #tree{} = Tree, Id) ->
-    Key = node_key(Tree#tree.prefix, Id),
-    Value = persist(Tree, Tx, get, Key),
-    decode_node(Tree, Id, Key, Value).
+    case cache(Tree, get, Id) of
+        undefined ->
+            Key = node_key(Tree#tree.prefix, Id),
+            Value = persist(Tree, Tx, get, Key),
+            Node = decode_node(Tree, Id, Key, Value),
+            cache(Tree, set, Node),
+            Node;
+        #node{} = Node ->
+            Node
+    end.
 
 
 clear_nodes(Tx, #tree{} = Tree, Nodes) ->
@@ -789,6 +799,7 @@ clear_nodes(Tx, #tree{} = Tree, Nodes) ->
 
 clear_node(Tx, #tree{} = Tree, #node{} = Node) ->
      Key = node_key(Tree#tree.prefix, Node#node.id),
+     cache(Tree, clear, Node),
      persist(Tree, Tx, clear, Key).
 
 
@@ -809,6 +820,7 @@ set_node(Tx, #tree{} = Tree, #node{} = Node) ->
     validate_node(Tree, Node),
     Key = node_key(Tree#tree.prefix, Node#node.id),
     Value = encode_node(Tree, Key, Node),
+    cache(Tree, set, Node),
     persist(Tree, Tx, set, [Key, Value]).
 
 
@@ -1026,6 +1038,37 @@ simple_persist(Tx, get, Key) ->
 simple_persist(Tx, clear, Key) ->
     erlfdb:clear(Tx, Key).
 
+%% cache functions
+
+cache_noop(set, _) ->
+    ok;
+cache_noop(clear, _) ->
+    ok;
+cache_noop(get, _) ->
+    undefined.
+
+
+cache(#tree{} = Tree, Action, #node{} = Node) when Action == set; Action == clear ->
+    #tree{cache_fun = CacheFun} = Tree,
+    NodeIsCacheable = node_is_cacheable(Node),
+    if
+        NodeIsCacheable andalso CacheFun /= undefined ->
+            CacheFun(Action, Node);
+        true ->
+            ok
+    end;
+
+cache(#tree{} = _Tree, get, ?NODE_ROOT_ID) ->
+    undefined;
+
+cache(#tree{} = Tree, get, Id) ->
+    #tree{cache_fun = CacheFun} = Tree,
+    if
+        CacheFun /= undefined ->
+            CacheFun(get, Id);
+        true ->
+            undefined
+    end.
 
 %% private functions
 


[couchdb] 02/06: mutate node id of non-leaf, non-root nodes on delete

Posted by rn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rnewson pushed a commit to branch prototype/fdb-layer-ebtree-immutable
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 4b9221f37e26ee40fd343ad0cdd3f6b329fd5cd7
Author: Robert Newson <rn...@apache.org>
AuthorDate: Thu Jul 23 19:01:02 2020 +0100

    mutate node id of non-leaf, non-root nodes on delete
---
 src/ebtree/src/ebtree.erl | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index 639406e..d9bc30b 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -684,20 +684,38 @@ delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
             end, Members2, NewNodes),
 
             Parent1 = Parent0#node{
-                %% TODO change id
                 members = Members3
             },
+            Parent2 = if
+                Parent1#node.id == ?NODE_ROOT_ID ->
+                    Parent1;
+                Parent0#node.members == Parent1#node.members ->
+                    Parent1;
+                true ->
+                    clear_node(Tx, Tree, Parent1),
+                    Parent1#node{id = new_node_id(Tx, Tree)}
+            end,
 
             clear_nodes(Tx, Tree, [Child0, Sibling]),
             set_nodes(Tx, Tree, NewNodes),
-            Parent1;
+            Parent2;
         false ->
             set_node(Tx, Tree, Child0, Child1),
             {_OldFirstKey, _OldLastKey, ChildId0, _OldReduction} = lists:keyfind(ChildId0, 3, Parent0#node.members),
-            Parent0#node{
+            Parent1 = Parent0#node{
                 members = lists:keyreplace(ChildId0, 3, Parent0#node.members,
                     {first_key(Child1), last_key(Child1), Child1#node.id, reduce_node(Tree, Child1)})
-            }
+            },
+            Parent2 = if
+                Parent1#node.id == ?NODE_ROOT_ID ->
+                    Parent1;
+                Parent0#node.members == Parent1#node.members ->
+                    Parent1;
+                true ->
+                    clear_node(Tx, Tree, Parent1),
+                    Parent1#node{id = new_node_id(Tx, Tree)}
+            end,
+            Parent2
     end.
 
 


[couchdb] 05/06: convert node ids to uuids

Posted by rn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rnewson pushed a commit to branch prototype/fdb-layer-ebtree-immutable
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 4bf5e30a06acc74b999e6aa09c99fcf22869ecd0
Author: Robert Newson <rn...@apache.org>
AuthorDate: Thu Jul 23 19:15:33 2020 +0100

    convert node ids to uuids
---
 src/ebtree/src/ebtree.erl | 50 +++++++++++++++++++++++++++--------------------
 1 file changed, 29 insertions(+), 21 deletions(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index 7c36fa5..d058669 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -53,10 +53,9 @@
 
 -define(META, 0).
 -define(META_ORDER, 0).
--define(META_NEXT_ID, 1).
 
 -define(NODE, 1).
--define(NODE_ROOT_ID, 0).
+-define(NODE_ROOT_ID, <<0>>).
 
 -define(underflow(Tree, Node), Tree#tree.min > length(Node#node.members)).
 -define(at_min(Tree, Node), Tree#tree.min == length(Node#node.members)).
@@ -102,7 +101,6 @@ open(Db, Prefix, Order, Options) when is_binary(Prefix), is_integer(Order), Orde
             not_found ->
                 erlfdb:clear_range_startswith(Tx, Prefix),
                 set_meta(Tx, Tree, ?META_ORDER, Order),
-                set_meta(Tx, Tree, ?META_NEXT_ID, 1),
                 set_node(Tx, Tree, #node{id = ?NODE_ROOT_ID}),
                 init_order(Tree, Order);
             ActualOrder when is_integer(ActualOrder) ->
@@ -495,7 +493,7 @@ insert(Db, #tree{} = Tree, Key, Value) ->
         Root0 = get_node(Tx, Tree, ?NODE_ROOT_ID),
         case ?is_full(Tree, Root0) of
             true ->
-                OldRoot = Root0#node{id = new_node_id(Tx, Tree)},
+                OldRoot = Root0#node{id = new_node_id()},
                 FirstKey = first_key(OldRoot),
                 LastKey = last_key(OldRoot),
                 Root1 = #node{
@@ -514,8 +512,8 @@ insert(Db, #tree{} = Tree, Key, Value) ->
 split_child(Tx, #tree{} = Tree, #node{} = Parent0, #node{} = Child) ->
     {LeftMembers, RightMembers} = lists:split(Tree#tree.min, Child#node.members),
 
-    LeftId = new_node_id(Tx, Tree),
-    RightId = new_node_id(Tx, Tree),
+    LeftId = new_node_id(),
+    RightId = new_node_id(),
 
     LeftChild = remove_pointers_if_not_leaf(#node{
         id = LeftId,
@@ -650,12 +648,12 @@ delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
             Sibling = get_node(Tx, Tree, SiblingId),
             NewNodes = case ?at_min(Tree, Sibling) of
                 true ->
-                    Merged = merge(Tx, Tree, Child1, Sibling),
+                    Merged = merge(Tree, Child1, Sibling),
                     update_prev_neighbour(Tx, Tree, Merged),
                     update_next_neighbour(Tx, Tree, Merged),
                     [Merged];
                 false ->
-                    {Left, Right} = rebalance(Tx, Tree, Child1, Sibling),
+                    {Left, Right} = rebalance(Tree, Child1, Sibling),
                     update_prev_neighbour(Tx, Tree, Left),
                     update_next_neighbour(Tx, Tree, Right),
                     [Left, Right]
@@ -688,11 +686,11 @@ delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
     end.
 
 
-merge(Tx, #tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = Node2) ->
+merge(#tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = Node2) ->
     [Left, Right] = sort_nodes(Tree, [Node1, Node2]),
 
     #node{
-        id = new_node_id(Tx, Tree),
+        id = new_node_id(),
         level = Level,
         prev = Left#node.prev,
         next = Right#node.next,
@@ -700,14 +698,14 @@ merge(Tx, #tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = N
     }.
 
 
-rebalance(Tx, #tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = Node2) ->
+rebalance(#tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = Node2) ->
     [Left0, Right0] = sort_nodes(Tree, [Node1, Node2]),
 
     Members = lists:append(Left0#node.members, Right0#node.members),
     {LeftMembers, RightMembers} = lists:split(length(Members) div 2, Members),
 
-    Left1Id = new_node_id(Tx, Tree),
-    Right1Id = new_node_id(Tx, Tree),
+    Left1Id = new_node_id(),
+    Right1Id = new_node_id(),
 
     Left1 = remove_pointers_if_not_leaf(Left0#node{
         id = Left1Id,
@@ -824,7 +822,7 @@ set_node(Tx, #tree{} = Tree, #node{} = Node) ->
     persist(Tree, Tx, set, [Key, Value]).
 
 
-node_key(Prefix, Id) when is_binary(Prefix), is_integer(Id) ->
+node_key(Prefix, Id) when is_binary(Prefix), is_binary(Id) ->
     erlfdb_tuple:pack({?NODE, Id}, Prefix).
 
 
@@ -1105,7 +1103,7 @@ new_node_id_if_cacheable(Tx, #tree{} = Tree, #node{} = Old, #node{} = New) ->
     if
         MembersChanged andalso NodeIsCacheable ->
             clear_node(Tx, Tree, New),
-            New#node{id = new_node_id(Tx, Tree)};
+            New#node{id = new_node_id()};
         true ->
             New
     end.
@@ -1121,10 +1119,8 @@ node_is_cacheable(#node{}) ->
     true.
 
 
-new_node_id(Tx, Tree) ->
-    NextId = get_meta(Tx, Tree, ?META_NEXT_ID),
-    set_meta(Tx, Tree, ?META_NEXT_ID, NextId + 1),
-    NextId.
+new_node_id() ->
+    crypto:strong_rand_bytes(16).
 
 
 %% remove prev/next pointers for nonleaf nodes
@@ -1135,10 +1131,22 @@ remove_pointers_if_not_leaf(#node{} = Node) ->
     Node#node{prev = undefined, next = undefined}.
 
 
+print_node(#node{level = 0} = Node) ->
+    io:format("#node{id = ~s, level = ~w, prev = ~s, next = ~s, members = ~w}~n~n",
+        [b64(Node#node.id), Node#node.level, b64(Node#node.prev), b64(Node#node.next),
+        Node#node.members]);
+
 print_node(#node{} = Node) ->
-    io:format("#node{id = ~w, level = ~w, prev = ~w, next = ~w, members = ~w}~n~n",
-        [Node#node.id, Node#node.level, Node#node.prev, Node#node.next, Node#node.members]).
+    io:format("#node{id = ~s, level = ~w, prev = ~s, next = ~s, members = ~s}~n~n",
+        [base64:encode(Node#node.id), Node#node.level, b64(Node#node.prev), b64(Node#node.next),
+        [io_lib:format("{~w, ~w, ~s, ~w}, ", [F, L, b64(P), R]) || {F, L, P, R} <- Node#node.members]]).
+
+
+b64(undefined) ->
+    undefined;
 
+b64(Bin) ->
+    base64:encode(Bin).
 
 %% tests
 


[couchdb] 01/06: mutate node id of non-leaf, non-root nodes on insert

Posted by rn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rnewson pushed a commit to branch prototype/fdb-layer-ebtree-immutable
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 9a0d67fb9ac79370b1a8616990eddd6d7ba30144
Author: Robert Newson <rn...@apache.org>
AuthorDate: Thu Jul 23 19:00:48 2020 +0100

    mutate node id of non-leaf, non-root nodes on insert
---
 src/ebtree/src/ebtree.erl | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index 536d3b1..639406e 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -549,9 +549,18 @@ split_child(Tx, #tree{} = Tree, #node{} = Parent0, #node{} = Child) ->
                 umerge_members(Tree, Parent0#node.level, [{FirstRightKey, LastRightKey, RightId, RightReduction}],
                     lists:keydelete(Child#node.id, 3, Parent0#node.members)))
     },
+    Parent2 =
+        if Parent1#node.id == ?NODE_ROOT_ID ->
+            Parent1;
+        Parent0#node.members == Parent1#node.members ->
+            Parent1;
+        true ->
+            clear_node(Tx, Tree, Parent1),
+            Parent1#node{id = new_node_id(Tx, Tree)}
+    end,
     clear_node(Tx, Tree, Child),
-    set_nodes(Tx, Tree, [LeftChild, RightChild, Parent1]),
-    {Parent1, LeftChild, RightChild}.
+    set_nodes(Tx, Tree, [LeftChild, RightChild, Parent2]),
+    {Parent2, LeftChild, RightChild}.
 
 
 update_prev_neighbour(_Tx, #tree{} = _Tree, #node{prev = undefined} = _Node) ->
@@ -575,7 +584,7 @@ insert_nonfull(Tx, #tree{} = Tree, #node{level = 0} = Node0, Key, Value) ->
         members = umerge_members(Tree, 0, [{Key, Value}], Node0#node.members)
     },
     set_node(Tx, Tree, Node0, Node1),
-    reduce_node(Tree, Node1);
+    {Node1#node.id, reduce_node(Tree, Node1)};
 
 insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, Value) ->
     ChildId0 = find_child_id(Tree, Node0, Key),
@@ -595,16 +604,25 @@ insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, Value) ->
             {Node0, Child0}
     end,
     ChildId1 = Child1#node.id,
-    NewReduction = insert_nonfull(Tx, Tree, Child1, Key, Value),
+    {ChildId2, NewReduction} = insert_nonfull(Tx, Tree, Child1, Key, Value),
     {CurrentFirstKey, CurrentLastKey, ChildId1, _OldReduction} = lists:keyfind(ChildId1, 3, Node1#node.members),
     [NewFirstKey, _] = sort_keys(Tree, [Key, CurrentFirstKey]),
     [_, NewLastKey] = sort_keys(Tree, [Key, CurrentLastKey]),
     Node2 = Node1#node{
         members = lists:keyreplace(ChildId1, 3, Node1#node.members,
-            {NewFirstKey, NewLastKey, ChildId1, NewReduction})
+            {NewFirstKey, NewLastKey, ChildId2, NewReduction})
     },
-    set_node(Tx, Tree, Node0, Node2),
-    reduce_node(Tree, Node2).
+    Node3 = if
+        Node2#node.id == ?NODE_ROOT_ID ->
+            Node2;
+        Node0#node.members == Node2#node.members ->
+            Node2;
+        true ->
+            clear_node(Tx, Tree, Node2),
+            Node2#node{id = new_node_id(Tx, Tree)}
+    end,
+    set_node(Tx, Tree, Node0, Node3),
+    {Node3#node.id, reduce_node(Tree, Node3)}.
 
 
 %% @doc Deletes an entry from the ebtree


[couchdb] 03/06: consolidate id mutation logic into one function

Posted by rn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rnewson pushed a commit to branch prototype/fdb-layer-ebtree-immutable
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 922c42ced8ce8998d1a993221a4c6847e08f473d
Author: Robert Newson <rn...@apache.org>
AuthorDate: Thu Jul 23 19:02:24 2020 +0100

    consolidate id mutation logic into one function
---
 src/ebtree/src/ebtree.erl | 64 +++++++++++++++++++----------------------------
 1 file changed, 26 insertions(+), 38 deletions(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index d9bc30b..34f42e6 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -549,15 +549,7 @@ split_child(Tx, #tree{} = Tree, #node{} = Parent0, #node{} = Child) ->
                 umerge_members(Tree, Parent0#node.level, [{FirstRightKey, LastRightKey, RightId, RightReduction}],
                     lists:keydelete(Child#node.id, 3, Parent0#node.members)))
     },
-    Parent2 =
-        if Parent1#node.id == ?NODE_ROOT_ID ->
-            Parent1;
-        Parent0#node.members == Parent1#node.members ->
-            Parent1;
-        true ->
-            clear_node(Tx, Tree, Parent1),
-            Parent1#node{id = new_node_id(Tx, Tree)}
-    end,
+    Parent2 = new_node_id_if_cacheable(Tx, Tree, Parent0, Parent1),
     clear_node(Tx, Tree, Child),
     set_nodes(Tx, Tree, [LeftChild, RightChild, Parent2]),
     {Parent2, LeftChild, RightChild}.
@@ -612,15 +604,7 @@ insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, Value) ->
         members = lists:keyreplace(ChildId1, 3, Node1#node.members,
             {NewFirstKey, NewLastKey, ChildId2, NewReduction})
     },
-    Node3 = if
-        Node2#node.id == ?NODE_ROOT_ID ->
-            Node2;
-        Node0#node.members == Node2#node.members ->
-            Node2;
-        true ->
-            clear_node(Tx, Tree, Node2),
-            Node2#node{id = new_node_id(Tx, Tree)}
-    end,
+    Node3 = new_node_id_if_cacheable(Tx, Tree, Node0, Node2),
     set_node(Tx, Tree, Node0, Node3),
     {Node3#node.id, reduce_node(Tree, Node3)}.
 
@@ -686,16 +670,7 @@ delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
             Parent1 = Parent0#node{
                 members = Members3
             },
-            Parent2 = if
-                Parent1#node.id == ?NODE_ROOT_ID ->
-                    Parent1;
-                Parent0#node.members == Parent1#node.members ->
-                    Parent1;
-                true ->
-                    clear_node(Tx, Tree, Parent1),
-                    Parent1#node{id = new_node_id(Tx, Tree)}
-            end,
-
+            Parent2 = new_node_id_if_cacheable(Tx, Tree, Parent0, Parent1),
             clear_nodes(Tx, Tree, [Child0, Sibling]),
             set_nodes(Tx, Tree, NewNodes),
             Parent2;
@@ -706,16 +681,7 @@ delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
                 members = lists:keyreplace(ChildId0, 3, Parent0#node.members,
                     {first_key(Child1), last_key(Child1), Child1#node.id, reduce_node(Tree, Child1)})
             },
-            Parent2 = if
-                Parent1#node.id == ?NODE_ROOT_ID ->
-                    Parent1;
-                Parent0#node.members == Parent1#node.members ->
-                    Parent1;
-                true ->
-                    clear_node(Tx, Tree, Parent1),
-                    Parent1#node{id = new_node_id(Tx, Tree)}
-            end,
-            Parent2
+            new_node_id_if_cacheable(Tx, Tree, Parent0, Parent1)
     end.
 
 
@@ -1090,6 +1056,28 @@ last_key(Members) when is_list(Members) ->
     end.
 
 
+new_node_id_if_cacheable(Tx, #tree{} = Tree, #node{} = Old, #node{} = New) ->
+    MembersChanged = Old#node.members /= New#node.members,
+    NodeIsCacheable = node_is_cacheable(New),
+    if
+        MembersChanged andalso NodeIsCacheable ->
+            clear_node(Tx, Tree, New),
+            New#node{id = new_node_id(Tx, Tree)};
+        true ->
+            New
+    end.
+
+
+node_is_cacheable(#node{id = ?NODE_ROOT_ID}) ->
+    false;
+
+node_is_cacheable(#node{level = 0}) ->
+    false;
+
+node_is_cacheable(#node{}) ->
+    true.
+
+
 new_node_id(Tx, Tree) ->
     NextId = get_meta(Tx, Tree, ?META_NEXT_ID),
     set_meta(Tx, Tree, ?META_NEXT_ID, NextId + 1),


[couchdb] 06/06: add cache test

Posted by rn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rnewson pushed a commit to branch prototype/fdb-layer-ebtree-immutable
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 5215aa3ec007d7c83159ba01b943867a2419bc1c
Author: Robert Newson <rn...@apache.org>
AuthorDate: Thu Jul 23 19:16:25 2020 +0100

    add cache test
---
 src/ebtree/src/ebtree.erl | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index d058669..5409966 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -1529,4 +1529,23 @@ validate_node_test_() ->
     ].
 
 
+cache_test_() ->
+    {spawn, [fun() ->
+        Db = erlfdb_util:get_test_db([empty]),
+        CacheFun = fun
+            (set, Node) ->
+                erlang:put(Node#node.id, Node);
+            (clear, Node) ->
+                erlang:erase(Node#node.id);
+            (get, Id) ->
+                erlang:get(Id)
+        end,
+        Tree = open(Db, <<1,2,3>>, 4, [{cache_fun, CacheFun}]),
+        [ebtree:insert(Db, Tree, I, I) || I <- lists:seq(1, 16)],
+        ?assertEqual({1, 1}, ebtree:lookup(Db, Tree, 1)),
+        NodeCache = [V || {_K, V} <- erlang:get(), is_record(V, node)],
+        ?assertEqual(3, length(NodeCache))
+    end]}.
+
+
 -endif.