|
@@ -89,6 +89,7 @@ protected:
|
|
|
unsigned __int64 sequence;
|
|
|
CRC32StartHT crcStartPosTable;
|
|
|
CRC32EndHT crcEndPosTable;
|
|
|
+ CRC32 headCRC;
|
|
|
bool doCrc = false;
|
|
|
|
|
|
public:
|
|
@@ -105,12 +106,14 @@ public:
|
|
|
prevLeafNode = NULL;
|
|
|
|
|
|
assertex(nodeSize >= CKeyHdr::getSize());
|
|
|
- assertex(nodeSize <= 0xffff); // stored in a short in the header - we should fix that if/when we restructure header
|
|
|
+ assertex(nodeSize <= 0xffff); // stored in a short in the header - we should fix that if/when we restructure header
|
|
|
+ if (flags & TRAILING_HEADER_ONLY)
|
|
|
+ flags |= USE_TRAILING_HEADER;
|
|
|
KeyHdr *hdr = keyHdr->getHdrStruct();
|
|
|
hdr->nodeSize = nodeSize;
|
|
|
hdr->extsiz = 4096;
|
|
|
hdr->length = keyValueSize;
|
|
|
- hdr->ktype = flags;
|
|
|
+ hdr->ktype = flags;
|
|
|
hdr->timeid = 0;
|
|
|
hdr->clstyp = 1; // IDX_CLOSE
|
|
|
hdr->maxkbn = nodeSize-sizeof(NodeHdr);
|
|
@@ -131,11 +134,12 @@ public:
|
|
|
hdr->blobHead = 0;
|
|
|
hdr->metadataHead = 0;
|
|
|
|
|
|
- keyHdr->write(out); // Reserve space for the header - we'll seek back and write it properly later
|
|
|
+ keyHdr->write(out, &headCRC); // Reserve space for the header - we may seek back and write it properly later
|
|
|
}
|
|
|
|
|
|
CKeyBuilderBase(CKeyHdr * chdr)
|
|
|
{
|
|
|
+ sequence = 0;
|
|
|
levels = 0;
|
|
|
records = 0;
|
|
|
prevLeafNode = NULL;
|
|
@@ -201,26 +205,34 @@ protected:
|
|
|
if (out)
|
|
|
{
|
|
|
out->flush();
|
|
|
- out->seek(0, IFSbegin);
|
|
|
- keyHdr->write(out, crc);
|
|
|
+ if (keyHdr->getKeyType() & USE_TRAILING_HEADER)
|
|
|
+ writeNode(keyHdr, out->tell()); // write a copy at end too, for use on systems that can't seek
|
|
|
+ if (!(keyHdr->getKeyType() & TRAILING_HEADER_ONLY))
|
|
|
+ {
|
|
|
+ out->seek(0, IFSbegin);
|
|
|
+ keyHdr->write(out, crc);
|
|
|
+ }
|
|
|
+ else if (crc)
|
|
|
+ {
|
|
|
+ *crc = headCRC;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- void writeNode(CWriteNodeBase *node)
|
|
|
+ void writeNode(CWritableKeyNode *node, offset_t _nodePos)
|
|
|
{
|
|
|
unsigned nodeSize = keyHdr->getNodeSize();
|
|
|
if (doCrc)
|
|
|
{
|
|
|
- offset_t nodePos = node->getFpos();
|
|
|
- CRC32HTE *rollingCrcEntry1 = crcEndPosTable.find(nodePos); // is start of this block end of another?
|
|
|
- nodePos += nodeSize; // update to endpos
|
|
|
+ CRC32HTE *rollingCrcEntry1 = crcEndPosTable.find(_nodePos); // is start of this block end of another?
|
|
|
+ offset_t endPos = _nodePos+nodeSize;
|
|
|
if (rollingCrcEntry1)
|
|
|
{
|
|
|
crcEndPosTable.removeExact(rollingCrcEntry1); // end pos will change
|
|
|
node->write(out, &rollingCrcEntry1->crc);
|
|
|
rollingCrcEntry1->size += nodeSize;
|
|
|
|
|
|
- CRC32HTE *rollingCrcEntry2 = crcStartPosTable.find(nodePos); // is end of this block, start of another?
|
|
|
+ CRC32HTE *rollingCrcEntry2 = crcStartPosTable.find(endPos); // is end of this block, start of another?
|
|
|
if (rollingCrcEntry2)
|
|
|
{
|
|
|
crcStartPosTable.removeExact(rollingCrcEntry2); // remove completely, will join to rollingCrcEntry1
|
|
@@ -236,12 +248,12 @@ protected:
|
|
|
delete rollingCrcEntry2;
|
|
|
}
|
|
|
else
|
|
|
- rollingCrcEntry1->endBlockPos = nodePos;
|
|
|
+ rollingCrcEntry1->endBlockPos = endPos;
|
|
|
crcEndPosTable.replace(*rollingCrcEntry1);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- rollingCrcEntry1 = crcStartPosTable.find(nodePos); // is end of this node, start of another?
|
|
|
+ rollingCrcEntry1 = crcStartPosTable.find(endPos); // is end of this node, start of another?
|
|
|
if (rollingCrcEntry1)
|
|
|
{
|
|
|
crcStartPosTable.removeExact(rollingCrcEntry1); // start pos will change
|
|
@@ -253,7 +265,7 @@ protected:
|
|
|
crcMerger.addChildCRC(rollingCrcEntry1->size, rollingCrcEntry1->crc.get(), true);
|
|
|
|
|
|
rollingCrcEntry1->crc.reset(~crcMerger.get());
|
|
|
- rollingCrcEntry1->startBlockPos = node->getFpos();
|
|
|
+ rollingCrcEntry1->startBlockPos = _nodePos;
|
|
|
rollingCrcEntry1->size += nodeSize;
|
|
|
crcStartPosTable.replace(*rollingCrcEntry1);
|
|
|
}
|
|
@@ -261,8 +273,8 @@ protected:
|
|
|
{
|
|
|
rollingCrcEntry1 = new CRC32HTE;
|
|
|
node->write(out, &rollingCrcEntry1->crc);
|
|
|
- rollingCrcEntry1->startBlockPos = node->getFpos();
|
|
|
- rollingCrcEntry1->endBlockPos = node->getFpos()+nodeSize;
|
|
|
+ rollingCrcEntry1->startBlockPos = _nodePos;
|
|
|
+ rollingCrcEntry1->endBlockPos = _nodePos+nodeSize;
|
|
|
rollingCrcEntry1->size = nodeSize;
|
|
|
crcStartPosTable.replace(*rollingCrcEntry1);
|
|
|
crcEndPosTable.replace(*rollingCrcEntry1);
|
|
@@ -270,7 +282,7 @@ protected:
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
- node->write(out);
|
|
|
+ node->write(out, nullptr);
|
|
|
}
|
|
|
|
|
|
void flushNode(CWriteNode *node, NodeInfoArray &nodeInfo)
|
|
@@ -287,7 +299,7 @@ protected:
|
|
|
}
|
|
|
else
|
|
|
nodeInfo.append(* new CNodeInfo(prevLeafNode->getFpos(), NULL, keyedSize, lastSequence));
|
|
|
- writeNode(prevLeafNode);
|
|
|
+ writeNode(prevLeafNode, prevLeafNode->getFpos());
|
|
|
prevLeafNode->Release();
|
|
|
prevLeafNode = NULL;
|
|
|
}
|
|
@@ -381,7 +393,7 @@ public:
|
|
|
}
|
|
|
if (NULL != activeBlobNode)
|
|
|
{
|
|
|
- writeNode(activeBlobNode);
|
|
|
+ writeNode(activeBlobNode, activeBlobNode->getFpos());
|
|
|
activeBlobNode->Release();
|
|
|
}
|
|
|
flushNode(NULL, leafInfo);
|
|
@@ -482,7 +494,7 @@ public:
|
|
|
{
|
|
|
activeBlobNode->setLeftSib(prevBlobNode->getFpos());
|
|
|
prevBlobNode->setRightSib(activeBlobNode->getFpos());
|
|
|
- writeNode(prevBlobNode);
|
|
|
+ writeNode(prevBlobNode, prevBlobNode->getFpos());
|
|
|
delete(prevBlobNode);
|
|
|
}
|
|
|
}
|
|
@@ -528,11 +540,11 @@ protected:
|
|
|
{
|
|
|
node->setLeftSib(prevNode->getFpos());
|
|
|
prevNode->setRightSib(node->getFpos());
|
|
|
- writeNode(prevNode);
|
|
|
+ writeNode(prevNode, prevNode->getFpos());
|
|
|
}
|
|
|
prevNode.setown(node.getClear());
|
|
|
}
|
|
|
- writeNode(prevNode);
|
|
|
+ writeNode(prevNode, prevNode->getFpos());
|
|
|
}
|
|
|
|
|
|
void writeBloomFilter(const BloomFilter &filter, __uint64 fields)
|
|
@@ -559,14 +571,14 @@ protected:
|
|
|
{
|
|
|
node->setLeftSib(prevNode->getFpos());
|
|
|
prevNode->setRightSib(node->getFpos());
|
|
|
- writeNode(prevNode);
|
|
|
+ writeNode(prevNode, prevNode->getFpos());
|
|
|
}
|
|
|
prevNode.setown(node.getClear());
|
|
|
if (!size)
|
|
|
break;
|
|
|
node.setown(new CBloomFilterWriteNode(nextPos, keyHdr));
|
|
|
}
|
|
|
- writeNode(prevNode);
|
|
|
+ writeNode(prevNode, prevNode->getFpos());
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -641,6 +653,17 @@ extern jhtree_decl IKeyDesprayer * createKeyDesprayer(IFile * in, IFileIOStream
|
|
|
|
|
|
Owned<CKeyHdr> hdr = new CKeyHdr;
|
|
|
hdr->load(*(KeyHdr *)buffer.get());
|
|
|
+ if (hdr->getKeyType() & USE_TRAILING_HEADER)
|
|
|
+ {
|
|
|
+ if (io->read(in->size() - hdr->getNodeSize(), sizeof(KeyHdr), (void *)buffer.get()) != sizeof(KeyHdr))
|
|
|
+ throw MakeStringException(4, "Invalid key %s: failed to read trailing key header", in->queryFilename());
|
|
|
+ hdr->load(*(KeyHdr*)buffer.get());
|
|
|
+ }
|
|
|
hdr->getHdrStruct()->nument = 0;
|
|
|
return new CKeyDesprayer(hdr, out);
|
|
|
}
|
|
|
+
|
|
|
+extern jhtree_decl bool checkReservedMetadataName(const char *name)
|
|
|
+{
|
|
|
+ return strsame(name, "_nodeSize") || strsame(name, "_noSeek") || strsame(name, "_useTrailingHeader");
|
|
|
+}
|