提交 2e880b99 authored 作者: Thomas Mueller's avatar Thomas Mueller

MVStore: the file format was changed slightly.

上级 00947d99
...@@ -66,12 +66,7 @@ TransactionStore: ...@@ -66,12 +66,7 @@ TransactionStore:
MVStore: MVStore:
- maybe let a chunk point to a list of potential next chunks
(so no fixed location header is needed), similar to a skip list
(options: just after the current chunk, list of next)
- document and review the file format - document and review the file format
- the newest chunk is the one with the newest version
(not necessarily the one with the highest chunk id)
- automated 'kill process' and 'power failure' test - automated 'kill process' and 'power failure' test
- update checkstyle - update checkstyle
...@@ -599,7 +594,6 @@ public class MVStore { ...@@ -599,7 +594,6 @@ public class MVStore {
int chunk = DataUtils.readHexInt(m, "chunk", 0); int chunk = DataUtils.readHexInt(m, "chunk", 0);
long version = DataUtils.readHexLong(m, "version", chunk); long version = DataUtils.readHexLong(m, "version", chunk);
if (version > newestVersion) { if (version > newestVersion) {
fileHeader.putAll(m);
newestVersion = version; newestVersion = version;
newestChunkBlock = DataUtils.readHexLong(m, "block", 0); newestChunkBlock = DataUtils.readHexLong(m, "block", 0);
validHeader = true; validHeader = true;
...@@ -619,21 +613,16 @@ public class MVStore { ...@@ -619,21 +613,16 @@ public class MVStore {
// ignore the exception, but exit the loop // ignore the exception, but exit the loop
break; break;
} }
if (header.version <= newestVersion) { if (header.version < newestVersion) {
// we reached the end // we have reached the end
break; break;
} }
fileHeader.put("chunk", header.id);
fileHeader.put("version", header.version);
fileHeader.put("block", testChunkBlock);
newestChunkBlock = testChunkBlock; newestChunkBlock = testChunkBlock;
newestVersion = header.version; newestVersion = header.version;
if (header.next == 0) { if (header.next == 0 || header.next >= fileStore.size() / BLOCK_SIZE) {
// try the chunk just after this one break;
testChunkBlock = header.block + header.len;
} else {
testChunkBlock = header.next;
} }
testChunkBlock = header.next;
} }
if (newestChunkBlock > 0) { if (newestChunkBlock > 0) {
...@@ -686,7 +675,7 @@ public class MVStore { ...@@ -686,7 +675,7 @@ public class MVStore {
} }
} }
private byte[] getFileHeaderBytes() { private void writeFileHeader() {
StringBuilder buff = new StringBuilder("H:2"); StringBuilder buff = new StringBuilder("H:2");
if (lastChunk != null) { if (lastChunk != null) {
fileHeader.put("chunk", lastChunk.id); fileHeader.put("chunk", lastChunk.id);
...@@ -702,11 +691,7 @@ public class MVStore { ...@@ -702,11 +691,7 @@ public class MVStore {
int checksum = DataUtils.getFletcher32(bytes, bytes.length / 2 * 2); int checksum = DataUtils.getFletcher32(bytes, bytes.length / 2 * 2);
DataUtils.appendMap(buff, "fletcher", checksum); DataUtils.appendMap(buff, "fletcher", checksum);
buff.append("\n"); buff.append("\n");
return buff.toString().getBytes(DataUtils.LATIN); bytes = buff.toString().getBytes(DataUtils.LATIN);
}
private void writeFileHeader() {
byte[] bytes = getFileHeaderBytes();
ByteBuffer header = ByteBuffer.allocate(2 * BLOCK_SIZE); ByteBuffer header = ByteBuffer.allocate(2 * BLOCK_SIZE);
header.put(bytes); header.put(bytes);
header.position(BLOCK_SIZE); header.position(BLOCK_SIZE);
...@@ -1023,10 +1008,6 @@ public class MVStore { ...@@ -1023,10 +1008,6 @@ public class MVStore {
long predictedNextStart = fileStore.allocate(predictBlocks * BLOCK_SIZE); long predictedNextStart = fileStore.allocate(predictBlocks * BLOCK_SIZE);
fileStore.free(predictedNextStart, predictBlocks * BLOCK_SIZE); fileStore.free(predictedNextStart, predictBlocks * BLOCK_SIZE);
c.next = predictedNextStart / BLOCK_SIZE; c.next = predictedNextStart / BLOCK_SIZE;
if (c.next == c.block + c.len) {
// just after this chunk
c.next = 0;
}
} else { } else {
// just after this chunk // just after this chunk
c.next = 0; c.next = 0;
...@@ -1042,30 +1023,33 @@ public class MVStore { ...@@ -1042,30 +1023,33 @@ public class MVStore {
write(filePos, buff.getBuffer()); write(filePos, buff.getBuffer());
releaseWriteBuffer(buff); releaseWriteBuffer(buff);
// whether to overwrite the file header // whether we need to write the file header
boolean needHeader = false; boolean needHeader = false;
// whether to reset the list of next chunks
boolean resetNextChain = false;
if (!storeAtEndOfFile) { if (!storeAtEndOfFile) {
if (lastChunk == null) { if (lastChunk == null) {
needHeader = true; needHeader = true;
} else if (lastChunk.block + lastChunk.len == c.block) { } else if (lastChunk.next != c.block) {
// just after the last chunk // the last prediction did not matched
} else if (lastChunk.next == c.block) {
// the last matched
} else {
needHeader = true; needHeader = true;
} else {
int chunkId = DataUtils.readHexInt(fileHeader, "chunk", 0);
if (lastChunk.id - chunkId > 20) {
// we write after at least 20 entries
needHeader = true;
} else {
while (chunkId <= lastChunk.id) {
if (chunks.get(chunkId) == null) {
// one of the chunks in between
// was removed
needHeader = true;
break;
}
chunkId++;
}
}
} }
; // TODO check the length of the list - if too large
// write anyway (lets assume 11 is too large)
; // TODO verify that no chunk between the last known one
// and the current chunk were removed
; // TODO remove this once we have implemented
// reading and once we have tests
needHeader = true;
} }
lastChunk = c; lastChunk = c;
if (needHeader) { if (needHeader) {
writeFileHeader(); writeFileHeader();
......
...@@ -148,7 +148,7 @@ public class MVStoreTool { ...@@ -148,7 +148,7 @@ public class MVStoreTool {
} }
} }
chunk.position(chunk.limit() - Chunk.FOOTER_LENGTH); chunk.position(chunk.limit() - Chunk.FOOTER_LENGTH);
pw.println(" store header"); pw.println(" chunk footer");
pw.println(" " + new String(chunk.array(), chunk.position(), Chunk.FOOTER_LENGTH, "UTF-8").trim()); pw.println(" " + new String(chunk.array(), chunk.position(), Chunk.FOOTER_LENGTH, "UTF-8").trim());
} }
} catch (IOException e) { } catch (IOException e) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论