
com.epam.deltix.util.id.FileHiLowIdentifierGenerator Maven / Gradle / Ivy
/*
* Copyright 2021 EPAM Systems, Inc
*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Licensed 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.
*/
package com.epam.deltix.util.id;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
/**
* HiLowIdentifierGenerator that uses file storage in given directory to persist last allocated block.
* This keep file storage locked during application up time, disallowing access from another process.
*
* @see SharedFileHiLowIdentifierGenerator
*/
public final class FileHiLowIdentifierGenerator extends FileBasedHiLowIdentifierGenerator implements Closeable {
private final RandomAccessFile raf;
private final FileChannel channel;
private final FileLock lock;
private final boolean storeLastUsedOnClose;
public FileHiLowIdentifierGenerator (File dir, String key, int blockSize, boolean writeLastUsedOnClose) throws IOException {
this (dir, key, blockSize, 1, writeLastUsedOnClose, "rwd");
}
public FileHiLowIdentifierGenerator(File dir, String key, int blockSize, long startId, boolean writeLastUsedOnClose, String fileMode) throws IOException {
super(dir, key, blockSize, startId);
storeLastUsedOnClose = writeLastUsedOnClose;
raf = new RandomAccessFile(file, fileMode);
channel = raf.getChannel();
lock = channel.tryLock();
if (lock == null)
throw new RuntimeException("Another program holds lock for file " + file.getAbsolutePath());
}
@Override
protected long acquireNextBlock(long resetNextBlock) {
try {
final long currentBlock;
if (resetNextBlock != 0) {
currentBlock = resetNextBlock;
} else {
if (file.length() == 0) {
currentBlock = startId;
} else {
raf.seek(0L);
String lastBlock = raf.readLine();
currentBlock = Long.parseLong(lastBlock);
}
}
raf.seek(0L);
raf.write(Long.toString(currentBlock + blockSize).getBytes()); // assuming number of digits always grows
//channel.force(true); not required since we access file in "rwd" mode (d).
return currentBlock;
} catch (IOException e) {
throw new RuntimeException ("Error accessing sequence storage file: " + e.getMessage(), e);
}
}
@Override
public void close() throws IOException {
if (storeLastUsedOnClose)
storeLastUsed();
lock.release();
channel.close();
raf.close();
}
private void storeLastUsed() {
store(next());
}
private void store(long lastUsed) {
if (channel != null && channel.isOpen() && raf != null)
try {
raf.seek(0L);
// storing last used may reduce number of bytes stored compared to last block, lets adjust file size
String block = Long.toString(lastUsed);
raf.write(block.getBytes());
raf.setLength(block.length());
} catch (Throwable e) {
e.printStackTrace();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy