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; }
static HEAP s_GetHeapCopy(TNCBI_Time now) { enum { eNone = 0, eAgain = 1, eFallback = 2 } retry = eNone; HEAP heap = 0; HEAP lbsm; for (;;) { const SLBSM_Version *c, *v; int serial = 0; CORE_LOCK_WRITE; if (s_Heap) { c = LBSM_GetVersion(s_Heap); assert(c && c->major == LBSM_HEAP_VERSION_MAJ); assert((void*) c == (void*) HEAP_Base(s_Heap)); if (c->entry.good < now) { #ifdef LBSM_DEBUG CORE_LOGF(eLOG_Trace, ("Cached LBSM heap[%p, %p, %d] expired, dropped", s_Heap, HEAP_Base(s_Heap), HEAP_Serial(s_Heap))); #endif /*LBSM_DEBUG*/ HEAP_Destroy(s_Heap); s_Heap = 0; } #ifdef LBSM_DEBUG else { CORE_LOGF(eLOG_Trace, ("Cached LBSM heap[%p, %p, %d] valid", s_Heap, HEAP_Base(s_Heap), HEAP_Serial(s_Heap))); } #endif /*LBSM_DEBUG*/ } else c = 0/*dummy for compiler not to complain*/; if (!(lbsm = LBSM_Shmem_Attach(retry == eFallback)) || (serial = HEAP_Serial(lbsm)) <= 0) { if (lbsm) { CORE_LOGF_X(1, eLOG_Error, ("Bad serial (%d) from LBSM heap attach", serial)); } /* else, an error has already been posted */ break; } if (!(v = LBSM_GetVersion(lbsm)) || (v->major < LBSM_HEAP_VERSION_MAJ || (v->major == LBSM_HEAP_VERSION_MAJ && v->minor < LBSM_HEAP_VERSION_MIN))) { if (v) { CORE_LOGF_X(2, eLOG_Error, ("LBSM heap[%d] version mismatch" " (current=%hu.%hu, expected=%u.%u+)", serial, v->major, v->minor, LBSM_HEAP_VERSION_MAJ, LBSM_HEAP_VERSION_MIN)); } else { CORE_LOGF_X(3, eLOG_Error, ("LBSM heap[%d] has no version", serial)); } break; } if (v->entry.good < now) { CORE_LOGF_X(4, eLOG_Warning, ("LBSM heap[%d] is out-of-date" " (current=%lu, expiry=%lu, delta=%lu)%s", serial, (unsigned long) now, (unsigned long) v->entry.good, (unsigned long) now -(unsigned long) v->entry.good, !retry && serial > 1 ? ", re-trying" : "")); if (!retry && serial > 1) { LBSM_Shmem_Detach(heap); retry = eFallback; CORE_UNLOCK; continue; } if (s_Heap) { #ifdef LBSM_DEBUG CORE_LOGF(eLOG_Trace, ("Cached LBSM heap[%p, %p, %d] dropped", s_Heap, HEAP_Base(s_Heap), HEAP_Serial(s_Heap))); #endif /*LBSM_DEBUG*/ HEAP_Destroy(s_Heap); s_Heap = 0; } break; } assert((void*) v == (void*) HEAP_Base(lbsm)); if (s_Heap) { if (c->count == v->count && c->cksum == v->cksum) { #ifdef LBSM_DEBUG CORE_LOGF(eLOG_Trace, ("Cached LBSM heap[%p, %p, %d] used", s_Heap, HEAP_Base(s_Heap), HEAP_Serial(s_Heap))); #endif /*LBSM_DEBUG*/ heap = s_Heap; break; } #ifdef LBSM_DEBUG CORE_LOGF(eLOG_Trace, ("Cached LBSM heap[%p, %p, %d] is stale, dropped", s_Heap, HEAP_Base(s_Heap), HEAP_Serial(s_Heap))); #endif /*LBSM_DEBUG*/ HEAP_Destroy(s_Heap); s_Heap = 0; } if (!(heap = HEAP_Copy(lbsm, 0, -serial))) { CORE_LOGF_ERRNO_X(6, eLOG_Error, errno, ("Unable to copy LBSM heap[%d]", serial)); break; } if (s_VerifyChecksum(heap, v->cksum)) { #ifdef LBSM_DEBUG CORE_LOGF(eLOG_Trace, ("Cached LBSM heap[%p, %p, %d] renewed", heap, HEAP_Base(heap), HEAP_Serial(heap))); #endif /*LBSM_DEBUG*/ s_Heap = heap; break; } CORE_LOGF_X(7, retry ? eLOG_Error : eLOG_Warning, ("LBSM heap[%p, %p, %d]%s checksum failure%s", (void*) heap, HEAP_Base(heap), HEAP_Serial(heap), retry == eAgain ? " persistent" : "", retry ? "" : ", re-trying")); verify(HEAP_Destroy(heap) == 0); heap = 0; if (retry) break; LBSM_Shmem_Detach(lbsm); retry = eAgain; CORE_UNLOCK; } assert(!heap || heap != lbsm); if (heap && heap == s_Heap) verify(HEAP_AddRef(s_Heap) > 1); LBSM_Shmem_Detach(lbsm); CORE_UNLOCK; return heap; }