From 791cec41dba4f8e06522b01e452fd0b8f4929519 Mon Sep 17 00:00:00 2001 From: Ulf Wiger Date: Wed, 4 Oct 2023 16:39:07 +0200 Subject: [PATCH 1/2] Adding/deleting indexes cleans up index metadata --- src/mnesia_rocksdb_admin.erl | 28 +++++++++++++++++++- src/mrdb_index.erl | 38 +++++++++++++++++++++++++++ test/mnesia_rocksdb_indexes_SUITE.erl | 21 +++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/mnesia_rocksdb_admin.erl b/src/mnesia_rocksdb_admin.erl index b2be125..f2682d1 100644 --- a/src/mnesia_rocksdb_admin.erl +++ b/src/mnesia_rocksdb_admin.erl @@ -33,6 +33,7 @@ , read_info/2 %% (Alias, Tab) , read_info/4 %% (Alias, Tab, Key, Default) , write_info/4 %% (Alias, Tab, Key, Value) + , delete_info/3 %% (Alias, Tab, Key) , write_table_property/3 %% (Alias, Tab, Property) ]). @@ -287,6 +288,14 @@ write_info_encv(Ref, Tab, K, V) -> maybe_write_standalone_info(Ref, K, V), mrdb:rdb_put(Ref, EncK, V, []). +delete_info(Alias, Tab, K) -> + delete_info_(get_ref({admin, Alias}), Tab, K). + +delete_info_(Ref, Tab, K) -> + EncK = mnesia_rocksdb_lib:encode_key({info, Tab, K}, sext), + maybe_delete_standalone_info(Ref, K), + mrdb:rdb_delete(Ref, EncK, []). + maybe_write_standalone_info(Ref, K, V) -> case Ref of #{type := standalone, vsn := 1, db_ref := DbRef} -> @@ -298,6 +307,16 @@ maybe_write_standalone_info(Ref, K, V) -> ok end. +maybe_delete_standalone_info(Ref, K) -> + case Ref of + #{type := standalone, vsn := 1, db_ref := DbRef} -> + EncK = mnesia_rocksdb_lib:encode_key(K, sext), + Key = <>, + rocksb:delete(DbRef, Key, []); + _ -> + ok + end. + write_table_property(Alias, Tab, Prop) when is_tuple(Prop), size(Prop) >= 1 -> call(Alias, {write_table_property, Tab, Prop}). @@ -521,7 +540,7 @@ handle_req(Alias, {create_table, Name, Props}, Backend, St) -> case create_trec(Alias, Name, Props, Backend, St) of {ok, NewCf} -> St1 = update_cf(Alias, Name, NewCf, St), - {reply, {ok, NewCf}, St1}; + {reply, {ok, NewCf}, maybe_update_main(Alias, Name, create, St1)}; {error, _} = Error -> {reply, Error, St} end @@ -637,8 +656,14 @@ maybe_update_main(Alias, {Main, index, I}, Op, St) -> case {Op, lists:member(I, Index)} of {delete, true} -> CfM1 = CfM#{properties => Props#{index => Index -- [I]}}, + delete_info(Alias, Main, {index_consistent, I}), maybe_update_pt(Main, CfM1), update_cf(Alias, Main, CfM1, St); + {create, _} -> + %% Due to a previous bug, this marker might linger + %% In any case, it mustn't be there for a newly created index + delete_info(Alias, Main, {index_consistent, I}), + St; _ -> St end; @@ -649,6 +674,7 @@ maybe_update_main(Alias, {Main, index, I}, Op, St) -> maybe_update_main(_, _, _, St) -> St. + %% The pt may not have been created yet. If so, don't do it here. maybe_update_pt(Name, Ref) -> case get_pt(Name, error) of diff --git a/src/mrdb_index.erl b/src/mrdb_index.erl index fcf1f6d..d73c0c6 100644 --- a/src/mrdb_index.erl +++ b/src/mrdb_index.erl @@ -6,6 +6,9 @@ , iterator_move/2 , iterator/2 , iterator_close/1 + , fold/4 + , rev_fold/4 + , index_ref/2 ]). -record(mrdb_ix_iter, { i :: mrdb:iterator() @@ -62,6 +65,41 @@ iterator(Tab, IxPos) -> iterator_move(#mrdb_ix_iter{type = set} = IxI, Dir) -> iterator_move_set(IxI, Dir); iterator_move(#mrdb_ix_iter{type = bag} = IxI, Dir) -> iterator_move_bag(IxI, Dir). +-spec fold(mrdb:ref_or_tab(), mrdb:index_position(), + fun( (index_value(), object() | [], Acc) -> Acc ), Acc) -> Acc + when Acc :: any(). +%% Folds over the index table corresponding to Tab and IxPos. +%% The fold fun is called with the index key and the corresponding object, +%% or [] if there is no such object. +fold(Tab, IxPos, FoldFun, Acc) when is_function(FoldFun, 3) -> + fold_(Tab, IxPos, first, next, FoldFun, Acc). + +-spec rev_fold(mrdb:ref_or_tab(), mrdb:index_position(), + fun( (index_value(), object() | [], Acc) -> Acc ), Acc) -> Acc + when Acc :: any(). +%% Like fold/4 above, but folds over the index in the reverse order. +rev_fold(Tab, IxPos, FoldFun, Acc) when is_function(FoldFun, 3) -> + fold_(Tab, IxPos, last, prev, FoldFun, Acc). + +fold_(Tab, IxPos, Start, Dir, FoldFun, Acc) -> + with_iterator( + Tab, IxPos, + fun(I) -> + iter_fold(I, Start, Dir, FoldFun, Acc) + end). + +iter_fold(I, Start, Dir, Fun, Acc) -> + iter_fold_(iterator_move(I, Start), I, Dir, Fun, Acc). + +iter_fold_({ok, IxVal, Obj}, I, Dir, Fun, Acc) -> + iter_fold_(iterator_move(I, Dir), I, Dir, Fun, Fun(IxVal, Obj, Acc)); +iter_fold_({error, _}, _, _, _, Acc) -> + Acc. + +index_ref(Tab, Pos) -> + TRef = mrdb:ensure_ref(Tab), + ensure_index_ref(Pos, TRef). + iterator_move_set(#mrdb_ix_iter{i = I, sub = Sub}, Dir) -> case mrdb:iterator_move(I, Dir) of {ok, {{FKey, PKey}}} -> diff --git a/test/mnesia_rocksdb_indexes_SUITE.erl b/test/mnesia_rocksdb_indexes_SUITE.erl index 1ff35b5..00ca1a3 100644 --- a/test/mnesia_rocksdb_indexes_SUITE.erl +++ b/test/mnesia_rocksdb_indexes_SUITE.erl @@ -33,6 +33,7 @@ -export([ index_plugin_mgmt/1 , add_indexes/1 + , delete_indexes/1 , create_bag_index/1 , create_ordered_index/1 , test_1_ram_copies/1 @@ -94,6 +95,7 @@ groups() -> , create_ordered_index , index_plugin_mgmt , add_indexes + , delete_indexes ]} , {access, [sequence], [ test_1_ram_copies @@ -239,6 +241,25 @@ add_indexes(_Config) -> {atomic, ok} = mnesia:add_table_index(T, a), ok. +delete_indexes(_Config) -> + T = ?TAB(t1), + {atomic, ok} = mnesia:create_table(T, [{rdb, [node()]}, {attributes, [k, a, b]}]), + ok = mrdb:insert(T, {T, a, 1, 1}), + ok = mrdb:insert(T, {T, b, 1, 2}), + {atomic, ok} = mnesia:add_table_index(T, a), + [{1, {T,a,1,1}}, {1, {T,b,1,2}}] = + mrdb_index:rev_fold(T, a, fun ix_fold_acc/3, []), + {atomic, ok} = mnesia:del_table_index(T, a), + ok = mrdb:delete(T, b), + ok = mrdb:insert(T, {T, c, 2, 3}), + {atomic, ok} = mnesia:add_table_index(T, a), + [{1, {T,a,1,1}}, {2, {T,c,2,3}}] = + mrdb_index:rev_fold(T, a, fun ix_fold_acc/3, []), + ok. + +ix_fold_acc(K, V, Acc) -> + [{K, V} | Acc]. + index_plugin_mgmt(_Config) -> {aborted,_} = mnesia:create_table(x, [{index,[{unknown}]}]), {aborted,_} = mnesia:create_table(x, [{index,[{{unknown},bag}]}]), From 57f02078bc74ec4c65f545e6ed1a34b8c08e5db9 Mon Sep 17 00:00:00 2001 From: Ulf Wiger Date: Wed, 4 Oct 2023 16:49:34 +0200 Subject: [PATCH 2/2] Fix typo --- src/mnesia_rocksdb_admin.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mnesia_rocksdb_admin.erl b/src/mnesia_rocksdb_admin.erl index f2682d1..3ae2c22 100644 --- a/src/mnesia_rocksdb_admin.erl +++ b/src/mnesia_rocksdb_admin.erl @@ -312,7 +312,7 @@ maybe_delete_standalone_info(Ref, K) -> #{type := standalone, vsn := 1, db_ref := DbRef} -> EncK = mnesia_rocksdb_lib:encode_key(K, sext), Key = <>, - rocksb:delete(DbRef, Key, []); + rocksdb:delete(DbRef, Key, []); _ -> ok end.