<commit_before>%  @copyright 2009-2010 Konrad-Zuse-Zentrum fuer Informationstechnik Berlin

%   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.

%%% @author <NAME> <<EMAIL>>
%%% @doc Vivaldi helper module for measuring latency between nodes.
%%% @end
%%% @version $Id$
-module(vivaldi_latency).
-author('<EMAIL>').
-vsn('$Id$').

-behaviour(gen_component).

-include("scalaris.hrl").

-export([on/2, init/1]).

-export([measure_latency/3, check_config/0]).

% state of the vivaldi loop
-type(state() ::
    {Owner::comm:erl_local_pid(),
     RemotePid::comm:mypid(),
     Token::{vivaldi:network_coordinate(), vivaldi:error()},
     Start::{MegaSecs::non_neg_integer(), Secs::non_neg_integer(), MicroSecs::non_neg_integer()} | unknown,
     Latencies::[vivaldi:latency()]}).

% accepted messages of vivaldi_latency processes
-type(message() :: {pong} | {start_ping} | {shutdown}).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Message Loop
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% @doc message handler
-spec on(Message::message(), State::state()) -> state().
on({pong}, {Owner, RemotePid, Token, Start, Latencies}) ->
    Stop = erlang:now(),
    NewLatencies = [timer:now_diff(Stop, Start) | Latencies],
    case length(NewLatencies) =:= config:read(vivaldi_count_measurements) of
        true ->
            comm:send_local(Owner, {update_vivaldi_coordinate, calc_latency(NewLatencies), Token}),
            kill;
        false ->
            comm:send_local_after(config:read(vivaldi_measurements_delay),
                              self(), {start_ping}),
            {Owner, RemotePid, Token, unknown, NewLatencies}
    end;

on({start_ping}, {Owner, RemotePid, Token, _, Latencies}) ->
    comm:send(RemotePid, {ping, comm:this()}),
    {Owner, RemotePid, Token, erlang:now(), Latencies};

on({shutdown}, _State) ->
    log:log(info, "shutdown vivaldi_latency due to timeout", []),
    kill.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Init
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec init({comm:erl_local_pid(), comm:mypid(), {vivaldi:network_coordinate(), vivaldi:error()}}) -> state().
init({Owner, RemotePid, Token}) ->
    %io:format("vivaldi_latency start ~n"),
    comm:send_local_after(config:read(vivaldi_latency_timeout), self(), {shutdown}),
    comm:send_local(self(), {start_ping}),
    {Owner, RemotePid, Token, unknown, []}.

-spec measure_latency(comm:mypid(), vivaldi:network_coordinate(), vivaldi:error()) -> {ok, pid()}.
measure_latency(RemotePid, RemoteCoordinate, RemoteConfidence) ->
    gen_component:start(?MODULE, {self(), RemotePid, {RemoteCoordinate, RemoteConfidence}}, []).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Helper functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec calc_latency([vivaldi:latency(),...]) -> number().
calc_latency(Latencies) ->
    mathlib:median(Latencies).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Miscellaneous
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% @doc Checks whether config parameters of the vivaldi_latency process exist
%%      and are valid.
-spec check_config() -> boolean().
check_config() ->
    config:is_integer(vivaldi_count_measurements) and<commit_msg>- kill vivaldi_latency processes if their vivaldi process dies<commit_after>%  @copyright 2009-2010 Konrad-Zuse-Zentrum fuer Informationstechnik Berlin

%   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.

%%% @author <NAME> <<EMAIL>>
%%% @doc Vivaldi helper module for measuring latency between nodes.
%%% @end
%%% @version $Id$
-module(vivaldi_latency).
-author('<EMAIL>').
-vsn('$Id$').

-behaviour(gen_component).

-include("scalaris.hrl").

-export([on/2, init/1]).

-export([measure_latency/3, check_config/0]).

% state of the vivaldi loop
-type(state() ::
    {Owner::comm:erl_local_pid(),
     RemotePid::comm:mypid(),
     Token::{vivaldi:network_coordinate(), vivaldi:error()},
     Start::{MegaSecs::non_neg_integer(), Secs::non_neg_integer(), MicroSecs::non_neg_integer()} | unknown,
     Latencies::[vivaldi:latency()]}).

% accepted messages of vivaldi_latency processes
-type(message() :: {pong} | {start_ping} | {shutdown}).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Message Loop
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% @doc message handler
-spec on(Message::message(), State::state()) -> state().
on({pong}, {Owner, RemotePid, Token, Start, Latencies}) ->
    Stop = erlang:now(),
    NewLatencies = [timer:now_diff(Stop, Start) | Latencies],
    case length(NewLatencies) =:= config:read(vivaldi_count_measurements) of
        true ->
            comm:send_local(Owner, {update_vivaldi_coordinate, calc_latency(NewLatencies), Token}),
            kill;
        false ->
            comm:send_local_after(config:read(vivaldi_measurements_delay),
                              self(), {start_ping}),
            {Owner, RemotePid, Token, unknown, NewLatencies}
    end;

on({start_ping}, {Owner, RemotePid, Token, _, Latencies}) ->
    comm:send(RemotePid, {ping, comm:this()}),
    {Owner, RemotePid, Token, erlang:now(), Latencies};

on({shutdown}, _State) ->
    log:log(info, "shutdown vivaldi_latency due to timeout", []),
    kill;

on({'DOWN', _MonitorRef, process, Owner, _Info}, {Owner, _RemotePid, _Token, _Start, _Latencies}) ->
    log:log(info, "shutdown vivaldi_latency due to vivaldi shutting down", []),
    kill.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Init
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec init({comm:erl_local_pid(), comm:mypid(), {vivaldi:network_coordinate(), vivaldi:error()}}) -> state().
init({Owner, RemotePid, Token}) ->
    %io:format("vivaldi_latency start ~n"),
    comm:send_local_after(config:read(vivaldi_latency_timeout), self(), {shutdown}),
    comm:send_local(self(), {start_ping}),
    erlang:monitor(process, Owner),
    {Owner, RemotePid, Token, unknown, []}.

-spec measure_latency(comm:mypid(), vivaldi:network_coordinate(), vivaldi:error()) -> {ok, pid()}.
measure_latency(RemotePid, RemoteCoordinate, RemoteConfidence) ->
    gen_component:start(?MODULE, {self(), RemotePid, {RemoteCoordinate, RemoteConfidence}}, []).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Helper functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec calc_latency([vivaldi:latency(),...]) -> number().
calc_latency(Latencies) ->
    mathlib:median(Latencies).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Miscellaneous
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% @doc Checks whether config parameters of the vivaldi_latency process exist
%%      and are valid.
-spec check_config() -> boolean().
check_config() ->
    config:is_integer(vivaldi_count_measurements) and
{'fraction_non_alphanumeric': 0.28328680665129263, 'fraction_numerical': 0.0038839665007889307, 'mean_word_length': 5.493301812450748, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7356410', 'n_tokens_mistral': 2432, 'n_tokens_neox': 2295, 'n_words': 546}