У меня есть метод, который использует индекс, расположенный в определенном каталоге.
public class TestSearchEngine implements SearchEngine<Tag> {
private static final String INDEX_PATH = "/test/index";
private Directory directory;
@Inject private TagDAO tagDAO;
private int organizationId;
@Override
public void add(Tag tag) {
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
IndexWriter indexWriter = getIndexWriter(indexWriterConfig);
//Create document
Document document = new Document();
document.add(new Field("id", String.valueOf(tag.getId()), Field.Store.YES, Field.Index.NOT_ANALYZED));
document.add(new Field("title", tag.getTitle(), Field.Store.NO, Field.Index.ANALYZED));
try {
indexWriter.addDocument(document);
indexWriter.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public synchronized void setDirectory(int organizationId) throws IOException {
this.organizationId = organizationId;
File path = new File(INDEX_PATH + "/" + String.valueOf(organizationId));
//If path does not exist, create it and create new index for organization
if(!path.exists()) {
path.mkdirs();
buildCompleteIndex(organizationId, false);
}
this.directory = FSDirectory.open(path); //Open directory
}
private void buildCompleteIndex(int organizationId, boolean rebuildDir) {
if(rebuildDir) {
File path = new File(INDEX_PATH + "/" + String.valueOf(organizationId));
try {
Utils.deleteDirectory(path);
} catch (IOException e) {
throw new LuceneIndexException("Error rebuilding index directory.", e);
}
path.mkdirs();
}
List<Tag> tagList = tagDAO.findAll(organizationId);
for(Tag tag : tagList) {
add(tag);
}
}
private IndexReader getIndexReader() {
try {
return IndexReader.open(directory);
} catch (CorruptIndexException e) {
buildCompleteIndex(organizationId, true);
} catch (IOException e) {
throw new LuceneIndexException("IOException prevented IndexReader from opening Index.", e);
} catch(NullPointerException e) {
throw new LuceneIndexException("Index resource not available.", e);
}
return null;
}
}
В некоторых ситуациях я ловлю исключение, если по какой-либо причине индекс становится поврежденным или просто еще не создан. В этом случае вызывается метод buildCompleteIndex (), который удаляет каталог и воссоздает индекс из источника данных.
В многопоточной среде, как я могу защитить от другого потока, создающего экземпляр класса и использующего метод, который вызывает каталог, когда он либо удаляется, либо перестраивается? Метод setDirectory () должен быть вызван до того, как сработает любой из других методов, поэтому я предполагаю, что установка синхронизации для метода решит эту проблему, но что, если каталог повреждается, когда потоки уже в нем, все они начинают вызывать пересборку? метод в то же время? Другими словами, я немного озадачен правильным способом удаления и обновления файлов ввода-вывода в многопоточной среде. Некоторые советы будут оценены.