2013-03-21 2 views
2

프로세스 A에서 digraph이라는 용어를 만들었으므로이 노드를 다른 노드의 프로세스에 전달하고 싶습니다. 나는 다른 프로세스에서이 소리를 나타내는 두 글자를 사용할 때마다 나는 다음과 같은 오류를 얻고있다하십시오 소리를 나타내는 두 글자 Becasuse다른 프로세스와 노드에 다이 그래프를 전달하는 방법은 무엇입니까?

** {badarg, 
    [{ets,insert,[598105,{"EPqzYxiM9UV0pplPTRg8vX28h",[]}],[]}, 
    {digraph,do_add_vertex,2,[{file,"digraph.erl"},{line,377}]}, 

이 ETS에 기반을,이는 소리를 나타내는 두 글자에게 꽤 많은 독립을 매우 더 복잡 것으로 보인다 그것이 만들어진 과정. 나는 비슷한 문제가 밝혀이 항목 발견 : ETS on a different process

나는 내가 다음 OTP 메시지를 통해 그것에 연결합니다 서버의 소리를 나타내는 두 글자를 만들 수 있습니다 알고,하지만 난 내 건축 할 수 없어. 모든 노드는 조건을 따라 상태를 전달하도록 설계된 특정 접근 방식을 사용하여 통신 할 수 있습니다.

직접적으로 서로 통신 할 수없는 서로 다른 노드로 보내지는 다이어그램을 갖는 것은 불가능합니다. 전반적으로 은 다이 그래프를 직접 직렬화 할 수없는 것으로 보입니다. 저는이 다이 그래프를 꼭지점과 모서리의 목록으로 "푸는"다음 다른 프로세스 (효율적이지 않거나 우아하지는 않음)에서 전송하고 다시 만들 수 있다고 생각합니다. 에 대한 더 나은 방법에 대한 생각은을 직렬화 하시겠습니까? ETS 저장소에서 다이 그래프 상태를 직렬화하는 방법이 있습니까?

의견이 있으십니까?

답변

2

다음과 같이 다이 그래프를 직렬화/역 직렬화 할 수 있습니다.

serialize({digraph, V, E, N, B}) -> 
    {ets:tab2list(V), 
    ets:tab2list(E), 
    ets:tab2list(N), 
    B}. 

deserialize({VL, EL, NL, B}) ->  
    DG = {digraph, V, E, N, B} = case B of 
     true -> digraph:new(); 
     false -> digraph:new([acyclic]) 
    end, 
    ets:delete_all_objects(V) 
    ets:delete_all_objects(L) 
    ets:delete_all_objects(N) 
    ets:insert(V, VL) 
    ets:insert(E, EL) 
    ets:insert(N, NL) 
    DG. 

그리고 이것은 이것을 테스트하는 데 사용 된 코드입니다.

passer() -> 
    G = digraph:new(), 
    V1 = digraph:add_vertex(G), 
    V2 = digraph:add_vertex(G), 
    V3 = digraph:add_vertex(G), 
    digraph:add_edge(G, V1, V2, "edge1"), 
    digraph:add_edge(G, V1, V3, "edge2"), 
    Pid = spawn(fun receiver/0), 
    Pid ! serialize(G). 

receiver() -> 
    receive 
     SG = {_VL, _EL, _NL, _B} -> 
      G = deserialize(SG), 
      io:format("Edges: ~p~n", [digraph:edges(G)]), 
      io:format("Edges: ~p~n", [digraph:vertices(G)]) 
    end. 

꽤 못생긴 해결책이지만 작동합니다. 이것은 노드간에 ets 테이블을 공유 할 수 없기 때문에 이것이 노드 간의 쌍극자를 전달하는 유일한 방법이라고 생각합니다.

편집 : 불필요한 루프를

+0

감사 캐시미어와 파스칼을 제거하면 모두 동일한 접근과 해결책을 가지고 있습니다. 한 가지 문제 : 탈염 생성에 사용되는 부울 (digraph : new (B))이 실패합니다. 예를 들어, "순환"항목이 몇 개있을 것으로 예상합니다. – gextra

+0

또 다른 문제입니다. 프로세스/노드에서 데이터를 전송 한 다음 동일한 프로세스/노드로 다시 전송하면 원본 ETS 데이터에는 여전히 원래 데이터가 포함될 수 있습니다. 이미 가지고있는 프로세스에서 다이 그래프를 다시 만든다면, 가장자리를 추가하는 것은 badmatch로 실패 할 것입니다. 이 문제를 해결하기 위해 바로 앞에 "ets : delete_all_objects (V)"를 추가했습니다 (E와 N도 마찬가지입니다). 그것은 ETS 수령인을 거기에 다시 끼우기 전에 그것을 깨끗하게하는 것이었다. – gextra

+0

@gextra 귀하의 발견에 따라 코드를 업데이트했습니다. – cashmere

2

해결책이 있지만 digrapgh : new()에서 반환 한 변수의 구조에 의존하므로 향후 버전과 호환 될지 잘 모르겠습니다.

D = digraph:new(), 
... 
%some code modifying D 
... 
{digraph,Vertices,Edges,Neighbours,Cyclic} = D, % get the table Id of the 3 tables containing D values 
% It should be preferable to use the record definition of the digraph module 
%-record(digraph, {vtab = notable :: ets:tab(), 
%   etab = notable :: ets:tab(), 
%   ntab = notable :: ets:tab(), 
%    cyclic = true :: boolean()}). 
LV = tab2list(Vertices), 
LE = tab2list(Edges), 
LN = tab2list(Neighbours), 
... 
% then serialize and send all this variables to the target node, ideally in one single tuple like 
% {my_digraph_data,LV,LE,LN,Cyclic} or using refs to avoid the mix of messages, 
% and on reception on the remote node: 

receive 
    {my_digraph_data,LV,LE,LN,Cyclic} -> 
     Dcopy = digrapgh:new(Cyclic), 
     {digraph,Vertices,Edges,Neighbours,_Cyclic} = Dcopy, 
     ets:insert(Vertices,LV), 
     ets:insert(Edges,LE), 
     ets:insert(Neighbours,LN), 
     Dcopy; 
... 

그게 전부입니다.

관련 문제