Package de.nava.informa.utils.cleaner

Source Code of de.nava.informa.utils.cleaner.Cleaner$SchedulerCallback

//
// Informa -- RSS Library for Java
// Copyright (c) 2002 by Niko Schmuck
//
// Niko Schmuck
// http://sourceforge.net/projects/informa
// mailto:niko_schmuck@users.sourceforge.net
//
// This library is free software.
//
// You may redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License as published by the Free Software Foundation.
//
// Version 2.1 of the license should be included with this distribution in
// the file LICENSE. If the license is not included with this distribution,
// you may find a copy at the FSF web site at 'www.gnu.org' or 'www.fsf.org',
// or you may write to the Free Software Foundation, 675 Mass Ave, Cambridge,
// MA 02139 USA.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied waranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// $Id: Cleaner.java,v 1.2 2005/03/11 11:35:39 spyromus Exp $
//

package de.nava.informa.utils.cleaner;

import de.nava.informa.utils.toolkit.WorkerThread;

import de.nava.informa.core.ChannelIF;
import de.nava.informa.utils.toolkit.Scheduler;
import de.nava.informa.utils.toolkit.SchedulerCallbackIF;
import de.nava.informa.utils.toolkit.WorkersManager;
import de.nava.informa.utils.toolkit.ChannelRecord;
import de.nava.informa.utils.toolkit.WorkerThreadFactoryIF;

/**
* Cleaner is an utility class, which is intended to help applications with detection of
* unwanted (old, corrupted and etc) items.
* <p>
* Cleaner works in background. It accepts unlimited number of observers, objects of
* <code>CleanerObserverIF</code> type, that are notified each time main engine finds
* unwanted items. In order to decide which item is unwanted engine uses matchers,
* objects of <code>CleanerMatcherIF</code> type. Each matcher is a rule. You can create
* unlimited number of rules to match items and tell that they are unwanted in some way.</p>
* <p>
* Engine accepts individual channels for registration. You can register channel either
* with global or custom periods. Global period defaults to <code>DEFAULT_CLEANING_PERIOD</code>
* right after creation and can be changed with call to <code>setPeriod(long)</code> method.</p>
* <p>
* At any time you can ask cleaner to unregister channel. After that it will never be cleaned
* by engine again and it's promised that all references to the object will be removed.</p>
* <p>
* Cleaner uses <code>WorkersManager</code> to maintain asynchronous processing. This means
* that there will be several working threads in memory, which will be processing scheduled
* requests for channel cleaning. At any time you can change number of running worker threads
* starting from 1. If number of threads you require is less than current number of threads
* extra threads will be marked for termination and will quit right after finishing their current
* jobs.</p>
*
* @author Aleksey Gureev (spyromus@noizeramp.com)
*/
public class Cleaner {

  private static final long DEFAULT_CLEANING_PERIOD = 3600000; // 1 hour
  private static final int DEFAULT_WORKER_THREADS = 2;

  private WorkersManager workersManager;
  private Scheduler scheduler;

  private CompositeObserver compositeObserver;
  private CompositeMatcher compositeMatcher;

  private long globalPollPeriod = DEFAULT_CLEANING_PERIOD;

  /**
   * Creates cleaner with default number of worker threads.
   * It's possible to change number of worker threads later
   * using <code>setWorkerThreads(int)</code> method.
   */
  public Cleaner() {
    this(DEFAULT_WORKER_THREADS);
  }

  /**
   * Creates cleaner with specified number of worker threads.
   * It's possible to change number of worker threads later
   * using <code>setWorkerThreads(int)</code> method.
   *
   * @param workerThreads number of worker threads.
   */
  public Cleaner(int workerThreads) {
    // Create composite objects.
    this.compositeMatcher = new CompositeMatcher();
    this.compositeObserver = new CompositeObserver();

    // Initialize workers manager.
    workersManager = new WorkersManager(new CleanerThreadFactory(), workerThreads);

    // Initialize scheduler.
    scheduler = new Scheduler(new SchedulerCallback());
  }

  /**
   * Adds observer to the list of interested parties.
   *
   * @param observer new observer.
   */
  public final void addObserver(CleanerObserverIF observer) {
    compositeObserver.add(observer);
  }

  /**
   * Adds matcher to the list.
   *
   * @param matcher new matcher.
   */
  public final void addMatcher(CleanerMatcherIF matcher) {
    compositeMatcher.add(matcher);
  }

  /**
   * Removes observer from the list.
   *
   * @param observer observer to remove.
   */
  public final void removeObserver(CleanerObserverIF observer) {
    compositeObserver.remove(observer);
  }

  /**
   * Removes matcher from the list.
   *
   * @param matcher matcher to remove.
   */
  public final void removeMatcher(CleanerMatcherIF matcher) {
    compositeMatcher.remove(matcher);
  }

  /**
   * Registers channel for scheduled cleaning with default period (1 hour).
   *
   * @param channel channel to schedule.
   */
  public final void registerChannel(ChannelIF channel) {
    if (channel != null) scheduler.schedule(channel, globalPollPeriod, ChannelRecord.PRIO_NORMAL);
  }

  /**
   * Registers channel for scheduled cleaning with given period.
   *
   * @param channel channel to schedule.
   * @param period  period to use.
   */
  public final void registerChannel(ChannelIF channel, long period) {
    if (channel != null) {
      scheduler.schedule(channel, period, ChannelRecord.PRIO_NORMAL);
    }
  }

  /**
   * Unregisters channel from cleaning.
   *
   * @param channel channel to unregister.
   */
  public final void unregisterChannel(ChannelIF channel) {
    if (channel != null) scheduler.unschedule(channel);
  }

  /**
   * Performs immediate cleaning of the channel and reworks the schedule starting from current time.
   * If channel isn't registered yet it will be registered with normal priority.
   *
   * @param channel channel to update.
   */
  public final void cleanChannel(ChannelIF channel) {
    if (channel != null) scheduler.triggerNow(channel);
  }

  /**
   * Changes the number of worker threads. In case when new number of threads is less than
   * current extra threads will not be terminated right away while they are doing their jobs.
   * Instead of this they will be marked for termination and finish their existence after
   * job is complete.
   *
   * @param count new number of worker threads.
   */
  public final void setWorkerThreads(int count) {
    workersManager.setWorkerThreads(count);
  }

  /**
   * Sets global cleaning period to the specified value. All tasks will be rescheduled.
   *
   * @param period period in millis.
   */
  public final void setPeriod(long period) {
    this.globalPollPeriod = period;
    scheduler.rescheduleAll(period);
  }

  /**
   * Factory of working threads.
   */
  private class CleanerThreadFactory implements WorkerThreadFactoryIF {
    /**
     * Creates new worker thread object.
     *
     * @return worker thread object.
     */
    public WorkerThread create() {
      return new CleanerWorkerThread(compositeObserver, compositeMatcher);
    }
  }

  /**
   * Callback from scheduler.
   */
  private class SchedulerCallback implements SchedulerCallbackIF {
    /**
     * Invoked by scheduler when time to process channel information comes.
     *
     * @param record channel record.
     */
    public void process(ChannelRecord record) {
      workersManager.process(record);
    }
  }
}
TOP

Related Classes of de.nava.informa.utils.cleaner.Cleaner$SchedulerCallback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.