package org.apache.blur.index;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.util.Arrays;
import org.apache.blur.trace.Trace;
import org.apache.blur.trace.Tracer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.lucene.store.Lock;
import org.apache.lucene.store.LockFactory;
public class OptimisticLockFactory extends LockFactory {
private final Configuration _configuration;
private final FileSystem _fileSystem;
private final String _baseLockKey;
private byte[] _lockKey;
private final Path _dir;
public OptimisticLockFactory(Configuration configuration, Path dir, String host, int pid) throws IOException {
_configuration = configuration;
_dir = dir;
_fileSystem = _dir.getFileSystem(_configuration);
_baseLockKey = host + "/" + pid;
}
@Override
public Lock makeLock(String lockName) {
final Path lockPath = new Path(_dir, lockName);
return new Lock() {
private boolean _set;
@Override
public boolean obtain() throws IOException {
Tracer trace = Trace.trace("filesystem - release", Trace.param("lockPath", lockPath));
try {
if (_set) {
throw new IOException("Lock for [" + _baseLockKey + "] can only be set once.");
}
try {
_lockKey = (_baseLockKey + "/" + System.currentTimeMillis()).getBytes();
FSDataOutputStream outputStream = _fileSystem.create(lockPath, true);
outputStream.write(_lockKey);
outputStream.close();
} finally {
_set = true;
}
return true;
} finally {
trace.done();
}
}
@Override
public void release() throws IOException {
Tracer trace = Trace.trace("filesystem - release", Trace.param("lockPath", lockPath));
try {
_fileSystem.delete(lockPath, false);
} finally {
trace.done();
}
}
@Override
public boolean isLocked() throws IOException {
Tracer trace = Trace.trace("filesystem - isLocked", Trace.param("lockPath", lockPath));
try {
if (!_set) {
return false;
}
if (!_fileSystem.exists(lockPath)) {
return false;
}
FileStatus fileStatus = _fileSystem.getFileStatus(lockPath);
long len = fileStatus.getLen();
if (len != _lockKey.length) {
return false;
}
byte[] buf = new byte[_lockKey.length];
FSDataInputStream inputStream = _fileSystem.open(lockPath);
inputStream.readFully(buf);
inputStream.close();
if (Arrays.equals(_lockKey, buf)) {
return true;
}
return false;
} finally {
trace.done();
}
}
};
}
@Override
public void clearLock(String lockName) throws IOException {
_fileSystem.delete(new Path(_dir, lockName), false);
}
}