在Lucene3搜索引擎开发中,我写了个继承Directory的类(VFSDirectory.java),目的是让Web服务可以跨服务器读取索引。但在写完继承以后,运行报了个IO错误,说句柄无效。可能是因为多线程引起的。下面是(VFSDirectory.java)的代码
package com.youboy.VFS;import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;import org.apache.commons.io.IOUtils;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.RandomAccessContent;
import org.apache.commons.vfs.VFS;
import org.apache.commons.vfs.util.RandomAccessMode;
import org.apache.lucene.store.BufferedIndexInput;
import org.apache.lucene.store.BufferedIndexOutput;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.Lock;/**
 * 扩展Lucene索引的存储,使用commons-vfs做为lucene的存储引擎
 * 
 * @author Administrator
 */
public class VFSDirectory extends Directory { private FileSystemManager fileManager;
private FileObject directory;
private FileObject locker; public VFSDirectory(String repository_uri, String lock_uri)
throws IOException {
this.fileManager = VFS.getManager();
this.directory = fileManager.resolveFile(repository_uri);
if (!directory.exists())
directory.createFolder();
this.locker = fileManager.resolveFile(lock_uri);
if (!locker.exists())
locker.createFolder();
} @Override
public void close() throws IOException {
directory.close();
} protected void finalize() throws IOException {
close(); // close the directory
} @Override
public IndexOutput createOutput(String name) throws IOException {
FileObject file = this.fileManager.resolveFile(directory, name);
return new VFSIndexOutput(file);
} @Override
public IndexInput openInput(String name) throws IOException {
FileObject file = this.fileManager.resolveFile(directory, name);
return new VFSIndexInput(file);
} @Override
public void deleteFile(String name) throws IOException {
FileObject file = this.fileManager.resolveFile(directory, name);
// System.out.println(file.getName().getFriendlyURI());
if (!file.delete())
throw new IOException("Cannot delete " + file);
} @Override
public boolean fileExists(String name) throws IOException {
FileObject file = this.fileManager.resolveFile(directory, name);
return file.exists();
} @Override
public long fileLength(String name) throws IOException {
FileObject file = this.fileManager.resolveFile(directory, name);
return file.getContent().getSize();
} @Override
public long fileModified(String name) throws IOException {
FileObject file = this.fileManager.resolveFile(directory, name);
return file.getContent().getLastModifiedTime();
} @Override
public Lock makeLock(String name) {
final StringBuffer buf = getLockPrefix();
buf.append("-");
buf.append(name); try {
final FileObject lockFile = this.fileManager.resolveFile(locker,
buf.toString());
return new Lock() {
public boolean obtain() throws IOException {
lockFile.createFile();
return lockFile.exists();
} public void release() {
try {
lockFile.delete();
} catch (FileSystemException e) {
throw new RuntimeException("Cannot release lock : "
+ buf.toString(), e);
}
} public boolean isLocked() {
try {
return lockFile.exists();
} catch (FileSystemException e) {
throw new RuntimeException(
"Cannot check locking status : "
+ buf.toString(), e);
}
} public String toString() {
return "Lock@" + lockFile;
}
};
} catch (IOException e) {
throw new RuntimeException("Request lock failed : "
+ buf.toString(), e);
}
} private static MessageDigest DIGESTER; /**
 * So we can do some byte-to-hexchar conversion below
 */
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; static {
try {
DIGESTER = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e.toString(), e);
}
} private StringBuffer getLockPrefix() {
String dirName; // name to be hashed
try {
dirName = directory.getURL().toString();
} catch (IOException e) {
throw new RuntimeException(e.toString(), e);
} byte digest[];
synchronized (DIGESTER) {
digest = DIGESTER.digest(dirName.getBytes());
}
StringBuffer buf = new StringBuffer();
buf.append("lucene-");
for (int i = 0; i < digest.length; i++) {
int b = digest[i];
buf.append(HEX_DIGITS[(b >> 4) & 0xf]);
buf.append(HEX_DIGITS[b & 0xf]);
} return buf;
} @Override
public void touchFile(String name) throws IOException {
FileObject file = this.fileManager.resolveFile(directory, name);
file.getContent().setLastModifiedTime(System.currentTimeMillis());
} private void close(FileObject file) {
if (file != null) {
try {
file.close();
} catch (IOException e) {
throw new RuntimeException("Cannot close input stream: "
+ e.toString(), e);
}
}
} private static class VFSIndexInput extends BufferedIndexInput { private long length;
private RandomAccessContent content; public VFSIndexInput(FileObject file) throws IOException {
this.content = file.getContent().getRandomAccessContent(
RandomAccessMode.READ);
this.length = content.length();
} @Override
public void close() throws IOException {
this.content.close();
} @Override
public long length() {
return length;
} @Override
protected void readInternal(byte[] b, int off, int len)
throws IOException {
this.content.readFully(b, off, len);
} @Override
protected void seekInternal(long position) throws IOException {
this.content.seek(position);
}
} private static class VFSIndexOutput extends BufferedIndexOutput { private RandomAccessContent content; public VFSIndexOutput(FileObject file) throws IOException {
if (!file.exists())
file.createFile();
this.content = file.getContent().getRandomAccessContent(
RandomAccessMode.READWRITE);
} @Override
public void seek(long pos) throws IOException {
super.seek(pos);
this.content.seek(pos);
} @Override
public long length() throws IOException {
return this.content.length();
} @Override
public void close() throws IOException {
super.close();
this.content.close();
} protected void finalize() throws IOException {
close(); // close the file
} @Override
protected void flushBuffer(byte[] arg0, int arg1, int arg2)
throws IOException {
this.content.write(arg0, 0, arg2);

} } @Override
public String[] listAll() throws IOException { List<String> names = new ArrayList<String>();
FileObject[] files = directory.getChildren();
for (int i = 0; i < files.length; i++) {
names.add(files[i].getName().getBaseName());
}
return names.toArray(new String[names.size()]); }}

解决方案 »

  1.   

    下面是报错的信息[09:27:18.171] {http--8080-1$32125196} Using "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\vfs_cache" as temporary files store.
    [09:27:18.750] {http--8080-1$32125196} java.io.IOException: 句柄无效。
    [09:27:18.750] {http--8080-1$32125196}  at java.io.RandomAccessFile.seek(Native Method)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.commons.vfs.provider.local.LocalFileRandomAccessContent.seek(LocalFileRandomAccessContent.java:119)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.commons.vfs.util.MonitorRandomAccessContent.seek(MonitorRandomAccessContent.java:94)
    [09:27:18.750] {http--8080-1$32125196}  at com.youboy.VFS.VFSDirectory$VFSIndexInput.seekInternal(VFSDirectory.java:228)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.store.BufferedIndexInput.seek(BufferedIndexInput.java:186)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.CompoundFileReader$CSIndexInput.readInternal(CompoundFileReader.java:256)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.store.BufferedIndexInput.refill(BufferedIndexInput.java:160)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.store.BufferedIndexInput.readByte(BufferedIndexInput.java:39)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.store.IndexInput.readInt(IndexInput.java:69)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.SegmentTermEnum.<init>(SegmentTermEnum.java:50)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.TermInfosReader.<init>(TermInfosReader.java:71)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.SegmentReader$CoreReaders.<init>(SegmentReader.java:123)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.SegmentReader.get(SegmentReader.java:605)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.SegmentReader.get(SegmentReader.java:583)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.DirectoryReader.<init>(DirectoryReader.java:109)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.ReadOnlyDirectoryReader.<init>(ReadOnlyDirectoryReader.java:27)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.DirectoryReader$1.doBody(DirectoryReader.java:79)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.SegmentInfos$FindSegmentsFile.run(SegmentInfos.java:677)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.DirectoryReader.open(DirectoryReader.java:73)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.IndexReader.open(IndexReader.java:316)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.index.IndexReader.open(IndexReader.java:202)
    [09:27:18.750] {http--8080-1$32125196}  at org.apache.lucene.search.IndexSearcher.<init>(IndexSearcher.java:78)
    [09:27:18.750] {http--8080-1$32125196}  at com.youboy.lucene.searcher.WebSearcher.search(WebSearcher.java:88)
    [09:27:18.750] {http--8080-1$32125196}  at _jsp._search__jsp._jspService(_search__jsp.java:74)
    [09:27:18.750] {http--8080-1$32125196}  at com.caucho.jsp.JavaPage.service(JavaPage.java:61)
    [09:27:18.750] {http--8080-1$32125196}  at com.caucho.jsp.Page.pageservice(Page.java:578)
    [09:27:18.750] {http--8080-1$32125196}  at com.caucho.server.dispatch.PageFilterChain.doFilter(PageFilterChain.java:195)
    [09:27:18.750] {http--8080-1$32125196}  at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:187)
    [09:27:18.750] {http--8080-1$32125196}  at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:265)
    [09:27:18.750] {http--8080-1$32125196}  at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:273)
    [09:27:18.750] {http--8080-1$32125196}  at com.caucho.server.port.TcpConnection.run(TcpConnection.java:682)
    [09:27:18.750] {http--8080-1$32125196}  at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
    [09:27:18.750] {http--8080-1$32125196}  at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
    [09:27:18.750] {http--8080-1$32125196}  at java.lang.Thread.run(Unknown Source)