public void deleteFileObserved(DirectoryWatcher watcher, UpdatingFileTree inAbsolutePath) {
    logger.finest("delete observed: " + inAbsolutePath.thisFile.getAbsolutePath());

    try {
      removalsToProcess.put(
          new FileChange(inAbsolutePath, watcher.getWatchType(), new File(watcher.getPath())));
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  public void newFileObserved(DirectoryWatcher watcher, UpdatingFileTree inAbsolutePath) {
    logger.finest("change event: " + inAbsolutePath.thisFile.getAbsolutePath());
    /** TODO: optimization: use prefix tree */
    synchronized (mExclusions) {
      for (String pre : mExclusions) {
        if (inAbsolutePath.thisFile.getAbsolutePath().startsWith(pre)) {
          // System.out.println("excluded by " + pre);
          return;
        }
      }
    }

    try {
      additionsToProcess.put(
          new FileChange(inAbsolutePath, watcher.getWatchType(), new File(watcher.getPath())));
      logger.finer("put into to check out q: " + inAbsolutePath.thisFile.getAbsolutePath());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  public void run() {
    // long last_audio_bind = System.currentTimeMillis() + (120 * 1000);
    int errors = 0;

    /**
     * Sleep for a bit during start to speed up UI loading tasks -- this doesn't need to happen
     * immediately
     */
    try {
      Thread.sleep(30 * 1000);
    } catch (Exception e) {
      e.printStackTrace();
    }

    sync();

    // try {
    // if(
    // COConfigurationManager.getBooleanParameter("oneswarm.v06.firstrun") )
    // {
    // COConfigurationManager.setParameter("oneswarm.v06.firstrun", false);
    // logger.info("First run of 0.6, trying to auto-add tags for audio");
    // autotag_existing_audio();
    // }
    // } catch( Exception e ) {
    // e.printStackTrace();
    // }

    while (!stopping) {
      try {
        if (stopWatching) {
          Thread.sleep(10 * 1000);
          continue;
        }

        try {
          process_additions();

          // we'll no longer have any removals now that we need to do
          // full scans to avoid memory usage
          // process_removals();

          if (System.currentTimeMillis() > nextSyncTime) {
            sync();
          } else {
            Thread.sleep(1000);
          }
        } catch (TOTorrentException e) {
          if (e.getReason()
              == TOTorrentException
                  .RT_CANCELLED) {; // this is okay actually -- skips just this one.
          } else {
            throw e;
          }
        }
      } catch (Exception e) {
        BackendErrorLog.get().logException(e);

        errors++;
        if (errors > 3) {
          for (DirectoryWatcher dw : watchers.values()) {
            dw.removeListener(this);
            dw.setDone();
          }
          watchers.clear();

          BackendErrorLog.get()
              .logString(
                  "Previous errors have caused OneSwarm to stop monitoring current watch directories.");
          stopWatching = true;
        }

        try {
          Thread.sleep(1 * 1000);
        } catch (Exception e2) {
        }
      }
    }
  }
  /**
   * We used to be much more proactive here -- maintaining file tree info and periodically
   * refreshing it. This used a lot of memory for large directory trees, so now we simply refresh
   * all watch directories periodically.
   */
  private void sync() {
    logger.fine("sync()");
    synchronized (watch_dirs) {
      long startSyncTime = System.currentTimeMillis();

      /** Since we are updating now, just remove all existing ones and create new ones. */
      for (DirectoryWatcher existing : watchers.values()) {
        existing.setDone();
      }
      watchers.clear();

      /**
       * We may have built up a backlog of things to hash -- these will regenerate once we do the
       * initial scan of the newly created watch directories
       */
      additionsToProcess.clear();

      /** first pass: anything to add */
      logger.fine(watch_dirs.size() + " watchdirs");
      for (int i = 0; i < watch_dirs.size(); i++) {
        MagicPath magic = null;

        try {
          if (watch_dirs.get(i) == null) {
            continue;
          }
          if (watch_dirs.get(i).length() == 0) {
            continue;
          }
          magic = new MagicPath(watch_dirs.get(i));

        } catch (MagicPathParseException e) {
          logger.warning(e.toString() + " on " + watch_dirs.get(i));
          watch_dirs = new StringListImpl();
          break;
        }

        String path = magic.getPath();
        if (watchers.containsKey(path) == false && !alreadyWatched(path)) {
          try {
            logger.fine("new directoryWatcher: " + path);
            DirectoryWatcher dw = new DirectoryWatcher(magic, 60);
            // dw.start();
            additionsToProcess.put(
                new FileChange(dw.mTree, magic.getType(), new File(magic.getPath())));
            // dw.addListener(this);
            // watchers.put(path, dw);

          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }

      int preferredIntervalMinutes = 0;
      try {
        preferredIntervalMinutes =
            COConfigurationManager.getIntParameter("oneswarm.watchdir.refresh.interval");
      } catch (Exception e) {
        e.printStackTrace();
      }
      long duration = System.currentTimeMillis() - startSyncTime;
      long interval = 120 * 1000;
      // if( duration < 1000 ) {
      // interval = 30*1000;
      // } else { // huge scan time!
      // at least once/hour, 10X the scan time, but no less than 60
      // seconds
      interval = (long) Math.min(Math.max(120 * 1000, 20 * duration), 60 * 60 * 1000);
      interval = Math.max(120 * 1000, interval);
      // }

      if (preferredIntervalMinutes > 0) {
        logger.finest("Using provided setting for watch directory refresh interval: " + interval);
        interval = preferredIntervalMinutes * 60 * 1000;
      }

      nextSyncTime = System.currentTimeMillis() + interval;
      logger.fine(
          "Watch directories sync took: "
              + duration
              + " (wall) next in: "
              + interval
              + " ("
              + new Date(nextSyncTime)
              + ")");
    }
  }