Home | About | Sematext search-lucene.com search-hadoop.com
 Search Lucene and all its subprojects:

Switch to Threaded View
Lucene, mail # user - Refreshing RAMDirectory


Copy link to this message
-
Re: Refreshing RAMDirectory
Ruslan Sivak 2007-12-12, 21:54
This seems to be problematic though.  There are other things that depend
on the reader that is not so obvious.  For example,

IndexReader reader=getReader();
IndexSearcher searcher=new IndexSearcher(reader);
Hits hits=searcher.search(query);
searcher.close();
reader.close();
Iterator i=hits.iterator();
if (i.hasNext())
    Hit h=(Hit) i.next();

This, for example, would not work, as accessing the hits after the
reader is closed will throw a "this reader is closed" exception.  You
need to have the reader open for the hits to retrieve data.

Since my app would be multithreaded, there could be multiple threads
accessing the reader, while i'm reloading it.  This means that if I
close the reader, and another thread is using it, it might get an
exception.  This forces me to use a new reader for every method
invocation.  This shouldn't be that bad, since it's accessing a
RAMDirectory, correct?  The overhead should be minimal.

Russ
Michael McCandless wrote:
>
> You need to keep a reader open so long as you plan to use any of its
> methods from any thread.
>
> The reader does close exactly when you ask it to (when you call
> reader.close()).
>
> You should not have to "open a new reader for every method call" --
> you only need to open a new reader (and in your case, RAMDirectory)
> whenever the underlying index has changed.
>
> Mike
>
> Ruslan Sivak wrote:
>
>> Thank you to everyone for your comments.  I didn't realize that
>> readers need to be kept open and won't close exactly when you ask
>> them too.  I have restructured my code to keep the RamDirectory
>> cached, and to open a new reader for every method call.  This seems
>> to be working fine.
>>
>> Russ
>>
>> Erick Erickson wrote:
>>> Even if you could tell a reader is closed, you'd wind up with
>>> unmaintainable code. I envision you have a bunch of places
>>> where you'd do something like
>>>
>>> if (reader.isClosed()) {
>>>      reader = create a new reader.
>>> }
>>>
>>> But practically, you'd be opening a new reader someplace,
>>> closing it someplace else, opening it in another place......
>>>
>>> This just leads to maintenance nightmares. For instance, how
>>> could you determine what the state of a particular reader was
>>> when trying to figure out why your searches didn't work if you don't
>>> have a clue where/when it was opened?
>>>
>>> Perhaps the easiest thing to do if you can't restructure your code
>>> as Michael suggested is just employ a singleton pattern to give you
>>> complete control over when/where a reader is opened.....
>>>
>>> Best
>>> Erick
>>>
>>> On Dec 12, 2007 5:36 AM, Michael McCandless <[EMAIL PROTECTED]>
>>> wrote:
>>>
>>>
>>>> Ruslan Sivak wrote:
>>>>
>>>>
>>>>> Michael McCandless wrote:
>>>>>
>>>>>> Ruslan Sivak wrote:
>>>>>>
>>>>>>
>>>>>>> I have an index of about 10mb.  Since it's so small, I would like
>>>>>>> to keep it loaded in memory, and reload it about every minute or
>>>>>>> so, assuming that it has changed on disk.  I have the following
>>>>>>> code, which works, except it doesn't reload the changes.
>>>>>>> protected String indexName;
>>>>>>> protected IndexReader reader;
>>>>>>> private long lastCheck=0;
>>>>>>> ...
>>>>>>> protected IndexReader getReader() throws CorruptIndexException,
>>>>>>> IOException
>>>>>>>    {
>>>>>>>        if (reader==null || System.currentTimeMillis() > lastCheck
>>>>>>> +60000)
>>>>>>>        {
>>>>>>>            lastCheck=System.currentTimeMillis();
>>>>>>>            if (reader==null || !reader.isCurrent())
>>>>>>>            {
>>>>>>>                if (reader!=null)
>>>>>>>                    reader.close();
>>>>>>>                              Directory dir = new RAMDirectory
>>>>>>> (indexName);
>>>>>>>                reader = IndexReader.open(dir);
>>>>>>>                searcher = new IndexSearcher(reader);
>>>>>>>            }
>>>>>>>        }
>>>>>>>        return reader;
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> Apparently reader.isCurrent() won't tell you if the underlying