IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Caml Discussion :

Inotify, incrément de wd et path de l'évènement


Sujet :

Caml

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 147
    Points : 102
    Points
    102
    Par défaut Inotify, incrément de wd et path de l'évènement
    Bonjour à tous,

    je ne sais pas si vous connaissez inotify alors je vais rappeler rapidement ce que c'est. Inotify est un module inclu dans le kernel qui permet la surveillance de fichiers/répertoires. Le premier "i" d'inotify voulant dire inode.
    Il existe un binding entre Ocaml et C pour faire fonctionner inotify en CAML.

    Je suis en train d'écrire un programme en OCAML et je souhaiterais m'appuyer sur inotify pour surveiller les dossiers.

    Ce que mon programme fait, c'est de prendre en entrée le path d'un dossier et d'aller chercher récursivement les sous-dossiers et appliquer à eux aussi la surveillance.

    Pour surveiller un dossier, il faut utiliser la fonction Inotify.add_watch qui retourne un identifiant unique appelé "wd".

    Enfin quand je crée un dossier dans un répertoire surveillé, ca génère un évènement qui ressort un "wd" ce qui me permet de savoir quel est le path du dossier où s'est produit l'évènement.

    Pour mettre le nouveau répertoire sous surveillance, il suffit alors de récupérer le path du dossier où il y a eu l'évènement grâve à l'association wd -> path et de concaténer à path le nom du nouveau dossier.

    Mais dans ma belle explication quelque chose m'échappe, voyez plutôt la session qui suit :

    Exemple de session :
    mkdir "/tmp/dev" :
    add_watch "/tmp/dev" -> wd = 1

    mkdir "/tmp/dev/hello" :
    add_watch "/tmp/dev/hello" -> wd = 2

    mkdir "/tmp/dev/world" :
    add_watch "/tmp/dev/world" -> wd = 3

    mkdir "/tmp/dev/salut" :
    add_watch "/tmp/dev/salut" -> wd = 4

    Jusqu'ici c'est normal puis je crée des répertoires un niveau en dessous :

    mkdir "/tmp/dev/hello/bonjour" :
    add_watch "/tmp/dev/hello/bonjour" -> wd = 2 ---> wd devrait valoir 5 !

    mkdir "/tmp/dev/hello/bye" :
    add_watch "/tmp/dev/hello/bonjour/bye" -> wd = 2 ----> wd devrait valoir 6 !

    Comme on peut le voir à l'erreur, on ne récupère pas le bon wd et du coup, la concaténation met en évidence le fait que ca foire.

    Qu'est-ce qui échoue ? Apparemment l'incrémentation ? J'ai parcouru le code du binding qui mène finalement au code C et l'incrément du wd se fait par la fonction kernel atom_inc. Donc je ne pense pas que le problème se situe de ce côté et puis depuis le temps qu'inotify est sorti, ca se saurait surement.

    C'est donc surement moi qui fait une erreur. Si wd qui est pourtant unique n'est pas la bonne méthode pour savoir où s'est situé l'évènement, quelle est la bonne méthode ?

    Ci-joint, j'ai mis mon programme de tests (avec création des répertoires dans /tmp/dev, vous pouvez le commenter et les créer à la main si vous le souhaitez) ainsi qu'un Makefile.

    Merci d'éclairer ma lanterne.

    PS: les fichiers joints ont l'extension .txt mais c'est uniquement pour pouvoir les uploader. Sinon le site refuse l'extension .ml
    Fichiers attachés Fichiers attachés

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Février 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 141
    Points : 142
    Points
    142
    Par défaut
    Salut,

    Je n'ai pas lu en détail tout ton code.

    2 choses :
    1 - La fonction Inotify.add_watch prend en argument un Unix.file_descr, et le wd produit est unique pour un file_descr fixé. As-tu vérifié que tu ne modifiais pas par inadvertance ton fd? Ou que tu ne réutilises pas le nom "fd" dans une sous-fonction, dans un cas qui interférerarit avec ta globale fd?

    2 - Tu as l'air d'avoir une fonction qui rajoute un watch pour chaque évènement ("Create", "Destroy", ...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    let type_event_next = List.hd q in
      (match type_event_next
    Mais l'effet de ta fonction, en réponse à aux évènements "Destroy" et "Moved_from" n'est pas de créer un watch suppélmentaire, associé à ces évènements, mais de détruire un watch.
    Est-ce que ça ne pourrait pas interférer avec la suite de ton programme?

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 147
    Points : 102
    Points
    102
    Par défaut
    Salut !

    Alors j'ai trouvé une première erreur.

    L'erreur, c'est lorsque je fais le add_watch de récupérer le wd et de l'associer au path du nouveau dossier surveillé. Car le wd récupéré est en fait le wd du répertoire où il y a eu l'évènement. Comme j'avais vu dans le code que wd s'incrémente uniquement de façon atomique, alors j'ai créé à mon tour une variable que j'incrémente et que j'utilise pour faire l'association.

    En clair:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    let bigger_wd = ref 1
     
    let add_watch folder =
      (* TO DO: add a test : if folder already watched *)
      try
        let _ = Inotify.add_watch fd folder [S_All]
        in
          print_endline ("*** "^folder^" is now watched");
     
          l_watched := (!bigger_wd, folder)::!l_watched;
     
          bigger_wd := !bigger_wd +1
     
      with Failure err -> failwith ("Error in function '"^err^"', is the name of the directory ok ? Here is the directory concerned: '"^folder^"'\n")
    Et par contre plus loin lorsque je récupère l'évènement, je récupère le wd et ca fonctionne bien.

    Maintenant, je suis confronté à un deuxième problème et je ne sais pas si l'erreur vient de mon code CAML ou du binding mais en tout cas je n'ai pas cette erreur en C.

    Je peux mettre en surveillance /tmp/dev puis /tmp/dev/a après création d'un répertoire puis /tmp/dev/a/b mais pas de surveillance pour /tmp/dev/a/b/c.

    Ce qui est d'autant plus étrange, c'est que cela passe sans lever d'exception le Inotify.add_watch fd "/tmp/dev/a/b" mais que ce dossier n'est pas réellement surveillé.
    A mon avis, l'erreur semble venir du Inotify.read qui ne lit rien.
    Je ne pense pas que cela vienne de Inotify.add_watch car si je lui donne une liste de path à surveiller, il fait correctement son job. Mais dans tous les cas, je ne peux pas récréer après coup des dossiers un peu plus en profondeur.

    Une idée ?

    PS: En réponse à ton point n°2. En fait, quand tu fais la création d'un répertoire, cela renvoie une liste avec deux évènements qui sont [Isdir ; Create]. Donc quand je teste et que je vois que c'est un Isdir, il y a forcément un autre évènement derrière qui est plus intéressant pour ce que je veux faire. D'où le List.hd q pour prendre le prochain type d'évènement (ici Create).

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 147
    Points : 102
    Points
    102
    Par défaut
    Alors en fait, je m'aperçois que j'ai répondu à côté de tes questions.

    n°1 : je ne modifie jamais fd et je ne fais que des select/read dessus.

    n°2 : alors oui, j'ajoute un watch comme tu dis mais uniquement pour create et move_to. Les autres cas, je supprime la surveillance. Et encore là, j'avais juste fait des cas simples. J'ai d'ailleurs laissé que le Create là dans ma version de test.

    C'est vraiment très étrange car dans le code C, je n'ai pas tout ces problèmes.

    Pour le moment, j'en suis réduit à compter le nombre de wd, fermer fd, réinitialiser le compteur des wd, effacer la liste des répertoires surveillés et relancer le tout comme on peut le voir dans le fichier que j'avais joint plus haut en faisant une commande système pour lister les dossiers récursivement. Bref c'est très très crade et pas viable du tout.

    J'ai écrit un mail il y a 2 jours à l'auteur du binding mais il ne m'a pas encore répondu.

    C'est couillon parce que sinon je vais devoir être obligé de coder en C.

    Si vous aviez de quoi me débloquer ce serait vraiment génial !

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 147
    Points : 102
    Points
    102
    Par défaut
    Bon alors en fait, j'avais raison, il y a un bug dans le binding Ocaml d'Inotify mais pas là où je vous disais. J'ai mis du temps à le traquer ce vilain bug !

    J'ai corrigé dans mon code l'erreur que le binding provoque et dans les jours qui viennent, je vais tenter de patcher le binding et le soumettre à son auteur.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 10/06/2003, 15h16
  2. Redhat-9 changer le path des databases
    Par jean christophe dans le forum Installation
    Réponses: 7
    Dernier message: 30/05/2003, 18h53
  3. [débutant][xsl]incrémenter une variable
    Par guitalca dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 01/04/2003, 16h19
  4. ca ne fonctionne pas (generateur auto-incrémentant)
    Par tripper.dim dans le forum SQL
    Réponses: 7
    Dernier message: 26/11/2002, 01h10
  5. Post incrémentation?
    Par Defrag dans le forum C
    Réponses: 4
    Dernier message: 08/10/2002, 11h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo