Package proj.zoie.impl.indexing

Source Code of proj.zoie.impl.indexing.SmartReaderCache

package proj.zoie.impl.indexing;

import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.index.IndexReader;

import proj.zoie.api.IndexReaderFactory;
import proj.zoie.api.ZoieException;
import proj.zoie.api.ZoieIndexReader;

public class SmartReaderCache<R extends IndexReader> extends AbstractReaderCache<R>
{
  private static final Logger log = Logger.getLogger(DefaultReaderCache.class);
  private final Thread _maintenance;
  private volatile boolean alreadyShutdown = false;
  private volatile List<ZoieIndexReader<R>> cachedreaders = new ArrayList<ZoieIndexReader<R>>(0);
  private volatile long cachedreaderTimestamp = 0;
  private final Object cachemonitor = new Object();
  private long _freshness = 10000L;
  private final IndexReaderFactory<ZoieIndexReader<R>> _readerfactory;
  private final HashMap<WeakReference<List<ZoieIndexReader<R>>>, List<ZoieIndexReader<R>>> readermap;
  private final ReferenceQueue<List<ZoieIndexReader<R>>> refq;

  public SmartReaderCache(IndexReaderFactory<ZoieIndexReader<R>> readerfactory)
  {
    readermap = new HashMap<WeakReference<List<ZoieIndexReader<R>>>, List<ZoieIndexReader<R>>>();
    refq = new ReferenceQueue<List<ZoieIndexReader<R>>>();
    _readerfactory = readerfactory;
    _maintenance = newMaintenanceThread();
    _maintenance.setDaemon(true);
  }

  @Override
  public List<ZoieIndexReader<R>> getIndexReaders()
  {
    return cachedreaders;
  }

  @Override
  public void returnIndexReaders(List<ZoieIndexReader<R>> readers)
  {
  }

  public void refreshCache(long timeout) throws ZoieException
  {
    long begintime = System.currentTimeMillis();
    while (cachedreaderTimestamp <= begintime)
    {
      synchronized (cachemonitor)
      {
        cachemonitor.notifyAll();
        long elapsed = System.currentTimeMillis() - begintime;
        if (elapsed > timeout)
        {
          log.debug("refreshCached reader timeout in " + elapsed + "ms");
          throw new ZoieException("refreshCached reader timeout in " + elapsed + "ms");
        }
        long timetowait = Math.min(timeout - elapsed, 200);
        try
        {
          cachemonitor.wait(timetowait);
        } catch (InterruptedException e)
        {
          log.warn("refreshCache", e);
        }
      }
    }
  }

  @Override
  public void shutdown()
  {
    _freshness = 30000L;
    alreadyShutdown = true;
  }

  @Override
  public void start()
  {
    _maintenance.start();
  }

  @Override
  public long getFreshness()
  {
    return _freshness;
  }

  @Override
  public void setFreshness(long freshness)
  {
    _freshness = freshness;
  }

  private Thread newMaintenanceThread()
  {
    return new Thread("zoie-indexReader-maintenance")
    {
      @Override
      public void run()
      {
        while (true)
        {
          try
          {
            synchronized (cachemonitor)
            {
              cachemonitor.wait(_freshness);
            }
          } catch (InterruptedException e)
          {
            Thread.interrupted(); // clear interrupted state
          }
          List<ZoieIndexReader<R>> newreaders = null;
          if (alreadyShutdown)
          {
            newreaders = new ArrayList<ZoieIndexReader<R>>();
            // clean up and quit
          } else
          {
            try
            {
              newreaders = _readerfactory.getIndexReaders();
            } catch (IOException e)
            {
              log.info("zoie-indexReader-maintenance", e);
              newreaders = new ArrayList<ZoieIndexReader<R>>();
            }
          }
          cachedreaders = new ArrayList<ZoieIndexReader<R>>(newreaders);
          WeakReference<List<ZoieIndexReader<R>>> w = new WeakReference<List<ZoieIndexReader<R>>>(cachedreaders, refq);
          readermap.put(w, newreaders); // when nobody uses cachedreaders, we will clean newreaders :)
          System.out.println("add   " + newreaders);
          cachedreaderTimestamp = System.currentTimeMillis();
          synchronized (cachemonitor)
          {
            cachemonitor.notifyAll();
          }
          // clearning and reference counting on the ones no longer in use
          Reference<? extends List<ZoieIndexReader<R>>> wclean = null;
          while((wclean = refq.poll()) != null)
          {
            List<ZoieIndexReader<R>> readers = readermap.remove(wclean);
            System.out.println("clean " + readers);
            _readerfactory.returnIndexReaders(readers);
          }
        }
      }
    };
  }

  public static ReaderCacheFactory FACTORY = new ReaderCacheFactory(){

    @Override
    public <R extends IndexReader> AbstractReaderCache<R> newInstance(IndexReaderFactory<ZoieIndexReader<R>> readerfactory)
    {
      return new SmartReaderCache<R>(readerfactory);
    }};
}
TOP

Related Classes of proj.zoie.impl.indexing.SmartReaderCache

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.