public void destroy() {
    TRTrackerAnnouncerFactoryImpl.destroy(this);

    List<TRTrackerAnnouncerHelper> to_destroy;

    synchronized (this) {
      destroyed = true;

      to_destroy = announcers.getList();
    }

    for (TRTrackerAnnouncer announcer : to_destroy) {

      announcer.destroy();
    }

    TimerEvent ev = event;

    if (ev != null) {

      ev.cancel();
    }
  }
  public static void queueMessage(
      PlatformMessage message, PlatformMessengerListener listener, boolean addToBottom) {

    if (!initialized) {
      init();
    }

    if (message == null) {
      debug("fire timerevent");
    }
    queue_mon.enter();
    try {
      long fireBefore;
      String queueID = null;
      if (message != null) {
        long networkID = message.getContentNetworkID();
        if (networkID <= 0) {
          debug("Content Network invalid for " + message);
          return;
        }
        if (!message.sendAZID()) {
          queueID = QUEUE_NOAZID;
        } else {
          queueID = QUEUE_NORMAL;
        }
        queueID += networkID;

        Map<PlatformMessage, PlatformMessengerListener> mapQueue = (Map) mapQueues.get(queueID);
        if (mapQueue == null) {
          mapQueue = new LinkedHashMap<PlatformMessage, PlatformMessengerListener>();
          mapQueues.put(queueID, mapQueue);
        }
        mapQueue.put(message, listener);

        debug(
            "q "
                + queueID
                + "("
                + mapQueue.size()
                + ") "
                + message.toShortString()
                + ": "
                + message
                + " @ "
                + new Date(message.getFireBefore())
                + "; in "
                + (message.getFireBefore() - SystemTime.getCurrentTime())
                + "ms");

        fireBefore = message.getFireBefore();
      } else {
        fireBefore = SystemTime.getCurrentTime();
      }

      if (queueID != null) {
        try {
          mon_mapTimerEvents.enter();

          TimerEvent timerEvent = mapTimerEvents.get(queueID);

          if (timerEvent == null || timerEvent.hasRun() || fireBefore < timerEvent.getWhen()) {
            if (timerEvent != null) {
              mapTimerEvents.remove(timerEvent);
              timerEvent.cancel();
            }

            final String fQueueID = queueID;
            timerEvent =
                timerProcess.addEvent(
                    fireBefore,
                    new TimerEventPerformer() {
                      public void perform(TimerEvent event) {
                        try {
                          mon_mapTimerEvents.enter();

                          mapTimerEvents.remove(event);
                        } finally {
                          mon_mapTimerEvents.exit();
                        }

                        Map mapQueue = mapQueues.get(fQueueID);
                        while (mapQueue != null && mapQueue.size() > 0) {
                          processQueue(fQueueID, mapQueue);
                        }
                        /*
                        Object[] keys = mapQueues.keySet().toArray();
                        for (int i = 0; i < keys.length; i++) {
                        	Map mapQueue = mapQueues.get(keys[i]);
                        	while (mapQueue != null && mapQueue.size() > 0) {
                        		processQueue(mapQueue);
                        	}
                        }
                        */
                      }
                    });
            mapTimerEvents.put(queueID, timerEvent);
          }
          if (timerEvent != null) {
            debug(
                " next q process for  "
                    + queueID
                    + " in "
                    + (timerEvent.getWhen() - SystemTime.getCurrentTime()));
          }
        } finally {
          mon_mapTimerEvents.exit();
        }
      }
    } finally {
      queue_mon.exit();
    }
  }
  protected void calculateSchedule() {
    Subscription[] subs = manager.getSubscriptions();

    synchronized (this) {
      if (!schedulng_permitted) {

        return;
      }

      if (schedule_in_progress) {

        return;
      }

      long next_ready_time = Long.MAX_VALUE;

      for (int i = 0; i < subs.length; i++) {

        Subscription sub = subs[i];

        if (!sub.isSubscribed()) {

          continue;
        }

        SubscriptionHistory history = sub.getHistory();

        if (!history.isEnabled()) {

          continue;
        }

        long next_scan = getNextScan(sub);

        sub.setUserData(SCHEDULER_NEXT_SCAN_KEY, new Long(next_scan));

        if (next_scan < next_ready_time) {

          next_ready_time = next_scan;
        }
      }

      long old_when = 0;

      if (schedule_event != null) {

        old_when = schedule_event.getWhen();

        schedule_event.cancel();

        schedule_event = null;
      }

      if (next_ready_time < Long.MAX_VALUE) {

        long now = SystemTime.getCurrentTime();

        if (now < last_schedule || now - last_schedule < 30 * 1000) {

          if (next_ready_time - now < 30 * 1000) {

            next_ready_time = now + 30 * 1000;
          }
        }

        log(
            "Calculate : "
                + "old_time="
                + new SimpleDateFormat().format(new Date(old_when))
                + ", new_time="
                + new SimpleDateFormat().format(new Date(next_ready_time)));

        schedule_event =
            SimpleTimer.addEvent(
                "SS:Scheduler",
                next_ready_time,
                new TimerEventPerformer() {
                  public void perform(TimerEvent event) {
                    synchronized (SubscriptionSchedulerImpl.this) {
                      if (schedule_in_progress) {

                        return;
                      }

                      schedule_in_progress = true;

                      last_schedule = SystemTime.getCurrentTime();

                      schedule_event = null;
                    }

                    new AEThread2("SS:Sched", true) {
                      public void run() {
                        try {
                          schedule();

                        } finally {

                          synchronized (SubscriptionSchedulerImpl.this) {
                            schedule_in_progress = false;
                          }

                          calculateSchedule();
                        }
                      }
                    }.start();
                  }
                });
      }
    }
  }