This is an automated email from the ASF dual-hosted git repository. garren pushed a commit to branch user-partitioned-dbs in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 235f0b1ffeb993223b49c30fcf45fbe43a43928a Author: Garren Smith <[email protected]> AuthorDate: Thu Jun 21 16:30:35 2018 +0200 Add props field to couch_db_engine Add the ability to store database properties to the couchdb engine. --- src/couch/src/couch_bt_engine.erl | 42 ++++++++++++++++++++++++++++- src/couch/src/couch_bt_engine_header.erl | 3 ++- src/couch/src/couch_db_engine.erl | 39 +++++++++++++++++++++++++++ src/couch/src/test_engine_get_set_props.erl | 35 ++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/src/couch/src/couch_bt_engine.erl b/src/couch/src/couch_bt_engine.erl index a42d116..e0992cf 100644 --- a/src/couch/src/couch_bt_engine.erl +++ b/src/couch/src/couch_bt_engine.erl @@ -39,12 +39,15 @@ get_purge_seq/1, get_revs_limit/1, get_security/1, + get_prop/2, + get_prop/3, get_size_info/1, get_update_seq/1, get_uuid/1, set_revs_limit/2, set_security/2, + set_prop/3, open_docs/2, open_local_docs/2, @@ -266,6 +269,28 @@ get_security(#st{header = Header} = St) -> end. +get_props(#st{header = Header} = St) -> + case couch_bt_engine_header:get(Header, props_ptr) of + undefined -> {ok, []}; + Pointer -> couch_file:pread_term(St#st.fd, Pointer) + end. + + +get_prop(St, Key) -> + {ok, Props} = get_props(St), + case lists:keyfind(Key, 1, Props) of + false -> {error, no_value}; + {Key, Value} -> {ok, Value} + end. + + +get_prop(St, Key, DefaultValue) -> + case get_prop(St, Key) of + {error, no_value} -> {ok, DefaultValue}; + Value -> Value + end. + + get_update_seq(#st{header = Header}) -> couch_bt_engine_header:get(Header, update_seq). @@ -296,6 +321,20 @@ set_security(#st{header = Header} = St, NewSecurity) -> {ok, increment_update_seq(NewSt)}. +set_prop(#st{header = Header} = St, Key, Value) -> + {ok, OldProps} = get_props(St), + NewProps = [{Key, Value} | OldProps], + Options = [{compression, St#st.compression}], + {ok, Ptr, _} = couch_file:append_term(St#st.fd, NewProps, Options), + NewSt = St#st{ + header = couch_bt_engine_header:set(Header, [ + {props_ptr, Ptr} + ]), + needs_commit = true + }, + {ok, increment_update_seq(NewSt)}. + + open_docs(#st{} = St, DocIds) -> Results = couch_btree:lookup(St#st.id_tree, DocIds), lists:map(fun @@ -682,7 +721,8 @@ init_state(FilePath, Fd, Header0, Options) -> Compression = couch_compress:get_compression_method(), Header1 = couch_bt_engine_header:upgrade(Header0), - Header = set_default_security_object(Fd, Header1, Compression, Options), + Header2 = set_default_security_object(Fd, Header1, Compression, Options), + Header = set_default_props(Fd, Header2, Compression, Options), IdTreeState = couch_bt_engine_header:id_tree_state(Header), {ok, IdTree} = couch_btree:open(IdTreeState, Fd, [ diff --git a/src/couch/src/couch_bt_engine_header.erl b/src/couch/src/couch_bt_engine_header.erl index 3d24f31..779bf26 100644 --- a/src/couch/src/couch_bt_engine_header.erl +++ b/src/couch/src/couch_bt_engine_header.erl @@ -66,7 +66,8 @@ revs_limit = 1000, uuid, epochs, - compacted_seq + compacted_seq, + props_ptr }). diff --git a/src/couch/src/couch_db_engine.erl b/src/couch/src/couch_db_engine.erl index 502faa7..75411ab 100644 --- a/src/couch/src/couch_db_engine.erl +++ b/src/couch/src/couch_db_engine.erl @@ -225,6 +225,17 @@ -callback get_security(DbHandle::db_handle()) -> SecProps::any(). +% Get the current properties. This should just return +% the last value that was passed to set_prop/2. +-callback get_prop(DbHandle::db_handle(), Prop::atom()) -> + {ok, SecProps::json()}. + +% Get the current properties. If the value isn't set it will return the set default value. +% This should just return the last value that was passed to set_prop/2. +-callback get_prop(DbHandle::db_handle(), Prop::atom(), DefaultValue::any()) -> + {ok, SecProps::json()}. + + % This information is displayed in the database info poperties. It % should just be a list of {Name::atom(), Size::non_neg_integer()} % tuples that will then be combined across shards. Currently, @@ -265,6 +276,15 @@ {ok, NewDbHandle::db_handle()}. +% This function is only called by couch_db_updater and +% as such is guaranteed to be single threaded calls. The +% database should simply store prop key and value somewhere so +% they can be returned by the corresponding get_prop calls. + +-callback set_prop(DbHandle::db_handle(), PropKey::atom(), PropValue::any()) -> + {ok, NewDbHandle::db_handle()}. + + % This function will be called by many processes concurrently. % It should return a #full_doc_info{} record or not_found for % every provided DocId in the order those DocId's appear in @@ -601,12 +621,15 @@ get_purge_seq/1, get_revs_limit/1, get_security/1, + get_prop/2, + get_prop/3, get_size_info/1, get_update_seq/1, get_uuid/1, set_revs_limit/2, set_security/2, + set_prop/3, open_docs/2, open_local_docs/2, @@ -757,6 +780,16 @@ get_security(#db{} = Db) -> Engine:get_security(EngineState). +get_prop(#db{} = Db, Prop) -> + #db{engine = {Engine, EngineState}} = Db, + Engine:get_prop(EngineState, Prop). + + +get_prop(#db{} = Db, Prop, DefaultValue) -> + #db{engine = {Engine, EngineState}} = Db, + Engine:get_prop(EngineState, Prop, DefaultValue). + + get_size_info(#db{} = Db) -> #db{engine = {Engine, EngineState}} = Db, Engine:get_size_info(EngineState). @@ -783,6 +816,12 @@ set_security(#db{} = Db, SecProps) -> {ok, Db#db{engine = {Engine, NewSt}}}. +set_prop(#db{} = Db, Key, Value) -> + #db{engine = {Engine, EngineState}} = Db, + {ok, NewSt} = Engine:set_prop(EngineState, Key, Value), + {ok, Db#db{engine = {Engine, NewSt}}}. + + open_docs(#db{} = Db, DocIds) -> #db{engine = {Engine, EngineState}} = Db, Engine:open_docs(EngineState, DocIds). diff --git a/src/couch/src/test_engine_get_set_props.erl b/src/couch/src/test_engine_get_set_props.erl index 6d2a447..28ab409 100644 --- a/src/couch/src/test_engine_get_set_props.erl +++ b/src/couch/src/test_engine_get_set_props.erl @@ -50,6 +50,41 @@ cet_set_revs_limit() -> check_prop_set(get_revs_limit, set_revs_limit, 1000, 50). +cet_set_props_at_init() -> + Engine = test_engine_util:get_engine(), + DbPath = test_engine_util:dbpath(), + + {ok, St} = Engine:init(DbPath, [ + create, + {default_security_object, dso}, + {default_props, [{shardkey, true}]} + ]), + + ?assertEqual({ok, true}, Engine:get_prop(St, shardkey)). + + +cet_set_prop() -> + Engine = test_engine_util:get_engine(), + DbPath = test_engine_util:dbpath(), + + {ok, St0} = Engine:init(DbPath, [ + create, + {default_security_object, dso} + ]), + ?assertEqual({error, no_value}, Engine:get_prop(St0, shardkey)), + + ?assertEqual({ok, false}, Engine:get_prop(St0, shardkey, false)), + + {ok, St1} = Engine:set_prop(St0, shardkey, true), + ?assertEqual({ok, true}, Engine:get_prop(St1, shardkey)), + + {ok, St2} = Engine:commit_data(St1), + Engine:terminate(normal, St2), + + {ok, St3} = Engine:init(DbPath, []), + ?assertEqual({ok, true}, Engine:get_prop(St3, shardkey)). + + check_prop_set(GetFun, SetFun, Default, Value) -> Engine = test_engine_util:get_engine(), DbPath = test_engine_util:dbpath(),
