Browse Source

version 5.10

Namdak Tonpa 6 years ago
parent
commit
f25e4238a5
7 changed files with 32 additions and 400 deletions
  1. 1 1
      LICENSE
  2. 2 55
      README.md
  3. 1 0
      rebar.config
  4. 1 1
      src/kvs.app.src
  5. 9 9
      src/kvs.erl
  6. 0 317
      src/kvs_double.erl
  7. 18 17
      src/kvs_stream.erl

+ 1 - 1
LICENSE

@@ -1,4 +1,4 @@
-Copyright (c) 2014 Maxim Sokhatsky <maxim@synrc.com>
+Copyright (c) 2014-2018 Maxim Sokhatsky <maxim@synrc.com>
 
 Permission to use, copy, modify, and/or distribute this software for any
 purpose with or without fee is hereby granted, provided that the above

+ 2 - 55
README.md

@@ -1,12 +1,12 @@
 KVS: Erlang Abstract Term Database
 ==================================
 
-Online Presentation: http://slid.es/maximsokhatsky/kvs
+[![Build Status](https://travis-ci.org/synrc/kvs.svg?branch=master)](https://travis-ci.org/synrc/kvs)
 
 Features
 --------
 
-* Polymorphic Tuples
+* Polymorphic Tuples aka Extensible Records
 * Managing Linked-Lists
 * Various Backends Support: Mnesia, Riak, KAI, Redis, MongoDB
 * Sequential Consistency via Feed Server
@@ -312,59 +312,6 @@ dispatch({rollback,_,_,Tx}, #state{})  ->
 
 See: https://github.com/spawnproc/cr
 
-### Feeds Server
-
-Here is Consumer behavior handlers of KVS FEEDS supervised processes
-
-```erlang
-handle_notice(  [kvs_feed,user,Owner,entry,Eid,add],
-                [#entry{feed_id=Fid}=Entry],
-                #state{feeds=Feeds}) ->
-
-                case lists:keyfind(Fid,2, S#state.feeds) of
-                    false -> skip;
-                    {_,_} -> add_entry(Eid,Fid,Entry) end,
-                {noreply, S};
-
-handle_notice(  [kvs_feed,user,Owner,entry,{Eid,FeedName},edit],
-                [#entry{feed_id=Fid}=Entry],
-                #state{feeds=Feeds}) ->
-
-                case lists:keyfind(FeedName,1,Feeds) of
-                    false -> skip;
-                    {_,Fid}-> update_entry(Eid,Fid,Entry) end,
-                {noreply, S};
-
-handle_notice(  [kvs_feed,user,Owner,entry,Eid,edit],
-                [#entry{feed_id=Fid}=Entry],
-                #state{feeds=Feeds}) ->
-
-                case lists:keyfind(Fid, 2, Feeds) of
-                    false -> skip;
-                    {_,_} -> update_entry(Eid,Fid,Entry) end,
-                {noreply, S};
-```
-
-Here is the private implementation
-
-```erlang
-add_entry(Eid,Fid,Entry) ->
-    E = Entry#entry{id = {Eid, Fid}, entry_id = Eid, feeds=[comments]},
-    Added = case kvs:add(E) of {error, Err} -> {error,Err}; {ok, En} -> En end,
-    msg:notify([kvs_feed, entry, {Eid, Fid}, added], [Added]).
-
-update_entry(Eid,Fid,Entry) -> ...
-```
-
-And that is how you can call it
-
-```erlang
-kvs:notify([kvs_feed, user, "maxim@synrc.com", entry, Eid, add],
-           [#entry{}]).
-```
-
-See: https://github.com/synrc/feeds
-
 Credits
 -------
 

+ 1 - 0
rebar.config

@@ -1,3 +1,4 @@
 {lib_dirs, [".."]}.
+{erl_opts, [nowarn_export_all]}.
 {deps_dir, ["deps"]}.
 {deps,[]}.

+ 1 - 1
src/kvs.app.src

@@ -1,6 +1,6 @@
 {application, kvs,
    [{description, "KVS Abstract Term Database"},
-    {vsn, "1"},
+    {vsn, "5.10"},
     {registered, []},
     {applications, [kernel,stdlib,mnesia]},
     {mod, { kvs_app, []}},

+ 9 - 9
src/kvs.erl

@@ -108,7 +108,7 @@ ensure_link(Record, #kvs{mod=_Store}=Driver) ->
             NC1 = list_to_tuple([CName | lists:map(fun(_) -> [] end,Fields)]),
             NC2 = setelement(#container.id, NC1, Cid),
             NC3 = setelement(#container.rear, NC2, Id),
-            NC4 = setelement(#container.count, NC3, 0);
+            setelement(#container.count, NC3, 0);
         _Error -> error end,
 
     case Container of
@@ -160,7 +160,7 @@ link(Record,#kvs{mod=_Store}=Driver) ->
         {error, not_found} -> {error, not_found} end.
 
 %add(Record, #kvs{mod=store_mnesia}=Driver) when is_tuple(Record) -> store_mnesia:add(Record);
-add(Record, #kvs{mod=Store}=Driver) when is_tuple(Record) -> append(Record,Driver).
+add(Record, #kvs{}=Driver) when is_tuple(Record) -> append(Record,Driver).
 
 append(Record, #kvs{mod=_Store}=Driver) when is_tuple(Record) ->
     Id = element(#iterator.id, Record),
@@ -212,15 +212,15 @@ delete(Tab, Key, #kvs{mod=Mod}) ->
          [] -> Mod:delete(Tab, Key);
           T -> Mod:delete(T, Key) end.
 
-remove(Record, Id,#kvs{mod=store_mnesia}=Driver) -> store_mnesia:remove(Record,Id);
-remove(Record, Id,#kvs{mod=Store}=Driver) -> takeoff(Record,Id,Driver).
+remove(Record, Id,#kvs{mod=store_mnesia}) -> store_mnesia:remove(Record,Id);
+remove(Record, Id,#kvs{}=Driver) -> takeoff(Record,Id,Driver).
 
-takeoff(Record,Id,#kvs{mod=Mod}=Driver) ->
+takeoff(Record,Id,#kvs{}=Driver) ->
     case get(Record,Id) of
          {error, not_found} -> kvs:error(?MODULE,"Can't remove ~p~n",[{Record,Id}]);
                      {ok,R} -> do_remove(R,Driver) end.
 
-do_remove(E,#kvs{mod=Mod}=Driver) ->
+do_remove(E,#kvs{}=Driver) ->
     case get(element(#iterator.container,E),element(#iterator.feed_id,E)) of
          {ok, C} -> unlink(C,E,Driver);
                _ -> skip end,
@@ -237,7 +237,7 @@ fold(Fun,Acc,Table,Start,Count,Direction,Driver) ->
          {ok, R} -> Prev = element(Direction, R),
                     Count1 = case Count of C when is_integer(C) -> C - 1; _-> Count end,
                     fold(Fun, Fun(R,Acc), Table, Prev, Count1, Direction, Driver);
-           Error -> %kvs:error(?MODULE,"Error: ~p~n",[Error]),
+           _Error -> %kvs:error(?MODULE,"Error: ~p~n",[Error]),
                     Acc end catch _:_ -> Acc end.
 
 entries({error,_},_,_,_)      -> [];
@@ -345,7 +345,7 @@ find([Range|T],RecordName,Id) ->
           [] -> find(T,RecordName,Id);
           Range -> Range end.
 
-lookup(#block{left=Left,right=Right,name=Name}=I,Id) when Id =< Right, Id >= Left -> I;
+lookup(#block{left=Left,right=Right}=I,Id) when Id =< Right, Id >= Left -> I;
 lookup(#block{},_) -> [].
 
 rotate_new() ->
@@ -369,7 +369,7 @@ rotate(Table) ->
 load_partitions()  ->
     [ case kvs:get(config,Table) of
         {ok,{config,_,List}} -> application:set_env(kvs,Table,List);
-        Else -> ok end || {table,Table} <- kvs:dir() ].
+        _Else -> ok end || {table,Table} <- kvs:dir() ].
 
 rnorm(Tag,List) -> [ setelement(1,R,Tag) || R <- List ].
 rlist(Table)   -> [ N || #block{name=N} <- kvs:config(Table) ]++[Table].

+ 0 - 317
src/kvs_double.erl

@@ -1,317 +0,0 @@
--module(kvs_double).
--description('KVS STREAM').
--copyrihgt('Synrc Research Center').
--author('Maxim Sokhatsky').
--license('ISC').
--include("kvs.hrl").
--export([ new/0, top/1, bot/1, take/1, drop/1, load/1, save/1, down/1, up/1, cons/1, snoc/1,
-          check/0, seek/1, rewind/1, next/1, prev/1, add/1, remove/1 ]).
-
-% n2o stream protocol
-
-info(#cur{id=I,status=load}=C,R,S) -> {reply, {bert, kvs_stream:load(I)},   R, S};
-info(#cur{status=Method}   =C,R,S) -> {reply, {bert, kvs_stream:Method(C)}, R, S};
-info(                       C,R,S) -> {reply, {unknown,C},                  R, S}.
-
-% section: kvs_stream prelude
-
-se(X,Y,Z) -> setelement(X,Y,Z).
-set(X,Y,Z) -> setelement(X,Z,Y).
-e(X,Y) -> element(X,Y).
-cv(R,V) -> se(#cur.writer,R, V).
-cb(R,V) -> se(#cur.bot,   R, V).
-ct(R,V) -> se(#cur.top,   R, V).
-cl(R,V) -> se(#cur.left,  R, V).
-cr(R,V) -> se(#cur.right, R, V).
-cd(R,V) -> se(#cur.dir,   R, V).
-sn(M,T) -> se(#iter.next, M, T).
-sp(M,T) -> se(#iter.prev, M, T).
-si(M,T) -> se(#iter.id, M, T).
-el(X,T) -> e(X, T).
-tab(T) -> e(1, T).
-et(T) -> e(#cur.top, T).
-eb(T) -> e(#cur.bot, T).
-id(T) -> e(#iter.id, T).
-en(T) -> e(#iter.next, T).
-ep(T) -> e(#iter.prev, T).
-dir(0) -> top;
-dir(1) -> bot.
-acc(0) -> prev;
-acc(1) -> next.
-
-% section: next, prev
-
-next (#cur{reader=[]}=C) -> {error,[]};
-next (#cur{reader=B} =C) -> pos(kvs:get(tab(B),en(B)),C,right(C)).
-prev (#cur{reader=[]}=C) -> {error,[]};
-prev (#cur{reader=B} =C) -> pos(kvs:get(tab(B),ep(B)),C,left(C)).
-
-left (#cur{left=0,right=0,dir=D}) -> swap(D,{0,  0});
-left (#cur{left=0,right=R,dir=D}) -> swap(D,{0,  R});
-left (#cur{left=L,right=R,dir=D}) -> swap(D,{L-1,R+1}).
-right(#cur{left=0,right=0,dir=D}) -> swap(D,{0,  0});
-right(#cur{left=L,right=0,dir=D}) -> swap(D,{L,  0});
-right(#cur{left=L,right=R,dir=D}) -> swap(D,{L+1,R-1}).
-
-swap(1,{L,R}) -> {R,L};
-swap(0,{L,R}) -> {L,R}.
-
-pos({ok,R},C,{X,Y}) -> C#cur{reader=R,left=X,right=Y};
-pos({error,X},C,_)  -> {error,X}.
-
-% section: take, drop
-
-drop(#cur{dir=D,reader=P,args=N}=C) -> drop(acc(D),N,C,C).
-take(#cur{dir=D,reader=P,args=N}=C) -> take(acc(D),N,C,C,[]).
-
-take(_,_,{error,C},C2,R) -> C2#cur{args=lists:flatten(R)};
-take(_,0,C,C2,R) -> C2#cur{args=lists:flatten(R)};
-take(A,N,#cur{reader=B}=C,C2,R) -> take(A,N-1,?MODULE:A(C),C2,[B|R]).
-
-drop(_,_,{error,C},C2) -> C2;
-drop(_,0,C,C2) -> C2;
-drop(A,N,#cur{reader=B}=C,C2) -> drop(A,N-1,?MODULE:A(C),C2).
-
-% rewind (moves writer)
-
-rewind(#cur{writer=[]}=C) -> {error,[]};
-rewind(#cur{dir=D,top=T,bot=B,writer=V}=C) ->
-    C#cur{writer=id(kvs:get(tab(V),select(D,T,B)))}.
-
-select(0,T,B) -> T;
-select(1,T,B) -> B;
-select(P,P,X) -> X;
-select(P,N,X) -> N.
-
-% seek (moves reader)
-
-seek(#cur{writer=[]}=C) -> C;
-seek(#cur{bot=X,reader=P,dir=0}=C) when element(2,P) == X -> C;
-seek(#cur{top=X,reader=P,dir=1}=C) when element(2,P) == X -> C;
-seek(#cur{top=T,bot=B,left=L,right=R,dir=0,reader=P}=C) ->
-     C#cur{reader=id(kvs:get(tab(P),B)),left=0,right=L+R};
-seek(#cur{top=T,bot=B,left=L,right=R,dir=1,reader=P}=C) ->
-     C#cur{reader=id(kvs:get(tab(P),T)),left=L+R,right=0}.
-
-% new, save, load, up, down, top, bot
-
-new   () -> #cur{id=kvs:next_id(cur,1)}.
-save (C) -> NC = C#cur{args=[]}, kvs:put(NC), NC.
-load (K) -> case kvs:get(cur,K) of {ok,C} -> C; E -> E end.
-up   (C) -> C#cur{dir=0}.
-down (C) -> C#cur{dir=1}.
-top  (C) -> seek(down(C)).
-bot  (C) -> seek(up(C)).
-
-% add
-
-add(#cur{dir=D,args=M}=C) when element(2,M) == [] ->
-    add(dir(D),si(M,kvs:next_id(tab(M),1)),C);
-add(#cur{dir=D,args=M}=C) ->
-    add(dir(D),M,C).
-
-inc(#cur{left=L,right=R,dir=D}) -> swap(D,{L+1,R}).
-
-cons(#cur{args=M}=C) -> add(top,M,C).
-snoc(#cur{args=M}=C) -> add(bot,M,C).
-
-add(bot,M,#cur{bot=T,writer=[]}=C) ->
-    Id=id(M), N=sn(sp(M,T),[]), kvs:put(N),
-    C#cur{writer=N,reader=N,bot=Id,top=Id};
-
-add(top,M,#cur{top=B,writer=[]}=C) ->
-    Id=id(M), N=sp(sn(M,B),[]), kvs:put(N),
-    C#cur{writer=N,reader=N,top=Id,bot=Id};
-
-add(top,M,#cur{top=T, writer=V}=C) when element(2,V) /= T ->
-    add(top, M, rewind(C));
-
-add(bot,M,#cur{bot=B, writer=V}=C) when element(2,V) /= B ->
-    add(bot, M, rewind(C));
-
-add(bot,M,#cur{bot=T,writer=V,reader=P}=C) ->
-    Id=id(M), H=sn(sp(M,T),[]), N=sn(V,Id), kvs:put([H,N]),
-    {L,R} = inc(C), C#cur{reader=select(V,P,N),writer=H,bot=Id,left=L,right=R};
-
-add(top,M,#cur{top=B,writer=V,reader=P}=C) ->
-    Id=id(M), H=sp(sn(M,B),[]), N=sp(V,Id), kvs:put([H,N]),
-    {L,R} = inc(C), C#cur{reader=select(V,P,N),writer=H,top=Id,left=L,right=R}.
-
-% remove
-
-remove(#cur{writer=[]}=C) -> {error,val};
-remove(#cur{writer=B,reader=X,args=I}=C) ->
-    {ok,R}=kvs:get(tab(B),I), kvs:delete(tab(B),I),
-    join(I,[fix(tab(B),X)||X<-[ep(R),en(R)]],C).
-
-fix(M,[])     -> [];
-fix(M,X)      -> fix(kvs:get(M,X)).
-fix({ok,O})   -> O;
-fix(_)        -> [].
-
-dec(#cur{left=0,right=0,dir=D}) -> swap(D,{0,  0});
-dec(#cur{left=L,right=0,dir=D}) -> swap(D,{L-1,0});
-dec(#cur{left=0,right=R,dir=D}) -> swap(D,{0,R-1});
-dec(#cur{left=L,right=R,dir=D}) -> swap(D,{L-1,R}).
-
-m(I,_,I,_,I,L,R,P,V) -> {R,R};
-m(_,I,I,_,I,L,R,P,V) -> {R,L};
-m(I,_,_,I,I,L,R,P,V) -> {L,R};
-m(_,I,_,I,I,L,R,P,V) -> {L,L};
-m(I,_,_,_,I,L,R,P,V) -> {sn(V,id(R)),P};
-m(_,I,_,_,I,L,R,P,V) -> {sp(V,id(R)),P};
-m(_,_,I,_,I,L,R,P,V) -> {V,sn(P,id(L))};
-m(_,_,_,I,I,L,R,P,V) -> {V,sp(P,id(L))};
-m(_,_,_,_,I,L,R,P,V) -> {V,P}.
-
-join(I,[[],[]],C) ->
-    {X,Y} = dec(C),
-    C#cur{top=[],bot=[],writer=[],reader=[],left=X,right=Y};
-
-join(I,[[], R],#cur{reader=P,writer=V}=Cur) ->
-    N=sp(R,[]), kvs:put(N), {X,Y} = dec(Cur),
-    {NV,NP} = m(en(V),ep(V),en(P),ep(P),I,[],N,P,V),
-    Cur#cur{top=id(N), writer=NV, reader=NP, left=X, right=Y};
-
-join(I,[L, []],#cur{reader=P,writer=V}=Cur) ->
-    N=sn(L,[]), kvs:put(N), {X,Y} = dec(Cur),
-    {NV,NP} = m(en(V),ep(V),en(P),ep(P),I,N,[],P,V),
-    Cur#cur{bot=id(N), writer=NV, left=X, reader=NP, right=Y};
-
-join(I,[L,  R],#cur{reader=P,writer=V}=Cur) ->
-    N=sp(R,id(L)), M=sn(L,id(R)), kvs:put([N,M]), {X,Y} = dec(Cur),
-    {NV,NP} = m(en(V),ep(V),en(P),ep(P),I,N,M,P,V),
-    Cur#cur{left=X, reader=NP, writer=NV, right=Y}.
-
-% TESTS
-
-check() ->
-    te_remove(),
-    test1(),
-    test2(),
-    drop(),
-    create_destroy(),
-    next_prev_duality(),
-    test_sides(),
-    rewind(),
-    ok.
-
-rewind() ->
-    Empty = {'user2',[],[],[],[],[],[],[],[]},
-    C = #cur{top=T,bot=B,left=L,right=R,writer=V,reader=P} =
-    save(add(set(#cur.args,Empty,down(
-         add(set(#cur.args,Empty,up(
-         add(set(#cur.args,Empty,down(
-         add(set(#cur.args,Empty,down(
-         add(set(#cur.args,Empty,up(new())))))))))))))))),
-    PId = id(P),
-    VId = id(V),
-    B = VId,
-    PId = B - 4,
-    ok.
-
-test_sides() ->
-    Empty = {'user2',[],[],[],[],[],[],[],[]},
-    #cur{top=T,bot=B,left=L,right=R,writer=V,reader=P} =
-    save(
-    add(set(#cur.args,Empty,up(
-    add(set(#cur.args,Empty,down(
-    add(set(#cur.args,Empty,new()))))))))),
-    PId = id(P),
-    VId = id(V),
-    VId = T,
-    PId = B - 1,
-    1 = T - B,
-    L = R = 1.
-
-next_prev_duality() ->
-    Cur = new(),
-    [A,B,C] = [ kvs:next_id('user2',1) || _ <- lists:seq(1,3) ],
-    R = save(
-        add(set(#cur.args,{'user2',A,[],[],[],[],[],[],[]},
-        add(set(#cur.args,{'user2',B,[],[],[],[],[],[],[]},
-        add(set(#cur.args,{'user2',C,[],[],[],[],[],[],[]},
-        Cur))))))),
-    X = load(id(Cur)),
-    X = next(
-        next(
-        prev(
-        prev(X)))).
-
-test2() ->
-    Cur = new(),
-    [A,B,C,D] = [ kvs:next_id('user2',1) || _ <- lists:seq(1,4) ],
-    #cur{args=[]} = take(
-         up(
-         bot(
-         remove(set(#cur.args,A,
-         remove(set(#cur.args,B,
-         remove(set(#cur.args,C,
-         remove(set(#cur.args,D,
-         add(set(#cur.args,{'user2',A,[],[],[],[],[],[],[]},
-         add(set(#cur.args,{'user2',B,[],[],[],[],[],[],[]},
-         add(set(#cur.args,{'user2',C,[],[],[],[],[],[],[]},
-         add(set(#cur.args,{'user2',D,[],[],[],[],[],[],[]},
-         up(Cur#cur{args=-1})))))))))))))))))))).
-
-create_destroy() ->
-    Cur = new(),
-    [A,B,C,D] = [ kvs:next_id('user2',1)
-             || _ <- lists:seq(1,4) ],
-    #cur{args=[]} = take(
-         remove(set(#cur.args,B,
-         remove(set(#cur.args,D,
-         remove(set(#cur.args,A,
-         remove(set(#cur.args,C,
-         add(set(#cur.args,{'user2',D,[],[],[],[],[],[],[]},
-         add(set(#cur.args,{'user2',C,[],[],[],[],[],[],[]},
-         add(set(#cur.args,{'user2',B,[],[],[],[],[],[],[]},
-         add(set(#cur.args,{'user2',A,[],[],[],[],[],[],[]},
-         up(new())))))))))))))))))).
-
-test1() ->
-    [A,B,C,D] = [ kvs:next_id('user2',1) || _ <- lists:seq(1,4) ],
-    R  = save(
-         add(set(#cur.args,{'user2',D,[],[],[],[],[],[],[]},
-         add(set(#cur.args,{'user2',C,[],[],[],[],[],[],[]},
-         add(set(#cur.args,{'user2',B,[],[],[],[],[],[],[]},
-         add(set(#cur.args,{'user2',A,[],[],[],[],[],[],[]},
-         new() ))))))))),
-    #cur{args=X}  = take(top(R#cur{args=-1})),
-    #cur{args=Y}  = take(bot(R#cur{args=-1})),
-    X  = lists:reverse(Y),
-    L  = length(X).
-
-drop() ->
-    #cur{id=S}=save(new()),
-    P = {'user2',[],[],[],[],[],[],[],[]},
-    S1 = save(
-         add(set(#cur.args,P,
-         add(set(#cur.args,P,
-         add(set(#cur.args,P,
-         add(set(#cur.args,P,
-         load(S)))))))))),
-    S2= drop(S1#cur{args=2}),
-    4 = length(e(#cur.args,take(S2#cur{args=-1}))),
-    4 = length(e(#cur.args,take(S1#cur{args=-1}))),
-    ok.
-
-te_remove() ->
-    #cur{id=S}=save(new()),
-    P = {'user2',[],[],[],[],[],[],[],[]},
-    S1 = save(
-         add(set(#cur.args,P,
-         add(set(#cur.args,P,
-         add(set(#cur.args,P,
-         add(set(#cur.args,P,
-         load(S)))))))))),
-
-    Res = e(#cur.args,take(S1#cur{args=-1})),
-    4 = length(Res),
-    S2 = save(top(S1)),
-    S3 = save(remove(S2#cur{args=S2#cur.top-1})),
-    #cur{args=List} = take(top(S3#cur{args=-1})),
-    #cur{args=Rev}  = take(bot(S3#cur{args=-1})),
-    List = lists:reverse(Rev),
-    3 = length(List),
-    {S3,List}.

+ 18 - 17
src/kvs_stream.erl

@@ -5,6 +5,7 @@
 -license('ISC').
 -include_lib("kvs/include/kvs.hrl").
 -compile(export_all).
+-include_lib("stdlib/include/assert.hrl").
 
 % section: kvs_stream prelude
 
@@ -40,33 +41,33 @@ acc(1)  -> prev.
 top(#reader{feed=F}=C) -> w(kvs:get(writer,F),top,C).
 bot(#reader{feed=F}=C) -> w(kvs:get(writer,F),bot,C).
 
-next(#reader{feed=F,cache=[]}=C)          -> {error,empty};
-next(#reader{feed=F,cache={T,R},pos=P}=C) -> n(kvs:get(T,R),C,P+1).
-prev(#reader{feed=F,cache=[]}=C)          -> {error,empty};
-prev(#reader{feed=F,cache={T,R},pos=P}=C) -> p(kvs:get(T,R),C,P-1).
+next(#reader{cache=[]}) -> {error,empty};
+next(#reader{cache={T,R},pos=P}=C) -> n(kvs:get(T,R),C,P+1).
+prev(#reader{cache=[]}) -> {error,empty};
+prev(#reader{cache={T,R},pos=P}=C) -> p(kvs:get(T,R),C,P-1).
 
 n({ok,R},C,P)    -> r(kvs:get(tab(R),en(R)),C,P);
-n({error,X},C,_) -> {error,X}.
+n({error,X},_,_) -> {error,X}.
 p({ok,R},C,P)    -> r(kvs:get(tab(R),ep(R)),C,P);
-p({error,X},C,_) -> {error,X}.
+p({error,X},_,_) -> {error,X}.
 r({ok,R},C,P)    -> C#reader{cache={tab(R),id(R)},pos=P};
-r({error,X},C,_) -> {error,X}.
+r({error,X},_,_) -> {error,X}.
 w({ok,#writer{first=B}},bot,C)            -> C#reader{cache={tab(B),id(B)},pos=1};
-w({ok,#writer{cache=B,count=Size}}=X,top,C) -> C#reader{cache={tab(B),id(B)},pos=Size};
-w({error,X},_,C)                          -> {error,X}.
+w({ok,#writer{cache=B,count=Size}},top,C) -> C#reader{cache={tab(B),id(B)},pos=Size};
+w({error,X},_,_)                          -> {error,X}.
 
 % section: take, drop
 
 drop(#reader{dir=D,cache=B,args=N,pos=P}=C) -> drop(acc(D),N,C,C,P,B).
 take(#reader{dir=D,cache=B,args=N,pos=P}=C) -> take(acc(D),N,C,C,[],P,B).
 
-take(_,_,{error,C},C2,R,P,B) -> C2#reader{args=lists:flatten(R),pos=P,cache=B};
-take(_,0,C,C2,R,P,B)         -> C2#reader{args=lists:flatten(R),pos=P,cache=B};
+take(_,_,{error,_},C2,R,P,B) -> C2#reader{args=lists:flatten(R),pos=P,cache=B};
+take(_,0,_,C2,R,P,B)         -> C2#reader{args=lists:flatten(R),pos=P,cache=B};
 take(A,N,#reader{cache={T,I},pos=P}=C,C2,R,_,_) ->
     take(A,N-1,?MODULE:A(C),C2,[element(2,kvs:get(T,I))|R],P,{T,I}).
 
-drop(_,_,{error,C},C2,P,B)     -> C2#reader{pos=P,cache=B};
-drop(_,0,C,C2,P,B)             -> C2#reader{pos=P,cache=B};
+drop(_,_,{error,_},C2,P,B)     -> C2#reader{pos=P,cache=B};
+drop(_,0,_,C2,P,B)             -> C2#reader{pos=P,cache=B};
 drop(A,N,#reader{cache=B,pos=P}=C,C2,_,_) ->
     drop(A,N-1,?MODULE:A(C),C2,P,B).
 
@@ -90,7 +91,7 @@ add(#writer{args=M}=C) when element(2,M) == [] -> add(si(M,kvs:next_id(tab(M),1)
 add(#writer{args=M}=C) -> add(M,C).
 
 add(M,#writer{cache=[]}=C) ->
-    Id=id(M), N=sp(sn(M,[]),[]), kvs:put(N),
+    _Id=id(M), N=sp(sn(M,[]),[]), kvs:put(N),
     C#writer{cache=N,count=1,first=N};
 
 add(M,#writer{cache=V,count=S}=C) ->
@@ -104,7 +105,7 @@ check() -> test1().
 test1() ->
     Id  = {p2p,1,2},
     X   = 5,
-    W   = kvs_stream:save(kvs_stream:writer(Id)),
+    _W   = kvs_stream:save(kvs_stream:writer(Id)),
     #reader{id=R1} = kvs_stream:save(kvs_stream:reader(Id)),
     #reader{id=R2} = kvs_stream:save(kvs_stream:reader(Id)),
     [ kvs_stream:save(
@@ -115,5 +116,5 @@ test1() ->
     Top = kvs_stream:top(kvs_stream:load_reader(R2)),
     #reader{args=F} = kvs_stream:take(Bot#reader{args=20,dir=0}),
     #reader{args=B} = kvs_stream:take(Top#reader{args=20,dir=1}),
-    X == length(F),
-    F == lists:reverse(B).
+    ?assertMatch(X,length(F)),
+    ?assertMatch(F,lists:reverse(B)).