jbuff.cpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  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 <stdio.h>
  15. #include <stdlib.h>
  16. #include <stdarg.h>
  17. #include <assert.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <time.h>
  21. #include <math.h>
  22. #ifndef WIN32
  23. #include <sys/mman.h>
  24. #define LARGEMEM_USE_MMAP_SIZE 0x10000 // in largemem use mmap for chunks bigger than 64K
  25. #endif
  26. #include "jbuff.hpp"
  27. #include "jexcept.hpp"
  28. #include "jmisc.hpp"
  29. #include "jutil.hpp"
  30. #ifdef _DEBUG
  31. #define KILL_CLEARS_MEMORY
  32. //#define TRACE_LARGEMEM
  33. //#define TRACE_LARGEMEM_ALLOC
  34. #define TRACE_LARGEMEM_OOM
  35. #endif
  36. #define VMPAGESIZE (0x1000)
  37. #define VMPAGEMASK (VMPAGESIZE-1)
  38. #define VMPAGEROUND(s) (((s)+VMPAGEMASK)&~VMPAGEMASK)
  39. #if 1
  40. #define ChunkSize 0x10000
  41. #define DOUBLE_LIMIT 0x7fffffff // avoid doubling hitting 0 and infinite loop
  42. #else
  43. #define ChunkSize 2048
  44. #define DOUBLE_LIMIT 4096
  45. #endif
  46. #define FIRST_CHUNK_SIZE 8
  47. #define DETACH_GRANULARITY 16
  48. #ifdef _DEBUG
  49. #define CHECKREADPOS(len) assertex(readPos+(len)<=length())
  50. #else
  51. #define CHECKREADPOS(len)
  52. #endif
  53. //-----------------------------------------------------------------------
  54. static inline size32_t checkMemoryBufferOverflow(size32_t curLen, size32_t inc)
  55. {
  56. size_t newLen = (size_t)curLen + (size_t)inc;
  57. if (newLen > MEMBUFFER_MAXLEN)
  58. RaiseOutOfMemException(-10, curLen, inc, false, "Exceeded maximum size");
  59. return (size32_t)newLen;
  60. }
  61. jlib_decl void *checked_realloc(void *orig, size_t newlen, size_t origlen,int errcode)
  62. {
  63. if (newlen==0) {
  64. free(orig);
  65. return NULL;
  66. }
  67. if (orig==NULL)
  68. return checked_malloc(newlen,errcode);
  69. void *ret = realloc(orig, newlen);
  70. if (!ret)
  71. RaiseOutOfMemException(errcode, newlen, origlen);
  72. return ret;
  73. }
  74. class jlib_thrown_decl COutOfMemException: implements IOutOfMemException, public CInterface
  75. {
  76. int errcode;
  77. size_t wanted;
  78. size_t got;
  79. static int recursion;
  80. bool expected;
  81. StringBuffer errorMsg;
  82. public:
  83. IMPLEMENT_IINTERFACE;
  84. COutOfMemException(int _errcode, size_t _wanted, size_t _got, bool _expected, const char *errMsg)
  85. {
  86. errcode = _errcode;
  87. wanted = _wanted;
  88. expected = _expected;
  89. got = _got;
  90. if (nullptr == errMsg)
  91. errorMsg.append("Out of Memory");
  92. else
  93. errorMsg.append(errMsg);
  94. // DebugBreak();
  95. if ((recursion++==0)&&!expected) {
  96. // Bit risky if *very* out of memory so protect against recursion and catch exceptions
  97. try {
  98. // try to log
  99. PROGLOG("Jbuff: %s (%d,%" I64F "d,%" I64F "dk)",errorMsg.str(),_errcode,(unsigned __int64)wanted,(unsigned __int64) (got/1024));
  100. PrintStackReport();
  101. PrintMemoryReport();
  102. }
  103. catch (...) {
  104. }
  105. }
  106. recursion--;
  107. };
  108. int errorCode() const { return errcode; }
  109. StringBuffer & errorMessage(StringBuffer &str) const
  110. {
  111. str.append("Jbuff: ").append(errorMsg.str()).append(" (").append((unsigned __int64)wanted);
  112. if (got)
  113. str.append(',').append((unsigned __int64)got);
  114. return str.append(")");
  115. }
  116. MessageAudience errorAudience() const { return MSGAUD_user; }
  117. };
  118. int COutOfMemException::recursion=0;
  119. IOutOfMemException *createOutOfMemException(int errcode, size_t wanted, size_t got, bool expected, const char *errMsg)
  120. {
  121. return new COutOfMemException(errcode, wanted, got, expected, errMsg);
  122. }
  123. void RaiseOutOfMemException(int errcode, size_t wanted, size_t got, bool expected, const char *errMsg)
  124. {
  125. throw createOutOfMemException(errcode, wanted, got, expected, errMsg);
  126. }
  127. MemoryAttr::MemoryAttr(size_t _len)
  128. {
  129. ptr = checked_malloc(_len,-1);
  130. len = _len;
  131. }
  132. MemoryAttr::MemoryAttr(size_t _len, const void * _ptr)
  133. {
  134. len = 0;
  135. ptr = NULL;
  136. set(_len, _ptr);
  137. }
  138. MemoryAttr::MemoryAttr(const MemoryAttr & src)
  139. {
  140. len = 0;
  141. ptr = NULL;
  142. set(src.length(), src.get());
  143. }
  144. void MemoryAttr::set(size_t _len, const void * _ptr)
  145. {
  146. if (_len)
  147. memcpy(allocate(_len), _ptr, _len);
  148. else
  149. clear();
  150. }
  151. void MemoryAttr::setOwn(size_t _len, void * _ptr)
  152. {
  153. free(ptr);
  154. len = _len;
  155. ptr = _ptr;
  156. }
  157. void MemoryAttr::clear()
  158. {
  159. free(ptr);
  160. ptr = NULL;
  161. len = 0;
  162. }
  163. void * MemoryAttr::detach()
  164. {
  165. void * ret=ptr;
  166. ptr = NULL;
  167. len = 0;
  168. return ret;
  169. }
  170. int MemoryAttr::compare(const MemoryAttr & m1, const MemoryAttr & m2)
  171. {
  172. size_t len1 = m1.length();
  173. size_t len2 = m2.length();
  174. size_t len = len1;
  175. if (len1 > len2)
  176. len = len2;
  177. int compare = memcmp(m1.get(), m2.get(), len);
  178. if (compare == 0)
  179. compare = (len1 > len2) ? +1 : (len1 < len2) ? -1 : 0;
  180. return compare;
  181. }
  182. void * MemoryAttr::allocate(size_t _len)
  183. {
  184. if (_len==len)
  185. return ptr;
  186. clear();
  187. ptr = checked_malloc(_len,-2);
  188. len = _len;
  189. return ptr;
  190. }
  191. void * MemoryAttr::ensure(size_t _len)
  192. {
  193. if (_len <=len)
  194. return ptr;
  195. return reallocate(_len);
  196. }
  197. void * MemoryAttr::reallocate(size_t _len)
  198. {
  199. if (_len==len)
  200. return ptr;
  201. ptr = checked_realloc(ptr, _len, len, -9);
  202. len = _len;
  203. return ptr;
  204. }
  205. //===========================================================================
  206. void MemoryBuffer::_realloc(size32_t newLen)
  207. {
  208. if (newLen > maxLen)
  209. {
  210. assertex(ownBuffer);
  211. size32_t newMax = maxLen;
  212. //double up to a certain size, otherwise go up in chunks.
  213. if (newLen < DOUBLE_LIMIT)
  214. {
  215. if (newMax == 0)
  216. newMax = FIRST_CHUNK_SIZE;
  217. while (newLen > newMax)
  218. {
  219. size32_t newMaxTmp = checkMemoryBufferOverflow(newMax, newMax);
  220. newMax = newMaxTmp;
  221. }
  222. }
  223. else
  224. {
  225. size32_t newMaxTmp = checkMemoryBufferOverflow((newLen & ~(ChunkSize-1)), ChunkSize);
  226. /*** ((Size + 1) + (ChunkSize - 1)) & ~(ChunkSize-1) ***/
  227. newMax = newMaxTmp;
  228. }
  229. buffer =(char *)checked_realloc(buffer, newMax, maxLen, -7);
  230. maxLen = newMax;
  231. }
  232. }
  233. void MemoryBuffer::_reallocExact(size32_t newLen)
  234. {
  235. if (newLen > maxLen)
  236. {
  237. assertex(ownBuffer);
  238. buffer =(char *)checked_realloc(buffer, newLen, maxLen, -8);
  239. maxLen = newLen;
  240. }
  241. }
  242. void MemoryBuffer::init()
  243. {
  244. buffer = NULL;
  245. curLen = 0;
  246. maxLen = 0;
  247. ownBuffer = true;
  248. readPos = 0;
  249. swapEndian = false;
  250. }
  251. void *MemoryBuffer::insertDirect(unsigned offset, size32_t insertLen)
  252. {
  253. assertex(offset<=curLen);
  254. unsigned newLen = checkMemoryBufferOverflow(curLen, insertLen);
  255. _realloc(newLen);
  256. memmove(buffer + offset + insertLen, buffer + offset, curLen - offset);
  257. curLen += insertLen;
  258. return buffer+offset;
  259. }
  260. void * MemoryBuffer::ensureCapacity(unsigned max)
  261. {
  262. if (maxLen - curLen < max)
  263. {
  264. unsigned newLen = checkMemoryBufferOverflow(curLen, max);
  265. _realloc(newLen);
  266. }
  267. return buffer + curLen;
  268. }
  269. void MemoryBuffer::kill()
  270. {
  271. if (ownBuffer)
  272. free(buffer);
  273. }
  274. MemoryBuffer & MemoryBuffer::_remove(unsigned start, unsigned len)
  275. {
  276. if (start > curLen) start = curLen;
  277. if (start + len > curLen) len = curLen - start;
  278. unsigned start2 = start + len;
  279. memmove(buffer + start, buffer + start2, curLen - start2);
  280. setLength(curLen - len);
  281. return *this;
  282. }
  283. void * MemoryBuffer::reserve(unsigned size)
  284. {
  285. unsigned newLen = checkMemoryBufferOverflow(curLen, size);
  286. _realloc(newLen);
  287. void * ret = buffer + curLen;
  288. curLen += size;
  289. return ret;
  290. }
  291. void * MemoryBuffer::reserveTruncate(unsigned size)
  292. {
  293. unsigned newLen = checkMemoryBufferOverflow(curLen, size);
  294. curLen += size;
  295. _reallocExact(newLen);
  296. truncate();
  297. return buffer + curLen - size;
  298. }
  299. void MemoryBuffer::truncate()
  300. {
  301. if (maxLen>curLen) {
  302. if (curLen==0) {
  303. free(buffer);
  304. buffer = NULL;
  305. }
  306. else
  307. buffer = (char *)realloc(buffer, curLen);
  308. maxLen = curLen;
  309. }
  310. }
  311. void MemoryBuffer::resetBuffer()
  312. {
  313. kill();
  314. init();
  315. }
  316. MemoryBuffer & MemoryBuffer::_reverse()
  317. {
  318. unsigned max = curLen/2;
  319. char * end = buffer + curLen;
  320. unsigned idx;
  321. for (idx = 0; idx < max; idx++)
  322. {
  323. char temp = buffer[idx];
  324. end--;
  325. buffer[idx] = *end;
  326. *end = temp;
  327. }
  328. return *this;
  329. }
  330. void MemoryBuffer::setBuffer(size_t len, void * _buffer, bool takeOwnership)
  331. {
  332. assertex((size32_t)len == len);
  333. kill();
  334. buffer = (char *) _buffer;
  335. if (len) assertex(buffer);
  336. curLen = maxLen = (size32_t)len;
  337. ownBuffer = takeOwnership;
  338. readPos = 0;
  339. }
  340. void *MemoryBuffer::detach()
  341. {
  342. void *ret;
  343. if (ownBuffer) {
  344. if (maxLen>curLen+DETACH_GRANULARITY)
  345. buffer = (char *)realloc(buffer,curLen);
  346. ret = buffer;
  347. }
  348. else {
  349. ret = memcpy(checked_malloc(curLen,-3), buffer, curLen);
  350. }
  351. init();
  352. return ret;
  353. }
  354. void *MemoryBuffer::detachOwn()
  355. {
  356. assertex(ownBuffer);
  357. void *ret = buffer;
  358. init();
  359. return ret;
  360. }
  361. void MemoryBuffer::setLength(unsigned len)
  362. {
  363. if (len > curLen)
  364. {
  365. _realloc(len);
  366. memset(buffer + curLen, 0, len-curLen);
  367. }
  368. else
  369. {
  370. #ifdef KILL_CLEARS_MEMORY
  371. if (curLen)
  372. memset(buffer + len, 'x', curLen-len);
  373. #endif
  374. }
  375. curLen = len;
  376. }
  377. void MemoryBuffer::setWritePos(unsigned len)
  378. {
  379. if (len > curLen)
  380. _realloc(len);
  381. curLen = len;
  382. }
  383. #define SWAP(x, y, t) { t t_##x = x; x = y; y = t_##x; }
  384. void MemoryBuffer::swapWith(MemoryBuffer & other)
  385. {
  386. //swap two string buffers. Used for efficiently moving a string on in a pipeline etc.
  387. SWAP(buffer, other.buffer, char *);
  388. SWAP(curLen, other.curLen, size32_t);
  389. SWAP(maxLen, other.maxLen, size32_t);
  390. SWAP(readPos, other.readPos, size32_t);
  391. SWAP(swapEndian, other.swapEndian, bool);
  392. }
  393. bool MemoryBuffer::matches(const MemoryBuffer & other) const
  394. {
  395. if (curLen != other.curLen)
  396. return false;
  397. return (memcmp(buffer, other.buffer, curLen) == 0);
  398. }
  399. //-----------------------------------------------------------------------
  400. MemoryBuffer::MemoryBuffer(size_t initial)
  401. {
  402. assertex((size32_t)initial == initial);
  403. init();
  404. _realloc((size32_t)initial);
  405. }
  406. MemoryBuffer::MemoryBuffer(size_t len, const void * newBuffer)
  407. {
  408. init();
  409. assertex((size32_t)len == len);
  410. append((size32_t)len, newBuffer);
  411. }
  412. MemoryBuffer & MemoryBuffer::append(char value)
  413. {
  414. unsigned newLen = checkMemoryBufferOverflow(curLen, 1);
  415. _realloc(newLen);
  416. buffer[curLen] = value;
  417. ++curLen;
  418. return *this;
  419. }
  420. MemoryBuffer & MemoryBuffer::append(unsigned char value)
  421. {
  422. unsigned newLen = checkMemoryBufferOverflow(curLen, 1);
  423. _realloc(newLen);
  424. buffer[curLen] = value;
  425. ++curLen;
  426. return *this;
  427. }
  428. MemoryBuffer & MemoryBuffer::append(bool value)
  429. {
  430. unsigned newLen = checkMemoryBufferOverflow(curLen, 1);
  431. _realloc(newLen);
  432. buffer[curLen] = (value==0)?0:1;
  433. ++curLen;
  434. return *this;
  435. }
  436. MemoryBuffer & MemoryBuffer::append(const char * value)
  437. {
  438. if (value)
  439. return append((size32_t)strlen(value)+1,value);
  440. else
  441. return append((char)0);
  442. }
  443. MemoryBuffer & MemoryBuffer::append(const unsigned char * value)
  444. {
  445. return append((const char *) value);
  446. }
  447. MemoryBuffer & MemoryBuffer::append(unsigned len, const void * value)
  448. {
  449. if (likely(len))
  450. {
  451. unsigned newLen = checkMemoryBufferOverflow(curLen, len);
  452. _realloc(newLen);
  453. memcpy(buffer + curLen, value, len);
  454. curLen += len;
  455. }
  456. return *this;
  457. }
  458. MemoryBuffer & MemoryBuffer::append(double value)
  459. {
  460. return appendEndian(sizeof(value), &value);
  461. }
  462. MemoryBuffer & MemoryBuffer::append(float value)
  463. {
  464. return appendEndian(sizeof(value), &value);
  465. }
  466. MemoryBuffer & MemoryBuffer::append(short value)
  467. {
  468. return appendEndian(sizeof(value), &value);
  469. }
  470. MemoryBuffer & MemoryBuffer::append(unsigned short value)
  471. {
  472. return appendEndian(sizeof(value), &value);
  473. }
  474. MemoryBuffer & MemoryBuffer::append(int value)
  475. {
  476. return appendEndian(sizeof(value), &value);
  477. }
  478. MemoryBuffer & MemoryBuffer::append(unsigned value)
  479. {
  480. return appendEndian(sizeof(value), &value);
  481. }
  482. #if 0
  483. MemoryBuffer & MemoryBuffer::append(long value)
  484. {
  485. return appendEndian(sizeof(value), &value);
  486. }
  487. MemoryBuffer & MemoryBuffer::append(unsigned long value)
  488. {
  489. return appendEndian(sizeof(value), &value);
  490. }
  491. #endif
  492. MemoryBuffer & MemoryBuffer::append(__int64 value)
  493. {
  494. return appendEndian(sizeof(value), &value);
  495. }
  496. MemoryBuffer & MemoryBuffer::append(unsigned __int64 value)
  497. {
  498. return appendEndian(sizeof(value), &value);
  499. }
  500. MemoryBuffer & MemoryBuffer::appendPacked(unsigned __int64 value)
  501. {
  502. //Append bytes with the top bit set until the value is less than 0x80
  503. while (value >= 0x80)
  504. {
  505. byte next = ((byte)value) | 0x80;
  506. append(next);
  507. value >>= 7;
  508. }
  509. return append((byte)value);
  510. }
  511. MemoryBuffer & MemoryBuffer::append(const MemoryBuffer & value)
  512. {
  513. size32_t SourceLen = value.length();
  514. unsigned newLen = checkMemoryBufferOverflow(curLen, SourceLen);
  515. _realloc(newLen);
  516. memcpy(buffer + curLen, value.toByteArray(), SourceLen);
  517. curLen += SourceLen;
  518. return *this;
  519. }
  520. MemoryBuffer & MemoryBuffer::appendBytes(unsigned char value, unsigned count)
  521. {
  522. unsigned newLen = checkMemoryBufferOverflow(curLen, count);
  523. _realloc(newLen);
  524. memset(buffer+curLen, value, count);
  525. curLen+=count;
  526. return *this;
  527. }
  528. MemoryBuffer & MemoryBuffer::appendEndian(size32_t len, const void * value)
  529. {
  530. unsigned newLen = checkMemoryBufferOverflow(curLen, len);
  531. _realloc(newLen);
  532. if (swapEndian)
  533. _cpyrevn(buffer + curLen, value, len);
  534. else
  535. memcpy(buffer + curLen, value, len);
  536. curLen += len;
  537. return *this;
  538. }
  539. MemoryBuffer & MemoryBuffer::appendSwap(size32_t len, const void * value)
  540. {
  541. unsigned newLen = checkMemoryBufferOverflow(curLen, len);
  542. _realloc(newLen);
  543. _cpyrevn(buffer + curLen, value, len);
  544. curLen += len;
  545. return *this;
  546. }
  547. MemoryBuffer &MemoryBuffer::appendFile(const char *fileName)
  548. {
  549. char buf[1024];
  550. int h = _open(fileName, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL);
  551. if (h == HFILE_ERROR)
  552. throw MakeStringException(0, "MemoryBuffer: Error reading file : %s", fileName);
  553. append(fileName);
  554. unsigned fileSize = _lseek(h, 0, FILE_END);
  555. _lseek(h, 0, FILE_BEGIN);
  556. append(fileSize);
  557. int r;
  558. while ((r = _read(h, buf, 1024)) != 0)
  559. {
  560. if (-1==r) throw makeErrnoException("MemoryBuffer::appendFile");
  561. append(r, buf);
  562. }
  563. _close(h);
  564. return *this;
  565. }
  566. MemoryBuffer & MemoryBuffer::read(char & value)
  567. {
  568. CHECKREADPOS(sizeof(value));
  569. value = buffer[readPos++];
  570. return *this;
  571. }
  572. MemoryBuffer & MemoryBuffer::read(unsigned char & value)
  573. {
  574. CHECKREADPOS(sizeof(value));
  575. value = buffer[readPos++];
  576. return *this;
  577. }
  578. MemoryBuffer & MemoryBuffer::read(bool & value)
  579. {
  580. CHECKREADPOS(sizeof(value));
  581. char _value = buffer[readPos++];
  582. value = (_value==0 ? false : true);
  583. return *this;
  584. }
  585. MemoryBuffer & MemoryBuffer::read(StringAttr & value)
  586. {
  587. char * src = buffer + readPos;
  588. size32_t len = (size32_t)strlen(src);
  589. CHECKREADPOS(len+1);
  590. value.set(src, len);
  591. readPos += (len+1);
  592. return *this;
  593. }
  594. MemoryBuffer & MemoryBuffer::read(StringBuffer & value)
  595. {
  596. char * src = buffer + readPos;
  597. size32_t len = (size32_t)strlen(src);
  598. CHECKREADPOS(len+1);
  599. value.append(len, src);
  600. readPos += (len+1);
  601. return *this;
  602. }
  603. MemoryBuffer & MemoryBuffer::read(const char * &value)
  604. {
  605. value = buffer+readPos;
  606. size32_t len = (size32_t)strlen(value);
  607. CHECKREADPOS(len+1);
  608. readPos += (len+1);
  609. return *this;
  610. }
  611. MemoryBuffer & MemoryBuffer::read(size32_t len, void * value)
  612. {
  613. CHECKREADPOS(len);
  614. memcpy(value, buffer + readPos, len);
  615. readPos += len;
  616. return *this;
  617. }
  618. MemoryBuffer & MemoryBuffer::read(double & value)
  619. {
  620. return readEndian(sizeof(value), &value);
  621. }
  622. MemoryBuffer & MemoryBuffer::read(float & value)
  623. {
  624. return readEndian(sizeof(value), &value);
  625. }
  626. MemoryBuffer & MemoryBuffer::read(short & value)
  627. {
  628. return readEndian(sizeof(value), &value);
  629. }
  630. MemoryBuffer & MemoryBuffer::read(unsigned short & value)
  631. {
  632. return readEndian(sizeof(value), &value);
  633. }
  634. MemoryBuffer & MemoryBuffer::read(int & value)
  635. {
  636. return readEndian(sizeof(value), &value);
  637. }
  638. MemoryBuffer & MemoryBuffer::read(unsigned & value)
  639. {
  640. return readEndian(sizeof(value), &value);
  641. }
  642. #if 0
  643. MemoryBuffer & MemoryBuffer::read(unsigned long & value)
  644. {
  645. return readEndian(sizeof(value), &value);
  646. }
  647. MemoryBuffer & MemoryBuffer::read(long & value)
  648. {
  649. return readEndian(sizeof(value), &value);
  650. }
  651. #endif
  652. MemoryBuffer & MemoryBuffer::read(unsigned __int64 & value)
  653. {
  654. return readEndian(sizeof(value), &value);
  655. }
  656. MemoryBuffer & MemoryBuffer::read(__int64 & value)
  657. {
  658. return readEndian(sizeof(value), &value);
  659. }
  660. const byte * MemoryBuffer::readDirect(size32_t len)
  661. {
  662. CHECKREADPOS(len);
  663. const byte * ret = (const byte *)buffer + readPos;
  664. readPos += len;
  665. return ret;
  666. }
  667. unsigned __int64 MemoryBuffer::readPacked()
  668. {
  669. unsigned __int64 value = 0;
  670. unsigned shift = 0;
  671. for (;;)
  672. {
  673. byte next;
  674. read(next);
  675. value = value | (((unsigned __int64)(next & 0x7f)) << shift);
  676. if (!(next & 0x80))
  677. break;
  678. shift += 7;
  679. }
  680. return value;
  681. }
  682. MemoryBuffer & MemoryBuffer::readPacked(unsigned & value)
  683. {
  684. unsigned __int64 serializedValue = readPacked();
  685. dbgassertex((unsigned)serializedValue == serializedValue);
  686. value = (unsigned)serializedValue;
  687. return *this;
  688. }
  689. MemoryBuffer & MemoryBuffer::readPacked(unsigned __int64 & value)
  690. {
  691. value = readPacked();
  692. return *this;
  693. }
  694. MemoryBuffer & MemoryBuffer::skip(unsigned len)
  695. {
  696. CHECKREADPOS(len);
  697. readPos += len;
  698. return *this;
  699. }
  700. void MemoryBuffer::writeDirect(size32_t pos,size32_t len,const void *buf)
  701. {
  702. assertex(pos+len<=curLen); // does not extend
  703. memcpy(buffer+pos,buf,len);
  704. }
  705. void MemoryBuffer::writeEndianDirect(size32_t pos,size32_t len,const void *buf)
  706. {
  707. assertex(pos+len<=curLen); // does not extend
  708. if (swapEndian)
  709. _cpyrevn(buffer+pos,buf,len);
  710. else
  711. memcpy(buffer+pos,buf,len);
  712. }
  713. MemoryBuffer & MemoryBuffer::readEndian(size32_t len, void * value)
  714. {
  715. CHECKREADPOS(len);
  716. if (swapEndian)
  717. _cpyrevn(value, buffer + readPos, len);
  718. else
  719. memcpy(value, buffer + readPos, len);
  720. readPos += len;
  721. return *this;
  722. }
  723. MemoryBuffer & MemoryBuffer::readSwap(size32_t len, void * value)
  724. {
  725. CHECKREADPOS(len);
  726. _cpyrevn(value, buffer + readPos, len);
  727. readPos += len;
  728. return *this;
  729. }
  730. MemoryBuffer &MemoryBuffer::readFile(StringAttr &fileName)
  731. {
  732. read(fileName);
  733. unsigned fileSize;
  734. read(fileSize);
  735. int h = _open(fileName.get(), _O_WRONLY|_O_CREAT|_O_TRUNC|_O_BINARY|_O_SEQUENTIAL, _S_IREAD | _S_IWRITE);
  736. if (h == HFILE_ERROR)
  737. throw MakeStringException(0, "MemoryBuffer: Unable to create file : %s, error=%d", fileName.get(), GetLastError());
  738. CHECKREADPOS(fileSize);
  739. int w;
  740. while (fileSize) {
  741. w = _write(h, buffer+readPos, fileSize);
  742. if (w == 0) {
  743. _close(h);
  744. throw MakeStringException(0, "MemoryBuffer: Disk full writing %d to file : %s", fileSize, fileName.get());
  745. }
  746. if (w == -1)
  747. {
  748. _close(h);
  749. throw MakeStringException(0, "MemoryBuffer: Error writing to file : %s, error=%d", fileName.get(), GetLastError());
  750. }
  751. readPos += (size32_t)w;
  752. fileSize -= (size32_t)w;
  753. }
  754. _close(h);
  755. return *this;
  756. }
  757. MemoryBuffer & MemoryBuffer::rewrite(size32_t pos)
  758. {
  759. assertex(pos<=maxLen);
  760. curLen = pos;
  761. if (readPos>pos)
  762. readPos = pos;
  763. return *this;
  764. }
  765. MemoryBuffer & MemoryBuffer::reset(size32_t pos)
  766. {
  767. CHECKREADPOS(pos-readPos);
  768. readPos = pos;
  769. return *this;
  770. }
  771. #if 0
  772. void MemoryBuffer::getBytes(int srcBegin, int srcEnd, char * target)
  773. {
  774. memcpy(target, buffer + srcBegin, srcEnd - srcBegin);
  775. }
  776. MemoryBuffer & MemoryBuffer::remove(unsigned start, unsigned len)
  777. {
  778. return (MemoryBuffer &)_remove(start, len);
  779. }
  780. #endif
  781. int MemoryBuffer::setEndian(int endian)
  782. {
  783. assertex((endian == __LITTLE_ENDIAN) || (endian == __BIG_ENDIAN));
  784. bool wasSwapped = setSwapEndian(endian != __BYTE_ORDER);
  785. return wasSwapped ? (__BYTE_ORDER ^ __LITTLE_ENDIAN ^ __BIG_ENDIAN) : __BYTE_ORDER;
  786. }
  787. bool MemoryBuffer::setSwapEndian(bool swap)
  788. {
  789. bool saved = swapEndian;
  790. swapEndian = swap;
  791. return saved;
  792. }
  793. MemoryBuffer & serialize(MemoryBuffer & buffer, const MemoryAttr & value)
  794. {
  795. size32_t length = (size32_t)value.length();
  796. buffer.append(length).append(length, value.get());
  797. return buffer;
  798. }
  799. MemoryBuffer & deserialize(MemoryBuffer & buffer, MemoryAttr & value)
  800. {
  801. unsigned length;
  802. buffer.read(length);
  803. void * target = value.allocate(length);
  804. buffer.read(length, target);
  805. return buffer;
  806. }
  807. MemoryBuffer & serialize(MemoryBuffer & buffer, const char * value)
  808. {
  809. if (value)
  810. {
  811. unsigned length = (size32_t)strlen(value);
  812. buffer.append(length).append(length, value);
  813. }
  814. else
  815. buffer.append((unsigned)-1);
  816. return buffer;
  817. }
  818. MemoryBuffer & deserialize(MemoryBuffer & buffer, StringAttr & value)
  819. {
  820. unsigned length;
  821. buffer.read(length);
  822. if (length == (unsigned)-1)
  823. value.clear();
  824. else
  825. {
  826. char * target = (char *)checked_malloc(length+1,-4);
  827. buffer.read(length, target);
  828. target[length] = 0;
  829. value.setown(target);
  830. }
  831. return buffer;
  832. }
  833. // =====================================================================================================
  834. const char * MemoryAttr2IStringVal::str() const
  835. {
  836. UNIMPLEMENTED;
  837. }
  838. // =====================================================================================================
  839. static memsize_t LMsemlimit=0;
  840. static memsize_t LMtotal=0;
  841. static CriticalSection LMsemsect;
  842. static Owned<ILargeMemLimitNotify> LMnotify;
  843. static bool LMlocked = false;
  844. void setLargeMemLimitNotify(memsize_t size,ILargeMemLimitNotify *notify)
  845. {
  846. CriticalBlock block(LMsemsect);
  847. LMsemlimit = size;
  848. LMnotify.set(notify);
  849. if (LMlocked&&(LMtotal<LMsemlimit))
  850. LMlocked = false;
  851. }
  852. inline void incLargeMemTotal(memsize_t sz)
  853. {
  854. if (sz) {
  855. CriticalBlock block(LMsemsect);
  856. LMtotal += sz;
  857. #ifdef TRACE_LARGEMEM
  858. if ((LMtotal/0x100000)!=((LMtotal-sz)/0x100000))
  859. PROGLOG("LARGEMEM(+): %" I64F "d",(offset_t)LMtotal);
  860. #endif
  861. if (!LMlocked&&LMnotify.get()&&(LMtotal>=LMsemlimit)) {
  862. LMlocked = true;
  863. DBGLOG("LargeMemTotal limit exceeded: %" I64F "d",(offset_t)LMtotal);
  864. if (!LMnotify->take(LMtotal)) {
  865. LMtotal -= sz;
  866. LMlocked = false;
  867. throw createOutOfMemException(-9,sz, LMtotal);
  868. }
  869. DBGLOG("LargeMem taken");
  870. }
  871. }
  872. }
  873. inline void decLargeMemTotal(memsize_t sz)
  874. {
  875. if (sz) {
  876. CriticalBlock block(LMsemsect);
  877. LMtotal -= sz;
  878. #ifdef TRACE_LARGEMEM
  879. if ((LMtotal/0x100000)!=((LMtotal+sz)/0x100000))
  880. PROGLOG("LARGEMEM(-): %" I64F "d",(offset_t)LMtotal);
  881. #endif
  882. if (LMlocked) {
  883. if (LMtotal<LMsemlimit) {
  884. DBGLOG("LargeMemTotal limit reduced to %" I64F "d",(offset_t)LMtotal);
  885. LMlocked = false;
  886. if (LMnotify.get())
  887. LMnotify->give(LMtotal);
  888. }
  889. }
  890. }
  891. }
  892. void CLargeMemoryAllocator::allocchunkmem()
  893. {
  894. #ifdef LARGEMEM_USE_MMAP_SIZE
  895. size32_t masize = VMPAGEROUND(chunk.max);
  896. if (masize>=LARGEMEM_USE_MMAP_SIZE) { // use mmap
  897. chunk.base = (byte *) mmap(NULL,masize,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS,-1,0);
  898. if (chunk.base == (byte *)MAP_FAILED)
  899. chunk.base = NULL;
  900. #ifdef TRACE_LARGEMEM_ALLOC
  901. PROGLOG("CLargeMemoryAllocator::allocchunkmem mmaped %d at %p",masize,chunk.base);
  902. #endif
  903. return;
  904. }
  905. #endif
  906. chunk.base = (byte *)malloc(chunk.max);
  907. #ifdef TRACE_LARGEMEM_ALLOC
  908. PROGLOG("CLargeMemoryAllocator::allocchunkmem malloced %d at %p",chunk.max,chunk.base);
  909. #endif
  910. }
  911. void CLargeMemoryAllocator::disposechunkmem()
  912. {
  913. #ifdef LARGEMEM_USE_MMAP_SIZE
  914. size32_t masize = VMPAGEROUND(chunk.max);
  915. if (masize>=LARGEMEM_USE_MMAP_SIZE) { // use mmap
  916. munmap(chunk.base,masize);
  917. return;
  918. }
  919. #endif
  920. free(chunk.base);
  921. }
  922. bool CLargeMemoryAllocator::newchunk(size32_t sz,size32_t extra,bool exceptionwanted)
  923. {
  924. size32_t newchunksz = (sz>chunkmin)?sz:chunkmin;
  925. if (maxallocated()+newchunksz+extra>totalmax) {
  926. #ifdef TRACE_LARGEMEM_OOM
  927. PrintStackReport();
  928. PROGLOG("OOM.1 wanted sz=%d, extra = %d, maxallocated=%" I64F "d, newchunksz=%u, totalmax=%" I64F "d",sz,extra,(offset_t)maxallocated(),newchunksz,(offset_t)totalmax);
  929. #endif
  930. if (exceptionwanted) {
  931. throw createOutOfMemException(-5,sz, maxallocated(),true);
  932. }
  933. return false;
  934. }
  935. if (chunk.size) {
  936. Chunk *p = new Chunk;
  937. *p = chunk;
  938. chunk.prev = p;
  939. atot += chunk.size;
  940. }
  941. else if (chunk.max) {
  942. decLargeMemTotal(chunk.max);
  943. amax -= chunk.max;
  944. disposechunkmem();
  945. }
  946. chunk.max = newchunksz;
  947. allocchunkmem();
  948. chunk.size = 0;
  949. if (!chunk.base) {
  950. // restore prev
  951. if (chunk.prev) {
  952. Chunk *p = chunk.prev;
  953. chunk = *p;
  954. atot -= chunk.size;
  955. delete p;
  956. }
  957. else
  958. chunk.max = 0;
  959. #ifdef TRACE_LARGEMEM_OOM
  960. PrintStackReport();
  961. PROGLOG("OOM.2 wanted sz=%d, extra = %d, maxallocated=%" I64F "d, newchunksz=%u, totalmax=%" I64F "d",sz,extra,(offset_t)maxallocated(),newchunksz,(offset_t)totalmax);
  962. #endif
  963. if (throwexception) {
  964. throw createOutOfMemException(-6,sz, maxallocated(),true);
  965. }
  966. return false;
  967. }
  968. amax += chunk.max;
  969. incLargeMemTotal(newchunksz);
  970. return true;
  971. }
  972. void CLargeMemoryAllocator::reset()
  973. {
  974. decLargeMemTotal(maxallocated());
  975. disposechunkmem();
  976. while (chunk.prev) {
  977. Chunk *p = chunk.prev;
  978. chunk = *chunk.prev;
  979. delete p;
  980. disposechunkmem();
  981. }
  982. chunk.max = 0;
  983. chunk.base = NULL;
  984. chunk.size = 0;
  985. atot = 0;
  986. amax = 0;
  987. }
  988. void CLargeMemoryAllocator::reduceSize(memsize_t amount)
  989. {
  990. if (amount<=chunk.size) {
  991. chunk.size-=amount;
  992. return;
  993. }
  994. memsize_t reduced = 0;
  995. do {
  996. amount -= chunk.size;
  997. reduced += chunk.max;
  998. disposechunkmem();
  999. amax -= chunk.max;
  1000. Chunk *p = chunk.prev;
  1001. chunk = *p;
  1002. atot -= chunk.size;
  1003. delete p;
  1004. } while (amount>chunk.size);
  1005. chunk.size-=amount;
  1006. decLargeMemTotal(reduced);
  1007. }
  1008. void CLargeMemoryAllocator::setSize(memsize_t pos)
  1009. {
  1010. memsize_t sz = allocated();
  1011. assertex(sz>=pos);
  1012. reduceSize(sz-pos);
  1013. }
  1014. byte *CLargeMemoryAllocator::next(memsize_t pos,size32_t &size) // this should not be used for small jumps as it is slow
  1015. {
  1016. memsize_t sz = allocated();
  1017. if (sz<=pos) {
  1018. size = 0;
  1019. return NULL;
  1020. }
  1021. memsize_t dif = sz-pos; // how much to go back
  1022. Chunk *p = &chunk;
  1023. while (dif>p->size) {
  1024. dif -= p->size;
  1025. p = p->prev;
  1026. }
  1027. size = (size32_t)dif; // must be smaller than chunk
  1028. return p->base+p->size-dif;
  1029. }
  1030. CLargeMemoryAllocator::CLargeMemoryAllocator()
  1031. {
  1032. // values overwritten by init
  1033. throwexception = true;
  1034. totalmax = 0;
  1035. chunkmin = 0x1000;
  1036. chunk.prev = NULL;
  1037. chunk.max = 0;
  1038. chunk.base = NULL;
  1039. chunk.size = 0;
  1040. atot = 0;
  1041. amax = 0;
  1042. }
  1043. void CLargeMemoryAllocator::init(memsize_t _totalmax,size32_t _chunkmin,bool _throwexception)
  1044. {
  1045. throwexception = _throwexception;
  1046. totalmax = _totalmax;
  1047. chunkmin = _chunkmin;
  1048. chunk.prev = NULL;
  1049. chunk.max = 0;
  1050. chunk.base = NULL;
  1051. chunk.size = 0;
  1052. atot = 0;
  1053. amax = 0;
  1054. }
  1055. MemoryBuffer &CLargeMemoryAllocator::serialize(MemoryBuffer &mb)
  1056. {
  1057. memsize_t al = allocated();
  1058. size32_t sz = (size32_t)al;
  1059. if (sz!=al)
  1060. throw MakeStringException(-1,"CLargeMemoryAllocator::serialize overflow");
  1061. byte *d = (byte *)mb.reserveTruncate(sz)+sz;
  1062. Chunk *p = &chunk;
  1063. while (sz&&p) {
  1064. size32_t s = p->size;
  1065. d -= s;
  1066. memcpy(d,p->base,s);
  1067. p = p->prev;
  1068. sz -= s;
  1069. }
  1070. return mb;
  1071. }
  1072. MemoryBuffer &CLargeMemoryAllocator::deserialize(MemoryBuffer &mb,size32_t sz, size32_t extra)
  1073. {
  1074. mb.read(sz,alloc(sz,extra));
  1075. return mb;
  1076. }
  1077. void *CLargeMemoryAllocator::nextBuffer(void *prev,size32_t &sz)
  1078. { // not fast
  1079. Chunk *p = NULL;
  1080. Chunk *n = &chunk;
  1081. while (n&&(n->base!=prev)) {
  1082. p = n;
  1083. n = n->prev;
  1084. }
  1085. if (!p) {
  1086. sz = 0;
  1087. return NULL;
  1088. }
  1089. sz = p->size;
  1090. return p->base;
  1091. }
  1092. CFixedSizeAllocator::CFixedSizeAllocator()
  1093. {
  1094. chunklist = NULL;
  1095. }
  1096. CFixedSizeAllocator::CFixedSizeAllocator(size32_t _allocsize,size32_t _chunksize)
  1097. {
  1098. chunklist = NULL;
  1099. init(_allocsize,_chunksize);
  1100. }
  1101. void CFixedSizeAllocator::init(size32_t _allocsize,size32_t _chunksize)
  1102. {
  1103. kill();
  1104. allocsize = _allocsize;
  1105. assertex(allocsize);
  1106. if (allocsize<sizeof(void *))
  1107. allocsize = sizeof(void *);
  1108. chunksize = _chunksize;
  1109. if (chunksize<allocsize*16)
  1110. chunksize = allocsize+sizeof(void *); // give up on sublety
  1111. }
  1112. void CFixedSizeAllocator::kill()
  1113. {
  1114. while (chunklist) {
  1115. void *p = chunklist;
  1116. chunklist = *(void **)p;
  1117. freeChunk(p);
  1118. }
  1119. freelist = NULL;
  1120. numalloc = 0;
  1121. numfree = 0;
  1122. chunklist = NULL;
  1123. }
  1124. CFixedSizeAllocator::~CFixedSizeAllocator()
  1125. {
  1126. kill();
  1127. }
  1128. void *CFixedSizeAllocator::allocChunk()
  1129. {
  1130. return checked_malloc(chunksize,-5); // don't try to be clever and allocate less (fragmentation)
  1131. }
  1132. void CFixedSizeAllocator::freeChunk(void *p)
  1133. {
  1134. free(p);
  1135. }
  1136. void *CFixedSizeAllocator::alloc()
  1137. {
  1138. NonReentrantSpinBlock block(lock);
  1139. void *ret;
  1140. if (numfree) {
  1141. numfree--;
  1142. ret = freelist;
  1143. freelist = *(void **)freelist;
  1144. }
  1145. else {
  1146. void **newchunk = (void **)allocChunk();
  1147. unsigned num = (chunksize-sizeof(void *))/allocsize;
  1148. assertex(num);
  1149. *newchunk = chunklist;
  1150. chunklist = (void *)newchunk;
  1151. newchunk++;
  1152. ret = (void *)newchunk;
  1153. numfree+=num-1;
  1154. while (--num) { // we could do this on the fly but I think this marginally better
  1155. newchunk = (void **)(((byte *)newchunk)+allocsize);
  1156. *newchunk = freelist;
  1157. freelist = (void *)newchunk;
  1158. }
  1159. }
  1160. numalloc++;
  1161. return ret;
  1162. }
  1163. void CFixedSizeAllocator::dealloc(void *blk)
  1164. {
  1165. if (blk) {
  1166. NonReentrantSpinBlock block(lock);
  1167. *(void **)blk = freelist;
  1168. freelist = blk;
  1169. numfree++;
  1170. numalloc--;
  1171. }
  1172. }
  1173. void CFixedSizeAllocator::stats(size32_t &sizealloc, size32_t &sizeunused)
  1174. {
  1175. NonReentrantSpinBlock block(lock);
  1176. sizealloc = numalloc*allocsize;
  1177. sizeunused = numfree*allocsize;
  1178. }