Example #1
0
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;
}
Example #2
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;
}