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:28 UTC

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

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