/*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*/ }
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; }
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; }
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); }
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); }
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; }
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; }
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; }
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; }