package quickbase.internal.index;
import gnu.trove.TIntProcedure;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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 quickbase.exception.BasicFileOperationDatabaseException;
public class Index {
public static final byte VERSION = 1;
private static final String SUFFIX = ".index";
private AdaptingIntLongMap index;
private File indexFile;
private Stats stats;
public Index(File path, String name, long maxPos) {
indexFile = new File(path, name + SUFFIX);
try {
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(indexFile), 100000));
try {
readContent(dis);
} finally {
dis.close();
}
if (maxPos != stats.size) {
// inconsistency -> rebuild index
clear();
}
} catch (IOException e) {
clear();
}
}
private void clear() {
index = new AdaptingIntLongMap(32);
stats = new Stats();
}
private void readContent(DataInputStream dis) throws IOException {
byte v = dis.readByte();
if (v == VERSION) {
stats = new Stats(dis);
index = new AdaptingIntLongMap(dis);
} else {
throw new IOException("Invalid version: " + v);
}
}
public Stats getStats() {
return stats;
}
public long getPosition(int hash) {
return index.get(hash);
}
public void put(int hash, long position) {
index.put(hash, position);
}
public void save(long size) throws BasicFileOperationDatabaseException {
try {
final DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(indexFile)));
try {
dos.writeByte(VERSION);
stats.size = size;
stats.write(dos);
index.write(dos);
} finally {
dos.close();
}
} catch (IOException e) {
throw new BasicFileOperationDatabaseException(e);
}
}
public void rename(String name) {
this.indexFile = new File(indexFile.getParent(), name + SUFFIX);
}
public void deleteFile() throws BasicFileOperationDatabaseException {
if (indexFile.exists() && !indexFile.delete()) {
throw new BasicFileOperationDatabaseException("Could not delete " + indexFile + ", " + indexFile.exists());
}
}
public void visitIndex(TIntProcedure visitor) {
index.visitKeys(visitor);
}
}