2013-04-19 2 views
1

J'ai créé un module qui gère de manière transparente certains fichiers de manière complètement différente, en remplacement des file:open/2 d'Erlang et du descripteur IoDevice/fichier qu'il renvoie. Dans de nombreux cas, il renvoie simplement le résultat du file:open/2 d'Erlang, et dans d'autres cas il renvoie un IoDevice personnalisé qui lit et écrit via une API HTTP (CloudFiles ou AWS S3).Comment gérer les fichiers ouverts via un Erlang gen_server?

Récemment, c'était un module simple, mais j'ai essayé de le convertir en un gen_server pour mieux gérer les appels HTTP asynchrones (entre autres raisons). Ces bits personnalisés fonctionnent bien, mais je rencontre des problèmes en appelant simplement file:open/2 à partir d'un gen_server:handle_call/3 et en retournant l'IoDevice résultant. Le problème est après que mon gen_server ouvre un fichier afin de répondre avec un IoDevice, il y a un appel immédiat, inattendu à gen_server:handle_info/2 et un délai d'attente éventuel sur mon 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} 
... 

Je suppose que cela est lié à ce qui suit de la documentation:

IODevice est vraiment le pid du processus qui gère le fichier. Ce processus est lié au processus qui a initialement ouvert le fichier. Si un processus auquel l'IoDevice est lié s'arrête, le fichier sera fermé et le processus lui-même sera terminé. Un IoDevice retourné à partir de cet appel peut être utilisé comme argument pour les fonctions IO (voir io (3)).

Est-il possible d'ouvrir un fichier à partir d'un gen_server, remettre son IODevice à un autre processus?

+0

Je pense que vous devriez laisser le 'gen_server' générer le processus qui utilisera le fichier. puis laissez ce processus ouvrir le fichier et l'utiliser. Il n'est pas possible d'utiliser gen_server pour ouvrir le fichier, mais attendez-vous à ce qu'un processus différent utilise le "descripteur de fichier" retourné –

Répondre

1

Le problème n'est pas avec le fichier: ouvrir le problème est avec le pilote de port ouvert dans external_file: open (chemin). L'IoDevice peut être utilisé par n'importe quel processus mais il ne sera disponible que jusqu'à ce que le processus de création existe. Alors que le processus qui crée le pilote de port devient le propriétaire du pilote de port et que seul ce processus peut communiquer avec le pilote de port. Si le port ref est renvoyé et que tout autre processus y accède, le programme peut tomber en panne. La meilleure approche serait que vous ne retourniez pas le port. Au lieu de cela, obtenez les données sous forme de message et utilisez le même serveur gen_server pour lire/écrire sur le port.

Questions connexes