diff options
author | Jan Lehnardt <jan@apache.org> | 2017-12-16 09:30:29 +0100 |
---|---|---|
committer | Jan Lehnardt <jan@apache.org> | 2019-01-19 14:20:06 +0100 |
commit | 6c369fecef3c9de5f7ba788362da27b8c12766a7 (patch) | |
tree | bab579abcf1c1c54eedb83b4a7e9e8c27e29617b | |
parent | b1d835a9d3ac8e8ad77dea785053cb7a3be3bed6 (diff) | |
download | couchdb-6c369fecef3c9de5f7ba788362da27b8c12766a7.tar.gz |
wip
-rw-r--r-- | src/couch/src/couch_access_native_proc.erl | 12 | ||||
-rw-r--r-- | src/couch/src/couch_btree.erl | 21 | ||||
-rw-r--r-- | src/couch/src/couch_db.erl | 144 | ||||
-rw-r--r-- | src/couch_mrview/src/couch_mrview.erl | 10 | ||||
-rw-r--r-- | src/couch_mrview/src/couch_mrview_updater.erl | 13 | ||||
-rw-r--r-- | src/couch_mrview/src/couch_mrview_util.erl | 6 |
6 files changed, 199 insertions, 7 deletions
diff --git a/src/couch/src/couch_access_native_proc.erl b/src/couch/src/couch_access_native_proc.erl index dd01de081..840cf1b19 100644 --- a/src/couch/src/couch_access_native_proc.erl +++ b/src/couch/src/couch_access_native_proc.erl @@ -36,7 +36,6 @@ }). start_link() -> - couch_log:info("~n~ncouch_access_native_proc: start_link~n~n", []), gen_server:start_link(?MODULE, [], []). @@ -49,7 +48,6 @@ prompt(Pid, Data) -> init(_) -> - couch_log:info("~n~ncouch_access_native_proc: init~n~n", []), {ok, #st{}}. @@ -129,10 +127,16 @@ map_doc(_St, {Doc}) -> Access when is_list(Access) -> Id = couch_util:get_value(<<"_id">>, Doc), Rev = couch_util:get_value(<<"_rev">>, Doc), + Seq = couch_util:get_value(<<"_seq">>, Doc), + % by-access-id lists:map(fun(UserOrRole) -> [ [[UserOrRole, Id], Rev] ] end, Access) - ++ [[]]; %TODO: implement by-access-seq + ++ + % by-access-seq + lists:map(fun(UserOrRole) -> [ + [[UserOrRole, Seq], Rev] + ] end, Access); _Else -> - [[],[]] % no comprende + [[],[]] % no comprende: should not be needed once we implement _access field validation end. diff --git a/src/couch/src/couch_btree.erl b/src/couch/src/couch_btree.erl index daf846ba8..ef2991064 100644 --- a/src/couch/src/couch_btree.erl +++ b/src/couch/src/couch_btree.erl @@ -16,6 +16,7 @@ -export([fold/4, full_reduce/1, final_reduce/2, size/1, foldl/3, foldl/4]). -export([fold_reduce/4, lookup/2, get_state/1, set_options/2]). -export([extract/2, assemble/3, less/3]). +-export([full_reduce_with_options/2]). -include_lib("couch/include/couch_db.hrl"). @@ -34,6 +35,8 @@ assemble(#btree{assemble_kv=Assemble}, Key, Value) -> less(#btree{less=undefined}, A, B) -> A < B; less(#btree{less=Less}, A, B) -> + couch_log:info("~n A:~p~n", [A]), + couch_log:info("~n B:~p~n", [B]), Less(A, B). % pass in 'nil' for State if a new Btree. @@ -92,11 +95,29 @@ fold_reduce(#btree{root=Root}=Bt, Fun, Acc, Options) -> throw:{stop, AccDone} -> {ok, AccDone} end. +full_reduce_with_options(Bt, Options0) -> + CountFun = fun(_SeqStart, PartialReds, 0) -> + {ok, couch_btree:final_reduce(Bt, PartialReds)} + end, + [UserName] = proplists:get_value(start_key, Options0, <<"">>), + % couch_log:info("~n Options0:~p~n", [Options0]), + % couch_log:info("~n UserName:~p~n", [UserName]), + EndKey = {[UserName, {[]}], {[]}}, + % couch_log:info("~n EndKey:~p~n", [EndKey]), + Options = Options0 ++ [ + {end_key, EndKey} + ], + couch_log:info("~n Options:~p~n", [Options]), + R = fold_reduce(Bt, CountFun, 0, Options), + couch_log:info("~n~n R: ~p ~n", [R]), + R. + full_reduce(#btree{root=nil,reduce=Reduce}) -> {ok, Reduce(reduce, [])}; full_reduce(#btree{root=Root}) -> {ok, element(2, Root)}. + size(#btree{root = nil}) -> 0; size(#btree{root = {_P, _Red}}) -> diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl index 2f63fcfe8..35b5c7978 100644 --- a/src/couch/src/couch_db.erl +++ b/src/couch/src/couch_db.erl @@ -133,6 +133,7 @@ -include_lib("couch/include/couch_db.hrl"). +-include_lib("couch_mrview/include/couch_mrview.hrl"). -include("couch_db_int.hrl"). -define(DBNAME_REGEX, @@ -576,6 +577,30 @@ get_db_info(Db) -> ActiveSize = couch_util:get_value(active, SizeInfo, null), ExternalSize = couch_util:get_value(external, SizeInfo, null), DiskVersion = couch_db_engine:get_disk_version(Db), + +% pre PSE TODO: PORT +% {ok, FileSize} = couch_file:bytes(Fd), +% {ok, DbReduction} = couch_btree:full_reduce(IdBtree), + % case is_admin(Db) of + % true -> + % couch_btree:full_reduce(IdBtree); + % false -> + % UserCtx = get_user_ctx(Db), + % UserName = UserCtx#user_ctx.name, + % couch_btree:full_reduce_with_options(IdBtree, [{start_key, UserName}]) + % end, +% SizeInfo0 = element(3, DbReduction), +% SizeInfo = case SizeInfo0 of +% SI when is_record(SI, size_info) -> +% SI; +% {AS, ES} -> +% #size_info{active=AS, external=ES}; +% AS -> +% #size_info{active=AS} +% end, +% ActiveSize = active_size(Db, SizeInfo), +% DiskVersion = couch_db_header:disk_version(Header), + Uuid = case get_uuid(Db) of undefined -> null; Uuid0 -> Uuid0 @@ -1458,6 +1483,125 @@ open_write_stream(Db, Options) -> open_read_stream(Db, AttState) -> couch_db_engine:open_read_stream(Db, AttState). +changes_since(Db, StartSeq, Fun, Options, Acc) when is_record(Db, db) -> + case couch_db:is_admin(Db) of + true -> changes_since_admin(Db#db.seq_tree, StartSeq, Fun, Options, Acc); + false -> changes_since_admin(Db#db.seq_tree, StartSeq, Fun, Options, Acc) + % false -> changes_since_access(Db, StartSeq, Fun, Options, Acc) + end. + +% TODO: nicked from couch_mrview, maybe move to couch_mrview.hrl +-record(mracc, { + db, + meta_sent=false, + total_rows, + offset, + limit, + skip, + group_level, + doc_info, + callback, + user_acc, + last_go=ok, + reduce_fun, + update_seq, + args +}). + +changes_since_access(Db, StartSeq, Fun, Options, Acc) -> + %% query view _access/_by_access_seq + %% fudge result to look like changes_since / Fun expect. + % query our not yest existing, home-grown _access view. + % use query_view for this. + DDoc = #doc{ % TODO: dupe: externalise or move into shared function + id = <<"_design/_access">>, + body = {[ + {<<"language">>,<<"_access">>}, + {<<"views">>, {[ + {<<"_access_by_id">>, {[ + {<<"map">>, <<"_access/by-id-map">>}, + {<<"reduce">>, <<"_count">>} + ]}}, + {<<"_access_by_seq">>, {[ + {<<"map">>, <<"_access/by-seq-map">>}, + {<<"reduce">>, <<"_count">>} + ]}} + ]}} + ]} + }, + %% add startkey/endkey + UserCtx = couch_db:get_user_ctx(Db), + UserName = UserCtx#user_ctx.name, + Direction = proplists:get_value(dir, Options, fwd), + Args0 = #mrargs{ + direction = Direction, + start_key = StartSeq, + reduce = false + }, + Args = prefix_startkey_endkey(UserName, Args0, Direction), + % filter out the user-prefix from the key, so _all_docs looks normal + % this isn’t a separate function because I’m binding Callback0 and I don’t + % know the Erlang equivalent of JS’s fun.bind(this, newarg) + % also translate view output into by-seq output + Callback = fun + ({meta, _}, Acc0) -> + Acc0; + ({row, Props}=Row, Acc0) -> + couch_log:info("~nRow: ~p~n~n", [Row]), + [_User, Key] = proplists:get_value(key, Props), + Row0 = proplists:delete(key, Props), + Row = [{key, Key} | Row0], + Fun({row, Row}, Acc0); + (Row, Acc0) -> + couch_log:info("~nRow: ~p~n~n", [Row]), + Fun(Row, Acc0) + end, + VName = <<"_access_by_seq">>, + couch_mrview:query_view(Db, DDoc, VName, Args, Callback, #mracc{user_acc = Acc}). + + +% TODO: dupe: externalise or move into shared function +prefix_startkey_endkey(UserName, Args, fwd) -> + #mrargs{start_key=StartKey, end_key=EndKey} = Args, + Args#mrargs { + start_key = case StartKey of + undefined -> [UserName]; + StartKey -> [UserName, StartKey] + end, + end_key = case EndKey of + undefined -> [UserName, {}]; + EndKey -> [UserName, EndKey, {}] + end + }; +prefix_startkey_endkey(UserName, Args, rev) -> + #mrargs{start_key=StartKey, end_key=EndKey} = Args, + Args#mrargs { + end_key = case StartKey of + undefined -> [UserName]; + StartKey -> [UserName, StartKey] + end, + start_key = case EndKey of + undefined -> [UserName, {}]; + EndKey -> [UserName, EndKey, {}] + end + }. + + +changes_since_admin(SeqTree, StartSeq, Fun, Options, Acc) -> + Wrapper = fun(FullDocInfo, _Offset, Acc2) -> + DocInfo = case FullDocInfo of + #full_doc_info{} -> + couch_doc:to_doc_info(FullDocInfo); + #doc_info{} -> + FullDocInfo + end, + couch_log:info("~nDocInfo: ~p~n~n", [DocInfo]), + Fun(DocInfo, Acc2) + end, + {ok, _LastReduction, AccOut} = couch_btree:fold(SeqTree, + Wrapper, Acc, [{start_key, StartSeq + 1}] ++ Options), + {ok, AccOut}. + is_active_stream(Db, StreamEngine) -> couch_db_engine:is_active_stream(Db, StreamEngine). diff --git a/src/couch_mrview/src/couch_mrview.erl b/src/couch_mrview/src/couch_mrview.erl index 9469fafca..bea945eb2 100644 --- a/src/couch_mrview/src/couch_mrview.erl +++ b/src/couch_mrview/src/couch_mrview.erl @@ -242,7 +242,6 @@ query_all_docs_access(Db, Args0, Callback0, Acc) -> ]}} ]} }, - %% add startkey/endkey UserCtx = couch_db:get_user_ctx(Db), UserName = UserCtx#user_ctx.name, % TODO: add roles @@ -551,7 +550,14 @@ all_docs_fold(Db, #mrargs{direction=Dir, keys=Keys0}=Args, Callback, UAcc) -> map_fold(Db, View, Args, Callback, UAcc) -> - {ok, Total} = couch_mrview_util:get_row_count(View), + % couch_log:info("~n~n View: ~p~n", [View]), + {ok, Total} = case View#mrview.def of + <<"_access/by-id-map">> -> + couch_mrview_util:get_access_row_count(View, Args#mrargs.start_key); + _Else -> + couch_mrview_util:get_row_count(View) + end, + couch_log:info("~n~n Total: ~p~n", [Total]), Acc = #mracc{ db=Db, total_rows=Total, diff --git a/src/couch_mrview/src/couch_mrview_updater.erl b/src/couch_mrview/src/couch_mrview_updater.erl index 3383b49b6..6d2c2842e 100644 --- a/src/couch_mrview/src/couch_mrview_updater.erl +++ b/src/couch_mrview/src/couch_mrview_updater.erl @@ -196,7 +196,18 @@ map_docs(Parent, #mrst{db_name = DbName, idx_name = IdxName} = State0) -> {erlang:max(Seq, SeqAcc), [{Id, Seq, Rev, []} | Results]}; ({Id, Seq, Rev, Doc}, {SeqAcc, Results}) -> couch_stats:increment_counter([couchdb, mrview, map_doc]), - {ok, Res} = couch_query_servers:map_doc_raw(QServer, Doc), + % couch_log:info("~nIdxName: ~p, Doc: ~p~n~n", [IdxName, Doc]), + Doc0 = case IdxName of + <<"_design/_access">> -> + % splice in seq + {Props} = Doc#doc.body, + Doc#doc{ + body = {Props++[{<<"_seq">>, Seq}]} + }; + _Else -> + Doc + end, + {ok, Res} = couch_query_servers:map_doc_raw(QServer, Doc0), {erlang:max(Seq, SeqAcc), [{Id, Seq, Rev, Res} | Results]} end, FoldFun = fun(Docs, Acc) -> diff --git a/src/couch_mrview/src/couch_mrview_util.erl b/src/couch_mrview/src/couch_mrview_util.erl index 4fd82e0af..63d389d37 100644 --- a/src/couch_mrview/src/couch_mrview_util.erl +++ b/src/couch_mrview/src/couch_mrview_util.erl @@ -20,6 +20,7 @@ -export([index_file/2, compaction_file/2, open_file/1]). -export([delete_files/2, delete_index_file/2, delete_compaction_file/2]). -export([get_row_count/1, all_docs_reduce_to_count/1, reduce_to_count/1]). +-export([get_access_row_count/2]). -export([get_view_changes_count/1]). -export([all_docs_key_opts/1, all_docs_key_opts/2, key_opts/1, key_opts/2]). -export([fold/4, fold_reduce/4]). @@ -383,6 +384,11 @@ temp_view_to_ddoc({Props}) -> ]}, couch_doc:from_json_obj(DDoc). +get_access_row_count(#mrview{btree=Bt}, UserName) -> + couch_btree:full_reduce_with_options(Bt, [ + {start_key, UserName} + ]). + get_row_count(#mrview{btree=Bt}) -> Count = case couch_btree:full_reduce(Bt) of |