コード例 #1
0
/*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*/
}
コード例 #2
0
const char* LBSMD_GetConfig(void)
{
    const char* s = 0;
    HEAP heap;

    if (LBSM_LBSMD(0) > 0  &&  errno == EAGAIN) {
        if ((heap = s_GetHeapCopy(time(0))) != 0) {
            if ((s = LBSM_GetConfig(heap)) != 0)
                s = strdup(s);
#ifdef LBSM_DEBUG
            CORE_LOGF(eLOG_Trace,
                      ("LBSM heap[%p, %p, %d] released",
                       heap, HEAP_Base(heap), HEAP_Serial(heap)));
#endif /*LBSM_DEBUG*/
            CORE_LOCK_WRITE;
            HEAP_Detach(heap);
            CORE_UNLOCK;
        }
    }
    if (!s_FastHeapAccess) {
        /* As a documented side effect, clean up cached copy of LBSM heap */
        s_Fini();
    }
    return s;
}
コード例 #3
0
static unsigned int s_GetLocalHostAddress(HEAP heap)
{
    unsigned int localhost;
    const SLBSM_Version* v = (const SLBSM_Version*) HEAP_Base(heap);
    assert(v->entry.type == eLBSM_Version);
    if (!(localhost = s_Localhost(v)))
        localhost = SOCK_GetLocalHostAddress(eDefault);
    return localhost;
}
コード例 #4
0
static void s_Fini(void)
{
    if (s_Heap) {
        CORE_LOCK_WRITE;
        if (s_Heap) {
#ifdef LBSM_DEBUG
            CORE_LOGF(eLOG_Trace,
                      ("Cached LBSM heap[%p, %p, %d] destroyed",
                       s_Heap, HEAP_Base(s_Heap), HEAP_Serial(s_Heap)));
#endif /*LBSM_DEBUG*/
            HEAP_Destroy(s_Heap);
            s_Heap = 0;
        }
        CORE_UNLOCK;
    }
    LBSM_UnLBSMD(-1);
}
コード例 #5
0
static void s_Close(SERV_ITER iter)
{
    if (iter->data) {
#ifdef LBSM_DEBUG
        CORE_LOGF(eLOG_Trace,
                  ("LBSM heap[%p, %p, %d] for \"%s\" deleted",
                   iter->data, HEAP_Base((HEAP) iter->data),
                   HEAP_Serial((HEAP) iter->data), iter->name));
#endif /*LBSM_DEBUG*/
        CORE_LOCK_WRITE;
        HEAP_Detach((HEAP) iter->data);
        CORE_UNLOCK;
        iter->data = 0;
    }
    if (!s_FastHeapAccess)
        LBSM_UnLBSMD(-1);
}
コード例 #6
0
HEAP LBSM_Shmem_Attach(void)
{
    int  fallback = 0; /*FIXME: to become a parameter*/
    int  which;
    HEAP heap;

#ifdef LBSM_DEBUG
    CORE_LOG(eLOG_Trace, "LBSM ATTACHING%s", fallback ? " (fallback)" : "");
#endif /*LBSM_DEBUG*/
    if ((which = s_Shmem_RLock(!fallback)) < 0) {
        CORE_LOG_ERRNO_X(10, eLOG_Warning, errno,
                         "Cannot lock LBSM shmem to attach");
        return 0;
    }
#ifdef LBSM_DEBUG
    CORE_LOGF(eLOG_Trace, ("LBSM R-lock[%d] acquired", which + 1));
#endif /*LBSM_DEBUG*/
    if (!(heap = s_Shmem_Attach(which))) {
        int/*bool*/ attached = s_Shmem[which] != 0 ? 1/*true*/ : 0/*false*/;
        s_Shmem_RUnlock(which);
        CORE_LOGF_ERRNO_X(11, eLOG_Error, errno,
                          ("Cannot %s LBSM shmem[%d]",
                           attached ? "access" : "attach", which + 1));
    }
#ifdef LBSM_DEBUG
    else {
        CORE_LOGF(eLOG_Trace,
                  ("LBSM heap[%p, %p, %d] attached",
                   heap, HEAP_Base(heap), which + 1));
        assert(HEAP_Serial(heap) == which + 1);
    }
#endif /*LBSM_DEBUG*/
    if (s_Shmem[which = !which]) {
#ifdef LBSM_DEBUG
        CORE_LOGF(eLOG_Trace, ("LBSM shmem[%d] detached", which + 1));
#endif /*LBSM_DEBUG*/
        shmdt(s_Shmem[which]);
        s_Shmem[which] =  0;
        s_Shmid[which] = -1;
    } else
        assert(s_Shmid[which] < 0);
    s_ShmemSize[which] =  0;
    return heap;
}
コード例 #7
0
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;
}
コード例 #8
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;
}
コード例 #9
0
static SSERV_Info* s_GetNextInfo(SERV_ITER iter, HOST_INFO* host_info)
{
    const TSERV_Type types = iter->types & ~fSERV_Firewall;
    size_t i, n, idx[eHost_NoMatch], n_cand, a_cand;
    EHost_Match best_match, match;
    struct SLBSM_Candidate* cand;
    const SLBSM_Service* svc;
    TNCBI_Time dns_info_time;
    const SLBSM_Host* host;
    const char* env, *a;
    SSERV_Info* info;
    const char* name;
    double status;
    int standby;
    HEAP heap;
    char* v;

    heap = (HEAP)(iter->data != iter ? iter->data : 0);
    if (heap) {
#ifdef LBSM_DEBUG
        CORE_LOGF(eLOG_Trace,
                  ("LBSM heap[%p, %p, %d] for \"%s\" detected",
                   heap, HEAP_Base(heap), HEAP_Serial(heap), iter->name));
#endif /*LBSM_DEBUG*/
        /*noop*/;
    } else if (!(heap = s_GetHeapCopy(iter->time))) {
        return iter->external  ||  iter->data == iter  ||  !(types & fSERV_Dns)
            ? 0 : s_FakeDnsReturn(iter, host_info, 0, NCBI_TIME_INFINITE);
    }

    best_match = eHost_InitMatch;
    memset(idx, 0, sizeof(idx));
    standby = -1/*unassigned*/;
    dns_info_time = 0/*none*/;
    n = n_cand = a_cand = 0;
    a = v = 0;
    cand = 0;
    svc = 0;

    name = *iter->name ? iter->name : 0;
    assert(name  ||  iter->ismask); /*NB: ismask ignored for NULL*/
    while ((svc = LBSM_LookupService(heap, name, iter->ismask, svc))) {
        if (svc->entry.good < iter->time)
            continue; /* out-of-date entry */

        if (!svc->info.time)
            continue; /* off */

        if (types != fSERV_Any  &&  !(types & svc->info.type))
            continue; /* type doesn't match */

        if (iter->external  &&  svc->info.locl)
            continue; /* external mapping requested; local/private server */

        if (svc->info.locl & 0xF0) {
            /* private server */
            if (svc->info.host  &&
                svc->info.host != s_GetLocalHostAddress(heap)) {
                continue;
            }
        }

        if (svc->info.type == fSERV_Dns) {
            if (types == fSERV_Any)
                continue; /* DNS entries have to be requested explicitly */
            if (!iter->ismask) {
                if (dns_info_time < svc->info.time)
                    dns_info_time = svc->info.time;
            }
        } else {
            if (iter->stateless  &&  svc->info.sful) {
                /* Skip stateful-only non-CGI (NCBID and standalone) svc */
                if (!(svc->info.type & fSERV_Http))
                    continue;
            }
            if (!iter->ismask  &&  iter->reverse_dns) {
                if (dns_info_time < svc->info.time)
                    dns_info_time = svc->info.time;
            }
        }

        if (svc->info.rate > 0.0  ||  host_info) {
            if (!(host = s_LookupHost(heap, iter, svc))
                &&  svc->info.rate > 0.0) {
                continue; /* no host information for non-static server */
            }
        } else
            host = 0;

        for (n = 0;  n < iter->n_skip;  n++) {
            const SSERV_Info* skip = iter->skip[n];
            const char* s = SERV_NameOfInfo(skip);
            if (*s) {
                assert(iter->ismask  ||  iter->reverse_dns);
                if (strcasecmp(s, (const char*) svc + svc->name) == 0
                    &&  ((skip->type == fSERV_Dns  &&  !skip->host)
                         ||  SERV_EqualInfo(skip, &svc->info))) {
                    break;
                }
            } else if (SERV_EqualInfo(skip, &svc->info))
                break;
            if (skip->type == fSERV_Firewall
                &&  skip->u.firewall.type == svc->info.type) {
                break;
            }
            if (iter->reverse_dns  &&  skip->type == fSERV_Dns
                &&  skip->host == svc->info.host
                &&  (!skip->port  ||  skip->port == svc->info.port)) {
                break;
            }
        }
        /*FIXME*//*CORE_LOG(eLOG_Note, (char*) svc + svc->name);*/
        if (n >= iter->n_skip) {
            status = LBSM_CalculateStatus(svc->info.rate, svc->fine,
                                          svc->info.flag, &host->sys.load);
            if (status <= 0.0) {
                if (!svc->info.rate) {
                    if (!iter->ok_down)
                        continue; /* not operational */
                    status = 0.0;
                } else
                    status = copysign(svc->info.rate, -1.0);
            }
        } else
            status = 0.0; /* dummy assignment to keep no-init warning off */

        if (v) {
            free(v);
            v = 0;
        }
        a = env = 0;
        if (iter->pref < 0.0  &&  iter->host
            &&  (iter->host != svc->info.host
                 ||  (iter->port  &&  iter->port != svc->info.port))) {
            /* not a suitable fixed latching */
            match = eHost_BadMatch;
        } else if (iter->arglen) {
            assert(iter->arg);
            if (!host)
                host = s_LookupHost(heap, iter, svc);
            if ( host  &&  host->env)
                env = (const char*) host + host->env;
            match = s_Match(env,
                            iter->arg, iter->arglen,
                            iter->val, iter->vallen, &a, &v);
            assert(!a  ||  a == iter->arg);
        } else
            match = eHost_GoodMatch;

        if (best_match > match)
            best_match = match;

        if (match > eHost_NoMatch) {
            assert(!v);
            continue;
        }

        if (svc->info.rate) {
            /* NB: server is _not_ down, but it may have been suppressed */
            if (fabs(svc->info.rate) < 0.01) {
                if (!standby) {
                    if (!iter->ok_suppressed)
                        continue;
                    /* this has to be given out as a suppressed one */
                    status = copysign(svc->info.rate, -1.0);
                } else if (standby < 0)
                    standby = 1;
            } else if (standby) {
                standby = 0/*cancel*/;
                if (!iter->ok_suppressed) {
                    memset(idx, 0, sizeof(idx));
                    for (i = 0;  i < n_cand;  i++) {
                        if (cand[i].val)
                            free((void*) cand[i].val);
                    }
                    n_cand = 0;
                } else for (i = 0;  i < n_cand;  i++)
                    cand[i].cand.status = copysign(cand[i].svc->info.rate,-1.);
            }
        }

        if (n < iter->n_skip)
            continue; /* excluded/seen;  NB: dummy assignment goes off here */

        if (!iter->ok_suppressed  &&  status < 0.0)
            continue;

#ifdef NCBI_LB_DEBUG
        if (iter->arglen) {
            char* s = SERV_WriteInfo(&svc->info);
            const char* m;
            assert(s);
            switch (match) {
            case eHost_BestMatch:
                m = "Best match";
                break;
            case eHost_GoodMatch:
                m = "Good match";
                break;
            case eHost_FairMatch:
                m = "Fair match";
                break;
            case eHost_PoorMatch:
                m = "Poor match";
                break;
            case eHost_NoMatch:
                m = "No match";
                break;
            default:
                assert(0);
                m = "?";
                break;
            }
            assert(!a  || *a);
            assert(!v  ||  a);
            CORE_LOGF(eLOG_Note, ("%s%s%s%s: %s%s%s%s%s%s", s,
                                  env ? " <" : "", env ? env : "",
                                  env ? ">"  : "", m,
                                  a   ? ", arg="             : "",
                                  a   ? a                    : "",
                                  v   ? ", val="             : "",
                                  v   ? (*v ? v : "\"\"")    : "",
                                  standby > 0 ? ", standby"  : ""));
            free(s);
        }
#endif /*NCBI_LB_DEBUG*/

        /* This server should be taken into consideration */
        if (n_cand == a_cand) {
            struct SLBSM_Candidate* temp;
            n = a_cand + 10;
            temp = (struct SLBSM_Candidate*)
                (cand
                 ? realloc(cand, n * sizeof(*temp))
                 : malloc (      n * sizeof(*temp)));
            if (!temp)
                break;
            cand = temp;
            a_cand = n;
        }

        if (match < eHost_NoMatch) {
            assert((size_t) match < sizeof(idx)/sizeof(idx[0]));
            n = idx[match];
            if (n < n_cand)
                memmove(&cand[n + 1], &cand[n], sizeof(cand[0])*(n_cand - n));
            for (i = match;  i < sizeof(idx)/sizeof(idx[0]);  i++)
                idx[i]++;
        } else
            n = n_cand;
        cand[n].cand.info   = &svc->info;
        cand[n].cand.status = status;
        cand[n].host        = host;
        cand[n].svc         = svc;
        cand[n].arg         = a;
        cand[n].val         = v;
        a = v = 0;
        n_cand++;
    }
    if (v)
        free(v);

    if (best_match < eHost_NoMatch) {
        assert(!best_match  ||  !idx[best_match - 1]);
        for (n = idx[best_match];  n < n_cand;  n++) {
            if (cand[n].val)
                free((void*) cand[n].val);
        }
        n_cand = idx[best_match];
    }
    if (n_cand) {
        assert(cand);
        do {
            if (standby <= 0) {
                struct SLBSM_Data data;
                data.cand   = cand;
                data.n_cand = n_cand;
                n = LB_Select(iter, &data, s_GetCandidate, LBSMD_LOCAL_BONUS);
            } else {
                qsort(cand, n_cand, sizeof(*cand), s_SortStandbys);
                status = cand[0].cand.status;
                for (n = 1;  n < n_cand;  n++) {
                    if (status != cand[n].cand.status)
                        break;
                }
                n = rand() % n;
            }
            svc = cand[n].svc;
            if (iter->reverse_dns  &&  svc->info.type != fSERV_Dns) {
                svc = 0;
                dns_info_time = 0/*none*/;
                while ((svc = LBSM_LookupService(heap, 0/*all*/, 0, svc)) !=0){
                    if (svc->info.type != fSERV_Dns  ||  !svc->info.time  ||
                        svc->info.host != cand[n].svc->info.host          ||
                        svc->info.port != cand[n].svc->info.port) {
                        continue;
                    }
                    if (!iter->ismask) {
                        if (dns_info_time < svc->info.time)
                            dns_info_time = svc->info.time;
                    }
                    if (iter->external  &&  svc->info.locl)
                        continue;/* external mapping requested; local server */
                    assert(!(svc->info.locl & 0xF0)); /* no private DNS */
                    status = LBSM_CalculateStatus(!svc->info.rate ? 0.0
                                                  : -LBSM_DEFAULT_RATE,
                                                  svc->fine, fSERV_Regular,
                                                  NULL);
                    if (status > 0.0)
                        break;
                    if ((!svc->info.rate  &&  iter->ok_down)  ||
                        ( svc->info.rate  &&  iter->ok_suppressed)) {
                        cand[n].cand.status = !svc->info.rate ? 0.0
                            : copysign(svc->info.rate, -1.0);
                        break;
                    }
                }
                if (!svc  &&  !dns_info_time)
                    svc = cand[n].svc;
            }
            if (svc)
                break;
            if (cand[n].val)
                free((void*) cand[n].val);
            if (n < --n_cand)
                memmove(cand + n, cand + n + 1, (n_cand - n) * sizeof(*cand));
        } while (n_cand);
    } else
        svc = 0;

    if (svc) {
        const char* name = (iter->ismask  ||  iter->reverse_dns ?
                            (const char*) svc + svc->name : "");
        if ((info = SERV_CopyInfoEx(&svc->info, name)) != 0) {
            info->rate = cand[n].cand.status;
            if (info->time != NCBI_TIME_INFINITE)
                info->time  = cand[n].svc->entry.good;
            if (host_info) {
                if ((host = cand[n].host) != 0) {
                    *host_info =
                        HINFO_Create(host->addr, &host->sys, sizeof(host->sys),
                                     host->env
                                     ? (const char*) host + host->env
                                     : 0, cand[n].arg, cand[n].val);
                } else
                    *host_info = 0;
            }
        }
    } else {
        info = !n_cand  &&  dns_info_time
            ? s_FakeDnsReturn(iter, host_info,
                              best_match == eHost_InitMatch ?  0/*down*/ :
                              best_match != eHost_BadMatch  ? -1/*busy*/ : 1,
                              dns_info_time)
            : 0;
    }

    for (n = 0;  n < n_cand;  n++) {
        if (cand[n].val)
            free((void*) cand[n].val);
    }
    if (cand)
        free(cand);

    if (!s_FastHeapAccess) {
#ifdef LBSM_DEBUG
        CORE_LOGF(eLOG_Trace,
                  ("LBSM heap[%p, %p, %d] for \"%s\" released",
                   heap, HEAP_Base(heap), HEAP_Serial(heap), iter->name));
#endif /*LBSM_DEBUG*/
        CORE_LOCK_WRITE;
        HEAP_Detach(heap);
        CORE_UNLOCK;
        heap = 0;
    }
#ifdef LBSM_DEBUG
    else {
        CORE_LOGF(eLOG_Trace,
                  ("LBSM heap[%p, %p, %d] for \"%s\" retained",
                   heap, HEAP_Base(heap), HEAP_Serial(heap), iter->name));
    }
#endif /*LBSM_DEBUG*/
    iter->data = heap;

    return info;
}
コード例 #10
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;
}