Author: j16sdiz
Date: 2008-09-20 05:37:54 +0000 (Sat, 20 Sep 2008)
New Revision: 22717
Modified:
trunk/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
Log:
SALTED-HASH: File Format Change - merge header/data files
This would increase the file size by around 1%
Modified: trunk/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
2008-09-20 05:32:46 UTC (rev 22716)
+++ trunk/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
2008-09-20 05:37:54 UTC (rev 22717)
@@ -42,6 +42,7 @@
import freenet.support.HTMLNode;
import freenet.support.HexUtil;
import freenet.support.Logger;
+import freenet.support.io.Closer;
import freenet.support.io.FileUtil;
import freenet.support.io.NativeThread;
@@ -99,6 +100,9 @@
headerBlockLength = callback.headerLength();
fullKeyLength = callback.fullKeyLength();
dataBlockLength = callback.dataLength();
+
+ hdPadding = (int) ((headerBlockLength + dataBlockLength) % 512
== 0 ? 0
+ : 512 - (headerBlockLength + dataBlockLength) % 512);
this.random = random;
storeSize = maxKeys;
@@ -278,7 +282,7 @@
try {
if (!collisionPossible)
return;
-
oldEntry.setData(readHeader(oldOffset), readData(oldOffset)); // read from disk
+
oldEntry.setHD(readHD(oldOffset)); // read from disk
StorableBlock oldBlock =
oldEntry.getStorableBlock(routingKey, fullKey);
if (block.equals(oldBlock)) {
return; // already in
store
@@ -339,14 +343,11 @@
private File metaFile;
private RandomAccessFile metaRAF;
private FileChannel metaFC;
- // header file
- private File headerFile;
- private RandomAccessFile headerRAF;
- private FileChannel headerFC;
- // data file
- private File dataFile;
- private RandomAccessFile dataRAF;
- private FileChannel dataFC;
+ // header+data file
+ private File hdFile;
+ private RandomAccessFile hdRAF;
+ private FileChannel hdFC;
+ private final int hdPadding;
/**
* Data entry
@@ -399,7 +400,7 @@
private Entry() {
}
- private Entry(ByteBuffer metaDataBuf, ByteBuffer headerBuf,
ByteBuffer dataBuf) {
+ private Entry(ByteBuffer metaDataBuf, ByteBuffer hdBuf) {
assert metaDataBuf.remaining() == METADATA_LENGTH;
digestedRoutingKey = new byte[0x20];
@@ -421,8 +422,8 @@
isEncrypted = true;
- if (headerBuf != null && dataBuf != null)
- setData(headerBuf, dataBuf);
+ if (hdBuf != null)
+ setHD(hdBuf);
}
/**
@@ -431,16 +432,15 @@
* @param storeBuf
* @param store
*/
- private void setData(ByteBuffer headerBuf, ByteBuffer dataBuf) {
- assert headerBuf.remaining() == headerBlockLength;
- assert dataBuf.remaining() == dataBlockLength;
+ private void setHD(ByteBuffer hdBuf) {
+ assert hdBuf.remaining() == headerBlockLength +
dataBlockLength + hdPadding;
assert isEncrypted;
header = new byte[headerBlockLength];
- headerBuf.get(header);
+ hdBuf.get(header);
data = new byte[dataBlockLength];
- dataBuf.get(data);
+ hdBuf.get(data);
}
/**
@@ -492,29 +492,17 @@
return out;
}
- private ByteBuffer toHeaderBuffer() {
+ private ByteBuffer toHDBuffer() {
assert isEncrypted; // should have encrypted to get
dataEncryptIV in control buffer
+ assert header.length == headerBlockLength;
+ assert data.length == dataBlockLength;
- if (header == null)
+ if (header == null || data == null)
return null;
- ByteBuffer out = ByteBuffer.allocate(headerBlockLength);
+ ByteBuffer out = ByteBuffer.allocate(headerBlockLength
+ dataBlockLength + hdPadding);
out.put(header);
- assert out.remaining() == 0;
-
- out.position(0);
- return out;
- }
-
- private ByteBuffer toDataBuffer() {
- assert isEncrypted; // should have encrypted to get
dataEncryptIV in control buffer
-
- if (data == null)
- return null;
-
- ByteBuffer out = ByteBuffer.allocate(dataBlockLength);
out.put(data);
- assert out.remaining() == 0;
out.position(0);
return out;
@@ -568,27 +556,76 @@
*/
private boolean openStoreFiles(File baseDir, String name) throws
IOException {
metaFile = new File(baseDir, name + ".metadata");
- headerFile = new File(baseDir, name + ".header");
- dataFile = new File(baseDir, name + ".data");
+ hdFile = new File(baseDir, name + ".hd");
- boolean newStore = !metaFile.exists() || !headerFile.exists()
|| !dataFile.exists();
+ boolean newStore = !metaFile.exists() || !hdFile.exists();
metaRAF = new RandomAccessFile(metaFile, "rw");
metaFC = metaRAF.getChannel();
metaFC.lock();
- headerRAF = new RandomAccessFile(headerFile, "rw");
- headerFC = headerRAF.getChannel();
- headerFC.lock();
+ hdRAF = new RandomAccessFile(hdFile, "rw");
+ hdFC = hdRAF.getChannel();
+ hdFC.lock();
- dataRAF = new RandomAccessFile(dataFile, "rw");
- dataFC = dataRAF.getChannel();
- dataFC.lock();
long storeFileSize = Math.max(storeSize, prevStoreSize);
WrapperManager.signalStarting(10 * 60 * 1000); // 10minutes,
for filesystem that support no sparse file.
setStoreFileSize(storeFileSize);
+ // XXX migrate from old format
+ {
+ // migrate
+ File headerFile = new File(baseDir, name + ".header");
+ File dataFile = new File(baseDir, name + ".data");
+
+ if (headerFile.exists() && dataFile.exists()) {
+ System.out.println("Migrating .header/.data
-to-> .hd");
+ WrapperManager.signalStarting(7 * 24 * 60 * 60
* 1000);
+
+ RandomAccessFile headerRAF = null;
+ RandomAccessFile dataRAF = null;
+ try {
+ cleanerGlobalLock.lock();
+ headerRAF = new
RandomAccessFile(headerFile, "rw");
+ dataRAF = new
RandomAccessFile(dataFile, "rw");
+
+ byte[] header = new
byte[headerBlockLength];
+ byte[] data = new byte[dataBlockLength];
+ byte[] pad = new byte[hdPadding];
+
+ long total = dataRAF.length() /
dataBlockLength;
+ newStore = false;
+
+ for (long offset = total - 1; offset >=
0; offset--) {
+ if (offset % 1024 == 0)
+ System.out.println(name
+ ": " + (total - offset) + "/" + total);
+
headerRAF.seek(headerBlockLength * offset);
+ headerRAF.readFully(header);
+ dataRAF.seek(dataBlockLength *
offset);
+ dataRAF.readFully(data);
+
+ hdRAF.seek((headerBlockLength +
dataBlockLength + hdPadding) * offset);
+ hdRAF.write(header);
+ hdRAF.write(data);
+ hdRAF.write(pad);
+
+
headerRAF.setLength(headerBlockLength * offset);
+
dataRAF.setLength(dataBlockLength * offset);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ cleanerGlobalLock.unlock();
+ Closer.close(headerRAF);
+ Closer.close(dataRAF);
+ }
+ headerFile.delete();
+ dataFile.delete();
+ setStoreFileSize(storeFileSize);
+ }
+ }
+
return newStore;
}
@@ -608,7 +645,7 @@
} while (mbf.hasRemaining());
mbf.flip();
- Entry entry = new Entry(mbf, null, null);
+ Entry entry = new Entry(mbf, null);
entry.curOffset = offset;
if (routingKey != null) {
@@ -618,9 +655,8 @@
return null;
if (withData) {
- ByteBuffer headerBuf = readHeader(offset);
- ByteBuffer dataBuf = readData(offset);
- entry.setData(headerBuf, dataBuf);
+ ByteBuffer hdBuf = readHD(offset);
+ entry.setHD(hdBuf);
boolean decrypted =
cipherManager.decrypt(entry, routingKey);
if (!decrypted)
return null;
@@ -631,41 +667,25 @@
}
/**
- * Read header from disk
+ * Read header + data from disk
*
* @param offset
* @throws IOException
*/
- private ByteBuffer readHeader(long offset) throws IOException {
- ByteBuffer buf = ByteBuffer.allocate(headerBlockLength);
+ private ByteBuffer readHD(long offset) throws IOException {
+ ByteBuffer buf = ByteBuffer.allocate(headerBlockLength +
dataBlockLength + hdPadding);
+ long pos = (headerBlockLength + dataBlockLength + hdPadding) *
offset;
do {
- int status = headerFC.read(buf, headerBlockLength *
offset + buf.position());
+ int status = hdFC.read(buf, pos + buf.position());
if (status == -1)
throw new EOFException();
} while (buf.hasRemaining());
buf.flip();
+
return buf;
}
-
- /**
- * Read data from disk
- *
- * @param offset
- * @throws IOException
- */
- private ByteBuffer readData(long offset) throws IOException {
- ByteBuffer buf = ByteBuffer.allocate(dataBlockLength);
-
- do {
- int status = dataFC.read(buf, dataBlockLength * offset
+ buf.position());
- if (status == -1)
- throw new EOFException();
- } while (buf.hasRemaining());
- buf.flip();
- return buf;
- }
-
+
private boolean isFree(long offset) throws IOException {
Entry entry = readEntry(offset, null, false);
return entry.isFree();
@@ -695,20 +715,14 @@
throw new EOFException();
} while (bf.hasRemaining());
- bf = entry.toHeaderBuffer();
+ bf = entry.toHDBuffer();
if (bf != null) {
+ long pos = (headerBlockLength + dataBlockLength +
hdPadding) * offset;
do {
- int status = headerFC.write(bf,
headerBlockLength * offset + bf.position());
+ int status = hdFC.write(bf, pos +
bf.position());
if (status == -1)
throw new EOFException();
} while (bf.hasRemaining());
-
- bf = entry.toDataBuffer();
- do {
- int status = dataFC.write(bf, dataBlockLength *
offset + bf.position());
- if (status == -1)
- throw new EOFException();
- } while (bf.hasRemaining());
}
entry.curOffset = offset;
@@ -722,17 +736,11 @@
Logger.error(this, "error flusing store", e);
}
try {
- headerFC.force(true);
- headerFC.close();
+ hdFC.force(true);
+ hdFC.close();
} catch (Exception e) {
Logger.error(this, "error flusing store", e);
}
- try {
- dataFC.force(true);
- dataFC.close();
- } catch (Exception e) {
- Logger.error(this, "error flusing store", e);
- }
bloomFilter.force();
}
@@ -745,8 +753,7 @@
private void setStoreFileSize(long storeFileSize) {
try {
metaRAF.setLength(Entry.METADATA_LENGTH *
storeFileSize);
- headerRAF.setLength(headerBlockLength * storeFileSize);
- dataRAF.setLength(dataBlockLength * storeFileSize);
+ hdRAF.setLength((headerBlockLength + dataBlockLength +
hdPadding) * storeFileSize);
} catch (IOException e) {
Logger.error(this, "error resizing store file", e);
}
@@ -1019,7 +1026,7 @@
bloomFilter.removeKey(entry.getDigestedRoutingKey());
}
try {
-
entry.setData(readHeader(entry.curOffset), readData(entry.curOffset));
+
entry.setHD(readHD(entry.curOffset));
oldEntryList.add(entry);
if (oldEntryList.size() >
RESIZE_MEMORY_ENTRIES)
oldEntryList.remove(0);
@@ -1244,7 +1251,7 @@
ByteBuffer enBuf = buf.slice();
enBuf.limit(Entry.METADATA_LENGTH);
- Entry entry = new Entry(enBuf,
null, null);
+ Entry entry = new Entry(enBuf,
null);
entry.curOffset = offset + j;
if (entry.isFree())