ECKeyTable.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. #ifndef TABLE_H
  18. #define TABLE_H
  19. /*
  20. * How this works
  21. *
  22. * Basically, we only have to keep a table in-memory of the object IDs of the objects
  23. * in a table, so when data is requested, we can give a list of all the object IDs
  24. * and the actual data can be retrieved from the database.
  25. *
  26. * The table class handles this, by having a table of rows, with per-row a TableRow
  27. * object. Each row contains an object ID and a sort key. This makes it very fast
  28. * to add new rows into the table, because we can pretty easily add (or remove) the
  29. * row into the sorted tree.
  30. *
  31. * The caller has to make sure that the sort key is correct.
  32. *
  33. * The sorting is done by a binary compare of the sortKeys.
  34. *
  35. * Memory considerations:
  36. *
  37. * Say we have 100 users, with each having 10 tables open with in each table, 10000 rows,
  38. * this means we have 10000*100*10*sizeof(TableRow) data in memory. Assume we're sorting on
  39. * two columns, both ints, then this is another 8 bytes of data per row, which would
  40. * give us a mem. requirement of 10000*100*10*(12+8) = 190 Mb of memory. This is pretty
  41. * good for 100 (heavy) users.
  42. *
  43. * Of course, when we're sorting on strings, which are 50 bytes each, the memory usage goes
  44. * up dramatically; sorting on 1 column with 50 bytes of sort data uses 476 Mb of mem.
  45. *
  46. * This could optimised by only sorting the first X characters, and expanding the sort key
  47. * when more precision is required.
  48. *
  49. * This structure will be hogging the largest amount of memory of all the server-side components,
  50. * that's for sure.
  51. *
  52. */
  53. #include <kopano/zcdefs.h>
  54. #include <kopano/kcodes.h>
  55. #include <list>
  56. #include <map>
  57. #include <mutex>
  58. #define BOOKMARK_LIMIT 100
  59. namespace KC {
  60. struct sObjectTableKey {
  61. sObjectTableKey(unsigned int obj_id, unsigned int order_id) : ulObjId(obj_id), ulOrderId(order_id) {}
  62. sObjectTableKey(void) = default;
  63. unsigned int ulObjId = 0;
  64. unsigned int ulOrderId = 0;
  65. };
  66. struct ObjectTableKeyCompare {
  67. bool operator()(const sObjectTableKey& a, const sObjectTableKey& b) const
  68. {
  69. return a.ulObjId < b.ulObjId || (a.ulObjId == b.ulObjId && a.ulOrderId < b.ulOrderId);
  70. }
  71. };
  72. bool operator!=(const sObjectTableKey& a, const sObjectTableKey& b);
  73. extern _kc_export bool operator==(const sObjectTableKey &, const sObjectTableKey &);
  74. extern _kc_export bool operator<(const sObjectTableKey &, const sObjectTableKey &);
  75. bool operator>(const sObjectTableKey& a, const sObjectTableKey& b);
  76. typedef std::map<sObjectTableKey, unsigned int, ObjectTableKeyCompare> ECObjectTableMap;
  77. typedef std::list<sObjectTableKey> ECObjectTableList;
  78. #define TABLEROW_FLAG_DESC 0x00000001
  79. #define TABLEROW_FLAG_FLOAT 0x00000002
  80. #define TABLEROW_FLAG_STRING 0x00000004
  81. class _kc_export ECTableRow _kc_final {
  82. public:
  83. ECTableRow(sObjectTableKey sKey, unsigned int ulSortCols, const unsigned int *lpSortLen, const unsigned char *lpFlags, unsigned char **lppSortData, bool fHidden);
  84. ECTableRow(const ECTableRow &other);
  85. ~ECTableRow();
  86. _kc_hidden unsigned int GetObjectSize(void) const;
  87. _kc_hidden static bool rowcompare(const ECTableRow *, const ECTableRow *);
  88. _kc_hidden static bool rowcompare(unsigned int sortcols_a, const int *sortlen_a, unsigned char **sortkeys_a, const unsigned char *sortflags_a, unsigned int sortcols_b, const int *sortlen_b, unsigned char **sortkeys_b, const unsigned char *sortflags_b, bool ignore_order = false);
  89. _kc_hidden static bool rowcompareprefix(unsigned int sortcolprefix, unsigned int sortcols_a, const int *sortlen_a, unsigned char **sortkeys_a, const unsigned char *sortflags_a, unsigned int sortcols_b, const int *sortlen_b, unsigned char **sortkeys_b, const unsigned char *sortflags_b);
  90. bool operator < (const ECTableRow &other) const;
  91. private:
  92. _kc_hidden void initSortCols(unsigned int sortcols, const int *sortlen, const unsigned char *flags, unsigned char **sortdata);
  93. _kc_hidden void freeSortCols(void);
  94. _kc_hidden ECTableRow &operator=(const ECTableRow &);
  95. public:
  96. sObjectTableKey sKey;
  97. unsigned int ulSortCols;
  98. int *lpSortLen;
  99. unsigned char **lppSortKeys;
  100. unsigned char *lpFlags;
  101. // b-tree data
  102. ECTableRow *lpParent = nullptr;
  103. ECTableRow *lpLeft = nullptr; // All nodes in left are such that *left < *this
  104. ECTableRow *lpRight = nullptr; // All nodes in right are such that *this <= *right
  105. unsigned int ulBranchCount = 0; // Count of all nodes in this branch (including this node)
  106. unsigned int ulHeight = 0; // For AVL
  107. unsigned int fLeft = 0; // 1 if this is a left node
  108. bool fRoot = false; // Only the root node has TRUE here
  109. bool fHidden; // The row is hidden (is it non-existent for all purposes)
  110. };
  111. typedef std::map<sObjectTableKey, ECTableRow*, ObjectTableKeyCompare> ECTableRowMap;
  112. struct sBookmarkPosition {
  113. unsigned int ulFirstRowPosition;
  114. ECTableRow* lpPosition;
  115. };
  116. typedef std::map<unsigned int, sBookmarkPosition> ECBookmarkMap;
  117. class _kc_export ECKeyTable _kc_final {
  118. public:
  119. /* this MUST be the same definitions as TABLE_NOTIFICATION event types passed in ulTableEvent */
  120. // FIXME this is rather ugly, the names must differ from those in mapi.h, as they clash !
  121. enum UpdateType {
  122. TABLE_CHANGE=1, TABLE_ERR, TABLE_ROW_ADD,
  123. TABLE_ROW_DELETE, TABLE_ROW_MODIFY,TABLE_SORT,
  124. TABLE_RESTRICT, TABLE_SETCOL, TABLE_DO_RELOAD,
  125. };
  126. enum { EC_SEEK_SET=0, EC_SEEK_CUR, EC_SEEK_END };
  127. ECKeyTable();
  128. ~ECKeyTable();
  129. ECRESULT UpdateRow(UpdateType ulType, const sObjectTableKey *lpsRowItem, unsigned int ulSortCols, const unsigned int *lpSortLen, const unsigned char *lpFlags, unsigned char **lppSortData, sObjectTableKey *lpsPrevRow, bool fHidden = false, UpdateType *lpulAction = NULL);
  130. ECRESULT GetPreviousRow(const sObjectTableKey *lpsRowItem, sObjectTableKey *lpsPrevItem);
  131. ECRESULT SeekRow(unsigned int ulBookmark, int lSeekTo, int *lplRowsSought);
  132. ECRESULT SeekId(const sObjectTableKey *lpsRowItem);
  133. ECRESULT GetRowCount(unsigned int *ulRowCount, unsigned int *ulCurrentRow);
  134. ECRESULT QueryRows(unsigned int ulRows, ECObjectTableList* lpRowList, bool bDirBackward, unsigned int ulFlags, bool bShowHidden = false);
  135. ECRESULT Clear();
  136. _kc_hidden ECRESULT GetBookmark(unsigned int p1, int *p2);
  137. ECRESULT CreateBookmark(unsigned int* lpulbkPosition);
  138. ECRESULT FreeBookmark(unsigned int ulbkPosition);
  139. ECRESULT GetRowsBySortPrefix(sObjectTableKey *lpsRowItem, ECObjectTableList *lpRowList);
  140. ECRESULT HideRows(sObjectTableKey *lpsRowItem, ECObjectTableList *lpHiddenList);
  141. ECRESULT UnhideRows(sObjectTableKey *lpsRowItem, ECObjectTableList *lpUnhiddenList);
  142. // Returns the first row where the sort columns are not less than the specified sortkey
  143. ECRESULT LowerBound(unsigned int ulSortColPrefixLen, int *lpSortLen, unsigned char **lppSortData, unsigned char *lpFlags);
  144. ECRESULT Find(unsigned int ulSortCols, int *lpSortLen, unsigned char **lppSortData, unsigned char *lpFlags, sObjectTableKey *lpsKey);
  145. ECRESULT UpdatePartialSortKey(sObjectTableKey *lpsRowItem, unsigned int ulColumn, unsigned char *lpSortData, unsigned int ulSortLen, unsigned char ulFlags, sObjectTableKey *lpsPrevRow, bool *lpfHidden, ECKeyTable::UpdateType *lpulAction);
  146. ECRESULT GetRow(sObjectTableKey *lpsRowItem, ECTableRow **lpRow);
  147. unsigned int GetObjectSize();
  148. private:
  149. _kc_hidden ECRESULT UpdateCounts(ECTableRow *);
  150. _kc_hidden ECRESULT CurrentRow(ECTableRow *, unsigned int *current_row);
  151. _kc_hidden ECRESULT InvalidateBookmark(ECTableRow *);
  152. // Functions for implemention AVL balancing
  153. _kc_hidden void RotateL(ECTableRow *pivot);
  154. _kc_hidden void RotateR(ECTableRow *pivot);
  155. _kc_hidden void RotateLR(ECTableRow *pivot);
  156. _kc_hidden void RotateRL(ECTableRow *pivot);
  157. _kc_hidden unsigned int GetHeight(ECTableRow *root) { return root->ulHeight; }
  158. _kc_hidden int GetBalance(ECTableRow *root);
  159. _kc_hidden void Restructure(ECTableRow *pivot);
  160. _kc_hidden void RestructureRecursive(ECTableRow *);
  161. // Advance / reverse cursor by one position
  162. _kc_hidden void Next(void);
  163. _kc_hidden void Prev(void);
  164. std::recursive_mutex mLock; /* Locks the entire b-tree */
  165. ECTableRow *lpRoot; // The root node, which is infinitely 'low', ie all nodes are such that *node > *root
  166. ECTableRow *lpCurrent; // The current node
  167. ECTableRowMap mapRow;
  168. ECBookmarkMap m_mapBookmarks;
  169. unsigned int m_ulBookmarkPosition;
  170. };
  171. #define EC_TABLE_NOADVANCE 1
  172. } /* namespace */
  173. #endif // TABLE_H