in lucene-directory-v2/src/main/java/jetbrains/exodus/lucene2/XodusDirectory.java [95:270]
public XodusDirectory(Environment environment) throws IOException {
this.environment = (EnvironmentImpl) environment;
var log = this.environment.getLog();
var logConfig = log.getConfig();
var path = Path.of(log.getLocation());
if (!Files.isDirectory(path)) {
throw new ExodusException("Path " + path + " does not exist in file system.");
}
if (logConfig.isSharedCache()) {
sharedLogCache = (SharedLogCache) log.cache;
} else {
throw new ExodusException("Lucene directory : " + log.getLocation() +
" . Only environments with shared cache are supported.");
}
this.cipherProvider = logConfig.getCipherProvider();
this.cipherKey = logConfig.getCipherKey();
this.identity = Log.Companion.getIdentityGenerator().nextId();
this.luceneOutputPath = path.resolve("luceneOutput");
this.luceneIndex = path.resolve("luceneIndex");
if (Files.exists(luceneOutputPath)) {
IOUtil.deleteRecursively(luceneOutputPath.toFile());
}
if (!environment.computeInTransaction(txn -> environment.storeExists(NAME_TO_ADDRESS_STORE_NAME, txn))) {
var removalMessage = NAME_TO_ADDRESS_STORE_NAME +
" store does not exist. All Lucene index files will be removed.";
if (Files.exists(luceneIndex)) {
logger.warn(removalMessage);
IOUtil.deleteRecursively(luceneIndex.toFile());
}
}
this.nameToAddressStore = environment.computeInTransaction(txn ->
environment.openStore(NAME_TO_ADDRESS_STORE_NAME, StoreConfig.WITHOUT_DUPLICATES, txn));
if (!Files.exists(luceneOutputPath)) {
Files.createDirectory(luceneOutputPath);
}
if (!Files.exists(luceneIndex)) {
Files.createDirectory(luceneIndex);
}
var runCheck = ((EnvironmentImpl) environment).isCheckLuceneDirectory();
LongOpenHashSet storedFiles = new LongOpenHashSet();
if (runCheck) {
logger.warn("Xodus directory " + log.getLocation() + " : clearing broken links between files and indexes.");
var namesToDelete = environment.computeInReadonlyTransaction(txn -> {
var toDelete = new ArrayList<ByteIterable>();
try (var cursor = nameToAddressStore.openCursor(txn)) {
while (cursor.getNext()) {
final var address = LongBinding.entryToLong(cursor.getValue());
if (address >= 0) {
final var indexFileName = DirUtil.getFileNameByAddress(address);
storedFiles.add(address);
if (!Files.exists(luceneIndex.resolve(indexFileName))) {
var key = cursor.getKey();
logger.info("File " + StringBinding.entryToString(key) +
" is absent and will be removed from index.");
toDelete.add(key);
}
} else {
var key = cursor.getKey();
toDelete.add(key);
}
}
}
return toDelete;
});
environment.executeInTransaction(txn -> {
for (var name : namesToDelete) {
nameToAddressStore.delete(txn, name);
}
});
}
long[] maxAddressLengthIv = new long[]{-1, -1, -1};
var fetchIvs = cipherKey != null;
LongOpenHashSet filesToDelete = new LongOpenHashSet();
try (var fileStream = DirUtil.listLuceneFiles(luceneIndex)) {
fileStream.forEach(p -> {
var indexFile = p.getFileName().toString();
var address = DirUtil.getFileAddress(indexFile);
if (runCheck && !storedFiles.contains(address)) {
logger.info("File " + indexFile + " is absent in index and will be removed.");
filesToDelete.add(address);
return;
}
if (address > maxAddressLengthIv[0]) {
maxAddressLengthIv[0] = address;
try {
maxAddressLengthIv[1] = Files.size(p);
} catch (IOException e) {
throw new ExodusException("Error during fetching of size of file " + p, e);
}
}
if (fetchIvs) {
var ivFileName = DirUtil.getIvFileName(indexFile);
var ivPath = luceneIndex.resolve(ivFileName);
if (Files.exists(ivPath)) {
try (var ivStream = new DataInputStream(Files.newInputStream(ivPath))) {
var iv = ivStream.readLong();
if (iv > maxAddressLengthIv[2]) {
maxAddressLengthIv[2] = iv;
}
} catch (EOFException eof) {
//ignore
} catch (IOException e) {
throw new ExodusException("Can not read iv file " + ivRnd, e);
}
}
}
}
);
}
if (!filesToDelete.isEmpty()) {
var addressIterator = filesToDelete.longIterator();
while (addressIterator.hasNext()) {
var address = addressIterator.nextLong();
var indexFileName = DirUtil.getFileNameByAddress(address);
var indexFile = luceneIndex.resolve(indexFileName);
var ivFileName = DirUtil.getIvFileName(indexFileName);
var ivFile = luceneIndex.resolve(ivFileName);
try {
Files.deleteIfExists(indexFile);
Files.deleteIfExists(ivFile);
} catch (IOException e) {
throw new ExodusException("Can not delete file " + indexFile, e);
}
}
}
this.pageSize = log.getCachePageSize();
if (maxAddressLengthIv[0] >= 0) {
var nextAddress = maxAddressLengthIv[0] + maxAddressLengthIv[1];
var pages = (nextAddress + pageSize - 1) / pageSize;
if (pages == 0) {
pages = 1;
}
this.nextAddress = new AtomicLong(pages * pageSize);
} else {
this.nextAddress = new AtomicLong(0);
}
this.ivGen = new AtomicLong(maxAddressLengthIv[2] + 1);
this.path = path;
}