Java, Lucene: Set a lock timeout for IndexWriter in Java.

I am working on integrating Lucene with our Spring-MVC application. We are currently working but rarely get an error cannot obtain lock

. After that I have to manually delete the lock file and then it works fine.

How do I set a timeout for an index lock in Java? I don't have any XML configuration for Lucene. I added a project library to maven via POM.xml and instantiated the required classes.

Code:

public void saveIndexes(String text, String tagFileName, String filePath, long groupId, boolean type, int objectId) {
        try {
            // path is the indexing directory. 
            File testDir;
            Path suggestionsPath;
            Directory suggestionsDir;

            Path phraseSuggestPath;
            Directory phraseSuggestDir;

            Directory directory = org.apache.lucene.store.FSDirectory.open(path);
            IndexWriterConfig config = new IndexWriterConfig(new SimpleAnalyzer());
            IndexWriter indexWriter = new IndexWriter(directory, config);

            org.apache.lucene.document.Document doc = new org.apache.lucene.document.Document();
            if (filePath != null) {
                File file = new File(filePath); // current directory
                doc.add(new TextField("path", file.getPath(), Field.Store.YES));
            }
            doc.add(new StringField("id", String.valueOf(objectId), Field.Store.YES));
            //  doc.add(new TextField("id",String.valueOf(objectId),Field.Store.YES));
            if (text == null) {
                if (filePath != null) {
                    FileInputStream is = new FileInputStream(filePath);
                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                    StringBuilder stringBuffer = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        stringBuffer.append(line).append("\n");
                    }
                    stringBuffer.append("\n").append(tagFileName);
                    reader.close();
                    doc.add(new TextField("contents", stringBuffer.toString(), Field.Store.YES));
                }
            } else {

                FieldType fieldType = new FieldType(TextField.TYPE_STORED);
                fieldType.setTokenized(false);
                doc.add(new Field("contents", text+"\n"+tagFileName, fieldType));
            }
            indexWriter.addDocument(doc);
            indexWriter.commit();
            indexWriter.flush();
            indexWriter.close();
            directory.close();

            StandardAnalyzer analyzer = new StandardAnalyzer();
            AnalyzingInfixSuggester wordSuggester = new AnalyzingInfixSuggester(suggestionsDir, analyzer);

            ArrayList<String> words = new ArrayList<>();
            if (text != null) {
                text = html2text(text);
                Pattern pt = Pattern.compile("[^\\w\\s]");
                Matcher match = pt.matcher(text);
                while (match.find()) {
                    String s = match.group();
                    text = text.replaceAll("\\" + s, "");
                }

                if (text.contains(" ")) {
                    Collections.addAll(words, text.split(" "));

                } else {
                    words.add(text);
                }
                SuggestionIterator suggestionIterator = new SuggestionIterator(words.iterator());
                wordSuggester.build(suggestionIterator);
                wordSuggester.close();
                suggestionsDir.close();
            }

            AnalyzingInfixSuggester phraseSuggester = new AnalyzingInfixSuggester(phraseSuggestDir, analyzer);
            if (text != null) {
                text = html2text(text);
                ArrayList<String> phrases = new ArrayList<>();
                phrases.add(text);
                SuggestionIterator suggestionIterator = new SuggestionIterator(phrases.iterator());
                phraseSuggester.build(suggestionIterator);
                phraseSuggester.close();
                phraseSuggestDir.close();
            }

        } catch (Exception ignored) {
        }
    }

      

Thank.

+3


source to share


1 answer


I am quoting two things from the IndexWriter Documentation ,

Opening IndexWriter creates a lock file for the directory being used. Attempting to open another IndexWriter in the same directory will result in a LockObtainFailedException exception.

and

NOTE. IndexWriters are completely thread safe, which means multiple threads can call any of their methods at the same time. If your application requires external synchronization, you should not synchronize on the IndexWriter instance, as this can lead to blocking; use native (non-Lucene) objects instead.

So, you cannot reopen the IndexWriter if it is already open and not closed somewhere else. In your case, there is some mishap when two users are in the same code block.

You can solve this problem in two ways:



1. Assign a critical section: Mark a piece of code by opening, using and closing an entry in a critical section and apply Java synchronization in that critical section. Use some Singleton bean app to sync. Therefore, when another user hits this block, it will wait until the first user is executed and the lock is released.

2. A copy of a single writer . Create a mechanism in your application to open and close the writer only once for the lifetime of the application and pass this single instance in the service code, so the write methods can be called as many users as you wish, from the moment the script is instantiated, streamed user-oriented Lucene. I think this can be achieved with a Singleton Spring bean and by injecting that bean into your service.

The disadvantage of the second approach is to deploy multiple servers for one global index catalog and if there are other applications trying to open the authors of that global index. This problem can be solved by moving the instantiation code of the index creator to some global service that returns the same instance depending on which application is trying to use it.

This is not a simple problem that you are trying to solve by deleting lock files or introducing timeouts. You should model your design according to the IndexWriter documentation, not the other way around.

Having a standalone instance will also lead to some performance improvements.

Also, make it a practice to make an empty commit right after the post is created. This has helped me solve some problems in the past.

+5


source







All Articles