// $Header: https://oberon.oapd.inaf.it/shins/trunk/shins/src/util/watch.cpp 2341 2020-01-31 14:56:39Z depa $

#include "watch.h"

namespace shins{
  namespace util{
    // Insert event information, used to create new watch, into Watch object.
    void Watch::insert( int pd, const std::string &name, int wd ) {
      wd_elem elem = {pd, name};
      watch[wd] = elem;
      rwatch[elem] = wd;
    }
    // Erase watch specified by pd (parent watch descriptor) and name from watch list.
    // Returns full name (for display etc), and wd, which is required for inotify_rm_watch.
    std::string Watch::erase( int pd, const std::string &name, int *wd ) {
      wd_elem pelem = {pd, name};
      *wd = rwatch[pelem];
      rwatch.erase(pelem);
      const wd_elem &elem = watch[*wd];
      std::string dir = elem.name;
      watch.erase(*wd);
      return dir;
    }
    // Given a watch descriptor, return the full directory name as string. Recurses up parent WDs to assemble name,
    // an idea borrowed from Windows change journals.
    std::string Watch::get( int wd ) {
      const wd_elem &elem = watch[wd];
      return elem.pd == -1 ? elem.name : this->get(elem.pd) + "/" + elem.name;
    }
    // Given a parent wd and name (provided in IN_DELETE events), return the watch descriptor.
    // Main purpose is to help remove directories from watch list.
    int Watch::get( int pd, std::string name ) {
      wd_elem elem = {pd, name};
      return rwatch[elem];
    }
    void Watch::cleanup( int fd ) {
      for (std::map<int, wd_elem>::iterator wi = watch.begin(); wi != watch.end(); wi++) {
        inotify_rm_watch( fd, wi->first );
        watch.erase(wi);
      }
      rwatch.clear();
    }
    void Watch::stats() {
      std::cout<< "number of watches=" << watch.size() << " & reverse watches=" << rwatch.size() << std::endl;
    }
  }
}
