You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2018/07/04 14:12:51 UTC
[couchdb] 01/02: Add props field to couch_db_engine
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 <ga...@gmail.com>
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(),