@@ -104,9 +104,9 @@ public class Lucene {
104104 * A bucket for accessing the read and write functionality for a single "shard"
105105 * Lucene index which can then be grouped to represent a single document type.
106106 */
107- private class ShardBucket {
107+ public class ShardBucket {
108108 private FSDirectory directory ;
109- private IndexWriter indexWriter ;
109+ public IndexWriter indexWriter ;
110110 private SearcherManager searcherManager ;
111111 private DefaultSortedSetDocValuesReaderState state ;
112112 private AtomicLong documentCount ;
@@ -147,8 +147,10 @@ public ShardBucket(java.nio.file.Path shardPath) throws IOException {
147147 *
148148 * @return The number of documents committed to this shard.
149149 * @throws IOException
150+ * @throws LuceneException If the IndexWriter is closed
150151 */
151- public int commit () throws IOException {
152+ public int commit () throws IOException , LuceneException {
153+ ensureOpen ();
152154 if (indexWriter .hasUncommittedChanges ()) {
153155 indexWriter .commit ();
154156 searcherManager .maybeRefreshBlocking ();
@@ -183,6 +185,32 @@ private void initState(IndexSearcher indexSearcher) throws IOException {
183185 searcherManager .release (indexSearcher );
184186 }
185187 }
188+
189+ /**
190+ * To be called before attempting to commit. If the IndexWriter has
191+ * been closed, e.g. due to a previous IOException, will create a new
192+ * one and throw (so that whatever process called this knows the commit
193+ * failed and changes will not have been persisted).
194+ *
195+ * @throws IOException If index directory cannot be read/written
196+ * @throws LuceneException If the IndexWriter is closed
197+ */
198+ public void ensureOpen () throws IOException , LuceneException {
199+ if (!indexWriter .isOpen ()) {
200+ IndexWriterConfig config = new IndexWriterConfig (analyzer );
201+ indexWriter = new IndexWriter (directory , config );
202+ searcherManager = new SearcherManager (indexWriter , null );
203+ IndexSearcher indexSearcher = searcherManager .acquire ();
204+ int numDocs = indexSearcher .getIndexReader ().numDocs ();
205+ documentCount = new AtomicLong (numDocs );
206+ initState (indexSearcher );
207+
208+ String fileName = directory .getDirectory ().getFileName ().toString ();
209+ String message = "IndexWriter for " + fileName + " was unexpectedly closed" ;
210+ logger .error (message );
211+ throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , message );
212+ }
213+ }
186214 }
187215
188216 /**
@@ -245,8 +273,9 @@ public List<IndexSearcher> acquireSearchers() throws IOException {
245273 *
246274 * @param document The document to be added.
247275 * @throws IOException
276+ * @throws LuceneException If the IndexWriter is closed
248277 */
249- public void addDocument (Document document ) throws IOException {
278+ public void addDocument (Document document ) throws IOException , LuceneException {
250279 ShardBucket shardBucket = routeShard ();
251280 shardBucket .indexWriter .addDocument (document );
252281 shardBucket .documentCount .incrementAndGet ();
@@ -282,8 +311,9 @@ public void deleteDocuments(String field, long value) throws IOException {
282311 * @param icatId The ICAT id of the document to be updated.
283312 * @param document The document that will replace the old document.
284313 * @throws IOException
314+ * @throws LuceneException If the IndexWriter is closed
285315 */
286- public void updateDocument (long icatId , Document document ) throws IOException {
316+ public void updateDocument (long icatId , Document document ) throws IOException , LuceneException {
287317 deleteDocument (icatId );
288318 addDocument (document );
289319 }
@@ -311,8 +341,9 @@ public ShardBucket buildShardBucket(int shardKey) throws IOException {
311341 * @param entityName The name of the entities being committed. Only used for
312342 * debug logging.
313343 * @throws IOException
344+ * @throws LuceneException If the IndexWriter is closed
314345 */
315- public void commit (String command , String entityName ) throws IOException {
346+ public void commit (String command , String entityName ) throws IOException , LuceneException {
316347 for (ShardBucket shardBucket : shardList ) {
317348 int cached = shardBucket .commit ();
318349 if (cached != 0 ) {
@@ -332,8 +363,10 @@ public void commit(String command, String entityName) throws IOException {
332363 public void close () throws IOException {
333364 for (ShardBucket shardBucket : shardList ) {
334365 shardBucket .searcherManager .close ();
335- shardBucket .indexWriter .commit ();
336- shardBucket .indexWriter .close ();
366+ if (shardBucket .indexWriter .isOpen ()) {
367+ shardBucket .indexWriter .commit ();
368+ shardBucket .indexWriter .close ();
369+ }
337370 shardBucket .directory .close ();
338371 }
339372 }
@@ -354,10 +387,12 @@ public ShardBucket getCurrentShardBucket() {
354387 *
355388 * @return The ShardBucket that the relevant Document is/should be indexed in.
356389 * @throws IOException
390+ * @throws LuceneException If the IndexWriter is closed
357391 */
358- public ShardBucket routeShard () throws IOException {
392+ public ShardBucket routeShard () throws IOException , LuceneException {
359393 ShardBucket shardBucket = getCurrentShardBucket ();
360394 if (shardBucket .documentCount .get () >= luceneMaxShardSize ) {
395+ shardBucket .ensureOpen ();
361396 shardBucket .indexWriter .commit ();
362397 shardBucket = buildShardBucket (shardList .size ());
363398 }
@@ -446,6 +481,7 @@ public void modify(@Context HttpServletRequest request) throws LuceneException {
446481 }
447482 count = operations .size ();
448483 } catch (IOException e ) {
484+ logger .error ("IOException while attempting to modify document(s)" , e );
449485 throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , e .getMessage ());
450486 }
451487 logger .debug ("Modified {} documents" , count );
@@ -474,6 +510,7 @@ public void addNow(@Context HttpServletRequest request, @PathParam("entityName")
474510 logger .error ("Could not parse JSON from {}" , value );
475511 throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , e .getMessage ());
476512 } catch (IOException e ) {
513+ logger .error ("IOException while attempting to add document(s)" , e );
477514 throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , e .getMessage ());
478515 }
479516 logger .debug ("Added {} {} documents" , documents .size (), entityName );
@@ -495,6 +532,7 @@ public void clear() throws LuceneException {
495532 Files .walk (luceneDirectory , FileVisitOption .FOLLOW_LINKS ).sorted (Comparator .reverseOrder ())
496533 .filter (f -> !luceneDirectory .equals (f )).map (java .nio .file .Path ::toFile ).forEach (File ::delete );
497534 } catch (IOException e ) {
535+ logger .error ("IOException while attempting to clear" , e );
498536 throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , e .getMessage ());
499537 }
500538
@@ -519,6 +557,7 @@ public void commit() throws LuceneException {
519557 }
520558 }
521559 } catch (IOException e ) {
560+ logger .error ("IOException while attempting to commit" , e );
522561 throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , e .getMessage ());
523562 }
524563 }
@@ -571,9 +610,10 @@ private void create(JsonObject operationBody) throws NumberFormatException, IOEx
571610 * @param entityId Icat id of entity to update as a JsonNumber.
572611 * @param index Index (entity) to update.
573612 * @throws IOException
613+ * @throws LuceneException If the IndexWriter is closed
574614 */
575615 private void aggregateFileSize (long sizeToAdd , long sizeToSubtract , long deltaFileCount , JsonNumber entityId ,
576- String index ) throws IOException {
616+ String index ) throws IOException , LuceneException {
577617 if (entityId != null ) {
578618 aggregateFileSize (sizeToAdd , sizeToSubtract , deltaFileCount , entityId .longValueExact (), index );
579619 }
@@ -592,9 +632,10 @@ private void aggregateFileSize(long sizeToAdd, long sizeToSubtract, long deltaFi
592632 * @param entityId Icat id of entity to update as a long.
593633 * @param index Index (entity) to update.
594634 * @throws IOException
635+ * @throws LuceneException If the IndexWriter is closed
595636 */
596637 private void aggregateFileSize (long sizeToAdd , long sizeToSubtract , long deltaFileCount , long entityId ,
597- String index ) throws IOException {
638+ String index ) throws IOException , LuceneException {
598639 long deltaFileSize = sizeToAdd - sizeToSubtract ;
599640 if (deltaFileSize != 0 || deltaFileCount != 0 ) {
600641 IndexBucket indexBucket = indexBuckets .computeIfAbsent (index , k -> new IndexBucket (k ));
@@ -766,6 +807,7 @@ private void delete(JsonObject operationBody) throws LuceneException, IOExceptio
766807 shardBucket .indexWriter .deleteDocuments (idQuery );
767808 }
768809 } catch (IOException e ) {
810+ logger .error ("IOException while attempting to delete document(s)" , e );
769811 throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , e .getMessage ());
770812 }
771813 }
@@ -921,6 +963,7 @@ public void freeSearcher(SearchBucket search) throws LuceneException {
921963 indexBuckets .computeIfAbsent (name .toLowerCase (), k -> new IndexBucket (k ))
922964 .releaseSearchers (subReaders );
923965 } catch (IOException e ) {
966+ logger .error ("IOException while attempting to freeSearcher" , e );
924967 throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , e .getMessage ());
925968 }
926969 }
@@ -1136,6 +1179,7 @@ public void lock(@PathParam("entityName") String entityName, @QueryParam("minId"
11361179 }
11371180 }
11381181 } catch (IOException e ) {
1182+ logger .error ("IOException while attempting to lock" , e );
11391183 throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , e .getMessage ());
11401184 }
11411185 }
@@ -1699,6 +1743,7 @@ public void unlock(@PathParam("entityName") String entityName) throws LuceneExce
16991743 try {
17001744 bucket .commit ("Unlock" , entityName );
17011745 } catch (IOException e ) {
1746+ logger .error ("IOException while attempting to unlock" , e );
17021747 throw new LuceneException (HttpURLConnection .HTTP_INTERNAL_ERROR , e .getMessage ());
17031748 }
17041749 }
0 commit comments