static inline void setCheck(size32_t size, void * _ptr) { byte * ptr = static_cast<byte *>(_ptr); size32_t capacity = RoxieRowCapacity(ptr); memset(ptr+size, 0, capacity - size - extraSize); unsigned short * check = reinterpret_cast<unsigned short *>(ptr + capacity - extraSize); *check = chksum16(ptr, capacity-extraSize); }
static inline void setCheck(size32_t size, void * _ptr) { byte * ptr = static_cast<byte *>(_ptr); memsize_t capacity = RoxieRowCapacity(ptr); if (capacity < size + extraSize) throw MakeStringException(0, "Data was written past the end of the row - allocated %d, written %d", (size32_t)(capacity - extraSize), size); memset(ptr+size, 0, capacity - size - extraSize); unsigned short * check = reinterpret_cast<unsigned short *>(ptr + capacity - extraSize); *check = chksum16(ptr, capacity-extraSize); }
static inline bool isValid(const void * _ptr) { if (RoxieRowHasDestructor(_ptr)) { const byte * ptr = static_cast<const byte *>(_ptr); memsize_t capacity = RoxieRowCapacity(ptr); const unsigned short * check = reinterpret_cast<const unsigned short *>(ptr + capacity - extraSize); return chksum16(ptr, capacity-extraSize) == *check; } return true; }
bool DynamicRoxieOutputRowArray::ensure(rowidx_t requiredRows) { unsigned newSize = maxRows; //This condition must be <= at least 1/scaling factor below otherwise you'll get an infinite loop. if (newSize <= 4) newSize = requiredRows; else { //What algorithm should we use to increase the size? Trading memory usage against copying row pointers. // adding 50% would reduce the number of allocations. // anything below 32% would mean that blocks n,n+1 when freed have enough space for block n+3 which might // reduce fragmentation. //Use 25% for the moment. It should possibly be configurable - e.g., higher for thor global sort. while (newSize < requiredRows) newSize += newSize/4; } const void * * newRows; try { newRows = static_cast<const void * *>(rowManager->allocate(newSize * sizeof(void*), RowArrayActivityId)); if (!newRows) return false; } catch (IException * e) { //Pahological cases - not enough memory to reallocate the target row buffer, or no contiguous pages available. unsigned code = e->errorCode(); if ((code == ROXIE_MEMORY_LIMIT_EXCEEDED) || (code == ROXIE_MEMORY_POOL_EXHAUSTED)) { e->Release(); return false; } throw; } //Only the writer is allowed to reallocate rows (otherwise append can't be optimized), so rows is valid outside the lock const void * * oldRows = rows; { RoxieOutputRowArrayLock block(*this); oldRows = rows; memcpy(newRows, oldRows+firstRow, (numRows - firstRow) * sizeof(void*)); numRows -= firstRow; commitRows -= firstRow; firstRow = 0; rows = newRows; maxRows = RoxieRowCapacity(newRows) / sizeof(void *); } ReleaseRoxieRow(oldRows); return true; }
RoxieOutputRowArray::RoxieOutputRowArray(IRowManager * _rowManager, rowidx_t initialSize, size32_t _commitDelta) : rowManager(_rowManager), commitDelta(_commitDelta) { if (initialSize) { rows = static_cast<const void * *>(rowManager->allocate(initialSize * sizeof(void*), RowArrayActivityId)); maxRows = RoxieRowCapacity(rows) / sizeof(void *); } else { rows = NULL; maxRows = 0; } commitRows = 0; numRows = 0; firstRow = 0; }