Lucene-同步机制
Lucene是一个优秀的开源搜索引擎library,其价值已经在众多的应用中体现出来。对于lucene的相关研究的文章每天都层出不穷的出现在各大论坛中。为初学者的学习之路打开了方便之门。本文仅针对Lucene中有关Directory同步机制做相关的论述。同步机制是保证索引的完备性、一致性的重要的一种方式,保持进程间的同步。
在使用Lucene 进行索引的过程中,首先我们需要创建或指定一个操作、存储索引数据的场景。因此,Directory以及与其相关的便承担了这个责任。
- Directory在Lucene中被定义为一个抽象类public abstract class Directory implements Closeable {...},其具体的实现类主要有FileSwitchDirectory、RAMDirectory、 FSDirectory,SimpleFSDirectory等(其次还有NIOFSDirectory--主要针对linux系统,MMapDirectory)。而通常我们在创建Directory 实例过程中的directory类型实际上是SimpleFSDirectory,它是FSDirectory的一个子类。
Directory directory=FSDirectory.open(new File(indexDirectory));在FSDirectory的open方法中首先会判断当前系统的类型如果是window则创建SimpleFSDirectory类型对象,如果是其他平台则创建NIOFSDirectory类型的对象。因此,实际上,对象的初始化过程是由 SimpleFSDirectory调用FSDirectory来完成的。
if (Constants.WINDOWS) {
return new SimpleFSDirectory(path, lockFactory);
} else {
return new NIOFSDirectory(path, lockFactory);
}
public SimpleFSDirectory(File path, LockFactory lockFactory) throws IOException {
super(path, lockFactory);
}
- FSDirecotry 中有一个LockFactory的对象lockFacotry,该对象主要用来生成Lock对象实例,Lock writeLock = directory.makeLock(WRITE_LOCK_NAME),由Directory对象发起,调用makeLock(object)方法,传入一个String类型的参数作为Lock对象的名称,通常该名称为一个固定的常量,public static final String WRITE_LOCK_NAME = "write.lock",这个文件在生成索引的时候可以直接在索引目录下,其中lockFactory实际类型为NativeFSLockFactory,makeLock方法返回一个 NativeFSLock对象实例因此,NativeFSLock是实际执行同步机制的Lock执行类,NativeFSLock是NativeFSLockFactory的内部类。参照如下代码及类图
//FSDirectory构造函数,对应Lucene3.0FSDirectory类中的144-170
protected FSDirectory(File path, LockFactory lockFactory) throws IOException {
//索引目录的路径
path = getCanonicalPath(path);
// 使用NativeFSLockFactory 作为默认的工厂类if (lockFactory == null) {
//建立一个Lock Facotry
lockFactory = new NativeFSLockFactory();
}
directory = path;
if (directory.exists() && !directory.isDirectory())throw new NoSuchDirectoryException("file '" + directory + "' exists but is not a directory");
//为FSDirectory属性lockFactory赋值
setLockFactory(lockFactory);
//设置LockFactory对象对应的目录 以及名称的前缀
if (lockFactory instanceof FSLockFactory) {
final FSLockFactory lf = (FSLockFactory) lockFactory;
final File dir = lf.getLockDir();
// if the lock factory has no lockDir set, use the this directory as lockDir
if (dir == null) {
lf.setLockDir(this.directory);
lf.setLockPrefix(null);
} else if (dir.getCanonicalPath().equals(this.directory.getCanonicalPath())) {
lf.setLockPrefix(null);
}
}}
//NNativeFSLockFactory 中的makeLock()方法,生成一个NativeFSLock对象,用于后面的进程同步。
@ lockName,对应要生成锁文件的名字
public synchronized Lock makeLock(String lockName) {
acquireTestLock();
if (lockPrefix != null)
lockName = lockPrefix + "-" + lockName;
return new NativeFSLock(lockDir, lockName);
}// NativeFSLock类中对应的obtain()方法,真正同步策略的执行体,在IndexWriter对象创建过程中被调用
//来探查是否已经存在相关进程进行索引目录的操作
public synchronized boolean obtain() throws IOException {
if (lockExists()) {
// Our instance is already locked:
return false;
}
// Ensure that lockDir exists and is a directory.
if (!lockDir.exists()) {
if (!lockDir.mkdirs())
throw new IOException("Cannot create directory: " +
lockDir.getAbsolutePath());
} else if (!lockDir.isDirectory()) {
throw new IOException("Found regular file where directory expected: " +
lockDir.getAbsolutePath());
}
String canonicalPath = path.getCanonicalPath();
boolean markedHeld = false;
try {
// Make sure nobody else in-process has this lock held
// already, and, mark it held if not:
//确保没有其他进程在使用该LOCK_HELD,一个HashSet<String>对象用来保存当前创建的所有Lock实例
synchronized(LOCK_HELD) {
if (LOCK_HELD.contains(canonicalPath)) {
//该锁已经存在
return false;
} else {
//添加一个实例
LOCK_HELD.add(canonicalPath);
markedHeld = true;
}
}
try {
f = new RandomAccessFile(path, "rw");
} catch (IOException e) {
failureReason = e;
f = null;
}
if (f != null) {
try {//类似指针
channel = f.getChannel();
try {
lock = channel.tryLock();
} catch (IOException e) {
failureReason = e;
} finally {
if (lock == null) {
try {
channel.close();
} finally {
channel = null;
}
}
}
} finally {
if (channel == null) {
try {
f.close();
} finally {
f = null;
}
}
}
}
} finally {
if (markedHeld && !lockExists()) {
synchronized(LOCK_HELD) {
if (LOCK_HELD.contains(canonicalPath)) {//清楚异常操作
LOCK_HELD.remove(canonicalPath);
}
}
}
}
return lockExists();
}
posted on 2010-09-16 14:34 Creative Common 阅读(582) 评论(0) 编辑 收藏 举报