void* NorlsAllocator::_AllocNonZero(size_t& sz) { AssertIfFalse((size_t)nextFree % sizeof(void*) == 0); AssertIfFalse((size_t)limitFree % sizeof(void*) == 0); void * p = nextFree; if (sz == 0 && p == NULL) { sz = 1; } size_t roundSize = VBMath::RoundUpAllocSize(sz); size_t available = limitFree - nextFree; if ( available < roundSize ) { AllocNewPage(sz); } p = nextFree; nextFree += roundSize; // this shouldn't overflow because we got the memory for the request (we would have thrown in AllocNewPage() otherwise) MakeCurrentPageWriteableInternal(); AssertIfFalse((size_t)nextFree % sizeof(void*) == 0); AssertIfFalse((size_t)limitFree % sizeof(void*) == 0); AssertIfFalse((size_t)p % sizeof(void*) == 0); #if NRLSTRACK m_nTotalAllocated += roundSize; m_dwAllocThreadId = 0; #endif NRLSTRACK sz = roundSize; #if NRLSTRACK VSASSERT(m_dwAllocThreadId == 0," NorlsAlloc: only 1 thread allowed at a time"); m_dwAllocThreadId = GetCurrentThreadId(); m_nSeqNo+=1; #if NRLSTRACK_GETSTACKS // NrlsHeapData *pdata = (NrlsHeapData *) VsDebugAllocInternal(TrackingHeapToUse(), HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, (sizeof (NrlsHeapData )), __FILE__, __LINE__, INSTANCE_GLOBAL, NULL); pdata->m_ptrNextBlock = m_pLastBlock; // linked list of allocations: point to prior one pdata->m_size = sz; // record the size pdata->m_data = p; // record the actual allocation m_pLastBlock = pdata; // track the most recent one #endif NRLSTRACK_GETSTACKS #endif NRLSTRACK return p; }
/* * Algorithm: * - Find bucket * - Check bucket pages - if it has enough free space, allocate that chunk * - Check pages in bigger buckets - if that has enough space, split that page and allocate from that chunk * - Allocate new page */ Allocation* Heap::Alloc(size_t bytes, ushort pdataCount, ushort xdataSize, bool canAllocInPreReservedHeapPageSegment, bool isAnyJittedCode, _Inout_ bool* isAllJITCodeInPreReservedRegion) { Assert(bytes > 0); Assert((allocXdata || pdataCount == 0) && (!allocXdata || pdataCount > 0)); Assert(pdataCount > 0 || (pdataCount == 0 && xdataSize == 0)); // Round up to power of two to allocate, and figure out which bucket to allocate in size_t bytesToAllocate = PowerOf2Policy::GetSize(bytes); BucketId bucket = (BucketId) GetBucketForSize(bytesToAllocate); Allocation* allocation; if (bucket == BucketId::LargeObjectList) { return AllocLargeObject(bytes, pdataCount, xdataSize, canAllocInPreReservedHeapPageSegment, isAnyJittedCode, isAllJITCodeInPreReservedRegion); } VerboseHeapTrace(L"Bucket is %d\n", bucket); VerboseHeapTrace(L"Requested: %d bytes. Allocated: %d bytes\n", bytes, bytesToAllocate); Page* page = nullptr; if(!this->buckets[bucket].Empty()) { page = &this->buckets[bucket].Head(); } else { page = FindPageToSplit(bucket, canAllocInPreReservedHeapPageSegment); } if(page == nullptr) { page = AllocNewPage(bucket, canAllocInPreReservedHeapPageSegment, isAnyJittedCode, isAllJITCodeInPreReservedRegion); } // Out of memory if (page == nullptr) { return nullptr; } allocation = AllocInPage(page, bytesToAllocate, pdataCount, xdataSize); return allocation; }
int UpdateObjDataByRange(ObjStoreContext* pContext, uint64_t objid, uint64_t startpos, const uint8_t* pData, uint64_t dataLen) { ObjMeta theMeta; //theMeta.objid = objid; //theMeta.datalen = dataLen; int result = -1; if (ReadObjMeta(pContext, objid, &theMeta) != 0) { return -1; } if (startpos > theMeta.datalen) { printf("start pos too big!\n"); return -1; } int startpage = startpos / pContext->pagesize; int endpage = (startpos + dataLen) / pContext->pagesize; int i = 0; int readlen = 0; uint64_t datalen = theMeta.datalen; uint8_t utf8path[257] = { 0 }; uint8_t* pWritePos = pData; uint8_t* pageBuffer = malloc(pContext->pagesize); uint8_t* willWritePageBuffer = pageBuffer; int willWriteLen = pContext->pagesize; int pagepos = startpos % pContext->pagesize; for (i = startpage; i <= endpage; ++i) { if (i == startpage) { //处理头部 if (pagepos != 0) { //不是整页 GetPagePath(pContext, theMeta.dataPage.pPageArray[i], utf8path); FILE* pfPage = fopen(utf8path, "rb"); if (pfPage) { uint64_t pagesize = pContext->pagesize; ReadFileContentWithPos(pfPage, pageBuffer, &pagesize,sizeof(uint64_t)); fclose(pfPage); } else { printf("read page error\n"); free(pageBuffer); return -1; } } int copylen = pagepos + dataLen > pContext->pagesize ? pContext->pagesize - pagepos : dataLen; memcpy(pageBuffer + pagepos, pData, copylen); willWritePageBuffer = pageBuffer; } else if (i == endpage) { //处理尾部 willWriteLen = dataLen - (pContext->pagesize - pagepos); if (willWriteLen > 0) { willWriteLen = willWriteLen % pContext->pagesize; } else { willWriteLen = 0; } if (willWriteLen != pContext->pagesize) { //不是整页 GetPagePath(pContext, theMeta.dataPage.pPageArray[i], utf8path); FILE* pfPage = fopen(utf8path, "rb"); if (pfPage) { uint64_t pagesize = pContext->pagesize; ReadFileContentWithPos(pfPage, pageBuffer, &pagesize,sizeof(uint64_t)); fclose(pfPage); } else { printf("read page error\n"); free(pageBuffer); return -1; } memcpy(pageBuffer, pData + dataLen - willWriteLen, willWriteLen); willWritePageBuffer = pageBuffer; } else { willWritePageBuffer = pData + (pContext->pagesize - pagepos) + (i - startpage - 1) * pContext->pagesize; willWriteLen = pContext->pagesize; } } else { willWritePageBuffer = pData + (pContext->pagesize - pagepos) + (i - startpage - 1) * pContext->pagesize; willWriteLen = pContext->pagesize; } //把准备好的pagebuffer写入新的页面文件 uint64_t newPageIndex = 0; AllocNewPage(pContext, utf8path, &newPageIndex); FILE* pfPage = fopen(utf8path, "wb"); if (pfPage) { fwrite(&objid, sizeof(uint64_t), 1, pfPage); WriteFileContent(pfPage, willWritePageBuffer, willWriteLen); theMeta.dataPage.pPageArray[i] = newPageIndex; fclose(pfPage); } else { printf("write page error\n"); free(pageBuffer); return -1; } } free(pageBuffer); uint8_t utf8Path[257] = { 0 }; uint8_t utf8MetaPath[257] = { 0 }; GetNewObjPageListDataPath(pContext, utf8Path); FILE* pfPageList = fopen(utf8Path, "wb"); if (pfPageList) { int bufferSize = GetSizeOfPageList(&(theMeta.dataPage)); uint8_t *pBuffer = (uint8_t*)malloc(bufferSize); WritePageList(pContext, pBuffer, &(theMeta.dataPage)); WriteFileContent(pfPageList, pBuffer, bufferSize); fclose(pfPageList); free(pBuffer); GetObjMetaPath(pContext, objid, utf8MetaPath); FILE* pfMeta = fopen(utf8MetaPath, "wb"); if (pfMeta) { bufferSize = GetSizeOfObjMeta(pContext, &theMeta, utf8Path); pBuffer = (uint8_t*)malloc(bufferSize); WriteObjMeta(pContext, pBuffer, &theMeta, utf8Path); WriteFileContent(pfMeta, pBuffer, bufferSize); fclose(pfMeta); free(pBuffer); free(theMeta.dataPage.pPageArray); return 0; } else { printf("write meta error\n"); free(theMeta.dataPage.pPageArray); return -1; } } else { printf("write pagelist error\n"); free(theMeta.dataPage.pPageArray); return -1; } return -1; }
int UpdateObjData(ObjStoreContext* pContext, uint64_t objid, const uint8_t* pData, uint64_t dataLen) { ObjMeta theMeta; theMeta.objid = objid; theMeta.datalen = dataLen; int pagelen = dataLen / pContext->pagesize; if (dataLen % pContext->pagesize != 0) { pagelen = pagelen + 1; } theMeta.dataPage.listSize = pagelen; theMeta.dataPage.pPageArray = (uint64_t*)malloc(sizeof(uint64_t) * pagelen); int i = 0; uint64_t writePos = 0; for (i = 0; i < pagelen; ++i) { uint8_t pagepath[257] = { 0 }; uint64_t pageIndex = 0; AllocNewPage(pContext, pagepath, &pageIndex); FILE* pfPage = fopen(pagepath, "wb"); if (pfPage) { fwrite(&objid, sizeof(uint64_t), 1, pfPage); WriteFileContent(pfPage, pData + writePos, dataLen - writePos > pContext->pagesize ? pContext->pagesize : dataLen - writePos); fclose(pfPage); writePos += pContext->pagesize; theMeta.dataPage.pPageArray[i] = pageIndex; } else { free(theMeta.dataPage.pPageArray); printf("error\n"); } } uint8_t utf8Path[257] = { 0 }; uint8_t utf8MetaPath[257] = { 0 }; GetNewObjPageListDataPath(pContext, utf8Path); FILE* pfPageList = fopen(utf8Path, "wb"); if (pfPageList) { int bufferSize = GetSizeOfPageList(&(theMeta.dataPage)); uint8_t *pBuffer = (uint8_t*)malloc(bufferSize); WritePageList(pContext, pBuffer, &(theMeta.dataPage)); WriteFileContent(pfPageList, pBuffer, bufferSize); fclose(pfPageList); free(pBuffer); GetObjMetaPath(pContext, objid, utf8MetaPath); FILE* pfMeta = fopen(utf8MetaPath, "wb"); if (pfMeta) { //用前面的方法,解决meta可能过大的问题 bufferSize = GetSizeOfObjMeta(pContext, &theMeta, utf8Path); pBuffer = (uint8_t*)malloc(bufferSize); WriteObjMeta(pContext, pBuffer, &theMeta, utf8Path); WriteFileContent(pfMeta, pBuffer, bufferSize); free(pBuffer); free(theMeta.dataPage.pPageArray); fclose(pfMeta); return 0; } else { printf("write meta error\n"); free(theMeta.dataPage.pPageArray); return -1; } } else { printf("write pagelist error\n"); free(theMeta.dataPage.pPageArray); return -1; } free(theMeta.dataPage.pPageArray); return -1; }