/*ARGSUSED*/ static int/*bool*/ s_VerifyChecksum(const HEAP heap, unsigned int cksum) { #if defined(_DEBUG) && !defined(NDEBUG) const char* base = (const char*) HEAP_Base(heap); const SLBSM_Version* v = (const SLBSM_Version*) base; static const unsigned char kZero[sizeof(v->cksum)] = { 0 }; const char* stop = (const char*) &v->cksum; size_t len = (size_t)(stop - base); unsigned int (*update)(unsigned int cksum, const void* ptr, size_t len); unsigned int sum; if (s_Localhost(v)) { update = UTIL_Adler32_Update; sum = 1; } else { update = UTIL_CRC32_Update; sum = 0; } sum = (*update)(sum, base, len); sum = (*update)(sum, kZero, sizeof(v->cksum)); len = HEAP_Size(heap) - sizeof(v->cksum) - len; sum = (*update)(sum, stop + sizeof(v->cksum), len); return sum == v->cksum && sum == cksum; #else return 1/*success*/; #endif /*_DEBUG && !NDEBUG*/ }
unsigned int LBSM_Shmem_Update(HEAP heap, int/*bool*/ wait) { size_t heapsize = HEAP_Size(heap); void* heapbase = HEAP_Base(heap); unsigned int updated = 0; int i; assert(heapbase && heapsize); for (i = 0; i < 2; i++) { int can_wait = wait || (s_ShmemSize[i] && (!i || updated)); if (!s_Shmem_WLock(i, can_wait)) continue; /* Update shmem here: strict checks for the first time */ if (s_ShmemSize[i] != heapsize) { int shmid; void* shmem; s_Shmem_Destroy(i, s_ShmemSize[i] ? 0 : getpid()); if ((shmid = shmget(k_ShmemKey[i], heapsize, LBSM_SHM_PROT | IPC_CREAT | IPC_EXCL)) < 0 || !(shmem = shmat(shmid, 0, 0)) || shmem == (void*)(-1)) { CORE_LOGF_ERRNO_X(22, eLOG_Error, errno, ("Unable to re-create LBSM shmem[%d]", i + 1)); s_Shmem_WUnlock(i); return 0/*update failed*/; } s_Shmid[i] = shmid; s_Shmem[i] = shmem; s_ShmemSize[i] = heapsize; } memcpy(s_Shmem[i], heapbase, heapsize); if (!s_Shmem_WUnlock(i)) { CORE_LOGF_ERRNO_X(23, eLOG_Warning, errno, ("Update failed to unlock shmem[%d]", i + 1)); } updated |= 1 << i; } return updated; }
int main(int argc, const char* argv[]) { SHEAP_Block* blk; int r, j, i, n; HEAP heap; char* c; /* CORE_SetLOGFormatFlags(fLOG_None | fLOG_Level | fLOG_OmitNoteLevel); */ CORE_SetLOGFILE(stderr, 0/*false*/); if (argc > 1) g_NCBI_ConnectRandomSeed = atoi(argv[1]); else g_NCBI_ConnectRandomSeed = (int) time(0) ^ NCBI_CONNECT_SRAND_ADDEND; CORE_LOGF(eLOG_Note, ("Using seed %d", g_NCBI_ConnectRandomSeed)); HEAP_Options(eOff/*slow*/, eOn/*newalk*/); srand(g_NCBI_ConnectRandomSeed); for (j = 1; j <= 3; j++) { CORE_LOGF(eLOG_Note, ("Creating heap %d", j)); if (!(heap = HEAP_Create(0, 0, 4096, s_Expand, 0))) CORE_LOG(eLOG_Error, "Cannot create heap"); for (n = 0; n < 1000 && (rand() & 0xFFFF) != 0x1234; n++) { r = rand() & 7; if (r == 1 || r == 3) { int/*bool*/ fast = rand() & 1; i = rand() & 0xFF; if (i) { CORE_LOGF(eLOG_Note, ("Allocating%s data size %d", fast ? " fast" : "", i)); blk = fast ? HEAP_AllocFast(heap, i) : HEAP_Alloc(heap, i); if (blk) { CORE_LOGF(eLOG_Note, ("Done @%u, size %u", HEAP_ADDR(blk, heap), blk->size)); } else CORE_LOG(eLOG_Error, "Allocation failed"); c = (char*) blk + sizeof(*blk); while (i--) *c++ = rand(); s_Walk(heap, 0); } else { assert(!(fast ? HEAP_AllocFast(heap, i) : HEAP_Alloc(heap, i))); } } else if (r == 2 || r == 4) { blk = 0; do { if (!(blk = HEAP_Walk(heap, blk))) break; } while (rand() & 7); if (blk && (short) blk->flag) { unsigned size = blk->size; unsigned data_size = size - sizeof(*blk); CORE_LOGF(eLOG_Note, ("Freeing @%u, size %u, data size %u", HEAP_ADDR(blk, heap), size, data_size)); assert(data_size); HEAP_Free(heap, blk); CORE_LOG(eLOG_Note, "Done"); s_Walk(heap, 0); } } else if (r == 5) { const SHEAP_Block* prev = 0; unsigned ok = 0; blk = 0; for (;;) { if (!(blk = HEAP_Walk(heap, blk))) break; if ((short) blk->flag && (rand() & 7)) { char buf[32]; unsigned size = blk->size; int/*bool*/ fast = rand() & 1; unsigned data_size = size - sizeof(*blk); if (!fast || !prev) *buf = '\0'; else sprintf(buf, ", prev @%u", HEAP_ADDR(prev, heap)); CORE_LOGF(eLOG_Note, ("Freeing%s%s @%u%s in walk," " size %u, data size %u", fast ? " fast" : "", ok ? " more" : "", HEAP_ADDR(blk,heap), buf, size, data_size)); assert(data_size); if (fast) HEAP_FreeFast(heap, blk, prev); else HEAP_Free(heap, blk); CORE_LOG(eLOG_Note, "Done"); s_Walk(heap, 0); ok = 1; if (prev && !((short) prev->flag)) continue; } prev = blk; } if (!ok) s_Walk(heap, "the"); else CORE_LOG(eLOG_Note, "Done with freeing while walking"); } else if (r == 6 || r == 7) { HEAP newheap; if (r == 6) { int/*bool*/ fast = rand() & 1; if (fast) { CORE_LOG(eLOG_Note, "Attaching heap fast"); newheap = HEAP_AttachFast(HEAP_Base(heap), HEAP_Size(heap), 0); } else { CORE_LOG(eLOG_Note, "Attaching heap"); newheap = HEAP_Attach(HEAP_Base(heap), 0); } } else { CORE_LOG(eLOG_Note, "Copying heap"); newheap = HEAP_Copy(heap, 0, 0); } if (!newheap) { CORE_LOGF(eLOG_Error, ("%s failed", r == 6 ? "Attach" : "Copy")); } else s_Walk(newheap, r == 6 ? "attached" : "copied"); HEAP_Detach(newheap); } else { TNCBI_Size size = HEAP_Size(heap); HEAP newheap; CORE_LOG(eLOG_Note, "Trimming heap"); newheap = HEAP_Trim(heap); CORE_LOGF(eLOG_Note, ("Heap %strimmed: %u -> %u", newheap ? "" : "NOT ", size, HEAP_Size(newheap))); if (newheap) { heap = newheap; s_Walk(heap, "trimmed"); } } } HEAP_Destroy(heap); CORE_LOGF(eLOG_Note, ("Heap %d done", j)); } CORE_LOG(eLOG_Note, "Test completed"); CORE_SetLOG(0); return 0; }