package lsr.paxos.storage;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Responsible for reading and writing single number to file.
*/
public class SingleNumberWriter {
private final String directoryPath;
private final String filePrefix;
private int fileNumber;
/**
* Creates new instance of <code>SingleNumberWriter</code>.
* <p>
* Creates files of following format:
*
* <pre>
* /directoryPath/filePrefix.0
* /directoryPath/filePrefix.1
* /directoryPath/filePrefix.2
* ...
* </pre>
*
* <p>
* Note: directoryPath doesn't have to exist. If it doesn't, it will be
* created automatically.
*
* @param directoryPath - the directory where files will be created.
* @param filePrefix - the prefix of file name
*/
public SingleNumberWriter(String directoryPath, String filePrefix) {
this.directoryPath = directoryPath;
this.filePrefix = filePrefix;
// prepare
new File(directoryPath).mkdirs();
fileNumber = getLastFileNumber(new File(directoryPath).list());
}
/**
* Reads number from file. If the file doesn't exist, returns 0.
*
* @return number from file or 0 if file doesn't exist
*/
public long readNumber() {
File file = new File(currentFilePath());
if (!file.exists()) {
return 0;
}
long number;
try {
DataInputStream stream = new DataInputStream(new FileInputStream(file));
number = stream.readLong();
stream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return number;
}
public void writeNumber(long number) {
File oldFile = new File(currentFilePath());
fileNumber++;
File nextFile = new File(currentFilePath());
try {
FileOutputStream fos = new FileOutputStream(nextFile, false);
DataOutputStream dos = new DataOutputStream(fos);
dos.writeLong(number);
fos.getFD().sync();
dos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (oldFile.exists() && !oldFile.delete()) {
throw new RuntimeException("Unnable to remove file: " + oldFile.getPath());
}
}
private String currentFilePath() {
return new File(directoryPath, filePrefix + "." + fileNumber).getAbsolutePath();
}
private int getLastFileNumber(String[] files) {
Pattern pattern = Pattern.compile(filePrefix + "\\.(\\d+)");
int last = -1;
for (String fileName : files) {
Matcher matcher = pattern.matcher(fileName);
if (matcher.find()) {
int x = Integer.parseInt(matcher.group(1));
last = Math.max(x, last);
}
}
return last;
}
}