Hi there
It appears my Lucene 2.3.1 index is corrupted. I get the following error
when searching:
/mnt/indexnew/_3wk0.cfs (No such file or directory)
java.io.FileNotFoundException: /mnt/indexnew/_3wk0.cfs (No such file or
directory)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:231)
at
org.apache.lucene.store.FSDirectory$FSIndexInput$Descriptor.<init>(FSDirectory.java:506)
at
org.apache.lucene.store.FSDirectory$FSIndexInput.<init>(FSDirectory.java:536)
at
org.apache.lucene.store.FSDirectory.openInput(FSDirectory.java:445)
at
org.apache.lucene.index.CompoundFileReader.<init>(CompoundFileReader.java:70)
at
org.apache.lucene.index.SegmentReader.initialize(SegmentReader.java:277)
at org.apache.lucene.index.SegmentReader.get(SegmentReader.java:262)
at org.apache.lucene.index.SegmentReader.get(SegmentReader.java:197)
at
org.apache.lucene.index.MultiSegmentReader.<init>(MultiSegmentReader.java:55)
at
org.apache.lucene.index.DirectoryIndexReader$1.doBody(DirectoryIndexReader.java:75)
at
org.apache.lucene.index.SegmentInfos$FindSegmentsFile.run(SegmentInfos.java:636)
at
org.apache.lucene.index.DirectoryIndexReader.open(DirectoryIndexReader.java:63)
at org.apache.lucene.index.IndexReader.open(IndexReader.java:209)
at org.apache.lucene.index.IndexReader.open(IndexReader.java:173)
at
org.apache.lucene.search.IndexSearcher.<init>(IndexSearcher.java:48)
at
Question #1: How can I recover from this error without regenerating the
entire index?
Is there a utility I could use?
Question #2: What is the reason why I am missing a segument cfs file?
Could it be a problem with the synchronization of threads during
Indexing (see attached code)?
Could it be a bug in MailArchiva?
I have tried to implement locks in appropriate places.
java.io.FileNotFoundException: /mnt/indexnew/_3wk0.cfs (No such file or
directory)
Any help would be much appreciated!
Jamie
package com.stimulus.archiva.index;
/* Copyright (C) 2005-2007 Jamie Angus Band
* MailArchiva Open Source Edition Copyright (c) 2005-2007 Jamie Angus Band
* This program is free software; you can redistribute it and/or modify it
under the terms of
* the GNU General Public License as published by the Free Software Foundation;
either version
* 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
this program;
* if not, see http://www.gnu.org/licenses or write to the Free Software
Foundation,Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
import javax.mail.*;
import javax.mail.internet.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import com.ice.tar.*;
import org.apache.log4j.Logger;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.store.*;
import com.stimulus.archiva.domain.*;
import com.stimulus.archiva.exception.*;
import com.stimulus.archiva.language.*;
import com.stimulus.archiva.extraction.*;
import com.stimulus.archiva.search.*;
import com.stimulus.util.TempFiles;
import com.stimulus.archiva.domain.fields.*;
import com.stimulus.util.*;
import java.nio.charset.Charset;
import org.apache.log4j.Level;
public class MessageIndex extends Indexer implements Serializable {
private static final long serialVersionUID = -17692874371162272L;
protected static final Logger logger =
Logger.getLogger(MessageIndex.class.getName());
protected static int INDEX_WAIT_PERIOD = 50;
protected static int DEAD_PERIOD = 300000000;
protected boolean shutdown = false;
static Hashtable<Volume,VolumeIndex> volumeIndexes = new
Hashtable<Volume,VolumeIndex>();
static Object volumeIndexLock = new Object();
public MessageIndex() {
}
public void deleteIndex(Volume volume) throws MessageSearchException {
VolumeIndex volumeIndex = getVolumeIndex(volume);
volumeIndex.deleteIndex();
}
public VolumeIndex getVolumeIndex(Volume volume) {
VolumeIndex volumeIndex = null;
synchronized (volumeIndexLock) {
volumeIndex = volumeIndexes.get(volume);
if (volumeIndex==null) {
volumeIndex = new VolumeIndex(this,volume);
volumeIndexes.put(volume,volumeIndex);
}
}
return volumeIndex;
}
public void indexMessage(Email email) throws MessageSearchException {
VolumeIndex volumeIndex =
getVolumeIndex(email.getEmailId().getVolume());
volumeIndex.indexMessage(email);
}
// Enterprise version
public void deleteMessage(EmailID emailID) throws
MessageSearchException {
if (emailID == null)
throw new MessageSearchException("assertion failure: null
emailID",logger);
logger.debug("delete message {'"+emailID+"'}");
Volume volume = emailID.getVolume();
File indexDir = new File(volume.getIndexPath());
if (!indexDir.exists())
throw new MessageSearchException("could not delete email from
index. volume does not exist. {'"+emailID+"}",logger);
IndexReader indexReader = null;
try {
indexReader = IndexReader.open(indexDir);
} catch (IOException e ) {
throw new MessageSearchException("failed to open index to
delete email",e,logger);
}
try {
indexReader.deleteDocuments(new
Term("uid",emailID.getUniqueID()));
indexReader.close();
} catch (Exception e) {
throw new MessageSearchException("failed to delete email from
index.",e,logger);
}
}
public void prepareIndex(Volume volume) throws MessageSearchException {
if (volume==null)
throw new MessageSearchException("assertion
failure: null volume",logger);
if (volume.getIndexPath().startsWith("rmi://"))
return;
File indexDir = new File(volume.getIndexPath());
if (!indexDir.exists()) {
logger.info("index directory does not exist. will proceed with
creation {location='" + volume.getIndexPath() + "'}");
boolean success = indexDir.mkdir();
if (!success)
throw new MessageSearchException("failed to
create index directory {location='" + volume.getIndexPath() + "'}",logger);
logger.info("index directory successfully created {location='"
+ volume.getIndexPath() + "'}");
}
}
protected void finalize() throws Throwable {
logger.debug("messagindex class is shutting down");
try {
shutdown = true;
} finally {
super.finalize();
}
}
}
package com.stimulus.archiva.index;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import javax.mail.MessagingException;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.*;
import org.apache.lucene.store.FSDirectory;
import com.stimulus.archiva.domain.Config;
import com.stimulus.archiva.domain.Email;
import com.stimulus.archiva.domain.Indexer;
import com.stimulus.archiva.domain.Volume;
import com.stimulus.archiva.exception.ExtractionException;
import com.stimulus.archiva.exception.MessageSearchException;
import com.stimulus.archiva.language.AnalyzerFactory;
import com.stimulus.archiva.search.*;
import java.util.*;
import org.apache.lucene.store.AlreadyClosedException;
public class VolumeIndex {
protected static final Logger logger =
Logger.getLogger(VolumeIndex.class.getName());
public static final int indexOpenTime = 2000;
IndexWriter writer = null;
Volume volume;
Timer closeIndexTimer = new Timer();
Object indexLock = new Object();
ArchivaAnalyzer analyzer = new ArchivaAnalyzer();
Indexer indexer = null;
public VolumeIndex(Indexer indexer, Volume volume) {
this.volume = volume;
this.indexer = indexer;
closeIndexTimer.scheduleAtFixedRate(new
TimerTask() {
public void run() {
closeIndex();
}
}, indexOpenTime, indexOpenTime);
}
protected void openIndex(boolean retry) throws
MessageSearchException {
Exception lastError = null;
synchronized(indexLock) {
if (writer==null) {
logger.debug("openIndex() index will be opened.
it is currently closed.");
} else {
logger.debug("openIndex() did not bother
opening index. it is already open.");
return;
}
logger.debug("opening index for write
{"+volume+"}");
indexer.prepareIndex(volume);
logger.debug("opening search index for write
{indexpath='"+volume.getIndexPath()+"'}");
try {
writer = new
IndexWriter(FSDirectory.getDirectory(volume.getIndexPath()),false, analyzer);
writer.setMaxFieldLength(50000);
if (logger.isDebugEnabled()) {
File file = new
File(Config.getFileSystem().getLogPath()+File.separator+"index.log");
PrintStream debugout =
new PrintStream(file);
writer.setInfoStream(debugout);
}
} catch (IOException io) {
lastError = io;
if (!retry) {
// most obvious reason for
error is that there is a lock on the index, due hard shutdown
// resolution delete the
lock, and try again
logger.warn("failed to open
search index for write. possible write lock due to hard system shutdown.",io);
logger.info("attempting
recovery. deleting index lock file and retrying..");
File lockFile = new
File(volume.getIndexPath()+File.separatorChar + "write.lock");
lockFile.delete();
openIndex(true);
} else {
throw new
MessageSearchException("failed to open/ index writer
{location='"+volume.getIndexPath()+"'}",lastError,logger);
}
}
}
}
public void indexMessage(Email message) throws
MessageSearchException {
long s = (new Date()).getTime();
if (message == null)
throw new MessageSearchException("assertion
failure: null message",logger);
logger.debug("indexing message {"+message+"}");
Document doc = new Document();
try {
DocumentIndex docIndex = new DocumentIndex(indexer);
docIndex.write(message,doc);
String language = doc.get("lang");
if (language==null)
language = indexer.getIndexLanguage();
synchronized (indexLock) {
openIndex(false);
writer.addDocument(doc,AnalyzerFactory.getAnalyzer(language,AnalyzerFactory.Operation.INDEX));
}
doc = null;
logger.debug("message indexed successfully
{"+message+",language='"+language+"'}");
} catch (MessagingException me)
{
throw new MessageSearchException("failed to decode
message during indexing",me,logger, Level.DEBUG);
} catch (IOException me) {
throw new MessageSearchException("failed to index
message {"+message+"}",me,logger, Level.DEBUG);
} catch (ExtractionException ee)
{
// we will want to continue indexing
//throw new MessageSearchException("failed to decode
attachments in message {"+message+"}",ee,logger, Level.DEBUG);
} catch (AlreadyClosedException ace) {
indexMessage(message);
} catch (Exception e) {
throw new MessageSearchException("failed to index
message",e,logger, Level.DEBUG);
}
logger.debug("indexing message end {"+message+"}");
long e = (new Date()).getTime();
logger.debug("indexing time {time='"+(e-s)+"'}");
}
protected void closeIndex() {
synchronized(indexLock) {
if (writer==null)
return;
try {
writer.close();
logger.debug("writer closed");
} catch (Exception io) {
logger.error("failed to close
index writer:"+io.getMessage(),io);
}
writer = null;
}
}
// deliberately non recursive (so we avoid situations
where the whole h/d is deleted)
public void deleteIndex() throws MessageSearchException {
logger.debug("delete index
{indexpath='"+volume.getIndexPath()+"'}");
try {
writer = new
IndexWriter(FSDirectory.getDirectory(volume.getIndexPath()),false,
analyzer,true);
} catch (Exception cie) {
logger.error("failed to delete index
{index='"+volume.getIndexPath()+"'}",cie);
File indexDir = new
File(volume.getIndexPath());
if (!indexDir.exists()) return;
if (indexDir.isDirectory()) {
String[] children = indexDir.list();
for (int i=0; i<children.length; i++) {
String filepath =
volume.getIndexPath()+File.separatorChar+children[i];
logger.debug("deleting file {path='" + filepath
+"'}");
File file = new File(filepath);
boolean success = file.delete();
if (!success) {
try {
File newFile =
File.createTempFile("temp","idx");
file.renameTo(newFile);
} catch (Exception e2) {
throw new
MessageSearchException("failed to delete file in existing index
{filepath='"+filepath+"'}",logger);
}
} else
logger.debug("deleted file successfully
{filepath='" + filepath +"'}");
}
}
return;
}
try {
writer.close();
} catch (Exception e) {
logger.error("failed to delete index
{index='"+volume.getIndexPath()+"'}",e);
}
MessageIndex.volumeIndexes.remove(this);
}
protected void finalize() throws Throwable {
logger.debug("volumeindex class is shutting down");
try {
closeIndexTimer.cancel();
closeIndex();
} finally {
super.finalize();
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]