synrc / kvs

💿 KVS: NVMe Key-Value Store

Home Page:https://kvs.n2o.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

kvs:add new entry leads to error badarg

Spoowy opened this issue · comments

I have created a new table with mnesia.

mnesia:schema(text).
-- Properties for text table --- 
access_mode          -> read_write
active_replicas      -> [nonode@nohost]
all_nodes            -> [nonode@nohost]
arity                -> 4
attributes           -> [id,title,body]
checkpoints          -> []
commit_work          -> []
cookie               -> {{1514407290293049786,-576460752303422623,1},
                         nonode@nohost}
disc_copies          -> [nonode@nohost]
disc_only_copies     -> []
external_copies      -> []
frag_properties      -> []
index                -> []
index_info           -> {index,bag,[]}
load_by_force        -> false
load_node            -> nonode@nohost
load_order           -> 0
load_reason          -> local_only
local_content        -> false
majority             -> false
master_nodes         -> []
memory               -> 306
ram_copies           -> []
record_name          -> text
record_validation    -> {text,4,bag}
setorbag             -> bag
size                 -> 0
snmp                 -> []
storage_properties   -> []
storage_type         -> disc_copies
subscribers          -> []
user_properties      -> []
version              -> {{2,0},[]}
where_to_commit      -> [{nonode@nohost,disc_copies}]
where_to_read        -> nonode@nohost
where_to_wlock       -> {[nonode@nohost],false}
where_to_write       -> [nonode@nohost]
wild_pattern         -> {text,'_','_','_'}

Now I try to add an entry via

event(submit) ->
    Title = wf:q(title),
    Body = wf:q(body),
    kvs:add(#text{id=kvs:next_id("text",1),title=Title,body=Body});

but get

<<"g2gCaAVkAAJldmQABXNtb2tlZAAGc3VibWl0bQAAAAZzdWJtaXRkAAVldmVudGgDYgAABepiAAY3fGIAC32Q">>,
                                                                                        [{{"submit",<<"detail">>},[]},
                                             {title,"Test title"},
                                                                                          {body,"Test body"}]}
n2o_nitrogen:Catch: error:badarg
                                [{erlang,atom_to_list,[<<"Test title">>],undefined},
                                                                               {kvs,rname,1,383},
                                                                                                  {kvs,range,2,334},
              {kvs,get,3,261},
                               {kvs,ensure_link,2,103},
                                                        {n2o_nitrogen,html_events,2,73},
                                                                                         {n2o_nitrogen,info,3,35},
            {n2o_proto,push,5,44}]

And I am unable to insert a new record.

What am I missing?

Thank you!

Edit: It works well when I attemt to insert a new record with mnesia

insert () ->
	Record = #text{id=1,title="Test title",body="Test body"},
	F = fun() ->
		mnesia:write(Record)
	end,

	mnesia:transaction(F).

leads to

database_logic:insert().
{atomic,ok}

and

kvs:all(text).
[{text,1,"Test title","Test body"}]

The story is that KVS after 3.3 KVS tables support versioning. It means you can tune KVS to rip the table when number of objects exceed some limit (in this example is 5):

> kvs:id_seq(user).
30
> kvs:config(user).
[{interval,31,infinity,user6,user},
 {interval,25,30,user5,user},
 {interval,19,24,user4,user},
 {interval,13,18,user3,user},
 {interval,7,12,user2,user}]

So when you read from mnesia you see only 5 entries as they are stored in dedicated table.

>  mnesia:transaction(fun() ->  qlc:eval(mnesia:table(user4)) end).
{atomic,[{user4,19,[],feed,user,18,20,[],true,
                [],[],[],[],[],[],
                [],[],[],[],[],[],
                [],[],[],[]},
         {user4,20,[],feed,user,19,21,[],true,[],
                [],[],[],[],[],[],
                [],[],[],[],[],[],
                [],[],[]},
         {user4,21,[],feed,user,20,22,[],true,[],
                [],[],[],[],[],[],
                [],[],[],[],[],[],
                [],[],...},
         {user4,22,[],feed,user,21,23,[],true,[],
                [],[],[],[],[],[],
                [],[],[],[],[],[],
                [],...},
         {user4,23,[],feed,user,22,24,[],true,[],
                [],[],[],[],[],[],
                [],[],[],[],[],[],...},
         {user4,24,[],feed,user,23,25,[],true,[],
                [],[],[],[],[],[],
                [],[],[],[],[],...}]}

But when you perform KVS traversal it uses config table and switch tables during traversal.

> length(kvs:entries(kvs:get(feed,user),user,infinity)).
30

This approach is not new, something similar happens in SQL and BitTables. But the reason I'm describing this here is directly connected with your questions. From 3.3 index fields (which is second field in record after atomic record name) should be.

> [ kvs:add(#user{id=kvs:next_id("user",1)}) || _ <- lists:seq(1,30) ], ok.
ok

That means when you populating data, you can put in id field only integer. Because the table will selected on particular interval intersection (taken from list of intervals: kvs:config/1).

Hope this helps. It is clearly that you put <<"Test title">> as index for kvs:rname/1

[{erlang,atom_to_list,[<<"Test title">>],undefined}, {kvs,rname,1,383}

Could you please give me the KVS schema definition (not mnesia one) of your table?

Hi @5HT,
Thank you for your help!

This is all the code I wrote to create the table & schema:

-module(database_logic).

-include_lib("stdlib/include/qlc.hrl").

-export([init/0, insert/0]).

-record(text, {id=[], title=[], body=[]}).

init () ->
	mnesia:create_table(text, [{attributes, record_info(fields, text)},
		{type, bag},
		{disc_copies, [node()]}]).

Hope this helps.

This is not correct usage of KVS. The example of table creation you can see in n2o/samples.

Basically you need to plug KVS schema into sys.config file.

$ cat sys.config
[
 {kvs, [{dba,store_mnesia},
        {schema, [kvs_feed ]} ]}
].
-module(kvs_feed).
metainfo() ->  #schema{name=kvs,tables= core() }.

core()
  -> [ #table{name=config,fields=record_info(fields,config)},
       #table{name=log,container=true,fields=record_info(fields,log)},
       #table{name=operation,container=log,fields=record_info(fields,operation)},
       #table{name=id_seq,fields=record_info(fields,id_seq),keys=[thing]} ].

Just follow the examples. Did you try to read the README.md ? ;-)

Ah yes, I've edited that file before! (I've been somewhat irritated by the example users.hrl file that you find in the review project)
Let me try again, and come back with the results.

I have succeeded in creating the table according to kvs's way, however, I'm still receiving an error in the console, when trying to insert data:

n2o_nitrogen:Pickle: {pickle,<<"submit">>,
                                                                       <<"g2gCaAVkAAJldmQABXNtb2tlZAAGc3VibWl0bQAAAAZzdWJtaXRkAAVldmVudGgDYgAABepiAAZSgWIADjSt">>,
                                               [{{"submit",<<"detail">>},[]},
                                   {title,"weafwef"},
                                                                                   {body,"awefawef"}]}
n2o_nitrogen:Catch: error:badarg
                                [{erlang,atom_to_list,[<<"weafwef">>],undefined},
          {kvs,rname,1,383},
                             {kvs,range,2,334},
                                                {kvs,get,3,261},
                                                                 {kvs,ensure_link,2,103},

My table schema has been -record(text, {id=[], title=[], body=[]}).

6> kvs:id_seq(text).
47
7> kvs:config(text).
[]
8> mnesia:transaction(fun() ->  qlc:eval(mnesia:table(text)) end). 
{atomic,[]}
9> length(kvs:entries(kvs:get(feed,text),text,infinity)).
0
10> [ kvs:add(#text{id=kvs:next_id("text",1)}) || _ <- lists:seq(1,30) ], ok.
* 1: record text undefined

getting undefined for user as well, a table which comes installed with kvs

11> [ kvs:add(#user{id=kvs:next_id("user",1)}) || _ <- lists:seq(1,30) ], ok.
* 1: record user undefined

Does this help?

This is wrong.

-record(text, {id=[], title=[], body=[]}).

Please read this fucking manual :-) You need to include ?ITERATOR field package in order this machinery to work.

I'm not having such a hard time reading the manual, and I've restarted the whole process with the ?ITERATOR field (note, in subscription.hrl there is no ?ITERATOR field as well for some reason).

And yes! It works!

Hope this may be beneficial to other newcomers. Thanks again, @5HT.

When record has no ITER section it means you can't use kvs:add, but only kvs:put.