thmem.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  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. #ifndef __THMEM__
  14. #define __THMEM__
  15. #ifdef _WIN32
  16. #ifdef GRAPH_EXPORTS
  17. #define graph_decl __declspec(dllexport)
  18. #else
  19. #define graph_decl __declspec(dllimport)
  20. #endif
  21. #else
  22. #define graph_decl
  23. #endif
  24. #include "jexcept.hpp"
  25. #include "jbuff.hpp"
  26. #include "jsort.hpp"
  27. #include "thormisc.hpp"
  28. #include "eclhelper.hpp"
  29. #include "rtlread_imp.hpp"
  30. #include "roxiemem.hpp"
  31. #define NO_BWD_COMPAT_MAXSIZE
  32. #include "thorcommon.hpp"
  33. #include "thorcommon.ipp"
  34. interface IRecordSize;
  35. interface ILargeMemLimitNotify;
  36. interface ISortKeySerializer;
  37. interface ICompare;
  38. //#define INCLUDE_POINTER_ARRAY_SIZE
  39. #define ReleaseThorRow(row) ReleaseRoxieRow(row)
  40. #define ReleaseClearThorRow(row) ReleaseClearRoxieRow(row)
  41. #define LinkThorRow(row) LinkRoxieRow(row)
  42. using roxiemem::OwnedRoxieString;
  43. graph_decl void setThorInABox(unsigned num);
  44. // used for non-row allocations
  45. #define ThorMalloc(a) malloc(a)
  46. #define ThorRealloc(p,a) realloc(p,a)
  47. #define ThorFree(p) free(p)
  48. // ---------------------------------------------------------
  49. // Thor link counted rows
  50. // these may be inline later
  51. #ifdef TEST_ROW_LINKS
  52. #define TESTROW(r) if (r) { LinkThorRow(r); ReleaseThorRow(r); }
  53. #else
  54. #define TESTROW(r)
  55. #endif
  56. #ifdef PARANOID_TEST_ROW_LINKS
  57. #define PARANOIDTESTROW(r) if (r) { LinkThorRow(r); ReleaseThorRow(r); }
  58. #else
  59. #define PARANOIDTESTROW(r)
  60. #endif
  61. class OwnedConstThorRow
  62. {
  63. public:
  64. inline OwnedConstThorRow() { ptr = NULL; }
  65. inline OwnedConstThorRow(const void * _ptr) { TESTROW(_ptr); ptr = _ptr; }
  66. inline OwnedConstThorRow(const OwnedConstThorRow & other) { ptr = other.getLink(); }
  67. inline ~OwnedConstThorRow() { ReleaseThorRow(ptr); }
  68. private:
  69. /* these overloaded operators are the devil of memory leak. Use set, setown instead. */
  70. void operator = (const void * _ptr) { set(_ptr); }
  71. void operator = (const OwnedConstThorRow & other) { set(other.get()); }
  72. /* this causes -ve memory leak */
  73. void setown(const OwnedConstThorRow &other) { }
  74. public:
  75. inline const void * operator -> () const { PARANOIDTESTROW(ptr); return ptr; }
  76. inline operator const void *() const { PARANOIDTESTROW(ptr); return ptr; }
  77. inline void clear() { const void *temp=ptr; ptr=NULL; ReleaseThorRow(temp); }
  78. inline const void * get() const { PARANOIDTESTROW(ptr); return ptr; }
  79. inline const void * getClear()
  80. {
  81. const void * ret = ptr;
  82. ptr = NULL;
  83. TESTROW(ret);
  84. return ret;
  85. }
  86. inline const void * getLink() const { LinkThorRow(ptr); return ptr; }
  87. inline void set(const void * _ptr)
  88. {
  89. const void * temp = ptr;
  90. if (_ptr)
  91. LinkThorRow(_ptr);
  92. ptr = _ptr;
  93. if (temp)
  94. ReleaseThorRow(temp);
  95. }
  96. inline void setown(const void * _ptr)
  97. {
  98. TESTROW(_ptr);
  99. const void * temp = ptr;
  100. ptr = _ptr;
  101. if (temp)
  102. ReleaseThorRow(temp);
  103. }
  104. inline void set(const OwnedConstThorRow &other) { set(other.get()); }
  105. inline void deserialize(IRowInterfaces *rowif, size32_t memsz, const void *mem)
  106. {
  107. if (memsz) {
  108. RtlDynamicRowBuilder rowBuilder(rowif->queryRowAllocator());
  109. //GH->NH This now has a higher overhead than you are likely to want at this point...
  110. CThorStreamDeserializerSource dsz(memsz,mem);
  111. size32_t size = rowif->queryRowDeserializer()->deserialize(rowBuilder,dsz);
  112. setown(rowBuilder.finalizeRowClear(size));
  113. }
  114. else
  115. clear();
  116. }
  117. private:
  118. const void * ptr;
  119. };
  120. interface IThorAllocator : extends IInterface
  121. {
  122. virtual IEngineRowAllocator *getRowAllocator(IOutputMetaData * meta, unsigned activityId, roxiemem::RoxieHeapFlags flags) const = 0;
  123. virtual IEngineRowAllocator *getRowAllocator(IOutputMetaData * meta, unsigned activityId) const = 0;
  124. virtual roxiemem::IRowManager *queryRowManager() const = 0;
  125. virtual roxiemem::RoxieHeapFlags queryFlags() const = 0;
  126. virtual bool queryCrc() const = 0;
  127. };
  128. IThorAllocator *createThorAllocator(memsize_t memSize, unsigned memorySpillAt, IContextLogger &logctx, bool crcChecking, bool usePacked);
  129. extern graph_decl IOutputMetaData *createOutputMetaDataWithExtra(IOutputMetaData *meta, size32_t sz);
  130. extern graph_decl IOutputMetaData *createOutputMetaDataWithChildRow(IEngineRowAllocator *childAllocator, size32_t extraSz);
  131. class CThorRowLinkCounter: public CSimpleInterface, implements IRowLinkCounter
  132. {
  133. public:
  134. IMPLEMENT_IINTERFACE_USING(CSimpleInterface);
  135. virtual void releaseRow(const void *row)
  136. {
  137. ReleaseThorRow(row);
  138. }
  139. virtual void linkRow(const void *row)
  140. {
  141. LinkThorRow(row);
  142. }
  143. };
  144. // ---------------------------------------------------------
  145. extern graph_decl void checkMultiThorMemoryThreshold(bool inc);
  146. extern graph_decl void setMultiThorMemoryNotify(size32_t size,ILargeMemLimitNotify *notify);
  147. extern graph_decl memsize_t setLargeMemSize(unsigned limit);
  148. /////////////
  149. // JCSMORE
  150. enum {
  151. InitialSortElements = 0,
  152. //The number of rows that can be added without entering a critical section, and therefore also the number
  153. //of rows that might not get freed when memory gets tight.
  154. CommitStep=32
  155. };
  156. graph_decl StringBuffer &getRecordString(const void *key, IOutputRowSerializer *serializer, const char *prefix, StringBuffer &out);
  157. //NB: low priorities are spilt 1st
  158. #define SPILL_PRIORITY_VERYLOW 50
  159. #define SPILL_PRIORITY_LOW 100
  160. #define SPILL_PRIORITY_HIGH 1000000
  161. #define SPILL_PRIORITY_DEFAULT SPILL_PRIORITY_LOW
  162. #define SPILL_PRIORITY_DISABLE UINT_MAX
  163. #define SPILL_PRIORITY_OVERFLOWABLE_BUFFER SPILL_PRIORITY_LOW
  164. #define SPILL_PRIORITY_SPILLABLE_STREAM SPILL_PRIORITY_LOW
  165. #define SPILL_PRIORITY_RESULT SPILL_PRIORITY_LOW
  166. #define SPILL_PRIORITY_GROUPSORT SPILL_PRIORITY_LOW+1000
  167. #define SPILL_PRIORITY_HASHDEDUP_REHASH SPILL_PRIORITY_LOW+1900
  168. #define SPILL_PRIORITY_HASHDEDUP SPILL_PRIORITY_LOW+2000
  169. #define SPILL_PRIORITY_HASHDEDUP_BUCKET_POSTSPILL SPILL_PRIORITY_VERYLOW // very low, by this stage it's cheap to dispose of
  170. #define SPILL_PRIORITY_JOIN SPILL_PRIORITY_HIGH
  171. #define SPILL_PRIORITY_SELFJOIN SPILL_PRIORITY_HIGH
  172. #define SPILL_PRIORITY_HASHJOIN SPILL_PRIORITY_HIGH
  173. #define SPILL_PRIORITY_LARGESORT SPILL_PRIORITY_HIGH
  174. #define SPILL_PRIORITY_LOOKUPJOIN SPILL_PRIORITY_HIGH
  175. enum StableSortFlag { stableSort_none, stableSort_earlyAlloc, stableSort_lateAlloc };
  176. class CThorSpillableRowArray;
  177. // general really
  178. interface IThorArrayLock
  179. {
  180. virtual void lock() const = 0;
  181. virtual void unlock() const = 0;
  182. };
  183. class CThorArrayLockBlock
  184. {
  185. CThorArrayLockBlock(CThorArrayLockBlock &); // avoid accidental use
  186. const IThorArrayLock &alock;
  187. public:
  188. inline CThorArrayLockBlock(const IThorArrayLock &_alock) : alock(_alock) { alock.lock(); }
  189. inline ~CThorArrayLockBlock() { alock.unlock(); }
  190. };
  191. class CThorArrayLockUnblock
  192. {
  193. CThorArrayLockUnblock(CThorArrayLockUnblock &); // avoid accidental use
  194. const IThorArrayLock &alock;
  195. public:
  196. inline CThorArrayLockUnblock(const IThorArrayLock &_alock) : alock(_alock) { alock.unlock(); }
  197. inline ~CThorArrayLockUnblock() { alock.lock(); }
  198. };
  199. class graph_decl CThorExpandingRowArray : public CSimpleInterface
  200. {
  201. class CDummyLock : implements IThorArrayLock
  202. {
  203. public:
  204. // IThorArrayLock
  205. virtual void lock() const { }
  206. virtual void unlock() const { }
  207. } dummyLock;
  208. bool _ensure(rowidx_t requiredRows, unsigned maxSpillCost);
  209. const void *_allocateRowTable(rowidx_t num, unsigned maxSpillCost);
  210. // for direct access by another CThorExpandingRowArray only
  211. inline void transferRowsCopy(const void **outRows, bool takeOwnership);
  212. protected:
  213. CActivityBase &activity;
  214. IRowInterfaces *rowIf;
  215. IEngineRowAllocator *allocator;
  216. IOutputRowSerializer *serializer;
  217. IOutputRowDeserializer *deserializer;
  218. roxiemem::IRowManager *rowManager;
  219. const void **rows;
  220. void **stableTable;
  221. bool throwOnOom; // tested during array expansion (ensure())
  222. bool allowNulls;
  223. StableSortFlag stableSort;
  224. rowidx_t maxRows; // Number of rows that can fit in the allocated memory.
  225. rowidx_t numRows; // High water mark of rows added
  226. unsigned defaultMaxSpillCost;
  227. void init(rowidx_t initialSize);
  228. const void *allocateRowTable(rowidx_t num);
  229. const void *allocateRowTable(rowidx_t num, unsigned maxSpillCost);
  230. rowidx_t getNewSize(rowidx_t requiredRows);
  231. bool resizeRowTable(void **oldRows, memsize_t newCapacity, bool copy, roxiemem::IRowResizeCallback &callback, unsigned maxSpillCost);
  232. void serialize(IRowSerializerTarget &out);
  233. void doSort(rowidx_t n, void **const rows, ICompare &compare, unsigned maxCores);
  234. inline rowidx_t getRowsCapacity() const { return rows ? RoxieRowCapacity(rows) / sizeof(void *) : 0; }
  235. public:
  236. CThorExpandingRowArray(CActivityBase &activity, IRowInterfaces *rowIf, bool allowNulls=false, StableSortFlag stableSort=stableSort_none, bool throwOnOom=true, rowidx_t initialSize=InitialSortElements);
  237. ~CThorExpandingRowArray();
  238. CActivityBase &queryActivity() { return activity; }
  239. // NB: throws error on OOM by default
  240. void setup(IRowInterfaces *rowIf, bool allowNulls=false, StableSortFlag stableSort=stableSort_none, bool throwOnOom=true);
  241. inline void setAllowNulls(bool b) { allowNulls = b; }
  242. inline void setDefaultMaxSpillCost(unsigned _defaultMaxSpillCost) { defaultMaxSpillCost = _defaultMaxSpillCost; }
  243. inline unsigned queryDefaultMaxSpillCost() const { return defaultMaxSpillCost; }
  244. void clearRows();
  245. void kill();
  246. void setRow(rowidx_t idx, const void *row) // NB: takes ownership
  247. {
  248. OwnedConstThorRow _row = row;
  249. dbgassertex(idx < maxRows);
  250. const void *oldRow = rows[idx];
  251. if (oldRow)
  252. ReleaseThorRow(oldRow);
  253. rows[idx] = _row.getClear();
  254. if (idx+1>numRows) // keeping high water mark
  255. numRows = idx+1;
  256. }
  257. inline bool append(const void *row) // NB: takes ownership on success
  258. {
  259. assertex(row || allowNulls);
  260. if (numRows >= maxRows)
  261. {
  262. if (!ensure(numRows+1))
  263. return false;
  264. }
  265. rows[numRows++] = row;
  266. return true;
  267. }
  268. bool binaryInsert(const void *row, ICompare &compare, bool dropLast=false); // NB: takes ownership on success
  269. inline const void *query(rowidx_t i) const
  270. {
  271. if (i>=numRows)
  272. return NULL;
  273. return rows[i];
  274. }
  275. inline const void *get(rowidx_t i) const
  276. {
  277. if (i>=numRows)
  278. return NULL;
  279. const void *row = rows[i];
  280. if (row)
  281. LinkThorRow(row);
  282. return row;
  283. }
  284. inline const void *getClear(rowidx_t i)
  285. {
  286. if (i>=numRows)
  287. return NULL;
  288. const void *row = rows[i];
  289. rows[i] = NULL;
  290. return row;
  291. }
  292. inline rowidx_t ordinality() const { return numRows; }
  293. inline rowidx_t queryMaxRows() const { return maxRows; }
  294. inline const void **getRowArray() { return rows; }
  295. void swap(CThorExpandingRowArray &src);
  296. void transfer(CThorExpandingRowArray &from)
  297. {
  298. kill();
  299. swap(from);
  300. }
  301. void transferRows(rowidx_t & outNumRows, const void * * & outRows);
  302. void transferFrom(CThorExpandingRowArray &src);
  303. void transferFrom(CThorSpillableRowArray &src);
  304. void removeRows(rowidx_t start, rowidx_t n);
  305. bool appendRows(CThorExpandingRowArray &inRows, bool takeOwnership);
  306. bool appendRows(CThorSpillableRowArray &inRows, bool takeOwnership);
  307. void clearUnused();
  308. void sort(ICompare &compare, unsigned maxCores);
  309. void reorder(rowidx_t start, rowidx_t num, rowidx_t *neworder);
  310. bool equal(ICompare *icmp, CThorExpandingRowArray &other);
  311. bool checkSorted(ICompare *icmp);
  312. IRowStream *createRowStream(rowidx_t start=0, rowidx_t num=(rowidx_t)-1, bool streamOwns=true);
  313. void partition(ICompare &compare, unsigned num, UnsignedArray &out); // returns num+1 points
  314. offset_t serializedSize();
  315. memsize_t getMemUsage();
  316. void serialize(MemoryBuffer &mb);
  317. void serializeCompress(MemoryBuffer &mb);
  318. rowidx_t serializeBlock(MemoryBuffer &mb, rowidx_t idx, rowidx_t count, size32_t dstmax, bool hardMax);
  319. void deserializeRow(IRowDeserializerSource &in); // NB single row not NULL
  320. void deserialize(size32_t sz, const void *buf);
  321. void deserializeExpand(size32_t sz, const void *data);
  322. bool ensure(rowidx_t requiredRows);
  323. bool ensure(rowidx_t requiredRows, unsigned maxSpillCost);
  324. void compact();
  325. virtual IThorArrayLock &queryLock() { return dummyLock; }
  326. friend class CThorSpillableRowArray;
  327. };
  328. interface IWritePosCallback : extends IInterface
  329. {
  330. virtual rowidx_t queryRecordNumber() = 0;
  331. virtual void filePosition(offset_t pos) = 0;
  332. };
  333. class graph_decl CThorSpillableRowArray : private CThorExpandingRowArray, implements IThorArrayLock
  334. {
  335. const size32_t commitDelta; // How many rows need to be written before they are added to the committed region?
  336. rowidx_t firstRow; // Only rows firstRow..numRows are considered initialized. Only read/write within cs.
  337. rowidx_t commitRows; // can only be updated by writing thread within a critical section
  338. mutable CriticalSection cs;
  339. ICopyArrayOf<IWritePosCallback> writeCallbacks;
  340. public:
  341. CThorSpillableRowArray(CActivityBase &activity, IRowInterfaces *rowIf, bool allowNulls=false, StableSortFlag stableSort=stableSort_none, rowidx_t initialSize=InitialSortElements, size32_t commitDelta=CommitStep);
  342. ~CThorSpillableRowArray();
  343. // NB: default throwOnOom to false
  344. void setup(IRowInterfaces *rowIf, bool allowNulls=false, StableSortFlag stableSort=stableSort_none, bool throwOnOom=false)
  345. {
  346. CThorExpandingRowArray::setup(rowIf, allowNulls, stableSort, throwOnOom);
  347. }
  348. void registerWriteCallback(IWritePosCallback &cb);
  349. void unregisterWriteCallback(IWritePosCallback &cb);
  350. inline void setAllowNulls(bool b) { CThorExpandingRowArray::setAllowNulls(b); }
  351. inline void setDefaultMaxSpillCost(unsigned defaultMaxSpillCost) { CThorExpandingRowArray::setDefaultMaxSpillCost(defaultMaxSpillCost); }
  352. inline unsigned queryDefaultMaxSpillCost() const { return CThorExpandingRowArray::queryDefaultMaxSpillCost(); }
  353. void kill();
  354. void compact();
  355. void flush();
  356. inline bool append(const void *row) __attribute__((warn_unused_result))
  357. {
  358. //GH->JCS Should this really be inline?
  359. assertex(row || allowNulls);
  360. if (numRows >= maxRows)
  361. {
  362. if (!ensure(numRows+1))
  363. {
  364. flush();
  365. if (numRows >= maxRows)
  366. return false;
  367. }
  368. }
  369. rows[numRows++] = row;
  370. if (numRows >= commitRows + commitDelta)
  371. flush();
  372. return true;
  373. }
  374. bool appendRows(CThorExpandingRowArray &inRows, bool takeOwnership);
  375. //The following must either be accessed within a lock, or when no rows can be appended,
  376. //(otherwise flush() might move all the rows, invalidating the indexes - or for query() the row)
  377. inline const void *query(rowidx_t i) const
  378. {
  379. return CThorExpandingRowArray::query(i);
  380. }
  381. inline const void *get(rowidx_t i) const
  382. {
  383. return CThorExpandingRowArray::get(i);
  384. }
  385. inline const void *getClear(rowidx_t i)
  386. {
  387. return CThorExpandingRowArray::getClear(i);
  388. }
  389. //A thread calling the following functions must own the lock, or guarantee no other thread will access
  390. void sort(ICompare & compare, unsigned maxcores);
  391. rowidx_t save(IFile &file, bool useCompression, const char *tracingPrefix);
  392. inline rowidx_t numCommitted() const { return commitRows - firstRow; } //MORE::Not convinced this is very safe!
  393. // access to
  394. void swap(CThorSpillableRowArray &src);
  395. void transfer(CThorSpillableRowArray &from)
  396. {
  397. kill();
  398. swap(from);
  399. }
  400. void transferFrom(CThorExpandingRowArray &src);
  401. IRowStream *createRowStream();
  402. offset_t serializedSize()
  403. {
  404. if (firstRow > 0)
  405. throwUnexpected();
  406. return CThorExpandingRowArray::serializedSize();
  407. }
  408. memsize_t getMemUsage() { return CThorExpandingRowArray::getMemUsage(); }
  409. void serialize(MemoryBuffer &mb)
  410. {
  411. if (firstRow > 0)
  412. throwUnexpected();
  413. CThorExpandingRowArray::serialize(mb);
  414. }
  415. void deserialize(size32_t sz, const void *buf, bool hasNulls){ CThorExpandingRowArray::deserialize(sz, buf); }
  416. void deserializeRow(IRowDeserializerSource &in) { CThorExpandingRowArray::deserializeRow(in); }
  417. bool ensure(rowidx_t requiredRows) { return CThorExpandingRowArray::ensure(requiredRows); }
  418. void transferRowsCopy(const void **outRows, bool takeOwnership);
  419. void readBlock(const void **outRows, rowidx_t readRows);
  420. virtual IThorArrayLock &queryLock() { return *this; }
  421. // IThorArrayLock
  422. virtual void lock() const { cs.enter(); }
  423. virtual void unlock() const { cs.leave(); }
  424. private:
  425. void clearRows();
  426. const void **getBlock(rowidx_t readRows);
  427. };
  428. enum RowCollectorSpillFlags { rc_mixed, rc_allMem, rc_allDisk, rc_allDiskOrAllMem };
  429. enum RowCollectorOptionFlags { rcflag_noAllInMemSort=0x01 };
  430. interface IThorRowCollectorCommon : extends IInterface
  431. {
  432. virtual rowcount_t numRows() const = 0;
  433. virtual unsigned numOverflows() const = 0;
  434. virtual unsigned overflowScale() const = 0;
  435. virtual void transferRowsOut(CThorExpandingRowArray &dst, bool sort=true) = 0;
  436. virtual void transferRowsIn(CThorExpandingRowArray &src) = 0;
  437. virtual void setup(ICompare *iCompare, StableSortFlag stableSort=stableSort_none, RowCollectorSpillFlags diskMemMix=rc_mixed, unsigned spillPriority=50) = 0;
  438. virtual void ensure(rowidx_t max) = 0;
  439. virtual void setOptions(unsigned options) = 0;
  440. };
  441. interface IThorRowLoader : extends IThorRowCollectorCommon
  442. {
  443. virtual IRowStream *load(IRowStream *in, const bool &abort, bool preserveGrouping=false, CThorExpandingRowArray *allMemRows=NULL, memsize_t *memUsage=NULL) = 0;
  444. virtual IRowStream *loadGroup(IRowStream *in, const bool &abort, CThorExpandingRowArray *allMemRows=NULL, memsize_t *memUsage=NULL) = 0;
  445. };
  446. interface IThorRowCollector : extends IThorRowCollectorCommon
  447. {
  448. virtual void setPreserveGrouping(bool tf) = 0;
  449. virtual IRowWriter *getWriter() = 0;
  450. virtual void reset() = 0;
  451. virtual IRowStream *getStream(bool shared=false, CThorExpandingRowArray *allMemRows=NULL) = 0;
  452. };
  453. extern graph_decl IThorRowLoader *createThorRowLoader(CActivityBase &activity, IRowInterfaces *rowIf, ICompare *iCompare=NULL, StableSortFlag stableSort=stableSort_none, RowCollectorSpillFlags diskMemMix=rc_mixed, unsigned spillPriority=SPILL_PRIORITY_DEFAULT);
  454. extern graph_decl IThorRowLoader *createThorRowLoader(CActivityBase &activity, ICompare *iCompare=NULL, StableSortFlag stableSort=stableSort_none, RowCollectorSpillFlags diskMemMix=rc_mixed, unsigned spillPriority=SPILL_PRIORITY_DEFAULT);
  455. extern graph_decl IThorRowCollector *createThorRowCollector(CActivityBase &activity, IRowInterfaces *rowIf, ICompare *iCompare=NULL, StableSortFlag stableSort=stableSort_none, RowCollectorSpillFlags diskMemMix=rc_mixed, unsigned spillPriority=SPILL_PRIORITY_DEFAULT, bool preserveGrouping=false);
  456. extern graph_decl IThorRowCollector *createThorRowCollector(CActivityBase &activity, ICompare *iCompare=NULL, StableSortFlag stableSort=stableSort_none, RowCollectorSpillFlags diskMemMix=rc_mixed, unsigned spillPriority=SPILL_PRIORITY_DEFAULT, bool preserveGrouping=false);
  457. class CSDSServerStatus;
  458. extern graph_decl ILargeMemLimitNotify *createMultiThorResourceMutex(const char *grpname,CSDSServerStatus *status=NULL);
  459. extern graph_decl void setThorVMSwapDirectory(const char *swapdir);
  460. class IPerfMonHook;
  461. extern graph_decl IPerfMonHook *createThorMemStatsPerfMonHook(IPerfMonHook *chain=NULL); // for passing to jdebug startPerformanceMonitor
  462. #endif