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

jaydoane pushed a commit to branch 3.x
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/3.x by this push:
     new 7d0f3db  Handle `not_found` lookups removing ddoc cache key
7d0f3db is described below

commit 7d0f3db7930daf9d64e40c2d2195bfa49507a7a6
Author: Jay Doane <[email protected]>
AuthorDate: Thu Dec 9 19:17:19 2021 -0800

    Handle `not_found` lookups removing ddoc cache key
    
    For non-existent ddocs, a new ddoc_cache_entry is spawned for each
    call to ddoc_cache:open. Multiple calls to open the same non-existent
    ddoc will create multiple cache entries with the same Key but
    different PIDs. This can result in khash lookups returning `not_found`
    as in the error below:
    
    [error] 2021-12-10T02:25:21.622743Z [email protected] <0.18923.9> -------- 
gen_server ddoc_cache_lru terminated with reason: no match of right hand value 
not_found at ddoc_cache_lru:remove_key/2(line:308) <= 
ddoc_cache_lru:handle_info/2(line:219) <= gen_server:try_dispatch/4(line:637) 
<= gen_server:handle_msg/6(line:711) <= proc_lib:init_p_do_apply/3(line:249)
    
    This checks the return values of `khash:lookup` and only proceeds to
    delete keys if the results are other than `not_found`.
---
 src/ddoc_cache/src/ddoc_cache_lru.erl | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/src/ddoc_cache/src/ddoc_cache_lru.erl 
b/src/ddoc_cache/src/ddoc_cache_lru.erl
index ec8f5ca..7381e6c 100644
--- a/src/ddoc_cache/src/ddoc_cache_lru.erl
+++ b/src/ddoc_cache/src/ddoc_cache_lru.erl
@@ -296,16 +296,30 @@ remove_key(St, Key) ->
     } = St,
     DbName = ddoc_cache_entry:dbname(Key),
     DDocId = ddoc_cache_entry:ddocid(Key),
-    {value, DDocIds} = khash:lookup(Dbs, DbName),
-    {value, Keys} = khash:lookup(DDocIds, DDocId),
-    khash:del(Keys, Key),
-    case khash:size(Keys) of
-        0 -> khash:del(DDocIds, DDocId);
-        _ -> ok
-    end,
-    case khash:size(DDocIds) of
-        0 -> khash:del(Dbs, DbName);
-        _ -> ok
+
+    % For non-existent ddocs, a new ddoc_cache_entry is spawned for
+    % each call to ddoc_cache:open. Multiple calls to open the same
+    % non-existent ddoc will create multiple cache entries with the
+    % same Key but different PIDs. This can result in the following
+    % khash lookups returning not_found, so handle those corner cases.
+    case khash:lookup(Dbs, DbName) of
+        {value, DDocIds} ->
+            case khash:lookup(DDocIds, DDocId) of
+                {value, Keys} ->
+                    ok = khash:del(Keys, Key),
+                    case khash:size(Keys) of
+                        0 -> khash:del(DDocIds, DDocId);
+                        _ -> ok
+                    end,
+                    case khash:size(DDocIds) of
+                        0 -> khash:del(Dbs, DbName);
+                        _ -> ok
+                    end;
+                not_found ->
+                    ok
+            end;
+        not_found ->
+            ok
     end.
 
 unlink_and_flush(Pid) ->

Reply via email to