This is an automated email from the ASF dual-hosted git repository.

jan pushed a commit to branch rebase/access-2023
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 5f7c075cc01b26ccc1bfc76669c4d8648569f204
Author: Jan Lehnardt <[email protected]>
AuthorDate: Fri Jun 24 17:18:11 2022 +0200

    feat(access): add access query server
---
 src/couch/src/couch_access_native_proc.erl | 143 +++++++++++++++++++++++++++++
 src/couch/src/couch_proc_manager.erl       |   1 +
 2 files changed, 144 insertions(+)

diff --git a/src/couch/src/couch_access_native_proc.erl 
b/src/couch/src/couch_access_native_proc.erl
new file mode 100644
index 000000000..965b124de
--- /dev/null
+++ b/src/couch/src/couch_access_native_proc.erl
@@ -0,0 +1,143 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(couch_access_native_proc).
+-behavior(gen_server).
+
+
+-export([
+    start_link/0,
+    set_timeout/2,
+    prompt/2
+]).
+
+-export([
+    init/1,
+    terminate/2,
+    handle_call/3,
+    handle_cast/2,
+    handle_info/2,
+    code_change/3
+]).
+
+
+-record(st, {
+    indexes = [],
+    timeout = 5000 % TODO: make configurable
+}).
+
+start_link() ->
+    gen_server:start_link(?MODULE, [], []).
+
+
+set_timeout(Pid, TimeOut) when is_integer(TimeOut), TimeOut > 0 ->
+    gen_server:call(Pid, {set_timeout, TimeOut}).
+
+
+prompt(Pid, Data) ->
+    gen_server:call(Pid, {prompt, Data}).
+
+
+init(_) ->
+    {ok, #st{}}.
+
+
+terminate(_Reason, _St) ->
+    ok.
+
+
+handle_call({set_timeout, TimeOut}, _From, St) ->
+    {reply, ok, St#st{timeout=TimeOut}};
+
+handle_call({prompt, [<<"reset">>]}, _From, St) ->
+    {reply, true, St#st{indexes=[]}};
+
+handle_call({prompt, [<<"reset">>, _QueryConfig]}, _From, St) ->
+    {reply, true, St#st{indexes=[]}};
+
+handle_call({prompt, [<<"add_fun">>, IndexInfo]}, _From, St) ->
+    {reply, true, St};
+
+handle_call({prompt, [<<"map_doc">>, Doc]}, _From, St) ->
+    {reply, map_doc(St, mango_json:to_binary(Doc)), St};
+
+handle_call({prompt, [<<"reduce">>, _, _]}, _From, St) ->
+    {reply, null, St};
+
+handle_call({prompt, [<<"rereduce">>, _, _]}, _From, St) ->
+    {reply, null, St};
+
+handle_call({prompt, [<<"index_doc">>, Doc]}, _From, St) ->
+    {reply, [[]], St};
+
+handle_call(Msg, _From, St) ->
+    {stop, {invalid_call, Msg}, {invalid_call, Msg}, St}.
+
+handle_cast(garbage_collect, St) ->
+    erlang:garbage_collect(),
+    {noreply, St};
+
+handle_cast(Msg, St) ->
+    {stop, {invalid_cast, Msg}, St}.
+
+
+handle_info(Msg, St) ->
+    {stop, {invalid_info, Msg}, St}.
+
+
+code_change(_OldVsn, St, _Extra) ->
+    {ok, St}.
+
+% return value is an array of arrays, first dimension is the different indexes
+% [0] will be by-access-id // for this test, later we should make this 
by-access
+% -seq, since that one we will always need, and by-access-id can be opt-in.
+% the second dimension is the number of emit kv pairs:
+% [ // the return value
+%   [ // the first view
+%     ['k1', 'v1'], // the first k/v pair for the first view
+%     ['k2', 'v2']  // second, etc.
+%   ],
+%   [ // second view
+%     ['l1', 'w1'] // first k/v par in second view
+%   ]
+% ]
+% 
{"id":"account/bongel","key":"account/bongel","value":{"rev":"1-967a00dff5e02add41819138abb3284d"}},
+
+map_doc(_St, {Doc}) ->
+    case couch_util:get_value(<<"_access">>, Doc) of
+        undefined ->
+            [[],[]]; % do not index this 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),
+            Deleted = couch_util:get_value(<<"_deleted">>, Doc, false),
+            BodySp = couch_util:get_value(<<"_body_sp">>, Doc),
+            % by-access-id
+            ById = case Deleted of
+                false ->
+                    lists:map(fun(UserOrRole) -> [
+                        [[UserOrRole, Id], Rev]
+                    ] end, Access);
+                _True -> [[]]
+            end,
+
+            % by-access-seq
+            BySeq = lists:map(fun(UserOrRole) -> [
+                [[UserOrRole, Seq], [{rev, Rev}, {deleted, Deleted}, {body_sp, 
BodySp}]]
+            ] end, Access),
+            ById ++ BySeq;
+        Else ->
+            % TODO: no comprende: should not be needed once we implement
+            % _access field validation
+            [[],[]]
+    end.
diff --git a/src/couch/src/couch_proc_manager.erl 
b/src/couch/src/couch_proc_manager.erl
index 623734e6e..e3396ab15 100644
--- a/src/couch/src/couch_proc_manager.erl
+++ b/src/couch/src/couch_proc_manager.erl
@@ -144,6 +144,7 @@ init([]) ->
     ets:insert(?SERVERS, get_servers_from_env("COUCHDB_QUERY_SERVER_")),
     ets:insert(?SERVERS, get_servers_from_env("COUCHDB_NATIVE_QUERY_SERVER_")),
     ets:insert(?SERVERS, [{"QUERY", {mango_native_proc, start_link, []}}]),
+    ets:insert(?SERVERS, [{"_ACCESS", {couch_access_native_proc, start_link, 
[]}}]),
     maybe_configure_erlang_native_servers(),
 
     {ok, #state{

Reply via email to