2013-04-19 2 views
1

나는 Erlang의 file:open/2과 그것을 돌려주는 IoDevice/file 디스크립터 대신에 완전히 다른 방식으로 특정 파일을 투명하게 처리하는 모듈을 만들었다. 대부분의 경우 Erlang의 file:open/2의 결과를 반환하며, 다른 경우에는 HTTP API (CloudFiles 또는 AWS S3)를 통해 읽고 쓰는 맞춤 IoDevice를 반환합니다.Erlang gen_server를 통해 열린 파일을 처리하는 방법?

최근에 이것은 일반 모듈 이었지만 다른 이유로 비동기 HTTP 호출을보다 잘 처리하기 위해 gen_server으로 변환하려고 시도해 왔습니다. 이 사용자 정의 비트는 정상적으로 작동하지만 단지 file:open/2gen_server:handle_call/3에서 호출하고 결과 IoDevice를 리턴하는 데 문제가 있습니다. 문제는 내 gen_server이 IoDevice로 회신하기 위해 파일을 연 후 gen_server:handle_info/2으로 즉시 예기치 않은 호출이 발생하고 궁극적으로 제한 시간이 내 gen_server에 발생합니다.

... 
handle_call({open, Path, Flags}, _From, State) -> 
    Reply = case handle_external_file(Path) of 
       false -> file:open(Path, Flags); 
       true -> external_file:open(Path) 
      end, 
    %% 
    %% Reply is {ok,{file_descriptor,prim_file,{#Port<0.1896>,14}}} 
    %% 
    {reply, Reply, State}; 
... 
handle_info(Message, State) -> 
    %% 
    %% Message is {#Port<0.1896>,{data,[3,0,0,0,0,0,0,0,0]}} 
    %% 
    io:format("UNEXPECTED MESSAGE: ~p~n", [Message]), 
    {noreply, State} 
... 

나는이가 워드 프로세서에서 다음과 관련이 가정

IoDevice 정말 파일을 처리하는 프로세스의 PID입니다. 이 프로세스는 원래 파일을 연 프로세스에 연결됩니다. IoDevice가 연결된 모든 프로세스가 종료되면 파일이 닫히고 프로세스 자체가 종료됩니다. 이 호출에서 반환 된 IoDevice는 IO 함수에 대한 인수로 사용할 수 있습니다 (io (3) 참조).

gen_server에서 파일을 열고 다른 프로세스로 IoDevice를 넘기는 방법이 있습니까?

+0

나는 당신이'gen_server'가 파일을 사용할 프로세스를 만들어야한다고 생각합니다. 그 프로세스가 파일을 열어서 사용하게하십시오. gen_server를 사용하여 파일을 열 수는 없지만 반환 된'파일 설명자 '를 사용하는 다른 프로세스를 기대합니다. –

답변

1

파일에 문제가 없습니다. 열린 포트 드라이버가 external_file : open (경로)에 열려 있습니다. IoDevice는 모든 프로세스에서 사용할 수 있지만 생성 프로세스가있을 때만 사용할 수 있습니다. 반면 포트 드라이버를 만드는 프로세스는 포트 드라이버의 소유자가되며 해당 프로세스 만 포트 드라이버와 통신 할 수 있습니다. Port ref가 반환되고 다른 프로세스가 액세스하면 프로그램이 중단 될 수 있습니다.

더 나은 방법은 포트를 반환하지 않는 것입니다. 대신 메시지로 데이터를 가져 와서 동일한 gen_server를 사용하여 포트를 읽고 쓸 수 있습니다.