This is an automated email from the ASF dual-hosted git repository. davisp pushed a commit to branch feature/user-partitioned-databases-davisp in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit a5df6ed806ff8b952e4caa6d1b6dc04c238ad03f Author: Garren Smith <garren.sm...@gmail.com> AuthorDate: Thu Jun 21 16:30:35 2018 +0200 Add PSE API to store opaque properties This allows us to implement features outside of the PSE API without requiring changes to the API for each bit of data we may want to end up storing. The use of this opaque object should only be used for features that don't require a beahvior change from the storage engine API. Co-authored-by: Garren Smith <garren.sm...@gmail.com> Co-authored-by: Robert Newson <rnew...@apache.org> --- src/couch/src/couch_bt_engine.erl | 55 +++++++++++++++++++++++++++-- src/couch/src/couch_bt_engine_compactor.erl | 8 +++-- src/couch/src/couch_bt_engine_header.erl | 3 +- src/couch/src/couch_db.erl | 5 +++ src/couch/src/couch_db_engine.erl | 26 ++++++++++++++ src/couch/src/couch_db_updater.erl | 5 +-- 6 files changed, 94 insertions(+), 8 deletions(-) diff --git a/src/couch/src/couch_bt_engine.erl b/src/couch/src/couch_bt_engine.erl index 6d858ed..cc62f4f 100644 --- a/src/couch/src/couch_bt_engine.erl +++ b/src/couch/src/couch_bt_engine.erl @@ -40,6 +40,7 @@ get_purge_infos_limit/1, get_revs_limit/1, get_security/1, + get_props/1, get_size_info/1, get_update_seq/1, get_uuid/1, @@ -47,6 +48,7 @@ set_revs_limit/2, set_purge_infos_limit/2, set_security/2, + set_props/2, open_docs/2, open_local_docs/2, @@ -104,7 +106,8 @@ -export([ set_update_seq/2, update_header/2, - copy_security/2 + copy_security/2, + copy_props/2 ]). @@ -143,8 +146,9 @@ init(FilePath, Options) -> true -> delete_compaction_files(FilePath), Header0 = couch_bt_engine_header:new(), - ok = couch_file:write_header(Fd, Header0), - Header0; + Header1 = init_set_props(Fd, Header0, Options), + ok = couch_file:write_header(Fd, Header1), + Header1; false -> case couch_file:read_header(Fd) of {ok, Header0} -> @@ -283,6 +287,16 @@ get_security(#st{header = Header} = St) -> end. +get_props(#st{header = Header} = St) -> + case couch_bt_engine_header:get(Header, props_ptr) of + undefined -> + []; + Pointer -> + {ok, Props} = couch_file:pread_term(St#st.fd, Pointer), + Props + end. + + get_update_seq(#st{header = Header}) -> couch_bt_engine_header:get(Header, update_seq). @@ -323,6 +337,18 @@ set_security(#st{header = Header} = St, NewSecurity) -> {ok, increment_update_seq(NewSt)}. +set_props(#st{header = Header} = St, Props) -> + 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 @@ -753,6 +779,17 @@ copy_security(#st{header = Header} = St, SecProps) -> }}. +copy_props(#st{header = Header} = St, Props) -> + Options = [{compression, St#st.compression}], + {ok, Ptr, _} = couch_file:append_term(St#st.fd, Props, Options), + {ok, St#st{ + header = couch_bt_engine_header:set(Header, [ + {props_ptr, Ptr} + ]), + needs_commit = true + }}. + + open_db_file(FilePath, Options) -> case couch_file:open(FilePath, Options) of {ok, Fd} -> @@ -939,6 +976,18 @@ upgrade_purge_info(Fd, Header) -> end. +init_set_props(Fd, Header, Options) -> + case couch_util:get_value(props, Options) of + undefined -> + Header; + InitialProps -> + Compression = couch_compress:get_compression_method(), + AppendOpts = [{compression, Compression}], + {ok, Ptr, _} = couch_file:append_term(Fd, InitialProps, AppendOpts), + couch_bt_engine_header:set(Header, props_ptr, Ptr) + end. + + delete_compaction_files(FilePath) -> RootDir = config:get("couchdb", "database_dir", "."), DelOpts = [{context, compaction}], diff --git a/src/couch/src/couch_bt_engine_compactor.erl b/src/couch/src/couch_bt_engine_compactor.erl index 10de686..737f772 100644 --- a/src/couch/src/couch_bt_engine_compactor.erl +++ b/src/couch/src/couch_bt_engine_compactor.erl @@ -276,9 +276,13 @@ copy_compact(DbName, St, NewSt0, Retry) -> SecProps = couch_bt_engine:get_security(St), {ok, NewSt4} = couch_bt_engine:copy_security(NewSt3, SecProps), + % Copy general properties over + Props = couch_bt_engine:get_props(St), + {ok, NewSt5} = couch_bt_engine:set_props(NewSt4, Props), + FinalUpdateSeq = couch_bt_engine:get_update_seq(St), - {ok, NewSt5} = couch_bt_engine:set_update_seq(NewSt4, FinalUpdateSeq), - commit_compaction_data(NewSt5). + {ok, NewSt6} = couch_bt_engine:set_update_seq(NewSt5, FinalUpdateSeq), + commit_compaction_data(NewSt6). copy_docs(St, #st{} = NewSt, MixedInfos, Retry) -> diff --git a/src/couch/src/couch_bt_engine_header.erl b/src/couch/src/couch_bt_engine_header.erl index 467bb2f..7f701fc 100644 --- a/src/couch/src/couch_bt_engine_header.erl +++ b/src/couch/src/couch_bt_engine_header.erl @@ -68,7 +68,8 @@ uuid, epochs, compacted_seq, - purge_infos_limit = 1000 + purge_infos_limit = 1000, + props_ptr }). diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl index 55664e9..b4ab873 100644 --- a/src/couch/src/couch_db.erl +++ b/src/couch/src/couch_db.erl @@ -579,6 +579,10 @@ get_db_info(Db) -> undefined -> null; Else1 -> Else1 end, + Props = case get_props(Db) of + undefined -> null; + Else2 -> Else2 + end, InfoList = [ {db_name, Name}, {engine, couch_db_engine:get_engine(Db)}, @@ -600,6 +604,7 @@ get_db_info(Db) -> {disk_format_version, DiskVersion}, {committed_update_seq, CommittedUpdateSeq}, {compacted_seq, CompactedSeq}, + {props, {Props}}, {uuid, Uuid} ], {ok, InfoList}. diff --git a/src/couch/src/couch_db_engine.erl b/src/couch/src/couch_db_engine.erl index ea30dbc..eed46e8 100644 --- a/src/couch/src/couch_db_engine.erl +++ b/src/couch/src/couch_db_engine.erl @@ -243,6 +243,10 @@ -callback get_security(DbHandle::db_handle()) -> SecProps::any(). +% Get the current properties. +-callback get_props(DbHandle::db_handle()) -> Props::any(). + + % 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, @@ -288,6 +292,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 provided property list +% unaltered. + +-callback set_props(DbHandle::db_handle(), Props::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 @@ -670,6 +683,7 @@ get_purge_infos_limit/1, get_revs_limit/1, get_security/1, + get_props/1, get_size_info/1, get_update_seq/1, get_uuid/1, @@ -677,6 +691,7 @@ set_revs_limit/2, set_security/2, set_purge_infos_limit/2, + set_props/2, open_docs/2, open_local_docs/2, @@ -836,6 +851,11 @@ get_security(#db{} = Db) -> Engine:get_security(EngineState). +get_props(#db{} = Db) -> + #db{engine = {Engine, EngineState}} = Db, + Engine:get_props(EngineState). + + get_size_info(#db{} = Db) -> #db{engine = {Engine, EngineState}} = Db, Engine:get_size_info(EngineState). @@ -868,6 +888,12 @@ set_security(#db{} = Db, SecProps) -> {ok, Db#db{engine = {Engine, NewSt}}}. +set_props(#db{} = Db, Props) -> + #db{engine = {Engine, EngineState}} = Db, + {ok, NewSt} = Engine:set_props(EngineState, Props), + {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/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl index 52a4d2f..be40788 100644 --- a/src/couch/src/couch_db_updater.erl +++ b/src/couch/src/couch_db_updater.erl @@ -310,14 +310,15 @@ init_db(DbName, FilePath, EngineState, Options) -> BDU = couch_util:get_value(before_doc_update, Options, nil), ADR = couch_util:get_value(after_doc_read, Options, nil), - CleanedOpts = [Opt || Opt <- Options, Opt /= create], + NonCreateOpts = [Opt || Opt <- Options, Opt /= create], + DbProps = couch_db_engine:get_props(InitDb), InitDb = #db{ name = DbName, filepath = FilePath, engine = EngineState, instance_start_time = StartTime, - options = CleanedOpts, + options = lists:keystore(props, 1, NonCreateOpts, {props, DbProps}), before_doc_update = BDU, after_doc_read = ADR },