<commit_before>%% @author Couchbase <<EMAIL>>
%% @copyright 2011 Couchbase, Inc.
%%
%% 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(capi_set_view_manager).

-behaviour(gen_server).

-export([init/1, handle_call/3, handle_cast/2,
         handle_info/2, terminate/2, code_change/3]).

-export([start_link/1]).

%% API
-export([set_vbucket_states/3]).

-include("couch_db.hrl").
-include_lib("couch_set_view/include/couch_set_view.hrl").
-include("ns_common.hrl").

-record(state, {bucket :: bucket_name(),
                num_vbuckets :: non_neg_integer(),
                use_replica_index :: boolean(),
                master_db_watcher :: pid(),
                wanted_states :: [missing | active | replica],
                rebalance_states :: [rebalance_vbucket_state()],
                usable_vbuckets}).

set_vbucket_states(Bucket, WantedStates, RebalanceStates) ->
    gen_server:call(server(Bucket), {set_vbucket_states, WantedStates, RebalanceStates}, infinity).

-define(csv_call(Call, Args),
        %% hack to not introduce any variables in the caller environment
        ((fun () ->
                  %% we may want to downgrade it to ?views_debug at some point
                  ?views_info("~nCalling couch_set_view:~p(~p)", [Call, Args]),
                  try
                      {__Time, __Result} = timer:tc(couch_set_view, Call, Args),

                      ?views_info("~ncouch_set_view:~p(~p) returned ~p in ~bms",
                                  [Call, Args, __Result, __Time div 1000]),
                      __Result
                  catch
                      __T:__E ->
                          ?views_info("~ncouch_set_view:~p(~p) raised ~p:~p",
                                      [Call, Args, __T, __E]),

                          %% rethrowing the exception
                          __Stack = erlang:get_stacktrace(),
                          erlang:raise(__T, __E, __Stack)
                  end
          end)())).


compute_index_states(WantedStates, RebalanceStates, ExistingVBuckets) ->
    AllVBs = lists:seq(0, erlang:length(WantedStates)-1),
    Triples = lists:zip3(AllVBs,
                         WantedStates,
                         RebalanceStates),
    WantedPairs = lists:flatmap(
                    fun ({VBucket, WantedState, TmpState}) ->
                            case sets:is_element(VBucket, ExistingVBuckets) of
                                true ->
                                    case {WantedState, TmpState} of
                                        %% {replica, passive} ->
                                        %%     [{VBucket, replica}, {VBucket, passive}];
                                        {_, passive} ->
                                            [{VBucket, passive}];
                                        {active, _} ->
                                            [{VBucket, active}];
                                        {replica, _} ->
                                            [{VBucket, replica}];
                                        _ ->
                                            []
                                    end;
                                false ->
                                    []
                            end
                    end,
                    Triples),
    Active = [VB || {VB, active} <- WantedPairs],
    Passive = [VB || {VB, passive} <- WantedPairs],
    Replica = [VB || {VB, replica} <- WantedPairs],
    AllMain = Active ++ Passive,
    MainCleanup = AllVBs -- AllMain,
    ReplicaCleanup = ((AllVBs -- Replica) -- Active),
    PauseVBuckets = [VBucket
                     || {VBucket, WantedState, TmpState} <- Triples,
                        TmpState =:= paused,
                        sets:is_element(VBucket, ExistingVBuckets),
                        begin
                            active = WantedState,
                            true
                        end],
    UnpauseVBuckets = AllVBs -- PauseVBuckets,
    {Active, Passive, MainCleanup, Replica, ReplicaCleanup, PauseVBuckets, UnpauseVBuckets}.

get_usable_vbuckets_set(Bucket) ->
    PrefixLen = erlang:length(Bucket) + 1,
    sets:from_list(
      [list_to_integer(binary_to_list(VBucketName))
       || FullName <- ns_storage_conf:bucket_databases(Bucket),
          VBucketName <- [binary:part(FullName, PrefixLen, erlang:size(FullName) - PrefixLen)],
          VBucketName =/= <<"master">>]).

do_apply_vbucket_states(SetName, Active, Passive, MainCleanup, Replica, ReplicaCleanup, PauseVBuckets, UnpauseVBuckets, State) ->
    RVs = capi_ddoc_replication_srv:foreach_live_ddoc_id(<commit_msg>CBD-546 More efficient index state computation<commit_after>%% @author Couchbase <<EMAIL>>
%% @copyright 2011 Couchbase, Inc.
%%
%% 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(capi_set_view_manager).

-behaviour(gen_server).

-export([init/1, handle_call/3, handle_cast/2,
         handle_info/2, terminate/2, code_change/3]).

-export([start_link/1]).

%% API
-export([set_vbucket_states/3]).

-include("couch_db.hrl").
-include_lib("couch_set_view/include/couch_set_view.hrl").
-include("ns_common.hrl").

-record(state, {bucket :: bucket_name(),
                num_vbuckets :: non_neg_integer(),
                use_replica_index :: boolean(),
                master_db_watcher :: pid(),
                wanted_states :: [missing | active | replica],
                rebalance_states :: [rebalance_vbucket_state()],
                usable_vbuckets}).

set_vbucket_states(Bucket, WantedStates, RebalanceStates) ->
    gen_server:call(server(Bucket), {set_vbucket_states, WantedStates, RebalanceStates}, infinity).

-define(csv_call(Call, Args),
        %% hack to not introduce any variables in the caller environment
        ((fun () ->
                  %% we may want to downgrade it to ?views_debug at some point
                  ?views_info("~nCalling couch_set_view:~p(~p)", [Call, Args]),
                  try
                      {__Time, __Result} = timer:tc(couch_set_view, Call, Args),

                      ?views_info("~ncouch_set_view:~p(~p) returned ~p in ~bms",
                                  [Call, Args, __Result, __Time div 1000]),
                      __Result
                  catch
                      __T:__E ->
                          ?views_info("~ncouch_set_view:~p(~p) raised ~p:~p",
                                      [Call, Args, __T, __E]),

                          %% rethrowing the exception
                          __Stack = erlang:get_stacktrace(),
                          erlang:raise(__T, __E, __Stack)
                  end
          end)())).


compute_index_states(WantedStates, RebalanceStates, ExistingVBuckets) ->
    AllVBs = lists:seq(0, erlang:length(WantedStates)-1),
    Triples = lists:zip3(AllVBs,
                         WantedStates,
                         RebalanceStates),
    % Ensure Active, Passive and Replica are ordsets
    {Active, Passive, Replica} = lists:foldr(
                                   fun ({VBucket, WantedState, TmpState}, {AccActive, AccPassive, AccReplica}) ->
                                           case sets:is_element(VBucket, ExistingVBuckets) of
                                               true ->
                                                   case {WantedState, TmpState} of
                                                       %% {replica, passive} ->
                                                       %%     {AccActibe, [VBucket | AccPassive], [VBucket | AccReplica]};
                                                       {_, passive} ->
                                                           {AccActive, [VBucket | AccPassive], AccReplica};
                                                       {active, _} ->
                                                           {[VBucket | AccActive], AccPassive, AccReplica};
                                                       {replica, _} ->
                                                           {AccActive, AccPassive, [VBucket | AccReplica]};
                                                       _ ->
                                                           {AccActive, AccPassive, AccReplica}
                                                   end;
                                               false ->
                                                   {AccActive, AccPassive, AccReplica}
                                           end
                                   end,
                                   {[], [], []},
                                   Triples),
    AllMain = ordsets:union(Active, Passive),
    MainCleanup = ordsets:subtract(AllVBs, AllMain),
    ReplicaCleanup = ordsets:subtract(ordsets:subtract(AllVBs, Replica), Active),
    PauseVBuckets = [VBucket
                     || {VBucket, WantedState, TmpState} <- Triples,
                        TmpState =:= paused,
                        sets:is_element(VBucket, ExistingVBuckets),
                        begin
                            active = WantedState,
                            true
                        end],
    UnpauseVBuckets = ordsets:subtract(AllVBs, PauseVBuckets),
    {Active, Passive, MainCleanup, Replica, ReplicaCleanup, PauseVBuckets, UnpauseVBuckets}.

get_usable_vbuckets_set(Bucket) ->
    PrefixLen = erlang:length(Bucket) + 1,
    sets:from_list(
      [list_to_integer(binary_to_list(VBucketName))
       || FullName <- ns_storage_conf:bucket_databases(Bucket),
          VBucketName <- [binary:part(FullName, PrefixLen, erlang:size(FullName) - PrefixLen)],
          VBucketName =/= <<"master">>]).

do_apply_vbucket_states(SetName, Active, Passive, MainCleanup, Replica, ReplicaCleanup, PauseVBuckets, UnpauseVBuckets, State) ->
    RVs = capi_ddoc_replication_srv:foreach_live_ddoc_id(
{'fraction_non_alphanumeric': 0.1024721992463928, 'fraction_numerical': 0.0046870692031982355, 'mean_word_length': 1.5073732718894008, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 63, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7461183', 'n_tokens_mistral': 2913, 'n_tokens_neox': 2812, 'n_words': 634}