ctfile.cpp 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #ifdef __linux__
  18. #include <alloca.h>
  19. #endif
  20. #include "jmisc.hpp"
  21. #include "hlzw.h"
  22. #include "ctfile.hpp"
  23. #include "jstats.h"
  24. inline void SwapBigEndian(KeyHdr &hdr)
  25. {
  26. _WINREV(hdr.phyrec);
  27. _WINREV(hdr.delstk);
  28. _WINREV(hdr.numrec);
  29. _WINREV(hdr.reshdr);
  30. _WINREV(hdr.lstmbr);
  31. _WINREV(hdr.sernum);
  32. _WINREV(hdr.nument);
  33. _WINREV(hdr.root);
  34. _WINREV(hdr.fileid);
  35. _WINREV(hdr.servid);
  36. _WINREV(hdr.verson);
  37. _WINREV(hdr.nodeSize);
  38. _WINREV(hdr.extsiz);
  39. _WINREV(hdr.flmode);
  40. _WINREV(hdr.maxkbl);
  41. _WINREV(hdr.maxkbn);
  42. // _WINREV(hdr.updflg);
  43. // _WINREV(hdr.autodup);
  44. // _WINREV(hdr.deltyp);
  45. // _WINREV(hdr.keypad);
  46. // _WINREV(hdr.flflvr);
  47. // _WINREV(hdr.flalgn);
  48. // _WINREV(hdr.flpntr);
  49. _WINREV(hdr.clstyp);
  50. _WINREV(hdr.length);
  51. _WINREV(hdr.nmem);
  52. _WINREV(hdr.kmem);
  53. _WINREV(hdr.lanchr);
  54. _WINREV(hdr.supid);
  55. _WINREV(hdr.hdrpos);
  56. _WINREV(hdr.sihdr);
  57. _WINREV(hdr.timeid);
  58. _WINREV(hdr.suptyp);
  59. _WINREV(hdr.maxmrk);
  60. _WINREV(hdr.namlen);
  61. _WINREV(hdr.xflmod);
  62. _WINREV(hdr.defrel);
  63. _WINREV(hdr.hghtrn);
  64. _WINREV(hdr.hdrseq);
  65. _WINREV(hdr.tstamp);
  66. _WINREV(hdr.rs3[0]);
  67. _WINREV(hdr.rs3[1]);
  68. _WINREV(hdr.rs3[2]);
  69. _WINREV(hdr.fposOffset);
  70. _WINREV(hdr.fileSize);
  71. _WINREV(hdr.nodeKeyLength);
  72. _WINREV(hdr.version);
  73. _WINREV(hdr.blobHead);
  74. _WINREV(hdr.metadataHead);
  75. }
  76. inline void SwapBigEndian(NodeHdr &hdr)
  77. {
  78. _WINREV(hdr.rightSib);
  79. _WINREV(hdr.leftSib);
  80. _WINREV(hdr.numKeys);
  81. _WINREV(hdr.keyBytes);
  82. _WINREV(hdr.crc32);
  83. // _WINREV(hdr.memNumber);
  84. // _WINREV(hdr.leafFlag);
  85. }
  86. extern bool isCompressedIndex(const char *filename)
  87. {
  88. OwnedIFile file = createIFile(filename);
  89. OwnedIFileIO io = file->open(IFOread);
  90. unsigned __int64 size = file->size();
  91. if (size)
  92. {
  93. KeyHdr hdr;
  94. if (io->read(0, sizeof(hdr), &hdr) == sizeof(hdr))
  95. {
  96. SwapBigEndian(hdr);
  97. if (size % hdr.nodeSize == 0 && hdr.phyrec == size-1 && hdr.root && hdr.root % hdr.nodeSize == 0 && hdr.ktype & (HTREE_COMPRESSED_KEY|HTREE_QUICK_COMPRESSED_KEY))
  98. {
  99. NodeHdr root;
  100. if (io->read(hdr.root, sizeof(root), &root) == sizeof(root))
  101. {
  102. SwapBigEndian(root);
  103. return root.leftSib==0 && root.rightSib==0;
  104. }
  105. }
  106. }
  107. }
  108. return false;
  109. }
  110. // CKeyHdr
  111. CKeyHdr::CKeyHdr()
  112. {
  113. memset(&hdr, 0, sizeof(hdr));
  114. }
  115. void CKeyHdr::load(KeyHdr &_hdr)
  116. {
  117. memcpy(&hdr, &_hdr, sizeof(hdr));
  118. SwapBigEndian(hdr);
  119. if (0xffff != hdr.version && KEYBUILD_VERSION < hdr.version)
  120. throw MakeKeyException(KeyExcpt_IncompatVersion, "This build is compatible with key versions <= %u. Key is version %u", KEYBUILD_VERSION, (unsigned) hdr.version);
  121. }
  122. void CKeyHdr::write(IWriteSeq *out, CRC32 *crc)
  123. {
  124. unsigned nodeSize = hdr.nodeSize;
  125. assertex(out->getRecordSize()==nodeSize);
  126. MemoryAttr ma;
  127. byte *buf = (byte *) ma.allocate(nodeSize);
  128. memcpy(buf, &hdr, sizeof(hdr));
  129. memset(buf+sizeof(hdr), 0xff, nodeSize-sizeof(hdr));
  130. SwapBigEndian(*(KeyHdr*) buf);
  131. out->put(buf);
  132. if (crc)
  133. crc->tally(nodeSize, buf);
  134. }
  135. void CKeyHdr::write(IFileIOStream *out, CRC32 *crc)
  136. {
  137. unsigned nodeSize = hdr.nodeSize;
  138. MemoryAttr ma;
  139. byte *buf = (byte *) ma.allocate(nodeSize);
  140. memcpy(buf, &hdr, sizeof(hdr));
  141. memset(buf+sizeof(hdr), 0xff, nodeSize-sizeof(hdr));
  142. SwapBigEndian(*(KeyHdr*) buf);
  143. out->write(nodeSize, buf);
  144. if (crc)
  145. crc->tally(nodeSize, buf);
  146. }
  147. unsigned int CKeyHdr::getMaxKeyLength()
  148. {
  149. return hdr.length;
  150. }
  151. bool CKeyHdr::isVariable()
  152. {
  153. return (hdr.ktype & HTREE_VARSIZE) == HTREE_VARSIZE;
  154. }
  155. //=========================================================================================================
  156. CNodeBase::CNodeBase()
  157. {
  158. keyHdr = NULL;
  159. fpos = 0;
  160. keyLen = 0;
  161. keyCompareLen = 0;
  162. isVariable = false;
  163. }
  164. void CNodeBase::load(CKeyHdr *_keyHdr, offset_t _fpos)
  165. {
  166. _keyHdr->Link();
  167. keyHdr = _keyHdr;
  168. keyLen = keyHdr->getMaxKeyLength();
  169. keyCompareLen = keyHdr->getNodeKeyLength();
  170. keyType = keyHdr->getKeyType();
  171. memset(&hdr, 0, sizeof(hdr));
  172. fpos = _fpos;
  173. isVariable = keyHdr->isVariable();
  174. }
  175. CNodeBase::~CNodeBase()
  176. {
  177. keyHdr->Release();
  178. }
  179. //=========================================================================================================
  180. CWriteNodeBase::CWriteNodeBase(offset_t _fpos, CKeyHdr *_keyHdr)
  181. {
  182. CNodeBase::load(_keyHdr, _fpos);
  183. unsigned nodeSize = keyHdr->getNodeSize();
  184. nodeBuf = (char *) malloc(nodeSize);
  185. memset(nodeBuf, 0, nodeSize);
  186. maxBytes = keyHdr->getMaxNodeBytes();
  187. keyPtr = nodeBuf + sizeof(hdr);
  188. }
  189. CWriteNodeBase::~CWriteNodeBase()
  190. {
  191. free(nodeBuf);
  192. }
  193. void CWriteNodeBase::writeHdr()
  194. {
  195. hdr.crc32 = crc32(nodeBuf+sizeof(hdr), hdr.keyBytes, 0);
  196. memcpy(nodeBuf, &hdr, sizeof(hdr));
  197. SwapBigEndian(*(NodeHdr *) nodeBuf);
  198. }
  199. void CWriteNodeBase::write(IFileIOStream *out, CRC32 *crc)
  200. {
  201. if (isLeaf() && (keyType & HTREE_COMPRESSED_KEY))
  202. lzwcomp.close();
  203. assertex(hdr.keyBytes<=maxBytes);
  204. writeHdr();
  205. assertex(fpos);
  206. out->seek(fpos, IFSbegin);
  207. out->write(keyHdr->getNodeSize(), nodeBuf);
  208. if (crc)
  209. crc->tally(keyHdr->getNodeSize(), nodeBuf);
  210. }
  211. //=========================================================================================================
  212. CWriteNode::CWriteNode(offset_t _fpos, CKeyHdr *_keyHdr, bool isLeaf) : CWriteNodeBase(_fpos, _keyHdr)
  213. {
  214. hdr.leafFlag = isLeaf ? 1 : 0;
  215. if (!isLeaf)
  216. {
  217. keyLen = keyHdr->getNodeKeyLength();
  218. }
  219. lastKeyValue = (char *) malloc(keyLen);
  220. lastSequence = 0;
  221. }
  222. CWriteNode::~CWriteNode()
  223. {
  224. free(lastKeyValue);
  225. }
  226. bool CWriteNode::add(offset_t pos, const void *indata, size32_t insize, unsigned __int64 sequence)
  227. {
  228. if (isLeaf() && !hdr.numKeys)
  229. {
  230. unsigned __int64 rsequence = sequence;
  231. _WINREV(rsequence);
  232. memcpy(keyPtr, &rsequence, sizeof(rsequence));
  233. keyPtr += sizeof(rsequence);
  234. hdr.keyBytes += sizeof(rsequence);
  235. }
  236. #if 0
  237. // This test is no longer valid if we don't treat all fields as keyed
  238. if (hdr.numKeys)
  239. {
  240. if (memcmp(indata, lastKeyValue, keyedSize) < 0)
  241. {
  242. // dump out the rows in question
  243. StringBuffer hex;
  244. unsigned i;
  245. for (i = 0; i < insize; i++)
  246. {
  247. hex.appendf("%02x ", ((unsigned char *) indata)[i]);
  248. }
  249. DBGLOG("this: %s", hex.str());
  250. hex.clear();
  251. for (i = 0; i < insize; i++)
  252. {
  253. hex.appendf("%02x ", ((unsigned char *) lastKeyValue)[i]);
  254. }
  255. DBGLOG("last: %s", hex.str());
  256. hex.clear();
  257. for (i = 0; i < insize; i++)
  258. {
  259. unsigned char c = ((unsigned char *) indata)[i];
  260. hex.appendf("%c", isprint(c) ? c : '.');
  261. }
  262. DBGLOG("this: %s", hex.str());
  263. hex.clear();
  264. for (i = 0; i < insize; i++)
  265. {
  266. unsigned char c = ((unsigned char *) lastKeyValue)[i];
  267. hex.appendf("%c", isprint(c) ? c : '.');
  268. }
  269. DBGLOG("last: %s", hex.str());
  270. throw MakeStringException(0, "Data written to key must be in sorted order");
  271. }
  272. }
  273. #endif
  274. if (isLeaf() && keyType & HTREE_COMPRESSED_KEY)
  275. {
  276. if (0 == hdr.numKeys)
  277. lzwcomp.open(keyPtr, maxBytes-hdr.keyBytes, isVariable, (keyType&HTREE_QUICK_COMPRESSED_KEY)==HTREE_QUICK_COMPRESSED_KEY);
  278. if (0xffff == hdr.numKeys || 0 == lzwcomp.writekey(pos, (const char *)indata, insize, sequence))
  279. {
  280. lzwcomp.close();
  281. return false;
  282. }
  283. hdr.keyBytes = lzwcomp.buflen() + sizeof(unsigned __int64); // rsequence added above
  284. }
  285. else
  286. {
  287. if (0xffff == hdr.numKeys)
  288. return false;
  289. bool lastnode = false;
  290. if (!indata)
  291. {
  292. lastnode = true;
  293. indata = alloca(insize);
  294. memset((void *) indata, 0xff, insize);
  295. }
  296. //assertex(insize==keyLen);
  297. const void *data;
  298. int size;
  299. if (keyType & COL_PREFIX)
  300. {
  301. char *result = (char *) alloca(insize+1); // Gets bigger if no leading common!
  302. size = compressValue((const char *) indata, insize, result);
  303. data = result;
  304. }
  305. else
  306. {
  307. size = insize;
  308. data = indata;
  309. }
  310. int bytes = sizeof(pos) + size;
  311. if (isVariable)
  312. bytes += sizeof(KEYRECSIZE_T);
  313. if (hdr.keyBytes + bytes >= maxBytes) // probably could be '>' (loses byte)
  314. return false;
  315. if (isVariable && isLeaf())
  316. {
  317. KEYRECSIZE_T _insize = insize;
  318. _WINREV(_insize);
  319. memcpy(keyPtr, &_insize, sizeof(_insize));
  320. keyPtr += sizeof(_insize);
  321. }
  322. _WINREV(pos);
  323. memcpy(keyPtr, &pos, sizeof(pos));
  324. keyPtr += sizeof(pos);
  325. memcpy(keyPtr, data, size);
  326. keyPtr += size;
  327. hdr.keyBytes += bytes;
  328. }
  329. if (insize>keyLen)
  330. throw MakeStringException(0, "key+payload (%u) exceeds max length (%u)", insize, keyLen);
  331. memcpy(lastKeyValue, indata, insize);
  332. lastSequence = sequence;
  333. hdr.numKeys++;
  334. return true;
  335. }
  336. size32_t CWriteNode::compressValue(const char *keyData, size32_t size, char *result)
  337. {
  338. unsigned int pack = 0;
  339. if (hdr.numKeys)
  340. {
  341. for (; pack<size && pack<255; pack++)
  342. {
  343. if (keyData[pack] != lastKeyValue[pack])
  344. break;
  345. }
  346. }
  347. result[0] = pack;
  348. memcpy(&result[1], keyData+pack, size-pack);
  349. return size-pack+1;
  350. }
  351. //=========================================================================================================
  352. CBlobWriteNode::CBlobWriteNode(offset_t _fpos, CKeyHdr *_keyHdr) : CWriteNodeBase(_fpos, _keyHdr)
  353. {
  354. hdr.leafFlag = 2;
  355. lzwcomp.openBlob(keyPtr, maxBytes);
  356. }
  357. CBlobWriteNode::~CBlobWriteNode()
  358. {
  359. }
  360. unsigned __int64 CBlobWriteNode::makeBlobId(offset_t nodepos, unsigned offset)
  361. {
  362. assertex(nodepos != 0);
  363. assertex((nodepos & I64C(0xffff000000000000)) == 0);
  364. assertex((offset & 0xf) == 0);
  365. return (((unsigned __int64) offset) << 44) | nodepos;
  366. }
  367. unsigned __int64 CBlobWriteNode::add(const char * &data, size32_t &size)
  368. {
  369. assertex(fpos);
  370. unsigned __int64 ret = makeBlobId(fpos, lzwcomp.getCurrentOffset());
  371. unsigned written = lzwcomp.writeBlob(data, size);
  372. if (written)
  373. {
  374. size -= written;
  375. data = (const char *) data + written;
  376. return ret;
  377. }
  378. else
  379. return 0;
  380. }
  381. //=========================================================================================================
  382. CMetadataWriteNode::CMetadataWriteNode(offset_t _fpos, CKeyHdr *_keyHdr) : CWriteNodeBase(_fpos, _keyHdr)
  383. {
  384. hdr.leafFlag = 3;
  385. }
  386. size32_t CMetadataWriteNode::set(const char * &data, size32_t &size)
  387. {
  388. assertex(fpos);
  389. unsigned short written = ((size > (maxBytes-sizeof(unsigned short))) ? (maxBytes-sizeof(unsigned short)) : size);
  390. _WINCPYREV2(keyPtr, &written);
  391. memcpy(keyPtr+sizeof(unsigned short), data, written);
  392. data += written;
  393. size -= written;
  394. return written;
  395. }
  396. //=========================================================================================================
  397. CNodeHeader::CNodeHeader()
  398. {
  399. }
  400. void CNodeHeader::load(NodeHdr &_hdr)
  401. {
  402. memcpy(&hdr, &_hdr, sizeof(hdr));
  403. SwapBigEndian(hdr);
  404. }
  405. //=========================================================================================================
  406. CJHTreeNode::CJHTreeNode()
  407. {
  408. keyBuf = NULL;
  409. keyRecLen = 0;
  410. firstSequence = 0;
  411. expandedSize = 0;
  412. }
  413. void CJHTreeNode::load(CKeyHdr *_keyHdr, const void *rawData, offset_t _fpos, bool needCopy)
  414. {
  415. CNodeBase::load(_keyHdr, _fpos);
  416. unpack(rawData, needCopy);
  417. }
  418. CJHTreeNode::~CJHTreeNode()
  419. {
  420. releaseMem(keyBuf, expandedSize);
  421. }
  422. void CJHTreeNode::releaseMem(void *togo, size32_t len)
  423. {
  424. free(togo);
  425. }
  426. void *CJHTreeNode::allocMem(size32_t len)
  427. {
  428. char *ret = (char *) malloc(len);
  429. if (!ret)
  430. {
  431. Owned<IException> E = MakeStringException(MSGAUD_operator,0, "Out of memory in CJHTreeNode::allocMem, requesting %d bytes", len);
  432. EXCLOG(E);
  433. if (flushJHtreeCacheOnOOM)
  434. {
  435. clearKeyStoreCache(false);
  436. ret = (char *) malloc(len);
  437. }
  438. if (!ret)
  439. throw E.getClear();
  440. }
  441. return ret;
  442. }
  443. char *CJHTreeNode::expandKeys(void *src,unsigned keylength,size32_t &retsize, bool rowcompression)
  444. {
  445. Owned<IExpander> exp = rowcompression?createRDiffExpander():createLZWExpander(true);
  446. int len=exp->init(src);
  447. if (len==0) {
  448. retsize = 0;
  449. return NULL;
  450. }
  451. char *outkeys=(char *) allocMem(len);
  452. exp->expand(outkeys);
  453. retsize = len;
  454. return outkeys;
  455. }
  456. IRandRowExpander *CJHTreeNode::expandQuickKeys(void *src, bool needCopy)
  457. {
  458. if (IRandRowExpander::isRand(src)) {
  459. // we are going to use node
  460. IRandRowExpander *rowexp=createRandRDiffExpander();
  461. rowexp->init(src, needCopy);
  462. return rowexp;
  463. }
  464. return NULL;
  465. }
  466. void CJHTreeNode::unpack(const void *node, bool needCopy)
  467. {
  468. memcpy(&hdr, node, sizeof(hdr));
  469. SwapBigEndian(hdr);
  470. __int64 maxsib = keyHdr->getHdrStruct()->phyrec;
  471. if (!hdr.isValid(keyHdr->getNodeSize()))
  472. {
  473. PROGLOG("hdr.leafFlag=%d",(int)hdr.leafFlag);
  474. PROGLOG("hdr.rightSib=%" I64F "d",hdr.rightSib);
  475. PROGLOG("hdr.leftSib=%" I64F "d",hdr.leftSib);
  476. PROGLOG("maxsib=%" I64F "d",maxsib);
  477. PROGLOG("nodeSize=%d", keyHdr->getNodeSize());
  478. PROGLOG("keyBytes=%d",(int)hdr.keyBytes);
  479. PrintStackReport();
  480. throw MakeStringException(0, "Htree: Corrupt key node detected");
  481. }
  482. if (!hdr.leafFlag)
  483. keyLen = keyHdr->getNodeKeyLength();
  484. keyRecLen = keyLen + sizeof(offset_t);
  485. char *keys = ((char *) node) + sizeof(hdr);
  486. if (hdr.crc32)
  487. {
  488. unsigned crc = crc32(keys, hdr.keyBytes, 0);
  489. if (hdr.crc32 != crc)
  490. throw MakeStringException(0, "CRC error on key node");
  491. }
  492. if (hdr.leafFlag==1)
  493. {
  494. firstSequence = *(unsigned __int64 *) keys;
  495. keys += sizeof(unsigned __int64);
  496. _WINREV(firstSequence);
  497. }
  498. if(isMetadata())
  499. {
  500. unsigned short len = *reinterpret_cast<unsigned short *>(keys);
  501. _WINREV(len);
  502. expandedSize = len;
  503. keyBuf = (char *) allocMem(len);
  504. memcpy(keyBuf, keys+sizeof(unsigned short), len);
  505. }
  506. else if (isLeaf() && (keyType & HTREE_COMPRESSED_KEY))
  507. {
  508. {
  509. MTIME_SECTION(queryActiveTimer(), "Compressed node expand");
  510. expandedSize = keyHdr->getNodeSize();
  511. bool quick = (keyType&HTREE_QUICK_COMPRESSED_KEY)==HTREE_QUICK_COMPRESSED_KEY;
  512. #ifndef _OLD_VERSION
  513. keyBuf = NULL;
  514. if (quick)
  515. rowexp.setown(expandQuickKeys(keys, needCopy));
  516. if (!quick||!rowexp.get())
  517. #endif
  518. {
  519. keyBuf = expandKeys(keys,keyLen,expandedSize,quick);
  520. }
  521. }
  522. assertex(keyBuf||rowexp.get());
  523. }
  524. else
  525. {
  526. int i;
  527. if (keyType & COL_PREFIX)
  528. {
  529. MTIME_SECTION(queryActiveTimer(), "COL_PREFIX expand");
  530. if (hdr.numKeys) {
  531. bool handleVariable = isVariable && isLeaf();
  532. KEYRECSIZE_T workRecLen;
  533. MemoryBuffer keyBufMb;
  534. const char *source = keys;
  535. char *target;
  536. // do first row
  537. if (handleVariable) {
  538. memcpy(&workRecLen, source, sizeof(workRecLen));
  539. _WINREV(workRecLen);
  540. size32_t tmpSz = sizeof(workRecLen) + sizeof(offset_t);
  541. target = (char *)keyBufMb.reserve(tmpSz+workRecLen);
  542. memcpy(target, source, tmpSz);
  543. source += tmpSz;
  544. target += tmpSz;
  545. }
  546. else {
  547. target = (char *)keyBufMb.reserveTruncate(hdr.numKeys * keyRecLen);
  548. workRecLen = keyRecLen - sizeof(offset_t);
  549. memcpy(target, source, sizeof(offset_t));
  550. source += sizeof(offset_t);
  551. target += sizeof(offset_t);
  552. }
  553. // this is where next row gets data from
  554. const char *prev, *next = NULL;
  555. unsigned prevOffset = 0;
  556. if (handleVariable)
  557. prevOffset = target-((char *)keyBufMb.bufferBase());
  558. else
  559. next = target;
  560. unsigned char pack1 = *source++;
  561. #ifdef _DEBUG
  562. assertex(0==pack1); // 1st time will be always be 0
  563. #endif
  564. KEYRECSIZE_T left = workRecLen;
  565. while (left--) {
  566. *target = *source;
  567. source++;
  568. target++;
  569. }
  570. // do subsequent rows
  571. for (i = 1; i < hdr.numKeys; i++) {
  572. if (handleVariable) {
  573. memcpy(&workRecLen, source, sizeof(workRecLen));
  574. _WINREV(workRecLen);
  575. target = (char *)keyBufMb.reserve(sizeof(workRecLen)+sizeof(offset_t)+workRecLen);
  576. size32_t tmpSz = sizeof(workRecLen)+sizeof(offset_t);
  577. memcpy(target, source, tmpSz);
  578. target += tmpSz;
  579. source += tmpSz;
  580. }
  581. else
  582. {
  583. memcpy(target, source, sizeof(offset_t));
  584. source += sizeof(offset_t);
  585. target += sizeof(offset_t);
  586. }
  587. pack1 = *source++;
  588. #ifdef _DEBUG
  589. assertex(pack1<=workRecLen);
  590. #endif
  591. if (handleVariable) {
  592. prev = ((char *)keyBufMb.bufferBase())+prevOffset;
  593. // for next
  594. prevOffset = target-((char *)keyBufMb.bufferBase());
  595. }
  596. else {
  597. prev = next;
  598. next = target;
  599. }
  600. left = workRecLen - pack1;
  601. while (pack1--) {
  602. *target = *prev;
  603. prev++;
  604. target++;
  605. }
  606. while (left--) {
  607. *target = *source;
  608. source++;
  609. target++;
  610. }
  611. }
  612. expandedSize = keyBufMb.length();
  613. keyBuf = (char *)keyBufMb.detach();
  614. assertex(keyBuf);
  615. }
  616. else {
  617. keyBuf = NULL;
  618. expandedSize = 0;
  619. }
  620. }
  621. else
  622. {
  623. MTIME_SECTION(queryActiveTimer(), "NO compression copy");
  624. expandedSize = hdr.keyBytes + sizeof( __int64 ); // MORE - why is the +sizeof() there?
  625. keyBuf = (char *) allocMem(expandedSize);
  626. memcpy(keyBuf, keys, hdr.keyBytes + sizeof( __int64 ));
  627. }
  628. }
  629. }
  630. offset_t CJHTreeNode::prevNodeFpos() const
  631. {
  632. offset_t ll;
  633. if (!isLeaf())
  634. ll = getFPosAt(0);
  635. else
  636. ll = hdr.leftSib;
  637. return ll;
  638. }
  639. offset_t CJHTreeNode::nextNodeFpos() const
  640. {
  641. offset_t ll;
  642. if (!isLeaf())
  643. ll = getFPosAt(hdr.numKeys - 1);
  644. else
  645. ll = hdr.rightSib;
  646. return ll;
  647. }
  648. void CJHTreeNode::dump()
  649. {
  650. for (unsigned int i=0; i<getNumKeys(); i++)
  651. {
  652. unsigned char *dst = (unsigned char *) alloca(keyLen+50);
  653. getValueAt(i,(char *) dst);
  654. offset_t pos = getFPosAt(i);
  655. StringBuffer nodeval;
  656. for (unsigned j = 0; j < keyLen; j++)
  657. nodeval.appendf("%02x", dst[j] & 0xff);
  658. DBGLOG("keyVal %d [%" I64F "d] = %s", i, pos, nodeval.str());
  659. }
  660. DBGLOG("==========");
  661. }
  662. int CJHTreeNode::compareValueAt(const char *src, unsigned int index) const
  663. {
  664. if (rowexp.get())
  665. return rowexp->cmpRow(src,index,sizeof(__int64),keyCompareLen);
  666. return memcmp(src, keyBuf + index*keyRecLen + sizeof(__int64), keyCompareLen);
  667. }
  668. bool CJHTreeNode::getValueAt(unsigned int index, char *dst) const
  669. {
  670. if (index >= hdr.numKeys) return false;
  671. if (dst)
  672. {
  673. if (rowexp.get()) {
  674. rowexp->expandRow(dst,index,sizeof(__int64),keyLen);
  675. }
  676. else {
  677. const char * p = keyBuf + index*keyRecLen + sizeof(__int64);
  678. memcpy(dst, p, keyLen);
  679. }
  680. }
  681. return true;
  682. }
  683. size32_t CJHTreeNode::getSizeAt(unsigned int index) const
  684. {
  685. return keyLen;
  686. }
  687. offset_t CJHTreeNode::getFPosAt(unsigned int index) const
  688. {
  689. if (index >= hdr.numKeys) return 0;
  690. offset_t pos;
  691. if (rowexp.get())
  692. rowexp->expandRow(&pos,index,0,sizeof(pos));
  693. else {
  694. const char * p = keyBuf + index*keyRecLen;
  695. memcpy( &pos, p, sizeof(__int64));
  696. }
  697. _WINREV(pos);
  698. return pos;
  699. }
  700. unsigned __int64 CJHTreeNode::getSequence(unsigned int index) const
  701. {
  702. if (index >= hdr.numKeys) return 0;
  703. return firstSequence + index;
  704. }
  705. bool CJHTreeNode::contains(const char *src) const
  706. { // returns true if node contains key
  707. if (compareValueAt(src, 0)<0)
  708. return false;
  709. if (compareValueAt(src, hdr.numKeys-1)>0)
  710. return false;
  711. return true;
  712. }
  713. extern jhtree_decl void validateKeyFile(const char *filename, offset_t nodePos)
  714. {
  715. OwnedIFile file = createIFile(filename);
  716. OwnedIFileIO io = file->open(IFOread);
  717. if (!io)
  718. throw MakeStringException(1, "Invalid key %s: cannot open file", filename);
  719. unsigned __int64 size = file->size();
  720. if (!size)
  721. throw MakeStringException(2, "Invalid key %s: zero size", filename);
  722. KeyHdr hdr;
  723. if (io->read(0, sizeof(hdr), &hdr) != sizeof(hdr))
  724. throw MakeStringException(4, "Invalid key %s: failed to read key header", filename);
  725. CKeyHdr keyHdr;
  726. keyHdr.load(hdr);
  727. _WINREV(hdr.phyrec);
  728. _WINREV(hdr.root);
  729. _WINREV(hdr.nodeSize);
  730. if (hdr.phyrec != size-1)
  731. throw MakeStringException(5, "Invalid key %s: phyrec was %" I64F "d, expected %" I64F "d", filename, hdr.phyrec, size-1);
  732. if (size % hdr.nodeSize)
  733. throw MakeStringException(3, "Invalid key %s: size %" I64F "d is not a multiple of key node size (%d)", filename, size, hdr.nodeSize);
  734. if (!hdr.root || hdr.root % hdr.nodeSize !=0)
  735. throw MakeStringException(6, "Invalid key %s: invalid root pointer %" I64F "x", filename, hdr.root);
  736. NodeHdr root;
  737. if (io->read(hdr.root, sizeof(root), &root) != sizeof(root))
  738. throw MakeStringException(7, "Invalid key %s: failed to read root node", filename);
  739. _WINREV(root.rightSib);
  740. _WINREV(root.leftSib);
  741. if (root.leftSib || root.rightSib)
  742. throw MakeStringException(8, "Invalid key %s: invalid root node sibling pointers 0x%" I64F "x, 0x%" I64F "x (expected 0,0)", filename, root.leftSib, root.rightSib);
  743. for (offset_t nodeOffset = (nodePos ? nodePos : hdr.nodeSize); nodeOffset < (nodePos ? nodePos+1 : size); nodeOffset += hdr.nodeSize)
  744. {
  745. MemoryAttr ma;
  746. char *buffer = (char *) ma.allocate(hdr.nodeSize);
  747. {
  748. MTIME_SECTION(queryActiveTimer(), "JHTREE read index node");
  749. io->read(nodeOffset, hdr.nodeSize, buffer);
  750. }
  751. CJHTreeNode theNode;
  752. {
  753. MTIME_SECTION(queryActiveTimer(), "JHTREE load index node");
  754. theNode.load(&keyHdr, buffer, nodeOffset, true);
  755. }
  756. NodeHdr *nodeHdr = (NodeHdr *) buffer;
  757. SwapBigEndian(*nodeHdr);
  758. if (!nodeHdr->isValid(hdr.nodeSize))
  759. throw MakeStringException(9, "Invalid key %s: invalid node header at position 0x%" I64F "x", filename, nodeOffset);
  760. if (nodeHdr->leftSib >= size || nodeHdr->rightSib >= size)
  761. throw MakeStringException(9, "Invalid key %s: out of range sibling pointers 0x%" I64F "x, 0x%" I64F "x at position 0x%" I64F "x", filename, nodeHdr->leftSib, nodeHdr->rightSib, nodeOffset);
  762. if (nodeHdr->crc32)
  763. {
  764. unsigned crc = crc32(buffer + sizeof(NodeHdr), nodeHdr->keyBytes, 0);
  765. if (crc != nodeHdr->crc32)
  766. throw MakeStringException(9, "Invalid key %s: crc mismatch at position 0x%" I64F "x", filename, nodeOffset);
  767. }
  768. else
  769. {
  770. // MORE - if we felt so inclined, we could decode the node and check records were in ascending order
  771. }
  772. }
  773. }
  774. //=========================================================================================================
  775. CJHVarTreeNode::CJHVarTreeNode()
  776. {
  777. recArray = NULL;
  778. }
  779. void CJHVarTreeNode::load(CKeyHdr *_keyHdr, const void *rawData, offset_t _fpos, bool needCopy)
  780. {
  781. CJHTreeNode::load(_keyHdr, rawData, _fpos, needCopy);
  782. unsigned n = getNumKeys();
  783. recArray = new const char * [n];
  784. const char *finger = keyBuf;
  785. for (unsigned int i=0; i<getNumKeys(); i++)
  786. {
  787. recArray[i] = finger + sizeof(KEYRECSIZE_T);
  788. KEYRECSIZE_T recsize = *(KEYRECSIZE_T *)finger;
  789. _WINREV(recsize);
  790. finger += recsize + sizeof(KEYRECSIZE_T) + sizeof(offset_t);
  791. }
  792. }
  793. CJHVarTreeNode::~CJHVarTreeNode()
  794. {
  795. delete [] recArray;
  796. }
  797. void CJHVarTreeNode::dump()
  798. {
  799. for (unsigned int i=0; i<getNumKeys(); i++)
  800. {
  801. const void * p = recArray[i];
  802. unsigned reclen = ((KEYRECSIZE_T *) p)[-1];
  803. _WINREV(reclen);
  804. unsigned char *dst = (unsigned char *) alloca(reclen);
  805. getValueAt(i,(char *) dst);
  806. offset_t pos = getFPosAt(i);
  807. StringBuffer nodeval;
  808. for (unsigned j = 0; j < reclen; j++)
  809. nodeval.appendf("%02x", dst[j] & 0xff);
  810. DBGLOG("keyVal %d [%" I64F "d] = %s", i, pos, nodeval.str());
  811. }
  812. DBGLOG("==========");
  813. }
  814. int CJHVarTreeNode::compareValueAt(const char *src, unsigned int index) const
  815. {
  816. return memcmp(src, recArray[index] + sizeof(offset_t), keyCompareLen);
  817. }
  818. bool CJHVarTreeNode::getValueAt(unsigned int num, char *dst) const
  819. {
  820. if (num >= hdr.numKeys) return false;
  821. if (NULL != dst)
  822. {
  823. const char * p = recArray[num];
  824. KEYRECSIZE_T reclen = ((KEYRECSIZE_T *) p)[-1];
  825. _WINREV(reclen);
  826. memcpy(dst, p + sizeof(offset_t), reclen);
  827. }
  828. return true;
  829. }
  830. size32_t CJHVarTreeNode::getSizeAt(unsigned int num) const
  831. {
  832. const char * p = recArray[num];
  833. KEYRECSIZE_T reclen = ((KEYRECSIZE_T *) p)[-1];
  834. _WINREV(reclen);
  835. return reclen;
  836. }
  837. offset_t CJHVarTreeNode::getFPosAt(unsigned int num) const
  838. {
  839. if (num >= hdr.numKeys) return 0;
  840. const char * p = recArray[num];
  841. offset_t pos;
  842. memcpy( &pos, p, sizeof(__int64) );
  843. _WINREV(pos);
  844. return pos;
  845. }
  846. //=========================================================================================================
  847. CJHTreeBlobNode::CJHTreeBlobNode()
  848. {
  849. }
  850. CJHTreeBlobNode::~CJHTreeBlobNode()
  851. {
  852. }
  853. size32_t CJHTreeBlobNode::getTotalBlobSize(unsigned offset)
  854. {
  855. assertex(offset < expandedSize);
  856. unsigned datalen;
  857. memcpy(&datalen, keyBuf+offset, sizeof(datalen));
  858. _WINREV(datalen);
  859. return datalen;
  860. }
  861. size32_t CJHTreeBlobNode::getBlobData(unsigned offset, void *dst)
  862. {
  863. unsigned sizeHere = getTotalBlobSize(offset);
  864. offset += sizeof(unsigned);
  865. if (sizeHere > expandedSize - offset)
  866. sizeHere = expandedSize - offset;
  867. memcpy(dst, keyBuf+offset, sizeHere);
  868. return sizeHere;
  869. }
  870. void CJHTreeMetadataNode::get(StringBuffer & out)
  871. {
  872. out.append(expandedSize, keyBuf);
  873. }
  874. class DECL_EXCEPTION CKeyException : implements IKeyException, public CInterface
  875. {
  876. int errCode;
  877. StringBuffer errMsg;
  878. public:
  879. IMPLEMENT_IINTERFACE;
  880. CKeyException(int _errCode, const char *_errMsg, va_list &args) __attribute__((format(printf,3,0))) : errCode(_errCode)
  881. {
  882. if (_errMsg)
  883. errMsg.valist_appendf(_errMsg, args);
  884. }
  885. StringBuffer &translateCode(StringBuffer &out) const
  886. {
  887. out.append("IKeyException: ");
  888. switch (errCode)
  889. {
  890. case KeyExcpt_IncompatVersion:
  891. return out.append("Incompatible key version.");
  892. default:
  893. return out.append("UNKNOWN ERROR");
  894. }
  895. }
  896. // IException
  897. int errorCode() const { return errCode; }
  898. StringBuffer &errorMessage(StringBuffer &out) const
  899. {
  900. return translateCode(out).append("\n").append(errMsg.str());
  901. }
  902. MessageAudience errorAudience() const { return MSGAUD_user; }
  903. };
  904. IKeyException *MakeKeyException(int code, const char *format, ...)
  905. {
  906. va_list args;
  907. va_start(args, format);
  908. IKeyException *e = new CKeyException(code, format, args);
  909. va_end(args);
  910. return e;
  911. }