LINUX.ORG.RU

erlang, посылка сообщения с одной ноды на другую.


0

0

erlang позволяет прозрачно отправлять сообщения не только внутри процессов ноды но и с одной ноды на другую.

то есть либо Pid ! { message } либо {Pid, server@localhost } ! { message }.

сейчас пишу программу и что-то не ладится.

-module(bhsql_storageserver).

-import(file).
-import(io).

-export([ init/1, find_last_rowid/1, main_loop_start/0, work_select/4, work_insert/5, work_update/5, work_delete/4 ]).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init(Path) ->
    register( storageserver, spawn( bhsql_storageserver, main_loop_start, [] ) ).
%   register( storageserver, spawn( fun main_loop_start/0 ) ).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
main_loop_start() ->
    put(last_rowid,find_last_rowid(1)),
    main_loop().

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
main_loop() ->
    receive
        { SrcProc, SrcNode, insert, N, Data }           -> spawn( bhsql_storageserver,work_insert,[SrcProc,SrcNode,N,Data,gen_rowid()]), main_loop();
        { SrcProc, SrcNode, stop }                      -> io:fwrite("GOT STOP~n");
        X                                               -> io:fwrite("GOT rubbish - ~w~n",[X]), main_loop()
    end.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
find_last_rowid(RowId) ->
    case file:read_file_info(rowid_to_filename(RowId)) of
        { error, enoent } -> RowId-1;
        { ok, _ } -> find_last_rowid(RowId+1)
    end.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
rowid_to_filename(RowId) ->
    integer_to_list(RowId).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
gen_rowid() ->
    RowId=get(last_rowid)+1,
    put(last_rowid,RowId),
    RowId.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
work_insert(SrcProc,SrcNode,N,Data,RowId) ->
    io:fwrite("work_insert - Called with SrcProc=~w SrcNode=~w N=~w Data=~w RowId=~w~n",[SrcProc,SrcNode,N,Data,RowId]),
    case file:write_file(rowid_to_filename(RowId),Data) of
        ok ->
            io:fwrite("work_insert - SENDING RET~n"),
            { SrcProc, SrcNode } ! { insert_result, ok, N, RowId },
            io:fwrite("work_insert - SENT RET~n");
        { error, Reason } -> { SrcProc, SrcNode } ! { insert_result, error, N, Reason };
        X -> io:fwrite("file:write_file, got rubbish - ~w~n",[X])
    end.


-module(msgtest).

-import(io).
-export([ test/0, send_insert/1, send_stop/0 ]).


recv() ->
    receive
        X -> io:fwrite("GOT ~w~n",[X])
    after 2000 ->
        io:fwrite("Timeout~n")
    end.

send_insert(Data) ->
    { storageserver, server@localhost } ! { self(), client@localhost, insert, 771, Data},
    recv().

send_stop() ->
    { storageserver, server@localhost } ! { self(), client@localhost, stop},
    recv().

(я немного сократил здесь текст программки, убрав select/update/delete, ибо они в тесте не участвуют)

консоль N1:

erl -sname server
c(bhsql_storageserver).
bhsql_storageserver:init("чтоугодно").

консоль N2:

erl -sname clent
c(msgtest).
msgtest:send_insert(<<"New line">>).
msgtest:send_stop().    

итого:

send_insert отрабатывает наполовину нормально, файл создаётся и туда пишется «New line»,

НО! не срабатывает возврат данных с помощью восклицательного знака.

то есть work_insert печатает следущее:

(server@localhost)17> bhsql_storageserver:init("src").
true
work_insert - Called with SrcProc=<8957.39.0> SrcNode=client@localhost N=771 Data=<<78,101,119,32,108,105,110,101>> RowId=14
work_insert - SENDING RET
(server@localhost)18>
=ERROR REPORT==== 12-Jan-2010::19:14:16 ===
Error in process <0.109.0> on node 'server@localhost' with exit value: {badarg,[{bhsql_storageserver,work_insert,5}]}

обламываясь перед

io:fwrite("work_insert - SENT RET~n");

★★★

опа. нашёл ошибку. только не понятно - то ли в ДНК то ли в erlang то ли в документации.

если сделать
register(storageclient,self())

и потом посылать storageclient вместо self() то всё работает. o_O

vahvarh ★★★ ()
Ответ на: комментарий от vahvarh

>то ли в erlang
хе-хе)

{ SrcProc, SrcNode } ! { insert_result, ok, N, RowId },

Заменить на SrcProc ! { insert_result, ok, N, RowId }

К тому же вообще жутко все выглядит.

На rpc:call посмотри хотя бы

arhibot ()
Ответ на: комментарий от arhibot

не хочу я rpc:call. не нравится оно мне.

Заменить на SrcProc ! { insert_result, ok, N, RowId }

и что, думаешь заработает? у меня ноды теоретически могут быть на разных компьютерах. с большой вероятностью даже на разных.

vahvarh ★★★ ()

Это юмор такой, писать:

-import(file). -import(io).

а потом вызывать функции явно указывая модуль:

... case file:read_file_info(rowid_to_filename(RowId)) of ... io:fwrite(«work_insert - SENDING RET~n»), ... и т.д.???

а вообще Lennart Öhman говорил что за -import, put, get и еще некоторые вещи, надо отрывать...

Cy6erBr4in ★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.