|
|
|
@ -30,6 +30,7 @@ import java.io.File;
|
|
|
|
|
import java.io.FileInputStream;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Map.Entry;
|
|
|
|
@ -66,6 +67,7 @@ public class HeapReader {
|
|
|
|
|
protected HandleMap index; // key/seek relation for used records
|
|
|
|
|
protected Gap free; // set of {seek, size} pairs denoting space and position of free records
|
|
|
|
|
private File fingerprintFileIdx, fingerprintFileGap; // files with dumped indexes. Will be deleted if file is written
|
|
|
|
|
private Date closeDate; // records a time when the file was closed; used for debugging
|
|
|
|
|
|
|
|
|
|
public HeapReader(
|
|
|
|
|
final File heapFile,
|
|
|
|
@ -78,6 +80,7 @@ public class HeapReader {
|
|
|
|
|
this.free = null; // will be initialized later depending on existing idx/gap file
|
|
|
|
|
this.heapFile.getParentFile().mkdirs();
|
|
|
|
|
this.file = new CachedFileWriter(this.heapFile);
|
|
|
|
|
this.closeDate = null;
|
|
|
|
|
|
|
|
|
|
// read or initialize the index
|
|
|
|
|
this.fingerprintFileIdx = null;
|
|
|
|
@ -348,14 +351,22 @@ public class HeapReader {
|
|
|
|
|
* @return the number of BLOBs in the heap
|
|
|
|
|
*/
|
|
|
|
|
public int size() {
|
|
|
|
|
if (this.index == null) return 0;
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in size(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
return (this.index == null) ? 0 : this.index.size();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isEmpty() {
|
|
|
|
|
if (this.index == null) return true;
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in isEmpty(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
return this.index.isEmpty();
|
|
|
|
|
}
|
|
|
|
@ -367,7 +378,11 @@ public class HeapReader {
|
|
|
|
|
* @return true if the key exists, false otherwise
|
|
|
|
|
*/
|
|
|
|
|
public boolean containsKey(byte[] key) {
|
|
|
|
|
assert this.index != null;
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in containsKey(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
key = normalizeKey(key);
|
|
|
|
|
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
@ -388,6 +403,11 @@ public class HeapReader {
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
protected synchronized byte[] firstKey() throws IOException {
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in firstKey(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
return this.index.smallestKey();
|
|
|
|
|
}
|
|
|
|
@ -401,6 +421,11 @@ public class HeapReader {
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
protected byte[] first() throws IOException, RowSpaceExceededException {
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in first(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
byte[] key = this.index.smallestKey();
|
|
|
|
|
if (key == null) return null;
|
|
|
|
@ -416,6 +441,12 @@ public class HeapReader {
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
protected byte[] lastKey() throws IOException {
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in lastKey(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
if (this.index == null) return null;
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
return this.index.largestKey();
|
|
|
|
|
}
|
|
|
|
@ -429,6 +460,11 @@ public class HeapReader {
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
protected byte[] last() throws IOException, RowSpaceExceededException {
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in last(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
byte[] key = this.index.largestKey();
|
|
|
|
|
if (key == null) return null;
|
|
|
|
@ -443,7 +479,11 @@ public class HeapReader {
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public byte[] get(byte[] key) throws IOException, RowSpaceExceededException {
|
|
|
|
|
if (this.index == null) return null;
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in get(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
key = normalizeKey(key);
|
|
|
|
|
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
@ -530,6 +570,11 @@ public class HeapReader {
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public long length(byte[] key) throws IOException {
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in length(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
key = normalizeKey(key);
|
|
|
|
|
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
@ -547,6 +592,7 @@ public class HeapReader {
|
|
|
|
|
* close the BLOB table
|
|
|
|
|
*/
|
|
|
|
|
public void close(boolean writeIDX) {
|
|
|
|
|
if (this.index == null) return;
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
if (this.file != null)
|
|
|
|
|
try {
|
|
|
|
@ -598,6 +644,8 @@ public class HeapReader {
|
|
|
|
|
this.free = null;
|
|
|
|
|
if (this.index != null) this.index.close();
|
|
|
|
|
this.index = null;
|
|
|
|
|
this.closeDate = new Date();
|
|
|
|
|
Log.logInfo("HeapReader", "close HeapFile " + this.heapFile.getName() + "; trace:" + Log.stackTrace());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -615,6 +663,12 @@ public class HeapReader {
|
|
|
|
|
* @return the length of the key
|
|
|
|
|
*/
|
|
|
|
|
public int keylength() {
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in keylength(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (this.index == null) return 0;
|
|
|
|
|
return this.index.row().primaryKeyLength;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -626,6 +680,11 @@ public class HeapReader {
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public CloneableIterator<byte[]> keys(final boolean up, final boolean rotating) throws IOException {
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in keys(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
return new RotateIterator<byte[]>(this.index.keys(up, null), null, this.index.size());
|
|
|
|
|
}
|
|
|
|
@ -639,12 +698,22 @@ public class HeapReader {
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public CloneableIterator<byte[]> keys(final boolean up, final byte[] firstKey) throws IOException {
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in keys(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
return this.index.keys(up, firstKey);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public long length() {
|
|
|
|
|
assert (this.index != null) : "index == null; closeDate=" + this.closeDate + ", now=" + new Date();
|
|
|
|
|
if (this.index == null) {
|
|
|
|
|
Log.logSevere("HeapReader", "this.index == null in length(); closeDate=" + this.closeDate + ", now=" + new Date() + this.heapFile == null ? "" : (" file = " + this.heapFile.toString()));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
synchronized (this.index) {
|
|
|
|
|
return this.heapFile.length();
|
|
|
|
|
}
|
|
|
|
|