001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.search.lucene;
016    
017    import com.liferay.portal.kernel.executor.PortalExecutorManagerUtil;
018    
019    import java.io.IOException;
020    
021    import org.apache.lucene.index.IndexReader;
022    import org.apache.lucene.index.IndexWriter;
023    import org.apache.lucene.search.IndexSearcher;
024    import org.apache.lucene.store.AlreadyClosedException;
025    import org.apache.lucene.store.Directory;
026    
027    /**
028     * @author Tina Tian
029     * @author Shuyang Zhou
030     */
031    public class IndexSearcherManager {
032    
033            public IndexSearcherManager(Directory directory) throws IOException {
034                    _indexSearcher = _createIndexSearcher(
035                            IndexReader.open(directory, true));
036            }
037    
038            public IndexSearcherManager(IndexWriter writer) throws IOException {
039                    _indexSearcher = _createIndexSearcher(IndexReader.open(writer, true));
040            }
041    
042            public IndexSearcher acquire() throws IOException {
043                    if (_invalid) {
044                            synchronized (this) {
045                                    if (_invalid) {
046                                            IndexSearcher indexSearcher = _indexSearcher;
047    
048                                            if (indexSearcher == null) {
049                                                    throw new AlreadyClosedException(
050                                                            "Index searcher manager is closed");
051                                            }
052    
053                                            IndexReader newIndexReader = IndexReader.openIfChanged(
054                                                    indexSearcher.getIndexReader());
055    
056                                            if (newIndexReader != null) {
057                                                    _indexSearcher = _createIndexSearcher(newIndexReader);
058    
059                                                    release(indexSearcher);
060                                            }
061    
062                                            _invalid = false;
063                                    }
064                            }
065                    }
066    
067                    IndexSearcher indexSearcher = null;
068    
069                    while ((indexSearcher = _indexSearcher) != null) {
070                            IndexReader indexReader = indexSearcher.getIndexReader();
071    
072                            if (indexReader.tryIncRef()) {
073                                    return indexSearcher;
074                            }
075    
076                            if (indexSearcher == _indexSearcher) {
077                                    throw new IllegalStateException(
078                                            "Index reader was closed externally");
079                            }
080                    }
081    
082                    throw new AlreadyClosedException("Index searcher manager is closed");
083            }
084    
085            public synchronized void close() throws IOException {
086                    IndexSearcher indexSearcher = _indexSearcher;
087    
088                    _indexSearcher = null;
089    
090                    release(indexSearcher);
091    
092                    PortalExecutorManagerUtil.shutdown(
093                            IndexSearcherManager.class.getName());
094            }
095    
096            public synchronized void invalidate() {
097                    _invalid = true;
098            }
099    
100            public void release(IndexSearcher indexSearcher) throws IOException {
101                    if (indexSearcher == null) {
102                            return;
103                    }
104    
105                    IndexReader indexReader = indexSearcher.getIndexReader();
106    
107                    indexReader.decRef();
108            }
109    
110            private IndexSearcher _createIndexSearcher(IndexReader indexReader) {
111                    IndexSearcher indexSearcher = new IndexSearcher(
112                            indexReader,
113                            PortalExecutorManagerUtil.getPortalExecutor(
114                                    IndexSearcherManager.class.getName()));
115    
116                    indexSearcher.setDefaultFieldSortScoring(true, false);
117                    indexSearcher.setSimilarity(new FieldWeightSimilarity());
118    
119                    return indexSearcher;
120            }
121    
122            private volatile IndexSearcher _indexSearcher;
123            private volatile boolean _invalid;
124    
125    }