Commits

Anonymous committed bb1e593 Merge

0.10.0 release.

Comments (0)

Files changed (23)

 *.exe
 *.beam
 *.pyc
-test/log*
+test/log*
+*/yatce.app
 3bc29aec8443201838ec3b94ffbb6ba04aed26fa 0.9
 0000000000000000000000000000000000000000 0.9
 5a84010fdd69f0f5e7afb7f7c36e4f88cc761688 0.9
+25bb547e8ee8b5333137b8d92a841dccbf63b4e5 0.10
+2009-11-20  UENISHI Kota  <kuenishi@gmail.com>
+
+	* src/yatce.erl (db): API changed;
+	 yatce:newdb/2 -> yatce:db/2
+	this API change aims at confirmation for users that API has changed.
+	versioned as 0.10.0 for new feature - application-ized.
+
 2009-09-10  UENISHI Kota  <kuenishi@gmail.com>
 
 	* src/yatce.erl (newdb): open options enabled.
 	@echo "  make clean (make c) - clean all"
 
 b: build
-build: so beam
+build: so beam app
 
 so:
 	cd c_src && make
 beam:
 	cd src && erl -make -smp -Wall
 
+app:
+	sed -e 's;%VSN%;$(YATCE_VSN);' ./src/yatce.app.src > ./ebin/yatce.app
+
 ##$(TARGET): # c_src/Makefile
 ##	cd c_src && make
 
 test: build
 	@echo "testing in ${ROOT} .."
 	@mkdir -p test/log
-	sh ${RUN_TEST_CMD}  -dir ${ROOT}/test -logdir ${ROOT}/test/log \
-	  -I ${ROOT}/include -I ${ROOT}/src \
+	sh ${RUN_TEST_CMD} -dir ${ROOT}/test -logdir ${ROOT}/test/log \
+	  -I ${ROOT}/include -I ${ROOT}/src  \
 	  -cover ${ROOT}/test/yatce.coverspec  -pa ${ROOT}/ebin
 	@echo "automated test done. see test/log/index.html."
 
 	@echo "performance test with ${NUM_THREAD} concurrency for ${NUM_REPEAT} reputation: "
 #	@erl +Ktrue +A 8 -pa ${ROOT}/ebin -noshell -eval 'performer:start("c_src", ${NUM_THREAD}, ${NUM_REPEAT}).' -s init stop
 	erl +Ktrue +A 8 -pa ${ROOT}/ebin -noshell -eval "supervisor:start_link({local,perf_sup},perf_sup, ['/tmp/sup_test.tch',  ${NUM_THREAD}])." #-s init stop
-##    {ok,Pid}=supervisor:start({local, ?SERVER_NAME}, perf_sup,['/tmp/sup_test.tch', 1]),
+##    {ok,Pid}=supervisor:start({local, ?SERVER_NAME}, perf_sup,['/tmp/sup_test.tch', 1]),
 INCLUDE=$(EI_INCLUDE) $(ERL_DRIVER_H) $(TC_INCLUDE)
 
 all: $(TARGET) raw_performer 
+	@cp $(TARGET) ../priv/lib
 
 .c.o:
 	$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
 %% $ escript tctest.erl <path to libyatce.so>
 tcadb_test()->
 %    io:format("~p~n", [YatceLib]),
-    T = yatce:newdb('/tmp/test.tch', []),                 % tcadbnew()
+    T = yatce:db('/tmp/test.tch', []),                 % tcadbnew()
     {ok,opened} =T:open(),                                % tcadbopen()
     str_str(T),
     str_int(T),
 
 iter()->
     List=[{"key","value"}, {"afkls;d", 23536}, {"afd;sj", <<"q34refdv]90i">>}],
-    T=yatce:newdb('/tmp/test2_iter.tch', []),
+    T=yatce:db('/tmp/test2_iter.tch', []),
     {ok,opened}=T:open(),
     {ok,init}=T:iterinit(),
     ok = insert_all(T,List),
 	    ng
     end.
 
-main(Argv)->
-    [YatceLib|_] = Argv,
+main(_Argv)->
+%    [YatceLib|_] = Argv,
     code:add_path("./ebin"),
-    {ok, _Pid} = yatce:start([{libdir, YatceLib}]), % initialize the library
-    {ok, all_passed} = yatce:test(),
+    ok=application:start(yatce),
+%    erlang:display( application:get_env(yatce, libdir) ),
+%    {ok, _Pid} = yatce:start([{libdir, YatceLib}]), % initialize the library
+    {ok, all_passed} = yatce_server:test(),
     tcadb_test(),
     iter(),
-    yatce:stop().
+%    yatce:stop().
+    application:stop(yatce).
     
 group: tools
-short: Yet Another Tokyo Cabinet-Erlang binding
+short: Yet Another TokyoCabinet-Erlang binding

priv/lib/dummy

Empty file added.
 
 -spec open() -> {ok, opened} | {error, tcadbopen_failure}.
 open() when is_atom( TableName )->
-    yatce:decode( port_control( Port, ?YATCE_OPEN, yatce:encode(TableName) ) ).
+    yatce_server:decode( port_control( Port, ?YATCE_OPEN, yatce_server:encode(TableName) ) ).
 
 -spec close() -> {ok, closed} | {error, tcadbclose_failure}.
 close() when is_atom( TableName )->
-    yatce:decode( port_control( Port, ?YATCE_CLOSE, yatce:encode(TableName)) ).
+    yatce_server:decode( port_control( Port, ?YATCE_CLOSE, yatce_server:encode(TableName)) ).
 
 -spec put(key(), value()) -> {ok, inserted} | {error,  'tcadbput(keep)_failure'}.
 put(Key,Value) ->
-    yatce:decode( port_control( Port, ?YATCE_PUT, yatce:encode({TableName, Key, Value}) ) ).
+    yatce_server:decode( port_control( Port, ?YATCE_PUT, yatce_server:encode({TableName, Key, Value}) ) ).
 
 -spec putkeep(key(), value()) -> {ok, inserted} | {error,  'tcadbput(keep)_failure'}.
 putkeep(Key,Value)->
-    yatce:decode( port_control( Port, ?YATCE_PKEEP, yatce:encode({TableName, Key, Value}) ) ).
+    yatce_server:decode( port_control( Port, ?YATCE_PKEEP, yatce_server:encode({TableName, Key, Value}) ) ).
 
 %% -spec putcat(key(), value()) -> {ok, appended} | {error,  'tcadbput(keep)_failure'}.
 %% putcat(_Key,_Value)->    
 
 -spec out(key()) -> {ok, inserted} | {error,  'tcadbout_failure'}.
 out(Key)->
-    yatce:decode( port_control( Port, ?YATCE_OUT, yatce:encode({TableName, Key} ) )).
+    yatce_server:decode( port_control( Port, ?YATCE_OUT, yatce_server:encode({TableName, Key} ) )).
 
 -spec get( key() )-> {ok, value()} | {error, record_doesnt_exist}.
 get(Key)->
-    yatce:decode( port_control( Port, ?YATCE_GET, yatce:encode( {TableName, Key}) )).
+    yatce_server:decode( port_control( Port, ?YATCE_GET, yatce_server:encode( {TableName, Key}) )).
 
 -spec iterinit() -> {ok, init} | {error, failed}.
 iterinit() when is_atom(TableName)->
-    yatce:decode( port_control( Port, ?YATCE_ITERINIT, yatce:encode(TableName) )).
+    yatce_server:decode( port_control( Port, ?YATCE_ITERINIT, yatce_server:encode(TableName) )).
 
 -spec iternext() -> {ok, value()} | {error, end_of_data}.
 iternext() when is_atom(TableName)->
-    yatce:decode( port_control( Port, ?YATCE_ITERNEXT, yatce:encode(TableName) )).
+    yatce_server:decode( port_control( Port, ?YATCE_ITERNEXT, yatce_server:encode(TableName) )).
 
 addint(_Key,_Int)->
     {error, not_yet_supported}.
 
 -spec sync() -> {ok, sync} | {error, not_synced}.
 sync()->
-    yatce:decode( port_control( Port, ?YATCE_SYNC, yatce:encode(TableName) )).
+    yatce_server:decode( port_control( Port, ?YATCE_SYNC, yatce_server:encode(TableName) )).
 
 optimize(_)->
     {error, not_yet_supported}.
 
 -spec vanish() -> {ok, vanished} | {error, not_vanished}.
 vanish() when is_atom(TableName) ->
-    yatce:decode( port_control( Port, ?YATCE_VANISH, yatce:encode(TableName) )).
+    yatce_server:decode( port_control( Port, ?YATCE_VANISH, yatce_server:encode(TableName) )).
 
 copy()->
     {error, not_yet_supported}.
 
 -spec rnum() -> non_neg_integer().
 rnum() when is_atom(TableName)->
-    yatce:decode( port_control( Port, ?YATCE_RNUM, yatce:encode(TableName) )).
+    yatce_server:decode( port_control( Port, ?YATCE_RNUM, yatce_server:encode(TableName) )).
 
 -spec size() -> non_neg_integer().
 size() when is_atom(TableName)->
-    yatce:decode( port_control( Port, ?YATCE_SIZE, yatce:encode(TableName) )).
+    yatce_server:decode( port_control( Port, ?YATCE_SIZE, yatce_server:encode(TableName) )).
 
 me()-> THIS.
 

src/yatce.app.src

+{application, yatce,
+ [{description, "Yatce - Yet Another TokyoCabinet-Erlang binding."},
+  {vsn, "%VSN%"},
+  {modules,    [ yatce, yatce_sup, yatce_server ]},
+  {registered, [ yatce, yatce_sup, yatce_server ]},
+  {applications, [kernel, stdlib]},
+  {env, [
+   	 {prefix, "yatce"},
+	 {libdir, "./c_src"}
+	 ]},
+  {mod, {yatce, []}}
+  ]
+}.
 %% -*- coding: utf-8 -*-
 -module(yatce).
 -author('kuenishi+tc@gmail.com').
+-behaviour(application).
 
+-export([start/2, stop/1]).
+-export([start/0, stop/0, db/2]).
 -include("tokyocabinet.hrl").
--import(random).
 
--record(yatce, {port, shared_lib}).
-
--export([
-	 start/0,	 start/1,
-	 start_link/0,	 start_link/1,
-	 stop/0,
-	 newdb/2,
-	 encode/1,	 decode/1,
-	 test/0
-	 ]).
-
--behaviour(gen_server).
-
--export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2 ]).
-
--spec newdb( tablename(), [option()] ) -> tcadb().
-newdb(TableName, Options)->    % TODO: parse Options here and create a real tablename
-    {ok, Port} = get_port(),
-    FullTableName = generate_open_argv(TableName, Options),
-    tcadb:new(FullTableName, Options, Port ).
-
--spec start()->{ok, pid()}.
-start()->   start([{libdir, "c_src"}]).
-
--spec start( list() )->{ok, pid()}.
-start(Options)->
-%    case gen_server:start({local, ?MODULE},?MODULE, Options, [{debug, [trace,log,statistics]}]) of
-    case gen_server:start({local, ?MODULE},?MODULE, Options, []) of
-	{ok, Pid}->
-	    timer:sleep(500),
-	    {ok, Pid};
-	{error, {already_started, Pid}} ->
-	    timer:sleep(500),
-	    {ok, Pid};
+start(_Type, _RestartType)->
+    LibPath = code:priv_dir(?MODULE)++ "/lib",
+%    io:format("~p ~p: ~p~n", [?FILE, ?LINE, LibPath]),
+    case erl_ddll:try_load(LibPath, ?DYLIB_NAME, []) of
+	{ok, _Status} -> 
+	    supervisor:start_link( {local, yatce_sup}, yatce_sup, [] );
+        {error, already_loaded} ->
+	    supervisor:start_link( {local, yatce_sup}, yatce_sup, [] );
+	{error, Reason}->
+	    io:format("you have to set exactly where libyatce.so exists: ~p , ~p~n",
+		      [ erl_ddll:format_error(Reason), LibPath ]),
+	    {error, Reason};
 	Other ->
-	    Other
-    end.
-
--spec start_link()->{ok, pid()}.
-start_link()->   start_link([{libdir, "c_src"}]).
-
--spec start_link( list() )->{ok, pid()}.
-start_link(Options)->
-    case gen_server:start_link({local, ?MODULE},?MODULE, [Options], [{debug, [trace,log,statistics]}]) of
-	{ok, Pid}->
-	    timer:sleep(500),
-	    {ok, Pid};
-	{error, {already_started, Pid}} ->
-	    timer:sleep(500),
-	    {ok, Pid};
-	Other ->
-	    Other
-    end.
-
-
--spec stop() -> {stop, atom(), ok, any()}.
-stop()->
-    Res = gen_server:call(?MODULE, stop),
-    Res.
-
-%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%%
-%%                     FUNCTIONS FOR INTERNAL USE                    %%
--spec encode( term() ) -> binary().
-encode(Object)->
-    term_to_binary(Object).
-    
-%% C drivers can't return in raw binary (don't know why; 
-%% set_port_control_flags doesn't work, causes error.
--spec decode( list() ) -> term().
-decode(Object) when is_list(Object) ->
-    binary_to_term( list_to_binary(Object) ).
-
-
-%% Create a new TCADB instance. you can use this TCADB concurrently.
-%% Take care when closing the instance.
-%% http://tokyocabinet.sourceforge.net/spex-ja.html#tcadbapi
-%% `name' specifies the name of the database. 
-%% If it is "*", the database will be an on-memory hash database. If it is "+", the database will be an on-memory tree database. If its suffix is ".tch", the database will be a hash database. If its suffix is ".tcb", the database will be a B+ tree database. If its suffix is ".tcf", the database will be a fixed-length database. If its suffix is ".tct", the database will be a table database. Otherwise, this function fails. 
-%% Tuning parameters can trail the name, separated by "#". 
-%% Each parameter is composed of the name and the value, separated by "=". 
-%% - On-memory hash database supports "bnum", "capnum", and "capsiz". 
-%% - On-memory tree database supports "capnum" and "capsiz". 
-%% - Hash database supports "mode", "bnum", "apow", "fpow", "opts", "rcnum", "xmsiz", and "dfunit". 
-%% - B+ tree database supports "mode", "lmemb", "nmemb", "bnum", "apow", "fpow", "opts", "lcnum", "ncnum", "xmsiz", and "dfunit".
-%% - Fixed-length database supports "mode", "width", and "limsiz". 
-%% - Table database supports "mode", "bnum", "apow", "fpow", "opts", "rcnum", "lcnum", "ncnum", "xmsiz", "dfunit", and "idx".
-%% Tuning parameters
-%% + The tuning parameter "capnum" specifies the capacity number of records. 
-%% "capsiz" specifies the capacity size of using memory. Records spilled the capacity are removed by the storing order. 
-%% "mode" can contain "w" of writer, "r" of reader, "c" of creating, "t" of truncating, "e" of no locking, and "f" of non-blocking lock. The default mode is relevant to "wc". 
-%% "opts" can contains "l" of large option, "d" of Deflate option, "b" of BZIP2 option, and "t" of TCBS option. 
-%% "idx" specifies the column name of an index and its type separated by ":". 
-%% For example, "casket.tch#bnum=1000000#opts=ld" means that the name of the database file is "casket.tch", and the bucket number is 1000000, and the options are large and Deflate.
--type option_key() :: bnum | capnum | capsiz | mode | bnum | apow | fpow | opts | rcnum | xmsiz | dfunit .
--type option_value() :: pos_integer() | list() .
--type open_option() :: { option_key(), option_value() }.
--spec generate_open_argv( atom() | list() , [ open_option() ] )-> atom().
-generate_open_argv(TableName, []) when is_atom( TableName ) ->
-    TableName;
-
-generate_open_argv(TableName, Options) when is_atom( TableName ) ->
-    generate_open_argv( atom_to_list(TableName), Options );
-
-generate_open_argv(TableName, []) when is_list( TableName ) ->
-    list_to_atom(TableName);
-
-generate_open_argv(TableName, [{Key,Value}|Options]) when is_list( TableName ) and is_integer(Value)->
-    StrKey = atom_to_list(Key),
-    generate_open_argv( TableName++"#"++StrKey++"="++io_lib:write(Value), Options );
-generate_open_argv(TableName, [{Key,Value}|Options]) when is_list( TableName ) and is_list(Value)->
-    StrKey = atom_to_list(Key),
-    generate_open_argv( TableName++"#"++StrKey++"="++Value, Options).
-
-%% -spec generate_open_argv_( list(), list() )-> atom().
-%% generate_open_argv_(TableName, Options) when is_list(TableName) ->
-%%     TableName.
-
--spec test() -> {ok,all_passed}|{error, test_failed}.
-test()->
-    gen_server:call(?MODULE, test).
-
--spec get_port() -> {ok, port()} | {error, any()}.
-get_port()->
-    case gen_server:call(?MODULE, get_port) of
-	Port when is_port(Port)->
-	    {ok, Port};
-	Other ->
+	    io:format("~p~n", [Other]),
 	    {error, Other}
     end.
 
--spec init( [ option() ] ) -> ok | {error, erl_ddll_error_desc()}.
-init(Options)->
-    {ok,CurrentDirectory} = get_libdir(Options),
-    LibPath = CurrentDirectory,
+stop(_State)->
     SharedLib = ?DYLIB_NAME,
-%%    case erl_ddll:load_driver(LibPath, SharedLib) of
-    case erl_ddll:try_load(LibPath, SharedLib, []) of
-        {ok, _Status} -> 
-	    Port = open_port({spawn_driver, SharedLib}, [binary]),
-	    {ok, #yatce{port=Port,shared_lib=SharedLib}};
-        {error, already_loaded} ->
-	    Port = open_port({spawn_driver, SharedLib}, [binary]),
-	    {ok, #yatce{port=Port,shared_lib=SharedLib}};
-	{error, Reason}->
-	    io:format("you have to set exactly where libyatce.so exists: ~p , ~p~n",
-		      [ erl_ddll:format_error(Reason), file:get_cwd() ]),
-	    {stop, Reason};
-	Other->
-	    {stop, Other}
+%    io:format("~p (~p, ~p) terminating.~n", [?MODULE, self(), State]),
+    case erl_ddll:unload(SharedLib) of
+	{error, ErrorDesc}->
+	    io:format("can't unload ~p: ~p~n", [ SharedLib, erl_ddll:format_error(ErrorDesc) ]);
+	ok ->
+	    ok
     end.
 
-handle_call(get_port, _From, State)->
-    {reply, State#yatce.port, State};
-handle_call(stop, _From, State) ->
-    Port = State#yatce.port,
-    Port ! {self(), close},
-    receive 
-	{Port , closed}->
-	    {stop, normal, ok, State};
-	_ -> 
-	    {stop, cant_close_port, ok, State}
-    after 5000->
-	    {stop, cant_close_port, ok, State}
-    end;
-handle_call(test, _From, State)->
-    Port = State#yatce.port,
-    Result=decode( port_control(Port, ?YATCE_TEST, list_to_binary([]) ) ),
-    {reply, Result, State};
-    
-handle_call(_, _From, State) ->    {noreply, State}.
+start()-> application:start(?MODULE).    
+stop()->  application:stop(?MODULE).    
 
+-spec db( tablename(), [option()] ) -> tcadb().
+db(TableName, Options)->
+    yatce_server:newdb(TableName,Options).
 
-handle_cast(_,State)->    {noreply, State}.
-
-handle_info(_,State)->    {noreply, State}.
-
-terminate(Reason,State)-> 
-    io:format("~p (~p, ~p) terminating.~n", [?MODULE, self(), State]),
-    case erl_ddll:unload(State#yatce.shared_lib) of
-	{error, ErrorDesc}->
-	    io:format("can't unload ~p: ~p~n", [ State#yatce.shared_lib, erl_ddll:format_error(ErrorDesc) ]);
-	ok ->
-	    ok
-    end,
-    {shutdown, Reason}.
-    
-code_change(_,_,State)->
-    {ok, State}.
-
-get_libdir([])->
-    file:get_cwd();
-get_libdir([OneConfigPair|OtherConfigs])->
-    case OneConfigPair of
-	{libdir, LibDir}->
-	    {ok, LibDir};
-	_Other ->
-	    get_libdir( OtherConfigs )
-    end.
-

src/yatce_server.erl

+%% -*- coding: utf-8 -*-
+-module(yatce_server).
+-author('kuenishi+tc@gmail.com').
+
+-include("tokyocabinet.hrl").
+-import(random).
+
+-record(yatce, {port, shared_lib}).
+
+-export([
+	 start/0,	 start/1,
+	 start_link/0,	 start_link/1,
+	 stop/0,
+	 newdb/2,
+	 encode/1,	 decode/1,
+	 test/0
+	 ]).
+
+-behaviour(gen_server).
+
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2 ]).
+
+-spec newdb( tablename(), [option()] ) -> tcadb().
+newdb(TableName, Options)->
+    {ok, Port} = get_port(),
+    FullTableName = generate_open_argv(TableName, Options),
+    tcadb:new(FullTableName, Options, Port ).
+
+-spec start()->{ok, pid()}.
+start()->   start([{libdir, "c_src"}]).
+
+-spec start( list() )->{ok, pid()}.
+start(Options)->
+%    case gen_server:start({local, ?MODULE},?MODULE, Options, [{debug, [trace,log,statistics]}]) of
+    case gen_server:start({local, ?MODULE},?MODULE, Options, []) of
+	{ok, Pid}->
+	    timer:sleep(500),
+	    {ok, Pid};
+	{error, {already_started, Pid}} ->
+	    timer:sleep(500),
+	    {ok, Pid};
+	Other ->
+	    Other
+    end.
+
+-spec start_link()->{ok, pid()}.
+start_link()->   start_link([{libdir, "c_src"}]).
+
+-spec start_link( list() )->{ok, pid()}.
+start_link(Options)->
+    case gen_server:start_link({local, ?MODULE},?MODULE, [Options], [{debug, [trace,log,statistics]}]) of
+	{ok, Pid}->
+	    timer:sleep(500),
+	    {ok, Pid};
+	{error, {already_started, Pid}} ->
+	    timer:sleep(500),
+	    {ok, Pid};
+	Other ->
+	    Other
+    end.
+
+
+-spec stop() -> {stop, atom(), ok, any()}.
+stop()->
+    Res = gen_server:call(?MODULE, stop),
+    Res.
+
+%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%%
+%%                     FUNCTIONS FOR INTERNAL USE                    %%
+-spec encode( term() ) -> binary().
+encode(Object)->
+    term_to_binary(Object).
+    
+%% C drivers can't return in raw binary (don't know why; 
+%% set_port_control_flags doesn't work, causes error.
+-spec decode( list() ) -> term().
+decode(Object) when is_list(Object) ->
+    binary_to_term( list_to_binary(Object) ).
+
+
+%% Create a new TCADB instance. you can use this TCADB concurrently.
+%% Take care when closing the instance.
+%% http://tokyocabinet.sourceforge.net/spex-ja.html#tcadbapi
+%% `name' specifies the name of the database. 
+%% If it is "*", the database will be an on-memory hash database. If it is "+", the database will be an on-memory tree database. If its suffix is ".tch", the database will be a hash database. If its suffix is ".tcb", the database will be a B+ tree database. If its suffix is ".tcf", the database will be a fixed-length database. If its suffix is ".tct", the database will be a table database. Otherwise, this function fails. 
+%% Tuning parameters can trail the name, separated by "#". 
+%% Each parameter is composed of the name and the value, separated by "=". 
+%% - On-memory hash database supports "bnum", "capnum", and "capsiz". 
+%% - On-memory tree database supports "capnum" and "capsiz". 
+%% - Hash database supports "mode", "bnum", "apow", "fpow", "opts", "rcnum", "xmsiz", and "dfunit". 
+%% - B+ tree database supports "mode", "lmemb", "nmemb", "bnum", "apow", "fpow", "opts", "lcnum", "ncnum", "xmsiz", and "dfunit".
+%% - Fixed-length database supports "mode", "width", and "limsiz". 
+%% - Table database supports "mode", "bnum", "apow", "fpow", "opts", "rcnum", "lcnum", "ncnum", "xmsiz", "dfunit", and "idx".
+%% Tuning parameters
+%% + The tuning parameter "capnum" specifies the capacity number of records. 
+%% "capsiz" specifies the capacity size of using memory. Records spilled the capacity are removed by the storing order. 
+%% "mode" can contain "w" of writer, "r" of reader, "c" of creating, "t" of truncating, "e" of no locking, and "f" of non-blocking lock. The default mode is relevant to "wc". 
+%% "opts" can contains "l" of large option, "d" of Deflate option, "b" of BZIP2 option, and "t" of TCBS option. 
+%% "idx" specifies the column name of an index and its type separated by ":". 
+%% For example, "casket.tch#bnum=1000000#opts=ld" means that the name of the database file is "casket.tch", and the bucket number is 1000000, and the options are large and Deflate.
+-type option_key() :: bnum | capnum | capsiz | mode | bnum | apow | fpow | opts | rcnum | xmsiz | dfunit .
+-type option_value() :: pos_integer() | list() .
+-type open_option() :: { option_key(), option_value() }.
+-spec generate_open_argv( atom() | list() , [ open_option() ] )-> atom().
+generate_open_argv(TableName, []) when is_atom( TableName ) ->
+    TableName;
+
+generate_open_argv(TableName, Options) when is_atom( TableName ) ->
+    generate_open_argv( atom_to_list(TableName), Options );
+
+generate_open_argv(TableName, []) when is_list( TableName ) ->
+    list_to_atom(TableName);
+
+generate_open_argv(TableName, [{Key,Value}|Options]) when is_list( TableName ) and is_integer(Value)->
+    StrKey = atom_to_list(Key),
+    generate_open_argv( TableName++"#"++StrKey++"="++io_lib:write(Value), Options );
+generate_open_argv(TableName, [{Key,Value}|Options]) when is_list( TableName ) and is_list(Value)->
+    StrKey = atom_to_list(Key),
+    generate_open_argv( TableName++"#"++StrKey++"="++Value, Options).
+
+%% -spec generate_open_argv_( list(), list() )-> atom().
+%% generate_open_argv_(TableName, Options) when is_list(TableName) ->
+%%     TableName.
+
+-spec test() -> {ok,all_passed}|{error, test_failed}.
+test()->
+    gen_server:call(?MODULE, test).
+
+-spec get_port() -> {ok, port()} | {error, any()}.
+get_port()->
+    case gen_server:call(?MODULE, get_port) of
+	Port when is_port(Port)->
+	    {ok, Port};
+	Other ->
+	    {error, Other}
+    end.
+
+-spec init( [ option() ] ) -> ok | {error, erl_ddll_error_desc()}.
+init(Options)->
+    SharedLib = ?DYLIB_NAME,
+    Port = open_port({spawn_driver, SharedLib}, [binary]),
+    {ok, #yatce{port=Port,shared_lib=SharedLib}}.
+
+handle_call(get_port, _From, State)->
+    {reply, State#yatce.port, State};
+handle_call(stop, _From, State) ->
+    Port = State#yatce.port,
+    Port ! {self(), close},
+    receive 
+	{Port , closed}->
+	    {stop, normal, ok, State};
+	_ -> 
+	    {stop, cant_close_port, ok, State}
+    after 5000->
+	    {stop, cant_close_port, ok, State}
+    end;
+handle_call(test, _From, State)->
+    Port = State#yatce.port,
+    Result=decode( port_control(Port, ?YATCE_TEST, list_to_binary([]) ) ),
+    {reply, Result, State};
+    
+handle_call(_, _From, State) ->    {noreply, State}.
+
+
+handle_cast(_,State)->    {noreply, State}.
+
+handle_info(_,State)->    {noreply, State}.
+
+terminate(Reason,State)-> 
+    io:format("~p (~p, ~p) terminating.~n", [?MODULE, self(), State]),
+    case erl_ddll:unload(State#yatce.shared_lib) of
+	{error, ErrorDesc}->
+	    io:format("can't unload ~p: ~p~n", [ State#yatce.shared_lib, erl_ddll:format_error(ErrorDesc) ]);
+	ok ->
+	    ok
+    end,
+    {shutdown, Reason}.
+    
+code_change(_,_,State)->
+    {ok, State}.
+

src/yatce_sup.erl

+%% -*- coding: utf-8 -*-
+-module(yatce_sup).
+-author('kuenishi+tc@gmail.com').
+
+-behaviour(supervisor).
+
+-export([start_link/0, init/1]).
+
+start_link()->
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([])->
+    Children =
+	[
+	 {yatce_server, {yatce_server, start, []}, permanent, 2000, worker, [yatce_server]}
+	],
+%    io:format("starting: ~p~n", [Children]),
+    {ok, {{one_for_one, 1, 1}, Children}}.
 %% -*- coding: utf-8 -*-
-%%   yatce
-%%   Copyright (C) 2009   UENISHI Kota <kuenishi+yatce@gmail.com>
-%%
-%%     This program is free software: you can redistribute it and/or modify
-%%     it under the terms of the GNU Lesser General Public License as published by
-%%     the Free Software Foundation, either version 3 of the License, or
-%%     (at your option) any later version.
-%%
-%%     This program is distributed in the hope that it will be useful,
-%%     but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%%     GNU Lesser General Public License for more details.
-%%
-%%     You should have received a copy of the GNU Lesser General Public License
-%%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
 -module(c_SUITE).
 -author('kuenishi@gmail.com').
 
 -include("ct.hrl").
 
 init_per_suite(Config) ->
-    {ok, _Pid} = yatce:start([{libdir, "../../../c_src/"}]),
+    ok=application:start(yatce),
     Config.
 
 end_per_suite(Config) ->
     yatce:stop(),
     Config.
 
-all() -> [ dup_init, tch %, tcb, tct, '*', '+' 
+all() -> [ dup_init, tch, tcb %, tct, '*', '+' 
 	  ].
 
 dup_init(Config)->
-    {ok, _Pid} = yatce:start([{libdir, "../../../c_src/"}]),
+    {error, {already_started, yatce}} = application:start(yatce),
     Config.
 
 tch(Config)->    
-    T = yatce:newdb('/tmp/test.tch', []), 
+    T = yatce:db('/tmp/test.tch', []), 
     {ok, opened} = T:open(),
     {ok, closed} = T:close(),
-    {ok, all_passed} = yatce:test(),
+    {ok, all_passed} = yatce_server:test(),
     Config.
 
 tcb(Config)->    
-    T = yatce:newdb('/tmp/test.tcb', []), 
+    T = yatce:db('/tmp/test.tcb', []), 
     {ok, opened} = T:open(),
     {ok, closed} = T:close(),
-    {ok, all_passed} = yatce:test(),
+    {ok, all_passed} = yatce_server:test(),
     Config.
 
 tct(Config)->    
-    T = yatce:newdb('/tmp/test.tct', []), 
+    T = yatce:db('/tmp/test.tct', []), 
     {ok, opened} = T:open(),
     {ok, closed} = T:close(),
-    {ok, all_passed} = yatce:test(),
+    {ok, all_passed} = yatce_server:test(),
     Config.
 
 '*'(Config)->    
-    T = yatce:newdb('*', []), 
+    T = yatce:db('*', []), 
     {ok, opened} = T:open(),
     {ok, closed} = T:close(),
-    {ok, all_passed} = yatce:test(),
+    {ok, all_passed} = yatce_server:test(),
     Config.
 
 '+'(Config)->    
-    T = yatce:newdb('+', []), 
+    T = yatce:db('+', []), 
     {ok, opened} = T:open(),
     {ok, closed} = T:close(),
-    {ok, all_passed} = yatce:test(),
+    {ok, all_passed} = yatce_server:test(),
     Config.

test/elementary_SUITE.erl

 %%     end.
 
 init_per_suite(Config) ->
-    {ok, _Pid} = yatce:start([{libdir, "../../../c_src/"}]),
+    ok=application:start(yatce),
     Config.
 
 end_per_suite(Config) ->
     [ {X, [sequencial], Set} || X <- Suffices ] ++ [ {X, [sequencial], MemSet} || X <- MemSuffices].
 	   
 new_config(TableName, Config) when is_atom(TableName) ->
-    TCADB = yatce:newdb(TableName, []),
+    TCADB = yatce:db(TableName, []),
     NewConfig = [{tablename, TableName}, {tcadb, TCADB} ] ++ Config,
     NewConfig.
     

test/perf_controller_SUITE.erl

 %% -*- coding: utf-8 -*-
-%%   yatce
-%%   Copyright (C) 2009   UENISHI Kota <kuenishi+yatce@gmail.com>
-%%
-%%     This program is free software: you can redistribute it and/or modify
-%%     it under the terms of the GNU Lesser General Public License as published by
-%%     the Free Software Foundation, either version 3 of the License, or
-%%     (at your option) any later version.
-%%
-%%     This program is distributed in the hope that it will be useful,
-%%     but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%%     GNU Lesser General Public License for more details.
-%%
-%%     You should have received a copy of the GNU Lesser General Public License
-%%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 -module(perf_controller_SUITE).
 -author('kuenishi@gmail.com').
 %% tests perf_controller, perf_timer, unit_performer here.
 -define(SERVER_NAME, ?MODULE).
 
-all()-> [start, stop].
+all()-> [ %start, stop
+	 ].
 
 init_per_suite(Config) ->    
     {ok,Pid}=gen_fsm:start({local, perf_timer}, perf_timer,1000,[]),
     Config.
 
 start(Config)-> 
-    yatce:start([{libdir, "../../../c_src"}]),
+    ok=application:start(yatce),
     FileName = '/tmp/test_perf_controller.tch',
     {ok,Pid}=gen_server:start({local, ?SERVER_NAME}, perf_controller, {[unit_performer0, unit_performer1], FileName},[{debug,[trace,log,statistics]}]),
     Config.

test/perf_timer_SUITE.erl

 %% -*- coding: utf-8 -*-
-%%   yatce
-%%   Copyright (C) 2009   UENISHI Kota <kuenishi+yatce@gmail.com>
-%%
-%%     This program is free software: you can redistribute it and/or modify
-%%     it under the terms of the GNU Lesser General Public License as published by
-%%     the Free Software Foundation, either version 3 of the License, or
-%%     (at your option) any later version.
-%%
-%%     This program is distributed in the hope that it will be useful,
-%%     but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%%     GNU Lesser General Public License for more details.
-%%
-%%     You should have received a copy of the GNU Lesser General Public License
-%%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 -module(perf_timer_SUITE).
 -author('kuenishi@gmail.com').
 generate(0)-> [];
 generate(Length)->   RChar = 96+random:uniform(26),  [RChar|generate(Length-1)].
 
-all()-> [start, stop].
+all()-> []. %[start, stop].
 
 init_per_suite(Config) ->    Config.
 end_per_suite(Config) ->     Config.

test/tcadb_SUITE.erl

 %% -*- coding: utf-8 -*-
-%%   yatce
-%%   Copyright (C) 2009   UENISHI Kota <kuenishi+yatce@gmail.com>
-%%
-%%     This program is free software: you can redistribute it and/or modify
-%%     it under the terms of the GNU Lesser General Public License as published by
-%%     the Free Software Foundation, either version 3 of the License, or
-%%     (at your option) any later version.
-%%
-%%     This program is distributed in the hope that it will be useful,
-%%     but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%%     GNU Lesser General Public License for more details.
-%%
-%%     You should have received a copy of the GNU Lesser General Public License
-%%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 -module(tcadb_SUITE).
 -author('kuenishi@gmail.com').
 -define(TESTVALUE2, "|+}{\":?u9im03w4ed5rf6t7gy8hu9ji0kf\poi").
 
 init_per_suite(Config) ->
-    {ok, _Pid} = yatce:start([{libdir, "../../../c_src/"}]),
+    ok=application:start(yatce),
     Config.
 
 end_per_suite(Config) ->  
 
 new_config(TableName, Config) when is_tuple(TableName) ->
     {TN1, TN2} = TableName,
-    T1 = yatce:newdb(TN1, []),    
-    T2 = yatce:newdb(TN2, []),
+    T1 = yatce:db(TN1, []),    
+    T2 = yatce:db(TN2, []),
     NewConfig = [{t1, T1}, {t2, T2} ] ++ Config,
     NewConfig.
     

test/types_SUITE.erl

 %% -*- coding: utf-8 -*-
-%%   yatce
-%%   Copyright (C) 2009   UENISHI Kota <kuenishi+yatce@gmail.com>
-%%
-%%     This program is free software: you can redistribute it and/or modify
-%%     it under the terms of the GNU Lesser General Public License as published by
-%%     the Free Software Foundation, either version 3 of the License, or
-%%     (at your option) any later version.
-%%
-%%     This program is distributed in the hope that it will be useful,
-%%     but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%%     GNU Lesser General Public License for more details.
-%%
-%%     You should have received a copy of the GNU Lesser General Public License
-%%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 -module(types_SUITE).
 -author('kuenishi@gmail.com').
 -define(LIST,  ["hoge", listtoooo, 2344]).
 
 init_per_suite(Config) ->
- %   TableName = '/tmp/test.tch',
-    {ok, _Pid} = yatce:start([{libdir, "../../../c_src/"}]),
- %   TCADB = yatce:newdb(TableName, []),
- %   {ok, opened} = TCADB:open(),
- %   [{tablename, TableName},{tcadb, TCADB}]++Config.
+    ok=application:start(yatce),
     Config.
 
 end_per_suite(Config) ->
 %    [ {X, [sequencial], Set} || {Suffix, Key, Value} <- Testcases ].
 
 new_config(TableName, Config) when is_atom(TableName) ->
-    TCADB = yatce:newdb(TableName, []),
+    TCADB = yatce:db(TableName, []),
 %    {ok, opened}=TCADB:open(),
     R = TCADB:open(),
     ct:log("~p <~p>~n", [R, TableName]),

test/unit_performer_SUITE.erl

 %% -*- coding: utf-8 -*-
-%%   yatce
-%%   Copyright (C) 2009   UENISHI Kota <kuenishi+yatce@gmail.com>
-%%
-%%     This program is free software: you can redistribute it and/or modify
-%%     it under the terms of the GNU Lesser General Public License as published by
-%%     the Free Software Foundation, either version 3 of the License, or
-%%     (at your option) any later version.
-%%
-%%     This program is distributed in the hope that it will be useful,
-%%     but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%%     GNU Lesser General Public License for more details.
-%%
-%%     You should have received a copy of the GNU Lesser General Public License
-%%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 -module(unit_performer_SUITE).
 -author('kuenishi@gmail.com').
 init_per_suite(Config) ->
     {A1, A2, A3}=now(),
     random:seed(A1, A2, A3),
-    {ok, _Pid} = yatce:start([{libdir, "../../../c_src/"}]),
+    ok=application:start(yatce),
     Config.
 
 end_per_suite(Config) ->
     yatce:stop(),
     Config.
 
-all()-> [ {group, tch} ].
+all()-> [ %{group, tch} 
+	 ].
 
 init_per_group(tch, Config)->
-    T=yatce:newdb('/tmp/test.tch', []),
+    T=yatce:db('/tmp/test.tch', []),
     T:open(),
     [{tcadb, T}|Config].
 

test/yatce.coverspec

 
 %% Directories to include in cover.
 %% Dirs = [string()]
-%{incl_dirs, ["../ebin"]}.
+%% {incl_dirs, ["../ebin"]}.
 
 %% Directories, including subdirectories, to include.
 %{incl_dirs_r, Dirs}.
 
 %% Specific modules to include in cover.
 %% Mods = [atom()]
-{incl_mods, [tcadb, yatce, perf_controller, perf_sup, perf_timer, unit_performer]}.
+{incl_mods, [tcadb, yatce, yatce_sup, yatce_server, perf_controller, perf_sup, perf_timer, unit_performer]}.
 
 %% Directories to exclude in cover.
 %{excl_dirs, Dirs}.

test/yatce_SUITE.erl

 %% -*- coding: utf-8 -*-
-%%   yatce
-%%   Copyright (C) 2009   UENISHI Kota <kuenishi+yatce@gmail.com>
-%%
-%%     This program is free software: you can redistribute it and/or modify
-%%     it under the terms of the GNU Lesser General Public License as published by
-%%     the Free Software Foundation, either version 3 of the License, or
-%%     (at your option) any later version.
-%%
-%%     This program is distributed in the hope that it will be useful,
-%%     but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%%     GNU Lesser General Public License for more details.
-%%
-%%     You should have received a copy of the GNU Lesser General Public License
-%%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 -module(yatce_SUITE).
 -author('kuenishi@gmail.com').
 %%     [ {options, [parallel], OptionPairs} ].
 
 init(Config)->
-    {ok, _Pid} = yatce:start([{libdir, "../../../c_src/"}]),
+    ok=application:start(yatce),
     Config.
 
 options(Config)->
 check([Pair|OptionPairs]) ->
     {Answer, {TableName, Options}}=Pair,
     ct:log("~p~n", [{tcadb, Answer, Options, make_ref()}]),
-    T = yatce:newdb(TableName, Options),
+    T = yatce:db(TableName, Options),
     {tcadb, Answer, Options, _} = T,
     {ok,opened}=T:open(),
     {ok,closed}=T:close(),
-YATCE_VSN = 0.9.5
+YATCE_VSN = 0.10.0