alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Lucene example source code file (FilterManager.java)

This example Lucene source code file (FilterManager.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Lucene tags/keywords

default_cache_clean_size, default_cache_sleep_time, deprecated, filter, filter, filtercleaner, filtercleaner, filteritem, filteritem, filtermanager, filtermanager, interruptedexception, thread, threadinterruptedexception, util

The Lucene FilterManager.java source code

package org.apache.lucene.search;

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;

import org.apache.lucene.util.ThreadInterruptedException;

/**
 * Filter caching singleton. It can be used to save filters locally for reuse.
 * This class makes it possible to cache Filters even when using RMI, as it
 * keeps the cache on the searcher side of the RMI connection.
 * 
 * Also could be used as a persistent storage for any filter as long as the
 * filter provides a proper hashCode(), as that is used as the key in the cache.
 * 
 * The cache is periodically cleaned up from a separate thread to ensure the
 * cache doesn't exceed the maximum size.
 * 
 * @deprecated used by remote package which is deprecated as well. You should
 *             use {@link CachingWrapperFilter} if you wish to cache
 *             {@link Filter}s.
 */
@Deprecated
public class FilterManager {

  protected static FilterManager manager;
  
  /** The default maximum number of Filters in the cache */
  protected static final int  DEFAULT_CACHE_CLEAN_SIZE = 100;
  /** The default frequency of cache cleanup */
  protected static final long DEFAULT_CACHE_SLEEP_TIME = 1000 * 60 * 10;

  /** The cache itself */
  protected Map<Integer,FilterItem>           cache;
  /** Maximum allowed cache size */
  protected int           cacheCleanSize;
  /** Cache cleaning frequency */
  protected long          cleanSleepTime;
  /** Cache cleaner that runs in a separate thread */
  protected FilterCleaner filterCleaner;

  public synchronized static FilterManager getInstance() {
    if (manager == null) {
      manager = new FilterManager();
    }
    return manager;
  }

  /**
   * Sets up the FilterManager singleton.
   */
  protected FilterManager() {
    cache            = new HashMap<Integer,FilterItem>();
    cacheCleanSize   = DEFAULT_CACHE_CLEAN_SIZE; // Let the cache get to 100 items
    cleanSleepTime   = DEFAULT_CACHE_SLEEP_TIME; // 10 minutes between cleanings

    filterCleaner   = new FilterCleaner();
    Thread fcThread = new Thread(filterCleaner);
    // set to be a Daemon so it doesn't have to be stopped
    fcThread.setDaemon(true);
    fcThread.start();
  }
  
  /**
   * Sets the max size that cache should reach before it is cleaned up
   * @param cacheCleanSize maximum allowed cache size
   */
  public void setCacheSize(int cacheCleanSize) {
    this.cacheCleanSize = cacheCleanSize;
  }

  /**
   * Sets the cache cleaning frequency in milliseconds.
   * @param cleanSleepTime cleaning frequency in milliseconds
   */
  public void setCleanThreadSleepTime(long cleanSleepTime) {
    this.cleanSleepTime  = cleanSleepTime;
  }

  /**
   * Returns the cached version of the filter.  Allows the caller to pass up
   * a small filter but this will keep a persistent version around and allow
   * the caching filter to do its job.
   * 
   * @param filter The input filter
   * @return The cached version of the filter
   */
  public Filter getFilter(Filter filter) {
    synchronized(cache) {
      FilterItem fi = null;
      fi = cache.get(Integer.valueOf(filter.hashCode()));
      if (fi != null) {
        fi.timestamp = new Date().getTime();
        return fi.filter;
      }
      cache.put(Integer.valueOf(filter.hashCode()), new FilterItem(filter));
      return filter;
    }
  }

  /**
   * Holds the filter and the last time the filter was used, to make LRU-based
   * cache cleaning possible.
   * TODO: Clean this up when we switch to Java 1.5
   */
  protected class FilterItem {
    public Filter filter;
    public long   timestamp;

    public FilterItem (Filter filter) {        
      this.filter = filter;
      this.timestamp = new Date().getTime();
    }
  }


  /**
   * Keeps the cache from getting too big.
   * If we were using Java 1.5, we could use LinkedHashMap and we would not need this thread
   * to clean out the cache.
   * 
   * The SortedSet sortedFilterItems is used only to sort the items from the cache,
   * so when it's time to clean up we have the TreeSet sort the FilterItems by
   * timestamp.
   * 
   * Removes 1.5 * the numbers of items to make the cache smaller.
   * For example:
   * If cache clean size is 10, and the cache is at 15, we would remove (15 - 10) * 1.5 = 7.5 round up to 8.
   * This way we clean the cache a bit more, and avoid having the cache cleaner having to do it frequently.
   */
  protected class FilterCleaner implements Runnable  {

    private boolean running = true;
    private TreeSet<Map.Entry sortedFilterItems;

    public FilterCleaner() {
      sortedFilterItems = new TreeSet<Map.Entry(new Comparator>() {
        public int compare(Map.Entry<Integer,FilterItem> a, Map.Entry b) {
            FilterItem fia = a.getValue();
            FilterItem fib = b.getValue();
            if ( fia.timestamp == fib.timestamp ) {
              return 0;
            }
            // smaller timestamp first
            if ( fia.timestamp < fib.timestamp ) {
              return -1;
            }
            // larger timestamp last
            return 1;
          
        }
      });
    }

    public void run () {
      while (running) {

        // sort items from oldest to newest 
        // we delete the oldest filters 
        if (cache.size() > cacheCleanSize) {
          // empty the temporary set
          sortedFilterItems.clear();
          synchronized (cache) {
            sortedFilterItems.addAll(cache.entrySet());
            Iterator<Map.Entry it = sortedFilterItems.iterator();
            int numToDelete = (int) ((cache.size() - cacheCleanSize) * 1.5);
            int counter = 0;
            // loop over the set and delete all of the cache entries not used in a while
            while (it.hasNext() && counter++ < numToDelete) {
              Map.Entry<Integer,FilterItem> entry = it.next();
              cache.remove(entry.getKey());
            }
          }
          // empty the set so we don't tie up the memory
          sortedFilterItems.clear();
        }
        // take a nap
        try {
          Thread.sleep(cleanSleepTime);
        } catch (InterruptedException ie) {
          throw new ThreadInterruptedException(ie);
        }
      }
    }
  }
}

Other Lucene examples (source code examples)

Here is a short list of links related to this Lucene FilterManager.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.