ECKeyTable.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. #include <kopano/platform.h>
  18. #include <memory>
  19. #include <cassert>
  20. #include <kopano/ECKeyTable.h>
  21. #include <kopano/lockhelper.hpp>
  22. #include <kopano/ustringutil.h>
  23. namespace KC {
  24. bool operator!=(const sObjectTableKey& a, const sObjectTableKey& b)
  25. {
  26. return !(a.ulObjId==b.ulObjId && a.ulOrderId == b.ulOrderId);
  27. }
  28. bool operator==(const sObjectTableKey& a, const sObjectTableKey& b)
  29. {
  30. return (a.ulObjId==b.ulObjId && a.ulOrderId == b.ulOrderId);
  31. }
  32. bool operator<(const sObjectTableKey& a, const sObjectTableKey& b)
  33. {
  34. return a.ulObjId < b.ulObjId || (a.ulObjId==b.ulObjId && a.ulOrderId < b.ulOrderId);
  35. }
  36. bool operator>(const sObjectTableKey& a, const sObjectTableKey& b)
  37. {
  38. return a.ulObjId > b.ulObjId || (a.ulObjId==b.ulObjId && a.ulOrderId > b.ulOrderId);
  39. }
  40. /*
  41. * Balanced binary tree node system
  42. *
  43. * To make the row system as fast as possible, we use a balanced binary tree algorithm. Main speed interests are:
  44. *
  45. * - Fast insertion
  46. * - Fast deletion by row ID
  47. * - Fast row update by row ID
  48. * - Fast seek by row number
  49. * - Fast current row number retrieval
  50. *
  51. * The insertion and row number functions can be directly related to the balanced b-tree. This makes sure that
  52. * inserting data only requires updating parent nodes and is therefore a O(log n) operation. Deletion also needs
  53. * to update parent nodes, and is therefore also a O(log n) operation.
  54. *
  55. * For the row ID retrieval, a simple hash map is used for almost constant-time retrieval of nodes. This makes row
  56. * update extremely fast, while getting the current row number is also O(log n)
  57. *
  58. * The b-tree is built up basically like a binary search tree, with the ordering being
  59. *
  60. * 2
  61. * / \
  62. * 1 3
  63. *
  64. * .. in each node. This means that the natural order for the tree is the sorted order.
  65. *
  66. */
  67. /*
  68. * A table row in the KeyTable contains only the row ID, used for the PR_INSTANCE_KEY in
  69. * the client table, and any columns that are required for sorting. This class does *not*
  70. * communicate with the database and is a standalone KeyTable implementation. Any other data
  71. * must be collected by the caller.
  72. *
  73. * Rows are immutable, changes are done with a delete/add
  74. */
  75. ECTableRow::ECTableRow(sObjectTableKey sKey, unsigned int ulSortCols,
  76. const unsigned int *lpSortLen, const unsigned char *lpFlags,
  77. unsigned char **lppSortData, bool fHidden)
  78. {
  79. this->sKey = sKey;
  80. this->fHidden = fHidden;
  81. initSortCols(ulSortCols, reinterpret_cast<const int *>(lpSortLen),
  82. lpFlags, lppSortData);
  83. }
  84. void ECTableRow::initSortCols(unsigned int ulSortCols, const int *lpSortLen,
  85. const unsigned char *lpFlags, unsigned char **lppSortData)
  86. {
  87. int len = 0;
  88. this->ulSortCols = ulSortCols;
  89. if(lpFlags) {
  90. this->lpFlags = new unsigned char [ ulSortCols ];
  91. memcpy(this->lpFlags, lpFlags, ulSortCols * sizeof(this->lpFlags[0]));
  92. } else {
  93. this->lpFlags = NULL;
  94. }
  95. this->lpSortLen = new int [ulSortCols];
  96. this->lppSortKeys = new unsigned char *[ulSortCols];
  97. // Copy sort lengths
  98. assert(ulSortCols == 0 || lpSortLen != NULL);
  99. if (ulSortCols != 0)
  100. memcpy(this->lpSortLen, lpSortLen, sizeof(unsigned int) * ulSortCols);
  101. // Copy sort keys
  102. for (unsigned int i = 0; i < ulSortCols; ++i) {
  103. len = lpSortLen[i];
  104. len = len < 0 ? -len : len;
  105. this->lppSortKeys[i] = new unsigned char[len];
  106. memcpy(this->lppSortKeys[i], lppSortData[i], len);
  107. }
  108. }
  109. ECTableRow::ECTableRow(const ECTableRow &other)
  110. {
  111. this->sKey = other.sKey;
  112. this->lpParent = NULL;
  113. this->lpLeft = NULL;
  114. this->lpRight = NULL;
  115. this->fLeft = 0;
  116. this->ulBranchCount = 0;
  117. this->fRoot = false;
  118. this->ulHeight = 0;
  119. this->fHidden = other.fHidden;
  120. initSortCols(other.ulSortCols, other.lpSortLen, other.lpFlags, other.lppSortKeys);
  121. }
  122. ECTableRow& ECTableRow::operator=(const ECTableRow &other)
  123. {
  124. if(this == &other)
  125. return *this;
  126. freeSortCols();
  127. initSortCols(other.ulSortCols, other.lpSortLen, other.lpFlags, other.lppSortKeys);
  128. return *this;
  129. }
  130. void ECTableRow::freeSortCols()
  131. {
  132. unsigned int i=0;
  133. delete[] lpSortLen;
  134. if(lppSortKeys)
  135. {
  136. for (i = 0; i < ulSortCols; ++i)
  137. delete [] lppSortKeys[i];
  138. delete [] lppSortKeys;
  139. }
  140. delete[] lpFlags;
  141. }
  142. ECTableRow::~ECTableRow()
  143. {
  144. freeSortCols();
  145. }
  146. /*
  147. * The sortkeys are stored as binary data, the caller must ensure that the ordering of this
  148. * binary data is the same as the ordering of the underlying fields; variable-size columns
  149. * are sorted like strings; ie "AAbb" comes before "AAbbcc". If two fields match exactly, the
  150. * next column is used for sorting.
  151. *
  152. * Columns that must be sorted in descending order have a NEGATIVE lpSortLen[] entry. We split
  153. * this into the ascending and descending cases below.
  154. */
  155. bool ECTableRow::rowcompare(const ECTableRow *a, const ECTableRow *b)
  156. {
  157. // The root node is before anything!
  158. if(a->fRoot && !b->fRoot)
  159. return true;
  160. if(b->fRoot)
  161. return false;
  162. return rowcompare(a->ulSortCols, a->lpSortLen, a->lppSortKeys, a->lpFlags, b->ulSortCols, b->lpSortLen, b->lppSortKeys, b->lpFlags);
  163. }
  164. // Does a normal row compare between two rows
  165. bool ECTableRow::rowcompare(unsigned int ulSortColsA, const int *lpSortLenA,
  166. unsigned char **lppSortKeysA, const unsigned char *lpSortFlagsA,
  167. unsigned int ulSortColsB, const int *lpSortLenB,
  168. unsigned char **lppSortKeysB, const unsigned char *lpSortFlagsB,
  169. bool fIgnoreOrder)
  170. {
  171. unsigned int i=0;
  172. bool ret = false;
  173. unsigned int ulSortCols;
  174. ulSortCols = ulSortColsA < ulSortColsB ? ulSortColsA : ulSortColsB;
  175. for (i = 0; i < ulSortCols; ++i) {
  176. int cmp = 0;
  177. if(lpSortFlagsA && lpSortFlagsA[i] & TABLEROW_FLAG_FLOAT) {
  178. if(lpSortLenA[i] != sizeof(double) || lpSortLenB[i] != sizeof(double)) {
  179. cmp = 0;
  180. } else {
  181. // only good way to cast from unsigned char * -> double is via a pointer
  182. double *ad, *bd;
  183. ad = (double *)lppSortKeysA[i];
  184. bd = (double *)lppSortKeysB[i];
  185. if(*ad == *bd)
  186. cmp = 0;
  187. else if(*ad < *bd)
  188. cmp = -1;
  189. else cmp = 1;
  190. }
  191. } else if (lpSortFlagsA && lpSortFlagsA[i] & TABLEROW_FLAG_STRING) {
  192. cmp = compareSortKeys(lpSortLenA[i], lppSortKeysA[i], lpSortLenB[i], lppSortKeysB[i]);
  193. } else {
  194. // Sort data is pre-constructed so a simple memcmp suffices for sorting
  195. cmp = memcmp(lppSortKeysA[i], lppSortKeysB[i], lpSortLenA[i] < lpSortLenB[i] ? lpSortLenA[i] : lpSortLenB[i]);
  196. }
  197. if(cmp < 0) {
  198. ret = true;
  199. break;
  200. } else if (cmp == 0) {
  201. if(lpSortLenA[i] == lpSortLenB[i])
  202. continue;
  203. ret = lpSortLenA[i] < lpSortLenB[i];
  204. break;
  205. } else {
  206. ret = false;
  207. break;
  208. }
  209. }
  210. if(i == ulSortCols) {
  211. if (ulSortColsA == ulSortColsB)
  212. // equal, always return false independent of asc/desc
  213. return false;
  214. // unequal number of sort columns, the item with the least sort columns comes first, independent of asc/desc
  215. return ulSortColsA < ulSortColsB;
  216. }
  217. // Unequal, flip order if desc
  218. if (!fIgnoreOrder && lpSortFlagsA && (lpSortFlagsA[i] & TABLEROW_FLAG_DESC))
  219. return !ret;
  220. else
  221. return ret;
  222. }
  223. // Compares a row by looking only at a certain prefix of sort columns
  224. bool ECTableRow::rowcompareprefix(unsigned int ulPrefix,
  225. unsigned int ulSortColsA, const int *lpSortLenA,
  226. unsigned char **lppSortKeysA, const unsigned char *lpSortFlagsA,
  227. unsigned int ulSortColsB, const int *lpSortLenB,
  228. unsigned char **lppSortKeysB, const unsigned char *lpSortFlagsB)
  229. {
  230. return ECTableRow::rowcompare(ulSortColsA > ulPrefix ? ulPrefix : ulSortColsA, lpSortLenA, lppSortKeysA, lpSortFlagsA,
  231. ulSortColsB > ulPrefix ? ulPrefix : ulSortColsB, lpSortLenB, lppSortKeysB, lpSortFlagsB);
  232. }
  233. bool ECTableRow::operator <(const ECTableRow &other) const
  234. {
  235. return ECTableRow::rowcompare(ulSortCols, lpSortLen, lppSortKeys, lpFlags,
  236. other.ulSortCols, other.lpSortLen, other.lppSortKeys, other.lpFlags, true);
  237. }
  238. /**
  239. * Get object size
  240. *
  241. * @return Object size in bytes
  242. */
  243. unsigned int ECTableRow::GetObjectSize(void) const
  244. {
  245. unsigned int ulSize = sizeof(*this);
  246. if (ulSortCols > 0)
  247. {
  248. ulSize+= (sizeof(unsigned char) + sizeof(unsigned char) + sizeof(unsigned int)) * ulSortCols; // flag, SortKey, Sortlen
  249. for (unsigned int i = 0; i < ulSortCols; ++i)
  250. ulSize += lpSortLen[i];
  251. }
  252. return ulSize;
  253. }
  254. ECKeyTable::ECKeyTable()
  255. {
  256. sObjectTableKey sKey;
  257. memset(&sKey, 0, sizeof(sObjectTableKey));
  258. this->lpRoot = new ECTableRow(sKey, 0, NULL, NULL, NULL, false);
  259. this->lpRoot->fRoot = true;
  260. this->lpCurrent = lpRoot;
  261. // The start of bookmark, the first 3 (0,1,2) are default
  262. m_ulBookmarkPosition = 3;
  263. }
  264. ECKeyTable::~ECKeyTable()
  265. {
  266. Clear();
  267. delete lpRoot;
  268. }
  269. // Propagate this node's counts up to the root
  270. ECRESULT ECKeyTable::UpdateCounts(ECTableRow *lpRow)
  271. {
  272. unsigned int ulHeight = 0;
  273. while(lpRow != NULL) {
  274. if(lpRow == lpRoot) {
  275. lpRow->ulHeight = 0;
  276. lpRow->ulBranchCount = 0; // makes sure that lpRoot->ulBranchCount is the total size
  277. } else if(lpRow->fHidden) {
  278. lpRow->ulHeight = 1; // Hidden rows count as 'height' for AVL ..
  279. lpRow->ulBranchCount = 0; // .. but not as a 'row' for rowcount
  280. } else {
  281. lpRow->ulHeight = 1;
  282. lpRow->ulBranchCount = 1;
  283. }
  284. if(lpRow->lpLeft)
  285. lpRow->ulBranchCount += lpRow->lpLeft->ulBranchCount;
  286. if(lpRow->lpRight)
  287. lpRow->ulBranchCount += lpRow->lpRight->ulBranchCount;
  288. // Get the height of the highest subtree
  289. ulHeight = 0;
  290. if(lpRow->lpLeft)
  291. ulHeight = lpRow->lpLeft->ulHeight;
  292. if(lpRow->lpRight)
  293. ulHeight = lpRow->lpRight->ulHeight > ulHeight ? lpRow->lpRight->ulHeight : ulHeight;
  294. // Our height is highest subtree plus one
  295. lpRow->ulHeight += ulHeight;
  296. lpRow = lpRow->lpParent;
  297. }
  298. return erSuccess;
  299. }
  300. ECRESULT ECKeyTable::UpdateRow(UpdateType ulType,
  301. const sObjectTableKey *lpsRowItem, unsigned int ulSortCols,
  302. const unsigned int *lpSortLen, const unsigned char *lpFlags,
  303. unsigned char **lppSortData, sObjectTableKey *lpsPrevRow, bool fHidden,
  304. UpdateType *lpulAction)
  305. {
  306. ECRESULT er = erSuccess;
  307. ECTableRow *lpRow = NULL;
  308. ECTableRowMap::const_iterator iterMap;
  309. ECTableRow *lpNewRow = NULL;
  310. unsigned int fLeft = 0;
  311. bool fRelocateCursor = false;
  312. scoped_rlock biglock(mLock);
  313. switch(ulType) {
  314. case TABLE_ROW_DELETE:
  315. // Find the row by ID
  316. iterMap = mapRow.find(*lpsRowItem);
  317. if (iterMap == mapRow.cend())
  318. return KCERR_NOT_FOUND;
  319. // The row exists
  320. lpRow = iterMap->second;
  321. // Do the delete
  322. if (lpRow->lpLeft == NULL && lpRow->lpRight == NULL) {
  323. // This is a leaf node, just delete the leaf
  324. if (lpRow->fLeft)
  325. lpRow->lpParent->lpLeft = NULL;
  326. else
  327. lpRow->lpParent->lpRight = NULL;
  328. UpdateCounts(lpRow->lpParent);
  329. RestructureRecursive(lpRow->lpParent);
  330. } else if (lpRow->lpLeft != NULL && lpRow->lpRight == NULL) {
  331. // We have a left branch, put that branch in place of this node
  332. if (lpRow->fLeft)
  333. lpRow->lpParent->lpLeft = lpRow->lpLeft;
  334. else
  335. lpRow->lpParent->lpRight = lpRow->lpLeft;
  336. lpRow->lpLeft->lpParent = lpRow->lpParent;
  337. lpRow->lpLeft->fLeft = lpRow->fLeft;
  338. UpdateCounts(lpRow->lpParent);
  339. RestructureRecursive(lpRow->lpParent);
  340. } else if (lpRow->lpRight != NULL && lpRow->lpLeft == NULL) {
  341. // We have a right branch, put that branch in place of this node
  342. if (lpRow->fLeft)
  343. lpRow->lpParent->lpLeft = lpRow->lpRight;
  344. else
  345. lpRow->lpParent->lpRight = lpRow->lpRight;
  346. lpRow->lpRight->lpParent = lpRow->lpParent;
  347. lpRow->lpRight->fLeft = lpRow->fLeft;
  348. UpdateCounts(lpRow->lpParent);
  349. RestructureRecursive(lpRow->lpParent);
  350. } else {
  351. // We have two child nodes ..
  352. ECTableRow *lpPredecessor = lpRow->lpLeft;
  353. ECTableRow *lpPredecessorParent = NULL;
  354. while (lpPredecessor->lpRight)
  355. lpPredecessor = lpPredecessor->lpRight;
  356. // Remove the predecessor from the tree, optionally moving the left tree into place
  357. if (lpPredecessor->fLeft)
  358. lpPredecessor->lpParent->lpLeft = lpPredecessor->lpLeft;
  359. else
  360. lpPredecessor->lpParent->lpRight = lpPredecessor->lpLeft;
  361. if (lpPredecessor->lpLeft) {
  362. lpPredecessor->lpLeft->lpParent = lpPredecessor->lpParent;
  363. lpPredecessor->lpLeft->fLeft = lpPredecessor->fLeft;
  364. }
  365. // Remember the predecessor parent for later use
  366. lpPredecessorParent = lpPredecessor->lpParent;
  367. // Replace the row to be deleted with the predecessor
  368. if (lpRow->fLeft)
  369. lpRow->lpParent->lpLeft = lpPredecessor;
  370. else
  371. lpRow->lpParent->lpRight = lpPredecessor;
  372. lpPredecessor->lpParent = lpRow->lpParent;
  373. lpPredecessor->fLeft = lpRow->fLeft;
  374. lpPredecessor->lpLeft = lpRow->lpLeft;
  375. lpPredecessor->lpRight = lpRow->lpRight;
  376. if (lpPredecessor->lpLeft)
  377. lpPredecessor->lpLeft->lpParent = lpPredecessor;
  378. if (lpPredecessor->lpRight)
  379. lpPredecessor->lpRight->lpParent = lpPredecessor;
  380. // Do a recursive update of the counts in the branch of the predecessorparent, (where we removed the predecessor)
  381. UpdateCounts(lpPredecessorParent);
  382. // Do a recursive update of the counts in the branch we moved to predecessor to
  383. UpdateCounts(lpPredecessor);
  384. // Restructure
  385. RestructureRecursive(lpPredecessor);
  386. if (lpPredecessorParent->sKey != *lpsRowItem)
  387. RestructureRecursive(lpPredecessorParent);
  388. }
  389. // Move cursor to next node (or previous if this was the last row)
  390. if (lpCurrent == lpRow) {
  391. this->SeekRow(EC_SEEK_CUR, -1, NULL);
  392. this->SeekRow(EC_SEEK_CUR, 1, NULL);
  393. }
  394. // Delete this uncoupled node
  395. InvalidateBookmark(lpRow); //ignore errors
  396. delete lpRow;
  397. // Remove the row from the id map
  398. mapRow.erase(*lpsRowItem);
  399. if (lpulAction)
  400. *lpulAction = TABLE_ROW_DELETE;
  401. break;
  402. case TABLE_ROW_MODIFY:
  403. case TABLE_ROW_ADD:
  404. lpRow = lpRoot;
  405. // Find the row by id (see if we already have the row)
  406. iterMap = mapRow.find(*lpsRowItem);
  407. if (iterMap != mapRow.cend()) {
  408. // Found the row
  409. // Indiciate that we are modifying an existing row
  410. if(lpulAction)
  411. *lpulAction = TABLE_ROW_MODIFY;
  412. // Create a new node
  413. lpNewRow = new ECTableRow(*lpsRowItem, ulSortCols, lpSortLen, lpFlags, lppSortData, fHidden);
  414. if (iterMap->second == lpCurrent)
  415. fRelocateCursor = true;
  416. // If the exact same row is already in here, just look up the predecessor
  417. if( !ECTableRow::rowcompare(iterMap->second, lpNewRow) &&
  418. !ECTableRow::rowcompare(lpNewRow, iterMap->second)) {
  419. // Find the predecessor
  420. if(lpsPrevRow) {
  421. ECTableRow *lpPredecessor = NULL;
  422. if(iterMap->second->lpLeft) {
  423. lpPredecessor = iterMap->second->lpLeft;
  424. while(lpPredecessor && lpPredecessor->lpRight)
  425. lpPredecessor = lpPredecessor->lpRight;
  426. } else {
  427. lpPredecessor = iterMap->second;
  428. while(lpPredecessor && lpPredecessor->fLeft)
  429. lpPredecessor = lpPredecessor->lpParent;
  430. if(lpPredecessor && lpPredecessor->lpParent)
  431. lpPredecessor = lpPredecessor->lpParent;
  432. else
  433. lpPredecessor = NULL;
  434. }
  435. if(lpPredecessor) {
  436. *lpsPrevRow = lpPredecessor->sKey;
  437. } else {
  438. lpsPrevRow->ulObjId = 0;
  439. lpsPrevRow->ulOrderId = 0;
  440. }
  441. }
  442. // Delete the unused new node
  443. delete lpNewRow;
  444. return er;
  445. }
  446. // new row data is different, so delete the old row now
  447. er = UpdateRow(TABLE_ROW_DELETE, lpsRowItem, 0, NULL, NULL, NULL, NULL);
  448. if (er != erSuccess) {
  449. // Delete the unused new node
  450. delete lpNewRow;
  451. return er;
  452. }
  453. // Indicate that we are adding a new row
  454. } else if (lpulAction != nullptr) {
  455. *lpulAction = TABLE_ROW_ADD;
  456. }
  457. // Create the row that we will be inserting
  458. if(lpNewRow == NULL)
  459. lpNewRow = new ECTableRow(*lpsRowItem, ulSortCols, lpSortLen, lpFlags, lppSortData, fHidden);
  460. // Do a binary search in the tree
  461. while(1) {
  462. if(ECTableRow::rowcompare(lpNewRow, lpRow)) {
  463. if(lpRow->lpLeft == NULL) {
  464. fLeft = 1;
  465. break;
  466. }
  467. lpRow = lpRow->lpLeft;
  468. continue;
  469. }
  470. if (lpRow->lpRight == NULL) {
  471. fLeft = 0;
  472. break;
  473. }
  474. lpRow = lpRow->lpRight;
  475. }
  476. // lpRow now points to our parent, fLeft is whether we're the new left or right node of this parent
  477. // Get the predecesor ID
  478. if(lpsPrevRow) {
  479. if(fLeft) {
  480. // Our predecessor is the parent of our rightmost parent
  481. ECTableRow *lpPredecessor = lpRow;
  482. while(lpPredecessor && lpPredecessor->fLeft)
  483. lpPredecessor = lpPredecessor->lpParent;
  484. if(lpPredecessor == NULL || lpPredecessor->lpParent == NULL) {
  485. lpsPrevRow->ulObjId = 0;
  486. lpsPrevRow->ulOrderId = 0;
  487. } else
  488. *lpsPrevRow = lpPredecessor->lpParent->sKey;
  489. } else {
  490. // Our predecessor is simply our parent
  491. *lpsPrevRow = lpRow->sKey;
  492. }
  493. }
  494. // Link the row into the table
  495. if(fLeft)
  496. lpRow->lpLeft = lpNewRow;
  497. else
  498. lpRow->lpRight = lpNewRow;
  499. lpNewRow->lpParent = lpRow;
  500. lpNewRow->fLeft = fLeft;
  501. // Add it in the id map
  502. mapRow[*lpsRowItem] = lpNewRow;
  503. // Do a recursive update of the counts in the branch
  504. UpdateCounts(lpNewRow);
  505. RestructureRecursive(lpNewRow);
  506. // Reposition the cursor if it used to be on the old row
  507. if(fRelocateCursor)
  508. lpCurrent = lpNewRow;
  509. break;
  510. // no action for: TABLE_CHANGE, TABLE_ERR, TABLE_SORT, TABLE_RESTRICT, TABLE_SETCOL, TABLE_DO_RELOAD
  511. default:
  512. break;
  513. }
  514. return er;
  515. }
  516. /*
  517. * Clears the KeyTable. This is done in linear time.
  518. */
  519. ECRESULT ECKeyTable::Clear()
  520. {
  521. ECTableRow *lpRow = NULL;
  522. ECTableRow *lpParent = NULL;
  523. scoped_rlock biglock(mLock);
  524. lpRow = lpRoot;
  525. // Depth-first delete of all nodes (excluding root)
  526. while(lpRow) {
  527. if(lpRow->lpLeft)
  528. lpRow = lpRow->lpLeft;
  529. else if(lpRow->lpRight)
  530. lpRow = lpRow->lpRight;
  531. else if(lpRow == lpRoot)
  532. break;
  533. else {
  534. // remember parent node
  535. lpParent = lpRow->lpParent;
  536. // decouple from parent
  537. if(lpRow->fLeft)
  538. lpParent->lpLeft = NULL;
  539. else
  540. lpParent->lpRight = NULL;
  541. // delete this node
  542. delete lpRow;
  543. // continue with parent
  544. lpRow = lpParent;
  545. }
  546. }
  547. lpCurrent = lpRoot;
  548. lpRoot->ulBranchCount = 0;
  549. mapRow.clear();
  550. // Remove all bookmarks
  551. m_mapBookmarks.clear();
  552. return erSuccess;
  553. }
  554. ECRESULT ECKeyTable::SeekId(const sObjectTableKey *lpsRowItem)
  555. {
  556. scoped_rlock biglock(mLock);
  557. auto iterMap = this->mapRow.find(*lpsRowItem);
  558. if (iterMap == mapRow.cend())
  559. return KCERR_NOT_FOUND;
  560. lpCurrent = iterMap->second;
  561. return erSuccess;
  562. }
  563. ECRESULT ECKeyTable::GetBookmark(unsigned int ulbkPosition, int* lpbkPosition)
  564. {
  565. unsigned int ulCurrPosition = 0;
  566. scoped_rlock biglock(mLock);
  567. auto iPosition = m_mapBookmarks.find(ulbkPosition);
  568. if (iPosition == m_mapBookmarks.cend())
  569. return KCERR_INVALID_BOOKMARK;
  570. ECRESULT er = CurrentRow(iPosition->second.lpPosition, &ulCurrPosition);
  571. if (er != erSuccess)
  572. return er;
  573. if (iPosition->second.ulFirstRowPosition != ulCurrPosition)
  574. er = KCWARN_POSITION_CHANGED;
  575. *lpbkPosition = ulCurrPosition;
  576. return er;
  577. }
  578. ECRESULT ECKeyTable::CreateBookmark(unsigned int* lpulbkPosition)
  579. {
  580. sBookmarkPosition sbkPosition;
  581. unsigned int ulbkPosition = 0;
  582. unsigned int ulRowCount = 0;
  583. scoped_rlock biglock(mLock);
  584. // Limit of bookmarks
  585. if (m_mapBookmarks.size() >= BOOKMARK_LIMIT)
  586. return KCERR_UNABLE_TO_COMPLETE;
  587. sbkPosition.lpPosition = lpCurrent;
  588. ECRESULT er = GetRowCount(&ulRowCount, &sbkPosition.ulFirstRowPosition);
  589. if (er != erSuccess)
  590. return er;
  591. // set unique bookmark id higher
  592. ulbkPosition = m_ulBookmarkPosition++;
  593. // insert into list
  594. m_mapBookmarks.insert( ECBookmarkMap::value_type(ulbkPosition, sbkPosition) );
  595. *lpulbkPosition = ulbkPosition;
  596. return erSuccess;
  597. }
  598. ECRESULT ECKeyTable::FreeBookmark(unsigned int ulbkPosition)
  599. {
  600. scoped_rlock biglock(mLock);
  601. auto iPosition = m_mapBookmarks.find(ulbkPosition);
  602. if (iPosition == m_mapBookmarks.cend())
  603. return KCERR_INVALID_BOOKMARK;
  604. m_mapBookmarks.erase(iPosition);
  605. return erSuccess;
  606. }
  607. // Intern function, no locking
  608. ECRESULT ECKeyTable::InvalidateBookmark(ECTableRow *lpRow)
  609. {
  610. ECBookmarkMap::iterator iPosition, iRemove;
  611. // Nothing todo
  612. if (m_mapBookmarks.empty())
  613. return erSuccess;
  614. for(iPosition = m_mapBookmarks.begin(); iPosition != m_mapBookmarks.end(); )
  615. {
  616. if (lpRow != iPosition->second.lpPosition) {
  617. ++iPosition;
  618. continue;
  619. }
  620. iRemove = iPosition++;
  621. m_mapBookmarks.erase(iRemove);
  622. }
  623. return erSuccess;
  624. }
  625. ECRESULT ECKeyTable::SeekRow(unsigned int lbkOrgin, int lSeekTo, int *lplRowsSought)
  626. {
  627. ECRESULT er = erSuccess;
  628. int lDestRow = 0;
  629. unsigned int ulCurrentRow = 0;
  630. unsigned int ulRowCount = 0;
  631. ECTableRow *lpRow = NULL;
  632. scoped_rlock biglock(mLock);
  633. er = this->GetRowCount(&ulRowCount, &ulCurrentRow);
  634. if(er != erSuccess)
  635. return er;
  636. // Go to the correct position in the table
  637. switch(lbkOrgin) {
  638. case EC_SEEK_SET:
  639. // Go to first node
  640. lDestRow = lSeekTo;
  641. break;
  642. case EC_SEEK_CUR:
  643. lDestRow = ulCurrentRow + lSeekTo;
  644. break;
  645. case EC_SEEK_END:
  646. lDestRow = ulRowCount + lSeekTo;
  647. break;
  648. default:
  649. er = GetBookmark(lbkOrgin, &lDestRow);
  650. if (er != KCWARN_POSITION_CHANGED && er != erSuccess)
  651. return er;
  652. lDestRow += lSeekTo;
  653. break;
  654. }
  655. if(lDestRow < 0)
  656. lDestRow = 0;
  657. if((ULONG)lDestRow >= ulRowCount)
  658. lDestRow = ulRowCount;
  659. // Go to the correct row
  660. if(lplRowsSought) {
  661. switch(lbkOrgin) {
  662. case EC_SEEK_SET:
  663. *lplRowsSought = lDestRow;
  664. break;
  665. case EC_SEEK_CUR:
  666. *lplRowsSought = lDestRow - ulCurrentRow;
  667. break;
  668. case EC_SEEK_END:
  669. *lplRowsSought = lDestRow - ulRowCount;
  670. break;
  671. default:
  672. *lplRowsSought = lDestRow - ulCurrentRow;
  673. break;
  674. }
  675. }
  676. if(ulRowCount == 0) {
  677. lpCurrent = lpRoot; // before front in empty table
  678. return er;
  679. }
  680. lpRow = lpRoot->lpRight;
  681. while(1) {
  682. if((!lpRow->lpLeft && lDestRow == 0) || (lpRow->lpLeft && lpRow->lpLeft->ulBranchCount == (ULONG)lDestRow))
  683. break; // found the row!
  684. if(lpRow->lpLeft == NULL && lpRow->lpRight == NULL) {
  685. lpRow = NULL;
  686. break;
  687. }
  688. else if(lpRow->lpLeft && lpRow->lpRight == NULL) {
  689. // Follow the left branche
  690. lpRow = lpRow->lpLeft;
  691. continue;
  692. }
  693. else if(lpRow->lpLeft == NULL && lpRow->lpRight) {
  694. // Follow the right branche
  695. lDestRow -= lpRow->fHidden ? 0 : 1;
  696. lpRow = lpRow->lpRight;
  697. continue;
  698. }
  699. // There is both a left and a right branch ...
  700. if (lpRow->lpLeft->ulBranchCount < (ULONG)lDestRow) {
  701. // ... in which our row doesn't exist, so go to the right branch
  702. lDestRow -= lpRow->lpLeft->ulBranchCount + (lpRow->fHidden ? 0 : 1);
  703. lpRow = lpRow->lpRight;
  704. } else {
  705. // ... in which we should be looking
  706. lpRow = lpRow->lpLeft;
  707. }
  708. }
  709. lpCurrent = lpRow; // may be NULL (after end of table)
  710. return er;
  711. }
  712. ECRESULT ECKeyTable::GetRowCount(unsigned int *lpulRowCount, unsigned int *lpulCurrentRow)
  713. {
  714. scoped_rlock biglock(mLock);
  715. ECRESULT er = CurrentRow(lpCurrent, lpulCurrentRow);
  716. if (er != erSuccess)
  717. return er;
  718. *lpulRowCount = lpRoot->ulBranchCount;
  719. return erSuccess;
  720. }
  721. // Intern function, no locking
  722. ECRESULT ECKeyTable::CurrentRow(ECTableRow *lpRow, unsigned int *lpulCurrentRow)
  723. {
  724. unsigned int ulCurrentRow = 0;
  725. if (lpulCurrentRow == NULL)
  726. return KCERR_INVALID_PARAMETER;
  727. if(lpRow == NULL) {
  728. *lpulCurrentRow = lpRoot->ulBranchCount;
  729. return erSuccess;
  730. }
  731. if(lpRow == lpRoot) {
  732. *lpulCurrentRow = 0;
  733. return erSuccess;
  734. }
  735. if (lpRow->lpLeft)
  736. ulCurrentRow += lpRow->lpLeft->ulBranchCount;
  737. while (lpRow && lpRow->lpParent != NULL && lpRow->lpParent != lpRoot) {
  738. if (!lpRow->fLeft)
  739. ulCurrentRow += lpRow->lpParent->ulBranchCount - lpRow->ulBranchCount;
  740. lpRow = lpRow->lpParent;
  741. }
  742. *lpulCurrentRow = ulCurrentRow;
  743. return erSuccess;
  744. }
  745. /*
  746. * Reads the object IDs from the table; the sorting data is not returned.
  747. *
  748. * This reads from the current row, traversing the data. The current row iterator
  749. * is also updated.
  750. */
  751. ECRESULT ECKeyTable::QueryRows(unsigned int ulRows, ECObjectTableList* lpRowList, bool bDirBackward, unsigned int ulFlags, bool bShowHidden)
  752. {
  753. ECTableRow *lpOrig = NULL;
  754. scoped_rlock biglock(mLock);
  755. lpOrig = lpCurrent;
  756. if(bDirBackward == true && lpCurrent == NULL) {
  757. SeekRow(EC_SEEK_CUR, -1, NULL);
  758. }else if(lpCurrent == lpRoot && lpRoot->ulBranchCount) {
  759. // Go to actual first row if still pre-first row
  760. SeekRow(EC_SEEK_SET, 0 , NULL);
  761. }
  762. // Cap to max. table length. (probably smaller due to cursor position not at start)
  763. ulRows = ulRows > lpRoot->ulBranchCount ? lpRoot->ulBranchCount : ulRows;
  764. while(ulRows && lpCurrent) {
  765. if(!lpCurrent->fHidden || bShowHidden) {
  766. lpRowList->push_back(lpCurrent->sKey);
  767. --ulRows;
  768. }
  769. if(bDirBackward == true && lpCurrent == lpRoot->lpRight)
  770. break;
  771. if(bDirBackward == true) {
  772. Prev();
  773. } else{// Go to next row
  774. Next();
  775. }
  776. }
  777. if(ulFlags & EC_TABLE_NOADVANCE)
  778. lpCurrent = lpOrig;
  779. return erSuccess;
  780. }
  781. void ECKeyTable::Next()
  782. {
  783. if(lpCurrent == NULL)
  784. return; // Already at end
  785. if(lpCurrent->lpRight) {
  786. lpCurrent = lpCurrent->lpRight;
  787. // go to leftmost node in right tree
  788. while(lpCurrent->lpLeft)
  789. lpCurrent = lpCurrent->lpLeft;
  790. return;
  791. }
  792. // Find node to top right from here
  793. while (lpCurrent && !lpCurrent->fLeft)
  794. lpCurrent = lpCurrent->lpParent;
  795. if (lpCurrent)
  796. lpCurrent = lpCurrent->lpParent;
  797. }
  798. void ECKeyTable::Prev()
  799. {
  800. if(lpCurrent == NULL) {
  801. // Past end, seek back one row
  802. SeekRow(EC_SEEK_END, -1, NULL);
  803. return;
  804. } else if(lpCurrent->lpLeft) {
  805. lpCurrent = lpCurrent->lpLeft;
  806. // Go to rightmost node in left tree
  807. while(lpCurrent->lpRight)
  808. lpCurrent = lpCurrent->lpRight;
  809. return;
  810. }
  811. // Find node to top left from here
  812. while (lpCurrent && lpCurrent->fLeft)
  813. lpCurrent = lpCurrent->lpParent;
  814. if (lpCurrent)
  815. lpCurrent = lpCurrent->lpParent;
  816. }
  817. ECRESULT ECKeyTable::GetPreviousRow(const sObjectTableKey *lpsRowItem, sObjectTableKey *lpsPrev)
  818. {
  819. ECTableRow *lpPos = NULL;
  820. scoped_rlock biglock(mLock);
  821. lpPos = lpCurrent;
  822. ECRESULT er = SeekId((sObjectTableKey *)lpsRowItem);
  823. if(er != erSuccess)
  824. return er;
  825. Prev();
  826. while (lpCurrent && lpCurrent->fHidden)
  827. Prev();
  828. if (lpCurrent != nullptr)
  829. *lpsPrev = lpCurrent->sKey;
  830. else
  831. er = KCERR_NOT_FOUND;
  832. // Go back to the previous cursor position
  833. lpCurrent = lpPos;
  834. return er;
  835. }
  836. // Do a Left rotation around lpPivot
  837. void ECKeyTable::RotateL(ECTableRow *lpPivot)
  838. {
  839. ECTableRow *lpLeft = lpPivot->lpLeft;
  840. // First, move left leg into position of pivot
  841. lpLeft->lpParent = lpPivot->lpParent;
  842. lpLeft->fLeft = lpPivot->fLeft;
  843. if(lpPivot->fLeft)
  844. lpPivot->lpParent->lpLeft = lpLeft;
  845. else
  846. lpPivot->lpParent->lpRight = lpLeft;
  847. // Pivot is now an orphan, with only a right leg
  848. // Now, move right leg of left leg to left leg of pivot
  849. lpPivot->lpLeft = lpLeft->lpRight;
  850. if(lpLeft->lpRight) {
  851. lpLeft->lpRight->fLeft = true;
  852. lpLeft->lpRight->lpParent = lpPivot;
  853. }
  854. // Now, pivot is orphan with left and right leg, and left leg has no right leg
  855. // Connect pivot as right leg
  856. lpLeft->lpRight = lpPivot;
  857. lpPivot->lpParent = lpLeft;
  858. lpPivot->fLeft = false;
  859. UpdateCounts(lpPivot);
  860. UpdateCounts(lpLeft);
  861. }
  862. // Do a Right rotation around lpPivot
  863. void ECKeyTable::RotateR(ECTableRow *lpPivot)
  864. {
  865. ECTableRow *lpRight = lpPivot->lpRight;
  866. // First, move right leg into position of pivot
  867. lpRight->lpParent = lpPivot->lpParent;
  868. lpRight->fLeft = lpPivot->fLeft;
  869. if(lpPivot->fLeft)
  870. lpPivot->lpParent->lpLeft = lpRight;
  871. else
  872. lpPivot->lpParent->lpRight = lpRight;
  873. // Pivot is now an orphan, with only a left leg
  874. // Now, move left leg of right leg to right leg of pivot
  875. lpPivot->lpRight = lpRight->lpLeft;
  876. if(lpRight->lpLeft) {
  877. lpRight->lpLeft->fLeft = false;
  878. lpRight->lpLeft->lpParent = lpPivot;
  879. }
  880. // Now, pivot is orphan with left and right leg, and right leg has no left leg
  881. // Connect pivot as left leg
  882. lpRight->lpLeft = lpPivot;
  883. lpPivot->lpParent = lpRight;
  884. lpPivot->fLeft = true;
  885. UpdateCounts(lpPivot);
  886. UpdateCounts(lpRight);
  887. }
  888. void ECKeyTable::RotateLR(ECTableRow *lpPivot)
  889. {
  890. ECTableRow *lpParent = lpPivot->lpParent;
  891. RotateR(lpPivot);
  892. RotateL(lpParent);
  893. }
  894. void ECKeyTable::RotateRL(ECTableRow *lpPivot)
  895. {
  896. ECTableRow *lpParent = lpPivot->lpParent;
  897. RotateL(lpPivot);
  898. RotateR(lpParent);
  899. }
  900. int ECKeyTable::GetBalance(ECTableRow *lpPivot)
  901. {
  902. int balance = 0;
  903. if(lpPivot) {
  904. if(lpPivot->lpLeft)
  905. balance += lpPivot->lpLeft->ulHeight;
  906. if(lpPivot->lpRight)
  907. balance -= lpPivot->lpRight->ulHeight;
  908. }
  909. return balance;
  910. }
  911. void ECKeyTable::Restructure(ECTableRow *lpPivot)
  912. {
  913. int balance = 0;
  914. balance = GetBalance(lpPivot);
  915. if(balance > 1) {
  916. // Unbalanced (too much on the left)
  917. balance = GetBalance(lpPivot->lpLeft);
  918. if (balance >= 0)
  919. // Subtree unbalanced in same direction
  920. RotateL(lpPivot);
  921. else
  922. // Subtree unbalanced in the other direction
  923. RotateLR(lpPivot->lpLeft);
  924. } else if(balance < -1) {
  925. // Unbalanced (too much on the right)
  926. balance = GetBalance(lpPivot->lpRight);
  927. if (balance <= 0)
  928. // Subtree unbalanced in the same direction
  929. RotateR(lpPivot);
  930. else
  931. // Subtree unbalanced in the other direction
  932. RotateRL(lpPivot->lpRight);
  933. }
  934. }
  935. void ECKeyTable::RestructureRecursive(ECTableRow *lpRow)
  936. {
  937. while(lpRow != lpRoot && lpRow != NULL) {
  938. Restructure(lpRow);
  939. lpRow = lpRow->lpParent;
  940. }
  941. }
  942. /**
  943. * Get all rows with a certain sorting prefix
  944. *
  945. * @param[in] lpsRowItem Item with the prefix to search for
  946. * @param[out] lpRowList Items that have a sort key that starts with the prefix of lpsRowItem
  947. */
  948. ECRESULT ECKeyTable::GetRowsBySortPrefix(sObjectTableKey *lpsRowItem, ECObjectTableList *lpRowList)
  949. {
  950. ECTableRow *lpCursor = NULL;
  951. unsigned int ulSortColPrefixLen = 0;
  952. unsigned char **lppSortData = 0;
  953. int *lpSortLen = NULL;
  954. unsigned char *lpFlags = NULL;
  955. scoped_rlock biglock(mLock);
  956. lpCursor = lpCurrent;
  957. ECRESULT er = SeekId(lpsRowItem);
  958. if(er != erSuccess)
  959. return er;
  960. ulSortColPrefixLen = lpCurrent->ulSortCols;
  961. lppSortData = lpCurrent->lppSortKeys;
  962. lpSortLen = lpCurrent->lpSortLen;
  963. lpFlags = lpCurrent->lpFlags;
  964. while(lpCurrent) {
  965. // Stop when lpCurrent > prefix, so prefix < lpCurrent
  966. if(ECTableRow::rowcompareprefix(ulSortColPrefixLen, ulSortColPrefixLen, lpSortLen, lppSortData, lpFlags, lpCurrent->ulSortCols, lpCurrent->lpSortLen, lpCurrent->lppSortKeys, lpCurrent->lpFlags))
  967. break;
  968. lpRowList->push_back(lpCurrent->sKey);
  969. Next();
  970. }
  971. lpCurrent = lpCursor;
  972. return erSuccess;
  973. }
  974. ECRESULT ECKeyTable::HideRows(sObjectTableKey *lpsRowItem, ECObjectTableList *lpHiddenList)
  975. {
  976. BOOL fCursorHidden = false;
  977. ECTableRow *lpCursor = NULL;
  978. unsigned int ulSortColPrefixLen = 0;
  979. unsigned char **lppSortData = 0;
  980. int *lpSortLen = NULL;
  981. unsigned char *lpFlags = NULL;
  982. scoped_rlock biglock(mLock);
  983. lpCursor = lpCurrent;
  984. ECRESULT er = SeekId(lpsRowItem);
  985. if(er != erSuccess)
  986. return er;
  987. ulSortColPrefixLen = lpCurrent->ulSortCols;
  988. lppSortData = lpCurrent->lppSortKeys;
  989. lpSortLen = lpCurrent->lpSortLen;
  990. lpFlags = lpCurrent->lpFlags;
  991. // Go to next row; we never hide the first row, as it is the header
  992. Next();
  993. while(lpCurrent) {
  994. // Stop hiding when lpCurrent > prefix, so prefix < lpCurrent
  995. if(ECTableRow::rowcompareprefix(ulSortColPrefixLen, ulSortColPrefixLen, lpSortLen, lppSortData, lpFlags, lpCurrent->ulSortCols, lpCurrent->lpSortLen, lpCurrent->lppSortKeys, lpCurrent->lpFlags))
  996. break;
  997. lpHiddenList->push_back(lpCurrent->sKey);
  998. lpCurrent->fHidden = true;
  999. UpdateCounts(lpCurrent); // FIXME SLOW
  1000. if(lpCurrent == lpCursor)
  1001. fCursorHidden = true;
  1002. Next();
  1003. }
  1004. // If the row pointed to by the cursor was not touched, leave it there, otherwise, put the cursor on the next unhidden row
  1005. if(!fCursorHidden) {
  1006. lpCurrent = lpCursor;
  1007. } else {
  1008. while(lpCurrent && lpCurrent->fHidden)
  1009. Next();
  1010. }
  1011. return erSuccess;
  1012. }
  1013. // @todo lpCurrent should stay pointing at the same row we started at?
  1014. ECRESULT ECKeyTable::UnhideRows(sObjectTableKey *lpsRowItem, ECObjectTableList *lpUnhiddenList)
  1015. {
  1016. unsigned int ulSortColPrefixLen = 0;
  1017. unsigned int ulFirstCols = 0;
  1018. unsigned char **lppSortData = 0;
  1019. int *lpSortLen = NULL;
  1020. unsigned char *lpFlags = NULL;
  1021. scoped_rlock biglock(mLock);
  1022. ECRESULT er = SeekId(lpsRowItem);
  1023. if(er != erSuccess)
  1024. return er;
  1025. ulSortColPrefixLen = lpCurrent->ulSortCols;
  1026. lppSortData = lpCurrent->lppSortKeys;
  1027. lpSortLen = lpCurrent->lpSortLen;
  1028. lpFlags = lpCurrent->lpFlags;
  1029. if (lpCurrent->fHidden)
  1030. /* You cannot expand a category whose header is hidden */
  1031. return KCERR_NOT_FOUND;
  1032. // Go to next row; we don't unhide the first row, as it is the header,
  1033. Next();
  1034. if(lpCurrent == NULL)
  1035. return erSuccess; /* No more rows */
  1036. ulFirstCols = lpCurrent->ulSortCols;
  1037. while(lpCurrent) {
  1038. // Stop unhiding when lpCurrent > prefix, so prefix < lpCurrent
  1039. if(ECTableRow::rowcompareprefix(ulSortColPrefixLen, ulSortColPrefixLen, lpSortLen, lppSortData, lpFlags, lpCurrent->ulSortCols, lpCurrent->lpSortLen, lpCurrent->lppSortKeys, lpCurrent->lpFlags))
  1040. break;
  1041. // Only unhide items with the same amount of sort columns as the first row (ensures we only expand the first layer)
  1042. if(lpCurrent->ulSortCols == ulFirstCols) {
  1043. lpUnhiddenList->push_back(lpCurrent->sKey);
  1044. lpCurrent->fHidden = false;
  1045. UpdateCounts(lpCurrent); // FIXME SLOW
  1046. }
  1047. Next();
  1048. }
  1049. return erSuccess;
  1050. }
  1051. ECRESULT ECKeyTable::LowerBound(unsigned int ulSortCols, int *lpSortLen, unsigned char **lppSortData, unsigned char *lpFlags)
  1052. {
  1053. scoped_rlock biglock(mLock);
  1054. // With B being the passed sort key, find the first item A, for which !(A < B), AKA B >= A
  1055. lpCurrent = lpRoot->lpRight;
  1056. // This is a standard binary search through the entire tree
  1057. while(lpCurrent) {
  1058. if(ECTableRow::rowcompare(lpCurrent->ulSortCols, lpCurrent->lpSortLen, lpCurrent->lppSortKeys, lpCurrent->lpFlags, ulSortCols, lpSortLen, lppSortData, lpFlags)) {
  1059. // Value we're looking for is right
  1060. if(lpCurrent->lpRight == NULL) {
  1061. // Value is not equal, go to next value
  1062. Next();
  1063. break;
  1064. } else {
  1065. lpCurrent = lpCurrent->lpRight;
  1066. }
  1067. } else if (lpCurrent->lpLeft == nullptr) {
  1068. // Value we're looking for is left
  1069. // Found it, if the value is left, then we're just 'right' of that value now.
  1070. break;
  1071. } else {
  1072. lpCurrent = lpCurrent->lpLeft;
  1073. }
  1074. }
  1075. return erSuccess;
  1076. }
  1077. // Find an exact match for a sort key
  1078. ECRESULT ECKeyTable::Find(unsigned int ulSortCols, int *lpSortLen, unsigned char **lppSortData, unsigned char *lpFlags, sObjectTableKey *lpsKey)
  1079. {
  1080. ECRESULT er = erSuccess;
  1081. ECTableRow *lpCurPos = NULL;
  1082. scoped_rlock biglock(mLock);
  1083. lpCurPos = lpCurrent;
  1084. er = LowerBound(ulSortCols, lpSortLen, lppSortData, lpFlags);
  1085. if(er != erSuccess)
  1086. goto exit;
  1087. // No item is *lpCurrent >= *search, so not found
  1088. if(lpCurrent == NULL) {
  1089. er = KCERR_NOT_FOUND;
  1090. goto exit;
  1091. }
  1092. // Lower bound has put us either on the first matching row, or at the first item which is *lpCurrent > *search, aka *lpCurrent >= *search
  1093. if(ECTableRow::rowcompare(ulSortCols, lpSortLen, lppSortData, lpFlags, lpCurrent->ulSortCols, lpCurrent->lpSortLen, lpCurrent->lppSortKeys, lpCurrent->lpFlags)) {
  1094. // *lpCurrent >= *search && *lpCurrent > *search, so *lpCurrent != *search
  1095. er = KCERR_NOT_FOUND;
  1096. } else
  1097. *lpsKey = lpCurrent->sKey;
  1098. // *lpCurrent >= *search && !(*lpCurrent > *search), so *lpCurrent >= *search && *lpCurrent <= *search, so *lpCurrent == *search
  1099. exit:
  1100. lpCurrent = lpCurPos;
  1101. return er;
  1102. }
  1103. /**
  1104. * Get object size
  1105. *
  1106. * @return Object size in bytes
  1107. */
  1108. unsigned int ECKeyTable::GetObjectSize()
  1109. {
  1110. unsigned int ulSize = sizeof(*this);
  1111. scoped_rlock biglock(mLock);
  1112. ulSize += MEMORY_USAGE_MAP(mapRow.size(), ECTableRowMap);
  1113. for (const auto &r : mapRow)
  1114. ulSize += r.second->GetObjectSize();
  1115. ulSize += MEMORY_USAGE_MAP(m_mapBookmarks.size(), ECBookmarkMap);
  1116. return ulSize;
  1117. }
  1118. /**
  1119. * Update a part of the sort data for a specific row
  1120. *
  1121. * This function updates only a part of the sort data for a certain row. All other 'columns' in the sort
  1122. * data are left untouched. The change of the sort data may cause the row to be relocated.
  1123. *
  1124. * @param[in] lpsRowItem Row item to modify
  1125. * @param[in] ulColumn Column id to modify (must be already present in the sort data, you cannot add a new column)
  1126. * @param[in] lpSortData New sort data
  1127. * @param[in] ulSortLen New sort length
  1128. * @param[in] ulFlags New sort flags (note: you MUST match the previous DESCENDING flag, or you will get unpredictable results)
  1129. * @param[out] lpsPrevRow Returns the 'previous row' of the new location of the row for notification
  1130. * @param[out] lpfHidden Returns the hidden flag of the modified row
  1131. * @param[out] lpulAction Returns the action of the modification (always TABLE_ROW_MODIFY). It's here only for convenience
  1132. * @return result
  1133. */
  1134. ECRESULT ECKeyTable::UpdatePartialSortKey(sObjectTableKey *lpsRowItem, unsigned int ulColumn, unsigned char *lpSortData, unsigned int ulSortLen, unsigned char ulFlags, sObjectTableKey *lpsPrevRow, bool *lpfHidden, ECKeyTable::UpdateType *lpulAction)
  1135. {
  1136. ECRESULT er = erSuccess;
  1137. ECTableRow *lpCursor = NULL;
  1138. std::unique_ptr<unsigned char *[]> lppSortKeys;
  1139. std::unique_ptr<unsigned int[]> lpSortLen;
  1140. std::unique_ptr<unsigned char[]> lpFlags;
  1141. ulock_rec biglock(mLock);
  1142. er = GetRow(lpsRowItem, &lpCursor);
  1143. if(er != erSuccess)
  1144. return er;
  1145. if (ulColumn >= lpCursor->ulSortCols)
  1146. return KCERR_INVALID_PARAMETER;
  1147. // Copy the sortkeys that we used to have
  1148. lppSortKeys.reset(new unsigned char *[lpCursor->ulSortCols]);
  1149. lpSortLen.reset(new unsigned int[lpCursor->ulSortCols]);
  1150. lpFlags.reset(new unsigned char[lpCursor->ulSortCols]);
  1151. // Note: we can just copy the pointers of the sort data here, since they are still valid, and are also valid
  1152. // to pass into UpdateRow()
  1153. memcpy(lppSortKeys.get(), lpCursor->lppSortKeys, sizeof(unsigned char *) * lpCursor->ulSortCols);
  1154. memcpy(lpSortLen.get(), lpCursor->lpSortLen, sizeof(unsigned int) * lpCursor->ulSortCols);
  1155. memcpy(lpFlags.get(), lpCursor->lpFlags, sizeof(unsigned char) * lpCursor->ulSortCols);
  1156. // Modify the updated colum
  1157. lppSortKeys[ulColumn] = lpSortData;
  1158. lpSortLen[ulColumn] = ulSortLen;
  1159. lpFlags[ulColumn] = ulFlags;
  1160. if(lpfHidden)
  1161. *lpfHidden = lpCursor->fHidden;
  1162. return UpdateRow(TABLE_ROW_MODIFY, lpsRowItem, lpCursor->ulSortCols,
  1163. lpSortLen.get(), lpFlags.get(), lppSortKeys.get(), lpsPrevRow,
  1164. lpCursor->fHidden, lpulAction);
  1165. }
  1166. /**
  1167. * Get row sort data
  1168. *
  1169. * NOTE, returning reference to internal data. Make sure that the table is not modified
  1170. * while handling the returned data. Also, caller does *not* need to free returned data.
  1171. *
  1172. * @param[in] lpsRowItem Row ID
  1173. * @param[out] lpRow Location to return reference to table's sort data
  1174. * @return result
  1175. */
  1176. ECRESULT ECKeyTable::GetRow(sObjectTableKey *lpsRowItem, ECTableRow **lpRow)
  1177. {
  1178. ulock_rec biglock(mLock);
  1179. ECTableRow *lpCursor = lpCurrent;
  1180. ECRESULT er = SeekId(lpsRowItem);
  1181. if(er != erSuccess)
  1182. goto exit;
  1183. *lpRow = lpCurrent;
  1184. exit:
  1185. lpCurrent = lpCursor;
  1186. return er;
  1187. }
  1188. } /* namespace */