You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-user@lucene.apache.org by Michael McCandless <lu...@mikemccandless.com> on 2006/12/05 12:03:40 UTC

Re: {SPAM 05.2 _____} IOException: Access is denied from IndexWriter.Optimize

trond.lindanger@dkdigital.no wrote:
> Hi, 
> In my test case, four Quartz jobs are starting each third minute storing 
> records in a database followed by an index update.
> After doing a test run over a period of 16 hours, I got this exception 
> after 10 hours:
> 
> java.io.IOException: Access is denied
>         at java.io.RandomAccessFile.writeBytes(Native Method)
>         at java.io.RandomAccessFile.write(RandomAccessFile.java:456)
>         at 
> org.apache.lucene.store.FSIndexOutput.flushBuffer(FSDirectory.java:575)
>         at 
> org.apache.lucene.store.BufferedIndexOutput.flush(BufferedIndexOutput.java:85)
>         at 
> org.apache.lucene.store.BufferedIndexOutput.writeBytes(BufferedIndexOutput.java:75)
>         at 
> org.apache.lucene.index.CompoundFileWriter.copyFile(CompoundFileWriter.java:212)
>         at 
> org.apache.lucene.index.CompoundFileWriter.close(CompoundFileWriter.java:169)
>         at 
> org.apache.lucene.index.SegmentMerger.createCompoundFile(SegmentMerger.java:148)
>         at 
> org.apache.lucene.index.IndexWriter.mergeSegments(IndexWriter.java:962)
>         at 
> org.apache.lucene.index.IndexWriter.flushRamSegments(IndexWriter.java:833)
>         at 
> org.apache.lucene.index.IndexWriter.optimize(IndexWriter.java:569)
>  
> Here is the relevant method:
> 
>   public void indexItems(boolean createNewIndex, Collection items)
>     throws java.io.IOException {
>         if (IndexReader.indexExists(indexDir)) {
>                 while (IndexReader.isLocked(indexDir)) {
>                         try {
>                                 logger.info(indexDir+" is locked, 
> waiting...");
>                                 Thread.sleep(1000); 
>                         } catch (InterruptedException e) {
>                                 e.printStackTrace();
>                         }
>                 }
>         }
>         logger.info(indexDir+" lock is open."); 
>     logger.info("Start writing index located at "+indexDir);
>     IndexWriter writer = new IndexWriter(indexDir, analyzer, 
> createNewIndex);
>     writer.setWriteLockTimeout(10000);
>     writer.setUseCompoundFile(true);
>  
>     Iterator itI = items.iterator();
>     while (itI.hasNext()) {
>       ItemIF item = (ItemIF) itI.next();
>       logger.info("Add item " + item + " to index.");
>       writer.addDocument(ItemDocument.makeDocument(item));
>     }
>     writer.optimize(); // This is where the exception is thrown
>     nrOfIndexedItems = writer.docCount();
>     writer.close();
>     logger.info("Finished writing index.");
>   } 
> 
> 
> The following environment is used:
> WinXP
> JDK 1.5
> Tomcat 5.5
> Lucene 2.0.0
> HSQLdb 1.8.0
> Quartz 1.6.0
> Hibernate 2.1.8

It seems like this may be another case of writer creating new index
while reader(s) are reading from the same index (which won't work in
2.0 but does work in trunk/next release).

But, this exception is rather mysterious.  I can't fully explain it.

The optimize method first flushes all documents in the in-memory
buffer (a RAMDirectory) to disk.  It's in this flush, specifically
when building the resulting compound file, that you hit the Access is
denied IOException.

What's spooky is you hit it during writeBytes.  Meaning, the file was
in fact successfully opened for writing.  I would have expected this
exception to occur on opening (if for example a reader was reading
the file at that time, and, if somehow the commit lock wasn't working
properly).

Is this process the only one that's doing writing to the index?  For
example, why do you have the loop up-front to pause for 1.0 seconds if
the index is locked?  Is this just to check the commit lock (in case a
reader is opening the index at that moment)?

It sounds like you may have 4 Quartz jobs running, and each of them
wants to write to the index?  (So maybe your loop that pauses if index
is locked is really trying to wait for another writer to finish its
indexing before it starts?)  Lucene only allows one writer on the
index at a time.

Is this exception easily repeated?  EG, it always happens many hours
into your runs?

Mike

---------------------------------------------------------------------
To unsubscribe, e-mail: java-user-unsubscribe@lucene.apache.org
For additional commands, e-mail: java-user-help@lucene.apache.org


Re: IOException: Access is denied from IndexWriter.Optimize

Posted by Michael McCandless <lu...@mikemccandless.com>.
trond.lindanger@dkdigital.no wrote:
> Thank you for quick and detailed answer.
> In this system multiple threads will, occasionally, try to write and/ or 
> read the same index, hence the pause waiting for the lock. This is not a 
> good way to implement it and was done as a temp solution for debug 
> purposes only. Multiple processes may still reach the init of IndexWriter/ 
> IndexReader for the same index at almost the same time. I guess 
> synchronizing some object, giving exclusive access for one IndexReader or 
> IndexWriter to some common index, is a better way to do it.

It's fine if there are multiple readers, but there can only be one
writer.

So I think for your case what's important is that you synchronize your
writers.  One simple way to do this is just always try to instantiate
your IndexWriter, catch an IOException, and if the IOException is the
"Lock obtained timed out" with the write lock, assume this means
another writer is writing to the index so loop & try again.

If the IndexWriter is instantiated with no IOException then it got the
write lock and you can proceed to do your indexinging and then close
the writer in a finally clause.

This would mean your current check for whether index is locked is not
needed.

> May this be a 
> work around for the parallel writer/ reader problem you describe?

Just to be clear: the specific problem here is if you try to create
(create=true) a new index while readers are reading from that same
index.  You will get IOExceptions in this case with Lucene 2.0 on
Windows, but it will (should!) work with the current trunk.

Note that if you try the trunk, because the index format has changed,
you can't use the resulting index from Lucene 2.0 (you would have to
re-create the index in 2.0).

>  Anyway, I guess I should give the trunc a try first.
> java.io.IOException: Access is denied has only been reported once. I have 
> not been able to reproduce it. I have some anti virus app running on my 
> machine (Trend Micro Office Scan). This includes a scan of the index dir. 
> Do you think that may cause the problem. Or perhaps some other windows 
> services/ tools accessing the file for some reason (windows indexer)?

This one makes me nervous.  There have been known issues about Access
Denied IOExceptions, some involving other services (indexing service,
google desktop, virus checkers, shell extensions, etc.).  We have been
trying lately (in the trunk) to reduce, when possible, what
functionality Lucene requires of the filesystem, to make sure we play
well with such services.

As far as I know, in the trunk version of Lucene we've addressed all
such known cases.  But your exception doesn't look quite like any of
these.  This is why I'd really like to get to the root cause of your
case, so we can fix it if indeed Lucene is interacting badly with such
software.

It is remotely possible you are hitting this issue (fixed on trunk):

     http://issues.apache.org/jira/browse/LUCENE-669

If you upgrade to trunk, and this exception happens again, please
reply back with as much detail as possible!

Mike

---------------------------------------------------------------------
To unsubscribe, e-mail: java-user-unsubscribe@lucene.apache.org
For additional commands, e-mail: java-user-help@lucene.apache.org


Re: IOException: Access is denied from IndexWriter.Optimize

Posted by tr...@dkdigital.no.
Thank you for quick and detailed answer.
In this system multiple threads will, occasionally, try to write and/ or 
read the same index, hence the pause waiting for the lock. This is not a 
good way to implement it and was done as a temp solution for debug 
purposes only. Multiple processes may still reach the init of IndexWriter/ 
IndexReader for the same index at almost the same time. I guess 
synchronizing some object, giving exclusive access for one IndexReader or 
IndexWriter to some common index, is a better way to do it. May this be a 
work around for the parallel writer/ reader problem you describe? Anyway, 
I guess I should give the trunc a try first.
java.io.IOException: Access is denied has only been reported once. I have 
not been able to reproduce it. I have some anti virus app running on my 
machine (Trend Micro Office Scan). This includes a scan of the index dir. 
Do you think that may cause the problem. Or perhaps some other windows 
services/ tools accessing the file for some reason (windows indexer)?

Re: IOException: Access is denied from IndexWriter.Optimize

Posted by Michael McCandless <lu...@mikemccandless.com>.
Sorry, I allowed my silly SPAM filter to pollute the subject line.
I'm fixing that in this reply so please reply to this one :)

Mike

Michael McCandless wrote:
> trond.lindanger@dkdigital.no wrote:
>> Hi, In my test case, four Quartz jobs are starting each third minute 
>> storing records in a database followed by an index update.
>> After doing a test run over a period of 16 hours, I got this exception 
>> after 10 hours:
>>
>> java.io.IOException: Access is denied
>>         at java.io.RandomAccessFile.writeBytes(Native Method)
>>         at java.io.RandomAccessFile.write(RandomAccessFile.java:456)
>>         at 
>> org.apache.lucene.store.FSIndexOutput.flushBuffer(FSDirectory.java:575)
>>         at 
>> org.apache.lucene.store.BufferedIndexOutput.flush(BufferedIndexOutput.java:85) 
>>
>>         at 
>> org.apache.lucene.store.BufferedIndexOutput.writeBytes(BufferedIndexOutput.java:75) 
>>
>>         at 
>> org.apache.lucene.index.CompoundFileWriter.copyFile(CompoundFileWriter.java:212) 
>>
>>         at 
>> org.apache.lucene.index.CompoundFileWriter.close(CompoundFileWriter.java:169) 
>>
>>         at 
>> org.apache.lucene.index.SegmentMerger.createCompoundFile(SegmentMerger.java:148) 
>>
>>         at 
>> org.apache.lucene.index.IndexWriter.mergeSegments(IndexWriter.java:962)
>>         at 
>> org.apache.lucene.index.IndexWriter.flushRamSegments(IndexWriter.java:833) 
>>
>>         at 
>> org.apache.lucene.index.IndexWriter.optimize(IndexWriter.java:569)
>>  
>> Here is the relevant method:
>>
>>   public void indexItems(boolean createNewIndex, Collection items)
>>     throws java.io.IOException {
>>         if (IndexReader.indexExists(indexDir)) {
>>                 while (IndexReader.isLocked(indexDir)) {
>>                         try {
>>                                 logger.info(indexDir+" is locked, 
>> waiting...");
>>                                 Thread.sleep(1000); 
>>                         } catch (InterruptedException e) {
>>                                 e.printStackTrace();
>>                         }
>>                 }
>>         }
>>         logger.info(indexDir+" lock is open.");     logger.info("Start 
>> writing index located at "+indexDir);
>>     IndexWriter writer = new IndexWriter(indexDir, analyzer, 
>> createNewIndex);
>>     writer.setWriteLockTimeout(10000);
>>     writer.setUseCompoundFile(true);
>>  
>>     Iterator itI = items.iterator();
>>     while (itI.hasNext()) {
>>       ItemIF item = (ItemIF) itI.next();
>>       logger.info("Add item " + item + " to index.");
>>       writer.addDocument(ItemDocument.makeDocument(item));
>>     }
>>     writer.optimize(); // This is where the exception is thrown
>>     nrOfIndexedItems = writer.docCount();
>>     writer.close();
>>     logger.info("Finished writing index.");
>>   }
>>
>> The following environment is used:
>> WinXP
>> JDK 1.5
>> Tomcat 5.5
>> Lucene 2.0.0
>> HSQLdb 1.8.0
>> Quartz 1.6.0
>> Hibernate 2.1.8
> 
> It seems like this may be another case of writer creating new index
> while reader(s) are reading from the same index (which won't work in
> 2.0 but does work in trunk/next release).
> 
> But, this exception is rather mysterious.  I can't fully explain it.
> 
> The optimize method first flushes all documents in the in-memory
> buffer (a RAMDirectory) to disk.  It's in this flush, specifically
> when building the resulting compound file, that you hit the Access is
> denied IOException.
> 
> What's spooky is you hit it during writeBytes.  Meaning, the file was
> in fact successfully opened for writing.  I would have expected this
> exception to occur on opening (if for example a reader was reading
> the file at that time, and, if somehow the commit lock wasn't working
> properly).
> 
> Is this process the only one that's doing writing to the index?  For
> example, why do you have the loop up-front to pause for 1.0 seconds if
> the index is locked?  Is this just to check the commit lock (in case a
> reader is opening the index at that moment)?
> 
> It sounds like you may have 4 Quartz jobs running, and each of them
> wants to write to the index?  (So maybe your loop that pauses if index
> is locked is really trying to wait for another writer to finish its
> indexing before it starts?)  Lucene only allows one writer on the
> index at a time.
> 
> Is this exception easily repeated?  EG, it always happens many hours
> into your runs?
> 
> Mike

---------------------------------------------------------------------
To unsubscribe, e-mail: java-user-unsubscribe@lucene.apache.org
For additional commands, e-mail: java-user-help@lucene.apache.org