Package org.infinispan.lucene.cachestore

Source Code of org.infinispan.lucene.cachestore.LuceneCacheLoader

package org.infinispan.lucene.cachestore;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.lucene.store.FSDirectory;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheLoaderConfiguration;
import org.infinispan.container.entries.ImmortalCacheEntry;
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.loaders.CacheLoaderException;
import org.infinispan.loaders.spi.AbstractCacheLoader;
import org.infinispan.loaders.spi.CacheLoader;
import org.infinispan.lucene.IndexScopedKey;
import org.infinispan.lucene.cachestore.configuration.LuceneCacheLoaderConfiguration;
import org.infinispan.lucene.logging.Log;
import org.infinispan.commons.marshall.StreamingMarshaller;
import org.infinispan.util.logging.LogFactory;

/**
* A CacheLoader meant to load Lucene index(es) from filesystem based Lucene index(es).
* This is exclusively suitable for keys being used by the Directory, any other key
* will be ignored.
*
* The InfinispanDirectory requires indexes to be named; this CacheLoader needs to be configured
* with the path of the root directory containing the indexes, and expects index names to match directory
* names under this common root path.
*
* @author Sanne Grinovero
* @since 5.2
*/
public class LuceneCacheLoader extends AbstractCacheLoader {

   private static final Log log = LogFactory.getLog(LuceneCacheLoader.class, Log.class);

   private final ConcurrentHashMap<String,DirectoryLoaderAdaptor> openDirectories = new ConcurrentHashMap<String, DirectoryLoaderAdaptor>();
   private String fileRoot;
   private File rootDirectory;
   private int autoChunkSize;

   private LuceneCacheLoaderConfiguration configuration;

   @Override
   public void init(CacheLoaderConfiguration configuration, final Cache<?, ?> cache,
                    final StreamingMarshaller m) throws CacheLoaderException {
      this.configuration = validateConfigurationClass(configuration, LuceneCacheLoaderConfiguration.class);

      super.init(configuration, cache, m);
      this.fileRoot = this.configuration.location();
      this.autoChunkSize = this.configuration.autoChunkSize();
   }

   @Override
   public InternalCacheEntry load(final Object key) throws CacheLoaderException {
      if (key instanceof IndexScopedKey) {
         final IndexScopedKey indexKey = (IndexScopedKey)key;
         DirectoryLoaderAdaptor directoryAdaptor = getDirectory(indexKey);
         Object value = directoryAdaptor.load(indexKey);
         if (value != null) {
            return new ImmortalCacheEntry(key, value);
         }
         else {
            return null;
         }
      }
      else {
         log.cacheLoaderIgnoringKey(key);
         return null;
      }
   }

   @Override
   public boolean containsKey(final Object key) throws CacheLoaderException {
      if (key instanceof IndexScopedKey) {
         final IndexScopedKey indexKey = (IndexScopedKey)key;
         final DirectoryLoaderAdaptor directoryAdaptor = getDirectory(indexKey);
         return directoryAdaptor.containsKey(indexKey);
      }
      else {
         log.cacheLoaderIgnoringKey(key);
         return false;
      }
   }

   @Override
   public Set<InternalCacheEntry> loadAll() throws CacheLoaderException {
      return load(Integer.MAX_VALUE);
   }

   /**
    * Loads up to a specific number of entries.  There is no guarantee about the order of loaded entries.
    */
   @Override
   public Set<InternalCacheEntry> load(int maxEntries) throws CacheLoaderException {
      scanForUnknownDirectories();
      final HashSet<InternalCacheEntry> allInternalEntries = new HashSet<InternalCacheEntry>();
      for (DirectoryLoaderAdaptor dir : openDirectories.values()) {
         dir.loadAllEntries(allInternalEntries, maxEntries);
      }
      return allInternalEntries;
   }

   @Override
   public Set<Object> loadAllKeys(final Set keysToExclude) throws CacheLoaderException {
      scanForUnknownDirectories();
      final HashSet allKeys = new HashSet(); //filthy generic covariants!
      for (DirectoryLoaderAdaptor dir : openDirectories.values()) {
         dir.loadAllKeys(allKeys, keysToExclude);
      }
      return allKeys;
   }

   /**
    * There might be Directories we didn't store yet in the openDirectories Map.
    * Make sure they are all initialized before serving methods such as {@link #loadAll()}
    * or {@link #loadAllKeys(Set)}.
    */
   private void scanForUnknownDirectories() {
      File[] filesInRoot = rootDirectory.listFiles();
      for (File maybeDirectory : filesInRoot) {
         if (maybeDirectory.isDirectory()) {
            String name = maybeDirectory.getName();
            try {
               getDirectory(name);
            } catch (CacheLoaderException e) {
               log.couldNotWalkDirectory(name, e);
            }
         }
      }
   }

   @Override
   public void start() throws CacheLoaderException {
      rootDirectory = new File(fileRoot);
      if (rootDirectory.exists()) {
         if (!rootDirectory.isDirectory() || ! rootDirectory.canRead()) {
            // we won't verify write capability to support read-only - should we have an explicit option for it?
            throw log.rootDirectoryIsNotADirectory(fileRoot);
         }
      }
      else {
         boolean mkdirsSuccess = rootDirectory.mkdirs();
         if (!mkdirsSuccess) {
            throw log.unableToCreateDirectory(fileRoot);
         }
      }
   }

   @Override
   public void stop() throws CacheLoaderException {
      for (Entry<String, DirectoryLoaderAdaptor> entry : openDirectories.entrySet()) {
         DirectoryLoaderAdaptor directory = entry.getValue();
         directory.close();
      }
   }

   private DirectoryLoaderAdaptor getDirectory(final IndexScopedKey indexKey) throws CacheLoaderException {
      final String indexName = indexKey.getIndexName();
      return getDirectory(indexName);
   }

   /**
    * Looks up the Directory adapter if it's already known, or attempts to initialize indexes.
    */
   private DirectoryLoaderAdaptor getDirectory(final String indexName) throws CacheLoaderException {
      DirectoryLoaderAdaptor adapter = openDirectories.get(indexName);
      if (adapter == null) {
         synchronized (openDirectories) {
            adapter = openDirectories.get(indexName);
            if (adapter == null) {
               final File path = new File(this.rootDirectory, indexName);
               final FSDirectory directory = openLuceneDirectory(path);
               final InternalDirectoryContract wrapped = ContractAdaptorFactory.wrapNativeDirectory(directory);
               adapter = new DirectoryLoaderAdaptor(wrapped, indexName, autoChunkSize);
               openDirectories.put(indexName, adapter);
            }
         }
      }
      return adapter;
   }

   /**
    * Attempts to open a Lucene FSDirectory on the specified path
    */
   private FSDirectory openLuceneDirectory(final File path) throws CacheLoaderException {
      try {
         return FSDirectory.open(path);
      } catch (IOException e) {
         throw log.exceptionInCacheLoader(e);
      }
   }

}
TOP

Related Classes of org.infinispan.lucene.cachestore.LuceneCacheLoader

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.