diff options
author | Jay Doane <jaydoane@apache.org> | 2021-12-09 19:17:19 -0800 |
---|---|---|
committer | Jay Doane <jay.s.doane@gmail.com> | 2022-03-29 13:45:51 -0700 |
commit | 7d0f3db7930daf9d64e40c2d2195bfa49507a7a6 (patch) | |
tree | bb37d467ae51e05a44f104df91613eac5793e438 | |
parent | d32e8c542a1222b40a587a7578456b788acb0217 (diff) | |
download | couchdb-7d0f3db7930daf9d64e40c2d2195bfa49507a7a6.tar.gz |
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 node1@127.0.0.1 <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`.
-rw-r--r-- | src/ddoc_cache/src/ddoc_cache_lru.erl | 34 |
1 files 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 ec8f5caaa..7381e6c28 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) -> |