package com.mysema.luja.impl; import java.io.FileNotFoundException; import java.io.IOException; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriter.MaxFieldLength; import org.apache.lucene.index.Term; import org.apache.lucene.store.AlreadyClosedException; import org.apache.lucene.store.Directory; import org.apache.lucene.store.LockObtainFailedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mysema.luja.LuceneWriter; import com.mysema.luja.WriteLockObtainFailedException; import com.mysema.query.QueryException; public class FileLockingWriter implements LuceneWriter, Leasable { protected static final Logger logger = LoggerFactory.getLogger(LuceneWriter.class); protected IndexWriter writer; protected final LuceneSessionFactoryImpl sessionFactory; public FileLockingWriter(Directory directory, boolean createNew, long defaultLockTimeout, LuceneSessionFactoryImpl sessionFactory) { IndexWriter.setDefaultWriteLockTimeout(defaultLockTimeout); boolean create = createNew; try { if (!create) { try { writer = new IndexWriter(directory, sessionFactory.getAnalyzerFactory() .newAnalyzer(), false, MaxFieldLength.LIMITED); } catch (FileNotFoundException e) { // Convience to create a new index if it's not already // existing create = true; } } if (create) { writer = new IndexWriter(directory, sessionFactory.getAnalyzerFactory().newAnalyzer(), true, MaxFieldLength.LIMITED); } } catch (LockObtainFailedException e) { throw new WriteLockObtainFailedException("Got lock timeout", e); } catch (IOException e) { throw new QueryException(e); } if (logger.isDebugEnabled()) { logger.debug("Created writer " + writer); } this.sessionFactory = sessionFactory; } @Override public LuceneWriter addDocument(Document doc) { try { writer.addDocument(doc); return this; } catch (IOException e) { throw new QueryException(e); } } @Override public LuceneWriter deleteDocuments(Term term) { try { writer.deleteDocuments(term); return this; } catch (IOException e) { throw new QueryException(e); } } @Override public LuceneWriter updateDocument(Term term, Document doc) { try { writer.updateDocument(term, doc); return this; } catch (IOException e) { throw new QueryException(e); } } public void commit() { try { writer.commit(); } catch (IOException e) { throw new QueryException(e); } } private void close() { Directory directory = null; try { directory = writer.getDirectory(); } catch (AlreadyClosedException e) { if (logger.isDebugEnabled()) { logger.debug("Writer is already closed"); } return; } try { // TODO What would be best way to control this? writer.optimize(); writer.close(); if (logger.isDebugEnabled()) { logger.debug("Closed writer " + writer); } } catch (IOException e) { try { if (IndexWriter.isLocked(directory)) { IndexWriter.unlock(directory); } } catch (IOException e1) { //Log this error, as otherwise we would loose IOException on close logger.error("Writer close failed", e); throw new QueryException("Lock release failed", e1); } throw new QueryException("Writer close failed", e); } } public IndexWriter getIndexWriter() { return writer; } @Override public boolean lease() { // This is no-op for writer as we always create new return true; } @Override public void release() { close(); } }