<commit_before>%%%-------------------------------------------------------------------
%%% @author <NAME>
%%% @copyright (C) 2019 ACK CYFRONET AGH
%%% This software is released under the MIT license
%%% cited in 'LICENSE.txt'.
%%% @end
%%%-------------------------------------------------------------------
%%% @doc
%%% This module provides ets cache for temporary data.
%%% @end
%%%-------------------------------------------------------------------
-module(tmp_cache).
-author("<NAME>").

%% Basic cache API
-export([get_or_calculate/4, get/2, calculate_and_cache/4,
    calculate_and_cache/5, invalidate/1, get_timestamp/0]).
%% Cache management API
-export([init_group_manager/0, init_cache/2, init_group/2,
    terminate_cache/2, check_cache_size/1]).

-type cache() :: atom().
-type group() :: atom().
-type key() :: term().
-type value() :: term().
-type additional_info() :: cached | term().
-type callback() :: fun((term()) -> {ok, value(), additional_info()} | {error, term()}).
-type callback_args() :: term().
-type timestamp() :: non_neg_integer().
-type cache_options() :: #{size := non_neg_integer(), check_frequency := non_neg_integer(),
    group => group()}.
-type group_options() :: #{size := non_neg_integer(), check_frequency := non_neg_integer()}.
-type terminate_options() :: #{group => group()}.
-type check_options() :: #{size := non_neg_integer(), name := cache() | group(),
    check_frequency := non_neg_integer(), group => boolean()}.

-define(TIMER_MESSAGE(Options), {tmp_cache_timer, Options}).
-define(CACHE_MANAGER, tmp_cache_manager).
-define(INVALIDATION_TIMESTAMP_KEY(Cache), {invalidation_timestamp, Cache}).
-define(GROUP_MEMBERS_KEY(Group), {group_members, Group}).
-define(CREATE_CRITICAL_SECTION(Group), {tmp_cache_group_create, Group}).
-define(INVALIDATE_CRITICAL_SECTION(Cache), {tmp_cache_invalidation, Cache}).

%%%===================================================================
%%% Basic cache API
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% Gets value from cache. If it is not found - uses callback to calculate it.
%% Calculated value is cached.
%% @end
%%--------------------------------------------------------------------
-spec get_or_calculate(cache(), key(), callback(), callback_args()) ->
    {ok, value(), additional_info()} | {error, term()}.
get_or_calculate(Cache, Key, CalculateCallback, Args) ->
    case get(Cache, Key) of
        {ok, Value} ->
            {ok, Value, cached};
        {error, not_found} ->
            calculate_and_cache(Cache, Key, CalculateCallback, Args)
    end.

%%--------------------------------------------------------------------
%% @doc
%% Gets value from cache.
%% @end
%%--------------------------------------------------------------------
-spec get(cache(), key()) -> {ok, value()} | {error, not_found}.
get(Cache, Key) ->
    case ets:lookup(Cache, Key) of
        [{Key, Value, Timestamp, Timestamp}] ->
            {ok, Value};
        [{Key, Value, Timestamp, _}] ->
            case check_invalidation(Cache, Timestamp) of
                invalidated -> {error, not_found};
                _ -> {ok, Value}
            end;
        [] ->
            {error, not_found}
    end.

%%--------------------------------------------------------------------
%% @doc
%% @equiv calculate_and_cache(Cache, Key, CalculateCallback, Args, get_timestamp()).
%% @end
%%--------------------------------------------------------------------
-spec calculate_and_cache(cache(), key(), callback(), callback_args()) ->
    {ok, value(), additional_info()} | {error, term()}.
calculate_and_cache(Cache, Key, CalculateCallback, Args) ->
    calculate_and_cache(Cache, Key, CalculateCallback, Args, get_timestamp()).

%%--------------------------------------------------------------------
%% @doc
%% Calculates value and caches it if invalidation has not been done in parallel.
%% @end
%%--------------------------------------------------------------------
-spec calculate_and_cache(cache(), key(), callback(), callback_args(), timestamp()) ->
    {ok, value(), additional_info()} | {error, term()}.
calculate_and_cache(Cache, Key, CalculateCallback, Args, Timestamp) ->
    case CalculateCallback(Args) of
        {ok, Value, _CalculationInfo} = Ans ->
            ets:insert(Cache, {Key, Value, Timestamp, 0}),

            case check_invalidation(Cache, Timestamp) of
                invalidated -> ok; % value in cache will be invalid without counter update
                _ -> catch ets:update_counter(Cache, Key, {4, Timestamp})
            end,

            Ans;<commit_msg>VFS-5392 Update tmp cache<commit_after>%%%-------------------------------------------------------------------
%%% @author <NAME>
%%% @copyright (C) 2019 ACK CYFRONET AGH
%%% This software is released under the MIT license
%%% cited in 'LICENSE.txt'.
%%% @end
%%%-------------------------------------------------------------------
%%% @doc
%%% This module provides ets cache for temporary data.
%%% @end
%%%-------------------------------------------------------------------
-module(tmp_cache).
-author("<NAME>").

%% Basic cache API
-export([get_or_calculate/4, get/2, calculate_and_cache/4,
    calculate_and_cache/5, invalidate/1, get_timestamp/0]).
%% Cache management API
-export([init_group_manager/0, init_cache/2, init_group/2,
    terminate_cache/2, check_cache_size/1]).

-type cache() :: atom().
-type group() :: atom().
-type key() :: term().
-type value() :: term().
-type additional_info() :: cached | term().
-type callback() :: fun((term()) -> {ok, value(), additional_info()} | {error, term()}).
-type callback_args() :: term().
-type timestamp() :: non_neg_integer().
-type cache_options() :: #{size := non_neg_integer(), check_frequency := non_neg_integer(),
    group => group()}.
-type group_options() :: #{size := non_neg_integer(), check_frequency := non_neg_integer()}.
-type terminate_options() :: #{group => group()}.
-type check_options() :: #{size := non_neg_integer(), name := cache() | group(),
    check_frequency := non_neg_integer(), group => boolean()}.

-define(TIMER_MESSAGE(Options), {tmp_cache_timer, Options}).
-define(CACHE_MANAGER, tmp_cache_manager).
-define(INVALIDATION_TIMESTAMP_KEY(Cache), {invalidation_timestamp, Cache}).
-define(GROUP_MEMBERS_KEY(Group), {group_members, Group}).
-define(CREATE_CRITICAL_SECTION(Group), {tmp_cache_group_create, Group}).
-define(INVALIDATE_CRITICAL_SECTION(Cache), {tmp_cache_invalidation, Cache}).

%%%===================================================================
%%% Basic cache API
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% Gets value from cache. If it is not found - uses callback to calculate it.
%% Calculated value is cached.
%% @end
%%--------------------------------------------------------------------
-spec get_or_calculate(cache(), key(), callback(), callback_args()) ->
    {ok, value(), additional_info()} | {error, term()}.
get_or_calculate(Cache, Key, CalculateCallback, Args) ->
    case get(Cache, Key) of
        {ok, Value} ->
            {ok, Value, cached};
        {error, not_found} ->
            calculate_and_cache(Cache, Key, CalculateCallback, Args)
    end.

%%--------------------------------------------------------------------
%% @doc
%% Gets value from cache.
%% @end
%%--------------------------------------------------------------------
-spec get(cache(), key()) -> {ok, value()} | {error, not_found}.
get(Cache, Key) ->
    case ets:lookup(Cache, Key) of
        [{Key, Value, Timestamp, Timestamp}] ->
            {ok, Value};
        [{Key, Value, Timestamp, _}] ->
            case check_invalidation(Cache, Timestamp) of
                invalidated -> {error, not_found};
                _ -> {ok, Value}
            end;
        [] ->
            {error, not_found}
    end.

%%--------------------------------------------------------------------
%% @doc
%% @equiv calculate_and_cache(Cache, Key, CalculateCallback, Args, get_timestamp()).
%% @end
%%--------------------------------------------------------------------
-spec calculate_and_cache(cache(), key(), callback(), callback_args()) ->
    {ok, value(), additional_info()} | {error, term()}.
calculate_and_cache(Cache, Key, CalculateCallback, Args) ->
    calculate_and_cache(Cache, Key, CalculateCallback, Args, get_timestamp()).

%%--------------------------------------------------------------------
%% @doc
%% Calculates value and caches it if invalidation has not been done in parallel.
%% @end
%%--------------------------------------------------------------------
-spec calculate_and_cache(cache(), key(), callback(), callback_args(), timestamp()) ->
    {ok, value(), additional_info()} | {error, term()}.
calculate_and_cache(Cache, Key, CalculateCallback, Args, Timestamp) ->
    % TODO - rozwazyc sekcje krytyczna zeby nie bylo potem sprawdzania invalidacji
    case CalculateCallback(Args) of
        {ok, Value, _CalculationInfo} = Ans ->
            ets:insert(Cache, {Key, Value, Timestamp, 0}),

            case check_invalidation(Cache, Timestamp) of
                invalidated -> ok; % value in cache will be invalid without counter update
                _ -> catch ets:update_counter(Cache, Key, {4, Timestamp, Timestamp, Timestamp})
            end,

            Ans;
{'fraction_non_alphanumeric': 0.3262133869091678, 'fraction_numerical': 0.004018187585915195, 'mean_word_length': 2.054909560723514, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '2734614', 'n_tokens_mistral': 2496, 'n_tokens_neox': 2454, 'n_words': 638}