|
|
@@ -8,12 +8,12 @@ import java.util.Map;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
import org.apache.lucene.index.DirectoryReader;
|
|
|
-import org.apache.lucene.index.IndexReader;
|
|
|
import org.apache.lucene.search.IndexSearcher;
|
|
|
import org.apache.lucene.store.FSDirectory;
|
|
|
import org.apache.lucene.store.NIOFSDirectory;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
|
|
|
import com.uas.search.b2b.service.SearchService.Table_name;
|
|
|
import com.uas.search.console.b2b.util.ClassAndTableNameUtils;
|
|
|
@@ -27,6 +27,8 @@ import com.uas.search.console.b2b.util.SearchUtils;
|
|
|
*/
|
|
|
public class IndexSearcherManager {
|
|
|
|
|
|
+ private static volatile IndexSearcherManager instance;
|
|
|
+
|
|
|
/**
|
|
|
* 用于存放指定表的索引IndexSearcher
|
|
|
*/
|
|
|
@@ -37,15 +39,31 @@ public class IndexSearcherManager {
|
|
|
*/
|
|
|
private Map<Table_name, Boolean> reopening = new ConcurrentHashMap<>();
|
|
|
|
|
|
+ /**
|
|
|
+ * 标识在后台是否存在线程在等待刷新缓存中的索引
|
|
|
+ */
|
|
|
+ private Map<Table_name, Boolean> waitingFlushCache = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
private Logger logger = LoggerFactory.getLogger(getClass());
|
|
|
|
|
|
- public IndexSearcherManager() {
|
|
|
+ private IndexSearcherManager() {
|
|
|
List<Table_name> tableNames = ClassAndTableNameUtils.getTableNames();
|
|
|
for (Table_name tableName : tableNames) {
|
|
|
reopening.put(tableName, false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public static IndexSearcherManager getInstance() {
|
|
|
+ if (instance == null) {
|
|
|
+ synchronized (IndexSearcherManager.class) {
|
|
|
+ if (instance == null) {
|
|
|
+ instance = new IndexSearcherManager();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return instance;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 对指定表的IndexSearcher进行初始化操作
|
|
|
*
|
|
|
@@ -53,21 +71,21 @@ public class IndexSearcherManager {
|
|
|
* 表名
|
|
|
* @return 指定表的FSDirectory
|
|
|
*/
|
|
|
- private synchronized FSDirectory warm(Table_name tableName) {
|
|
|
- String indexPath = SearchUtils.getIndexPath(tableName);
|
|
|
- FSDirectory directory = null;
|
|
|
+ private synchronized void warm(Table_name tableName) {
|
|
|
IndexSearcher indexSearcher = indexSearchers.get(tableName);
|
|
|
- // 本来NIOFSDirectory速度更快,但因为jre的bug,在Windows平台上,其性能很差
|
|
|
- try {
|
|
|
- if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
|
|
|
- directory = FSDirectory.open(Paths.get(indexPath));
|
|
|
- } else {
|
|
|
- directory = NIOFSDirectory.open(Paths.get(indexPath));
|
|
|
- }
|
|
|
+ // 不为空的话说明索引已成功加载
|
|
|
+ if (indexSearcher == null) {
|
|
|
+ String indexPath = SearchUtils.getIndexPath(tableName);
|
|
|
+ FSDirectory directory = null;
|
|
|
+ // 本来NIOFSDirectory速度更快,但因为jre的bug,在Windows平台上,其性能很差
|
|
|
+ try {
|
|
|
+ if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
|
|
|
+ directory = FSDirectory.open(Paths.get(indexPath));
|
|
|
+ } else {
|
|
|
+ directory = NIOFSDirectory.open(Paths.get(indexPath));
|
|
|
+ }
|
|
|
|
|
|
- File[] files = directory.getDirectory().toFile().listFiles();
|
|
|
- // 不为空的话说明索引已成功加载
|
|
|
- if (indexSearcher == null) {
|
|
|
+ File[] files = directory.getDirectory().toFile().listFiles();
|
|
|
// 路径不为空文件夹
|
|
|
if (files.length != 0) {
|
|
|
try {
|
|
|
@@ -79,11 +97,10 @@ public class IndexSearcherManager {
|
|
|
} else {
|
|
|
logger.error("索引文件不存在:" + tableName.value());
|
|
|
}
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("索引路径打开失败:" + indexPath, e);
|
|
|
}
|
|
|
- } catch (IOException e) {
|
|
|
- logger.error("索引路径打开失败:" + indexPath, e);
|
|
|
}
|
|
|
- return directory;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -99,18 +116,15 @@ public class IndexSearcherManager {
|
|
|
startReopen(tableName);
|
|
|
|
|
|
try {
|
|
|
- // 每次都要进行初始化处理,是为了防止加载索引时,索引为空,而后来索引不为空时,却不能够正确加载
|
|
|
- FSDirectory directory = warm(tableName);
|
|
|
IndexSearcher currentSearcher = indexSearchers.get(tableName);
|
|
|
if (currentSearcher == null) {
|
|
|
return;
|
|
|
}
|
|
|
IndexSearcher searcher = get(tableName);
|
|
|
- Long currentVersion = ((DirectoryReader) searcher.getIndexReader()).getVersion();
|
|
|
- // 版本号不一致(本地索引有更改),更新IndexReader
|
|
|
try {
|
|
|
- if (DirectoryReader.open(directory).getVersion() != currentVersion) {
|
|
|
- IndexReader newReader = DirectoryReader.open(directory);
|
|
|
+ // 本地索引有更改,更新IndexReader
|
|
|
+ DirectoryReader newReader = DirectoryReader.openIfChanged((DirectoryReader) searcher.getIndexReader());
|
|
|
+ if (newReader != null) {
|
|
|
IndexSearcher newSearcher = new IndexSearcher(newReader);
|
|
|
updateIndexSearcher(tableName, newSearcher);
|
|
|
}
|
|
|
@@ -151,6 +165,7 @@ public class IndexSearcherManager {
|
|
|
if (tableName == null) {
|
|
|
return null;
|
|
|
}
|
|
|
+ warm(tableName);
|
|
|
IndexSearcher currentSearcher = indexSearchers.get(tableName);
|
|
|
if (currentSearcher != null) {
|
|
|
currentSearcher.getIndexReader().incRef();
|
|
|
@@ -187,4 +202,40 @@ public class IndexSearcherManager {
|
|
|
release(currentSearcher);
|
|
|
indexSearchers.put(tableName, newIndexSearcher);
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 刷新缓存中的索引
|
|
|
+ *
|
|
|
+ * @param tableName
|
|
|
+ * 表名
|
|
|
+ * @param delay
|
|
|
+ * 延迟一定时间刷新/ms,可为空,默认延迟3000ms
|
|
|
+ */
|
|
|
+ public void flushCache(final Table_name tableName, final Long delay) {
|
|
|
+ if (StringUtils.isEmpty(tableName)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Boolean waiting = waitingFlushCache.get(tableName);
|
|
|
+ // 有等待的线程,则不增加线程
|
|
|
+ if (waiting == null || !waiting.booleanValue()) {
|
|
|
+ final long delayCopy = (delay == null || delay.longValue() < 0) ? 3000 : delay.longValue();
|
|
|
+ new Thread(new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ try {
|
|
|
+ // 延迟一定时间再刷新缓存
|
|
|
+ Thread.sleep(delayCopy);
|
|
|
+ maybeReopen(tableName);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ logger.error("", e);
|
|
|
+ } finally {
|
|
|
+ // 线程执行完毕,无论是否成功,均将状态改为false
|
|
|
+ waitingFlushCache.put(tableName, false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).start();
|
|
|
+ // 将状态改为true
|
|
|
+ waitingFlushCache.put(tableName, true);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|