FileDocCategorySizeDatePackage
IndexController.javaAPI DocApache Lucene 2.1.020069Wed Feb 14 10:46:06 GMT 2007org.apache.lucene.gdata.search.index

IndexController

public class IndexController extends Object implements IndexEventListener, org.apache.lucene.gdata.search.SearchComponent, org.apache.lucene.gdata.server.registry.EntryEventListener
Default implementation of the {@link SearchComponent} interface. All actions on the index will be controlled from this class. Only this class grants read or write actions access to the index.
author
Simon Willnauer

Fields Summary
static final Log
LOG
private final AtomicBoolean
isInitialized
private final AtomicBoolean
destroyed
protected Map
indexerMap
private final ExecutorService
taskExecutor
Constructors Summary
public IndexController()
Creates a new IndexController -- call {@link IndexController#initialize()} to set up the controller.


                      
      
        this.taskExecutor = Executors.newCachedThreadPool();
    
Methods Summary
protected voidaddIndexSchema(org.apache.lucene.gdata.search.config.IndexSchema schema)

        checkDestroyed();
        if (schema.getName() == null)
            throw new IllegalStateException(
                    "schema has no name -- is not associated with any service");
        if (this.indexerMap.containsKey(schema.getName()))
            throw new IllegalStateException("schema for service "
                    + schema.getName() + " is already registered");
        if (LOG.isInfoEnabled())
            LOG.info("add new IndexSchema for service " + schema.getName()
                    + " -- " + schema);
        try {
            ServiceIndex bean = createIndexer(schema);
            ReferenceCounter<IndexSearcher> searcher = getNewServiceSearcher(bean.getDirectory());
            bean.setSearcher(searcher);
            this.indexerMap.put(schema.getName(), bean);
        } catch (IOException e) {
            LOG.error("Can not create indexer for service " + schema.getName(),
                    e);
            throw new GdataIndexerException(
                    "Can not create indexer for service " + schema.getName(), e);
        }

    
private voidcheckDestroyed()

        if (this.destroyed.get())
            throw new IllegalStateException(
                    "IndexController has been destroyed");   
    
private voidcheckInitialized()

        if(!this.isInitialized.get())
            throw new IllegalStateException(
            "IndexController has not been initialized");
    
public synchronized voidcommitCallBack(java.lang.String service)

see
org.apache.lucene.gdata.search.index.IndexEventListener#commitCallBack(java.lang.String)

        checkDestroyed();
        if(LOG.isInfoEnabled())
            LOG.info("CommitCallback triggered - register new searcher for service: "+service);
        /*
         * get the old searcher and replace it if possible.
         */
        ServiceIndex index = this.indexerMap.get(service);
        ReferenceCounter<IndexSearcher> searcher = index.getSearcher();

        try {
            index.setSearcher(getNewServiceSearcher(index.getDirectory()));
        } catch (IOException e) {
            LOG.fatal("Can not create new Searcher -- keep the old one ", e);
            return;
        }
        /*
         * if new searcher if registered decrement old one to get it destroyed if unused
         */
        searcher.decrementRef();
    
protected booleancreateIndexDirectory(java.io.File file)

        /*
         * use a lucene filename filter to figure out if there is an existing
         * index in the defined directory
         */
        String[] luceneFiles = file.list(new IndexFileNameFilter());
        return !(luceneFiles.length > 0);

    
protected java.io.FilecreateIndexLocation(java.lang.String path, java.lang.String name)

        if (path == null || name == null)
            throw new GdataIndexerException(
                    "Path or Name of the index location is not set Path: "
                            + path + " name: " + name);
        /*
         * check if parent e.g. the configured path is a directory
         */
        File parent = new File(path);
        if (!parent.isDirectory())
            throw new IllegalArgumentException(
                    "the given path is not a directory -- " + path);
        /*
         * try to create and throw ex if fail
         */
        if (!parent.exists())
            if (!parent.mkdir())
                throw new RuntimeException("Can not create directory -- "
                        + path);
        /*
         * try to create and throw ex if fail
         */
        File file = new File(parent, name);
        if (file.isFile())
            throw new IllegalArgumentException(
                    "A file with the name"
                            + name
                            + " already exists in "
                            + path
                            + " -- a file of the name of the service must not exist in the index location");

        if (!file.exists()) {
            if (!file.mkdir())
                throw new RuntimeException("Can not create directory -- "
                        + file.getAbsolutePath());
        }
        return file;
    
protected org.apache.lucene.gdata.search.index.IndexController$ServiceIndexcreateIndexer(org.apache.lucene.gdata.search.config.IndexSchema schema)

        GDataIndexer indexer;
        File indexLocation = createIndexLocation(schema.getIndexLocation(),
                schema.getName());
        boolean create = createIndexDirectory(indexLocation);
        Directory dir = FSDirectory.getDirectory(indexLocation, create);
        if (LOG.isInfoEnabled())
            LOG.info("Create new Indexer for IndexSchema: " + schema);
        /*
         * timed or committed indexer?! keep the possibility to let users decide
         * to use scheduled commits
         */
        if (schema.isUseTimedIndexer())
            indexer = GDataIndexer.createTimedGdataIndexer(schema, dir, create,
                    schema.getIndexerIdleTime());
        else
            indexer = GDataIndexer.createGdataIndexer(schema, dir, create);
        indexer.registerIndexEventListener(this);
        return new ServiceIndex(schema, indexer, dir);
    
private voidcreateNewDeleteAllEntriesTask(org.apache.lucene.gdata.data.ServerBaseFeed feed)

        checkDestroyed();
        checkInitialized();
        if(LOG.isInfoEnabled())
            LOG.info("Deleting all entries for feed dispatch new IndexDocumentBuilder -- "+feed.getId());
        String serviceName = feed.getServiceConfig().getName();
        ServiceIndex bean = this.indexerMap.get(serviceName);
        if (bean == null)
            throw new RuntimeException("no indexer for service " + serviceName
                    + " registered");
        Lock lock = bean.getLock();
        lock.lock();
        try{
            IndexDocumentBuilder<IndexDocument> callable = new IndexFeedDeleteTask(feed.getId());
            sumbitTask(callable,bean.getIndexer());
        }finally{
            lock.unlock();
        }
            
        
    
private voidcreateNewIndexerTask(org.apache.lucene.gdata.data.ServerBaseEntry entry, IndexAction action)

        checkDestroyed();
        checkInitialized();
        String serviceName = entry.getServiceConfig().getName();
        if (LOG.isInfoEnabled())
            LOG.info("New Indexer Task submitted - Action: " + action
                    + " for service: " + serviceName);
        ServiceIndex bean = this.indexerMap.get(serviceName);
        if (bean == null)
            throw new RuntimeException("no indexer for service " + serviceName
                    + " registered");
        /*
         * lock on service to synchronize the event order. This lock has
         * fairness parameter set to true. Grant access to the longest waiting
         * thread. Using fairness is slower but is acceptable in this context
         */
        Lock lock = bean.getLock();
        lock.lock();
        try {
            IndexSchema schema = bean.getSchema();
            boolean commitAfter = bean.incrementActionAndReset(schema.getCommitAfterDocuments());
            IndexDocumentBuilder<IndexDocument> callable = new IndexDocumentBuilderTask<IndexDocument>(
                    entry, bean.getSchema(), action, commitAfter,bean.getOptimize(schema.getOptimizeAfterCommit()));
            sumbitTask(callable,bean.getIndexer());
        } finally {
            /*
             * make sure to unlock
             */
            lock.unlock();
        }

    
public synchronized voiddestroy()

see
org.apache.lucene.gdata.search.SearchComponent#destroy()

        checkDestroyed();
        if(!this.isInitialized.get())
            return;
        this.destroyed.set(true);
        this.isInitialized.set(false);
        LOG.info("Shutting down IndexController -- destroy has been called");
        Set<Entry<String, ServiceIndex>> entrySet = this.indexerMap.entrySet();
        for (Entry<String, ServiceIndex> entry : entrySet) {
            ServiceIndex bean = entry.getValue();
            bean.getSearcher().decrementRef();
            GDataIndexer indexer = bean.getIndexer();
            try {
                indexer.destroy();
            } catch (IOException e) {
                LOG.warn("Can not destroy indexer for service: "
                        + bean.getSchema().getName(), e);
            }
        }
        this.taskExecutor.shutdown();
        this.indexerMap.clear();
    
public voidfireDeleteAllEntries(org.apache.lucene.gdata.data.ServerBaseFeed feed)

see
org.apache.lucene.gdata.server.registry.EntryEventListener#fireDeleteAllEntries(org.apache.lucene.gdata.data.ServerBaseFeed)

        createNewDeleteAllEntriesTask(feed);
    
public voidfireDeleteEvent(org.apache.lucene.gdata.data.ServerBaseEntry entry)

see
org.apache.lucene.gdata.server.registry.EntryEventListener#fireDeleteEvent(org.apache.lucene.gdata.data.ServerBaseEntry)

        createNewIndexerTask(entry, IndexAction.DELETE);

    
public voidfireInsertEvent(org.apache.lucene.gdata.data.ServerBaseEntry entry)

see
org.apache.lucene.gdata.server.registry.EntryEventListener#fireInsertEvent(org.apache.lucene.gdata.data.ServerBaseEntry)

        createNewIndexerTask(entry, IndexAction.INSERT);
    
public voidfireUpdateEvent(org.apache.lucene.gdata.data.ServerBaseEntry entry)

see
org.apache.lucene.gdata.server.registry.EntryEventListener#fireUpdateEvent(org.apache.lucene.gdata.data.ServerBaseEntry)

        createNewIndexerTask(entry, IndexAction.UPDATE);
    
private org.apache.lucene.gdata.utils.ReferenceCountergetNewServiceSearcher(org.apache.lucene.store.Directory dir)

        if(LOG.isInfoEnabled())
            LOG.info("Create new ServiceSearcher");
        IndexSearcher searcher = new IndexSearcher(dir);
        ReferenceCounter<IndexSearcher> holder = new ReferenceCounter<IndexSearcher>(
                searcher) {

            @Override
            protected void close() {
                try {
                    LOG
                            .info("Close IndexSearcher -- Zero references remaining");
                    this.resource.close();
                } catch (IOException e) {
                    LOG.warn("Can not close IndexSearcher -- ", e);
                }
            }

        };
        holder.increamentReference();
        return holder;
    
public org.apache.lucene.gdata.search.GDataSearchergetServiceSearcher(org.apache.lucene.gdata.server.registry.ProvidedService service)

see
org.apache.lucene.gdata.search.SearchComponent#getServiceSearcher(org.apache.lucene.gdata.server.registry.ProvidedService)

        checkDestroyed();
        checkInitialized();

        /*
         * get and increment. searcher will be decremented if GdataSearcher is
         * closed
         */
        ReferenceCounter<IndexSearcher> searcher;
        synchronized (this) {
            ServiceIndex serviceIndex = this.indexerMap.get(service.getName());
            if(serviceIndex == null)
                throw new RuntimeException("no index for service "+service.getName());
            searcher = serviceIndex.getSearcher();
            searcher.increamentReference();
        }

        return new StandardGdataSearcher(searcher);
    
public synchronized voidinitialize()

see
org.apache.lucene.gdata.search.SearchComponent#initialize()

        if (this.isInitialized.get())
            throw new IllegalStateException(
                    "IndexController is already initialized");
        this.destroyed.set(false);
        /*
         * if this fails the server must not startup --> throw runtime exception
         */
        GDataServerRegistry.getRegistry().registerEntryEventListener(this);

        GDataServerRegistry.getRegistry().registerEntryEventListener(this);
        Collection<ProvidedService> services = GDataServerRegistry
                .getRegistry().getServices();
        this.indexerMap = new ConcurrentHashMap<String, ServiceIndex>(services
                .size());
       
        for (ProvidedService service : services) {
            IndexSchema schema = service.getIndexSchema();
            /*
             * initialize will fail if mandatory values are not set. This is
             * just a
             */
            schema.initialize();
            addIndexSchema(schema);
        }
        this.isInitialized.set(true);
        

    
private voidsumbitTask(java.util.concurrent.Callable callable, GDataIndexer indexer)

        Future<IndexDocument> task = this.taskExecutor.submit(callable);
        try {
            indexer.addIndexableDocumentTask(task);
        } catch (InterruptedException e) {
            throw new GdataIndexerException(
                    "Can not accept any index tasks -- interrupted. ", e);

        }