(#15) : add atomic apply function to modify value

This commit is contained in:
Dmitry Kolesnikov 2017-03-09 20:38:10 +02:00
parent 9f31083a2a
commit 4ca5b8caba
6 changed files with 92 additions and 25 deletions

View File

@ -1,9 +1,6 @@
install:
- make rebar3
script:
- make && make test
script: make && make test
language: erlang
otp_release:
- 18.2.1
- 17.5
- 19.2
- 18.3

View File

@ -4,7 +4,7 @@
## @description
## Makefile to build and release Erlang applications using standard development tools
##
## @version 0.11.5
## @version 0.11.8
#####################################################################
##
@ -22,9 +22,12 @@ TEST ?= ${APP}
S3 ?=
VMI ?= fogfish/erlang
NET ?= lo0
URL ?= undefined
URL ?= undefined
LATEST ?= latest
## rebar version (no spaces at end)
REBAR ?= 3.3.2
## root path to benchmark framework
BB = ../basho_bench
SSHENV = /tmp/ssh-agent.conf
@ -46,17 +49,17 @@ EFLAGS = \
## self-extracting bundle wrapper
BUNDLE_INIT = PREFIX=${PREFIX}\nREL=${PREFIX}/${REL}\nAPP=${APP}\nVSN=${VSN}\nLINE=`grep -a -n "BUNDLE:$$" $$0`\nmkdir -p $${REL}\ntail -n +$$(( $${LINE%%%%:*} + 1)) $$0 | gzip -vdc - | tar -C $${REL} -xvf - > /dev/null\n
BUNDLE_FREE = exit\nBUNDLE:\n
BUILDER = FROM ${VMI}\nRUN mkdir ${APP}\nCOPY . ${APP}/\nRUN cd ${APP} && make && make rel\n
BUILDER = FROM ${VMI}\nARG VERSION=\nRUN mkdir ${APP}\nCOPY . ${APP}/\nRUN cd ${APP} && make VSN=\x24{VERSION} && make rel VSN=\x24{VERSION}\n
CTRUN = \
-module(test). \
-export([run/1]). \
run(Spec) -> \
{ok, Test} = file:consult(Spec), \
case lists:keyfind(node, 1, Test) of \
false -> ct:run_test([{spec, Spec}]); \
-module(test). \
-export([run/1]). \
run(Spec) -> \
{ok, Test} = file:consult(Spec), \
Error = case lists:keyfind(node, 1, Test) of \
false -> element(2, ct:run_test([{spec, Spec}])); \
true -> ct_master:run(Spec) \
end, \
erlang:halt().
end, \
erlang:halt(Error).
#####################################################################
##
@ -119,7 +122,7 @@ relx.config: rel/relx.config.src
@cat $< | sed 's/release/release, {${APP}, "${VSN}"}/' > $@
else
${PKG}.tar.gz: _build/dockermake
@docker build --file=$< --force-rm=true --tag=build/${APP}:latest . ;\
@docker build --file=$< --force-rm=true --build-arg="VERSION=${VSN}" --tag=build/${APP}:latest . ;\
I=`docker create build/${APP}:latest` ;\
docker cp $$I:/${APP}/$@ $@ ;\
docker rm -f $$I ;\
@ -136,7 +139,7 @@ docker: rel/Dockerfile
--build-arg APP=${APP} \
--build-arg VSN=${VSN} \
-t ${URL}/${APP}:${VSN} -f $< .
docker tag -f ${URL}/${APP}:${VSN} ${URL}/${APP}:${LATEST}
docker tag ${URL}/${APP}:${VSN} ${URL}/${APP}:${LATEST}
@ -207,8 +210,9 @@ console: ${PKG}.tar.gz
##
#####################################################################
rebar3:
@curl -L -O https://s3.amazonaws.com/rebar3/rebar3 ; \
chmod ugo+x $@
@echo "==> install rebar (${REBAR})" ;\
curl -L -O --progress-bar https://github.com/erlang/rebar3/releases/download/${REBAR}/rebar3 ;\
chmod +x $@
.PHONY: test rel deps all pkg

View File

@ -1,7 +1,7 @@
{application, cache,
[
{description, "in-memory cache"},
{vsn, "2.1.1"},
{vsn, "2.2.0"},
{modules, []},
{registered, []},
{applications,[

View File

@ -62,7 +62,11 @@
remove/2,
remove/3,
remove_/2,
remove_/3
remove_/3,
apply/3,
apply/4,
apply_/4,
apply_/3
]).
%% extended cache i/o interface
-export([
@ -303,6 +307,36 @@ remove_(Cache, Key, true) ->
remove_(Cache, Key, false) ->
send(Cache, {remove, Key}).
%%
%% synchronous apply function to entity on cache
%% the function maps element, the new value is returned
%% the operation prolongs value ttl
-spec apply(cache(), key(), fun((_) -> _)) -> val() | undefined.
-spec apply(cache(), key(), fun((_) -> _), timeout()) -> val() | undefined.
apply(Cache, Key, Fun) ->
cache:apply(Cache, Key, Fun, ?CONFIG_TIMEOUT).
apply(Cache, Key, Fun, Timeout) ->
call(Cache, {apply, Key, Fun}, Timeout).
%%
%% asynchronous apply function to entity on cache
%% the function maps element, the new value is returned
%% the operation prolongs value ttl
-spec apply_(cache(), key(), fun((_) -> _)) -> ok | reference().
-spec apply_(cache(), key(), fun((_) -> _), true | false) -> ok | reference().
apply_(Cache, Key, Fun) ->
cache:apply_(Cache, Key, Fun, false).
apply_(Cache, Key, Fun, true) ->
cast(Cache, {apply, Key, Fun});
apply_(Cache, Key, Fun, false) ->
cast(Cache, {apply, Key, Fun}).
%%%----------------------------------------------------------------------------
%%%
%%% extended cache i/o interface

View File

@ -121,6 +121,10 @@ handle_call({ttl, Key}, _, State) ->
handle_call({remove, Key}, _, State) ->
{reply, ok, cache_remove(Key, State)};
handle_call({apply, Key, Fun}, _, State0) ->
{Result, State1} = cache_apply(Key, Fun, State0),
{reply, Result, State1};
handle_call({acc, Key, Val}, _, State0) ->
{Result, State1} = cache_acc(Key, Val, State0),
{reply, Result, State1};
@ -328,6 +332,16 @@ cache_remove(Key, #cache{name=_Name, heap=Heap}=State) ->
?DEBUG("cache ~p: remove ~p~n", [_Name, Key]),
State.
%%
%%
cache_apply(Key, Fun, State) ->
case Fun(cache_get(Key, State)) of
undefined ->
{undefined, State};
Val ->
{Val, cache_put(Key, Val, undefined, State)}
end.
%%
%% @todo: reduce one write
cache_acc(Key, Val, State)

View File

@ -42,7 +42,9 @@
lookup/1,
has/1,
remove/1,
remove_/1
remove_/1,
apply/1,
apply_/1
]).
%%
@ -77,7 +79,7 @@ groups() ->
{primitives, [parallel],
[lifecycle]},
{basic_io, [parallel],
[put, put_, get, lookup, has, remove, remove_]},
[put, put_, get, lookup, has, remove, remove_, apply, apply_]},
{extended_io, [parallel],
[acc, set, add, replace, append, append_, prepend, prepend_, delete]}
].
@ -169,6 +171,22 @@ remove_(_Config) ->
false= cache:has(Cache, key),
ok = cache:drop(Cache).
apply(_Config) ->
{ok, Cache} = cache:start_link([]),
val = cache:apply(Cache, key, fun(undefined) -> val end),
val = cache:get(Cache, key),
lav = cache:apply(Cache, key, fun(val) -> lav end),
lav = cache:get(Cache, key),
ok = cache:drop(Cache).
apply_(_Config) ->
{ok, Cache} = cache:start_link([]),
cache:apply_(Cache, key, fun(undefined) -> val end),
val = cache:get(Cache, key),
cache:apply_(Cache, key, fun(val) -> lav end),
lav = cache:get(Cache, key),
ok = cache:drop(Cache).
%%%----------------------------------------------------------------------------
%%%
%%% cache extended i/o