ugh_header_t *ugh_subreq_header_get(ugh_subreq_t *r, const char *data, size_t size) { void **dest = JudyLGet(r->headers_hash, aux_hash_key_lc_header(data, size), PJE0); if (PJERR == dest || NULL == dest) return &ugh_empty_header; return *dest; }
strp ugh_client_getvar_nt(ugh_client_t *c, const char *data) { void **dest = JudyLGet(c->vars_hash, aux_hash_key_nt(data), PJE0); if (PJERR == dest || NULL == dest) return &aux_empty_string; return *dest; }
ugh_header_t *ugh_client_header_get_nt(ugh_client_t *c, const char *data) { void **dest = JudyLGet(c->headers_hash, aux_hash_key_lc_header_nt(data), PJE0); if (PJERR == dest || NULL == dest) return &ugh_empty_header; return *dest; }
strp ugh_client_body_getarg(ugh_client_t *c, const char *data, size_t size) { void **dest = JudyLGet(c->body_hash, aux_hash_key(data, size), PJE0); if (PJERR == dest || NULL == dest) return &aux_empty_string; return *dest; }
gc_shape_t *flx_collector_t::get_shape(void *memory) { assert(memory); //fprintf(stderr, "Get shape of %p\n",memory); Word_t *pshape= (Word_t*)JudyLGet(j_shape,(Word_t)memory,&je); if(pshape==(Word_t*)PPJERR)judyerror("get_shape"); if(pshape==NULL) abort(); return (gc_shape_t*)(*pshape & (~1ul)); }
// max number of available slots in an array unsigned long flx_collector_t::get_count(void *memory) { assert(memory); //fprintf(stderr, "Get count of %p\n",memory); Word_t *p = (Word_t*)(void*)JudyLGet(j_nalloc,(Word_t)memory,&je); if(p==(Word_t*)PPJERR)judyerror("get_count"); //fprintf(stderr, "Count slot at address %p\n",p); unsigned long z = p!=NULL?*p:1; // defaults to 1 for non-array support //fprintf(stderr,"Count of %p is %ld\n",memory,z); return z; }
static strp ugh_variable_map_handle(ugh_client_t *c, const char *name, size_t size, void *data) { ugh_module_map_conf_t *conf = data; strp vv = ugh_get_varvalue(c, conf->key.data, conf->key.size); void **dest; dest = JudyLGet(conf->hash, aux_hash_key(vv->data, vv->size), PJE0); if (PJERR == dest || NULL == dest) return &conf->default_value; return *dest; }
void flx_collector_t::incr_used(void *memory, unsigned long n) { assert(memory); assert(n>=0); //fprintf(stderr,"Incr used of %p by %ld\n",memory,n); assert(get_used(memory) + n <= get_count(memory)); Word_t *p = (Word_t*)(void*)JudyLGet(j_nused,(Word_t)memory,&je); if(p==(Word_t*)PPJERR)judyerror("incr_used"); if(p==NULL) { //fprintf(stderr,"incr_used: No recorded usage! Creating store for data\n"); p = (Word_t*)(void*)JudyLIns(&j_nused,(Word_t)memory,&je); if(p==(Word_t*)PPJERR)judyerror("incr_used: new slot"); *p = n; } else *p+=n; }
void flx_collector_t::set_used(void *memory, unsigned long n) { assert(memory); assert(n>=0); // this check is expensive, but set_used is not used often assert(n<=get_count(memory)); //fprintf(stderr,"Set used of %p to %ld\n",memory,n); Word_t *p = (Word_t*)(void*)JudyLGet(j_nused,(Word_t)memory,&je); if(p==(Word_t*)PPJERR)judyerror("set_used"); if(p==NULL) { //fprintf(stderr,"set_used: No recorded usage! Creating store for data\n"); p = (Word_t*)(void*)JudyLIns(&j_nused,(Word_t)memory,&je); } //fprintf(stderr,"Slot for %p usage is address %p\n",memory,p); *p = (Word_t)n; }
FUNCTION Word_t JUDY_EXTERN Judy1Count #else FUNCTION Word_t JUDY_EXTERN JudyLCount #endif ( Pcvoid_t PArray, // JRP to first branch/leaf in SM. Word_t Index1, // starting Index. Word_t Index2, // ending Index. PJError_t PJError // optional, for returning error info. ) { jpm_t fakejpm; // local temporary for small arrays. Pjpm_t Pjpm; // top JPM or local temporary for error info. jp_t fakejp; // constructed for calling j__udy1LCountSM(). Pjp_t Pjp; // JP to pass to j__udy1LCountSM(). Word_t pop1; // total for the array. Word_t pop1above1; // indexes at or above Index1, inclusive. Word_t pop1above2; // indexes at or above Index2, exclusive. int retcode; // from Judy*First() calls. JUDYLCODE(PPvoid_t PPvalue); // from JudyLFirst() calls. // CHECK FOR SHORTCUTS: // // As documented, return C_JERR if the Judy array is empty or Index1 > Index2. if ((PArray == (Pvoid_t) NULL) || (Index1 > Index2)) { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } // If Index1 == Index2, simply check if the specified Index is set; pass // through the return value from Judy1Test() or JudyLGet() with appropriate // translations. if (Index1 == Index2) { #ifdef JUDY1 retcode = Judy1Test(PArray, Index1, PJError); if (retcode == JERRI) return(C_JERR); // pass through error. if (retcode == 0) { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } #else PPvalue = JudyLGet(PArray, Index1, PJError); if (PPvalue == PPJERR) return(C_JERR); // pass through error. if (PPvalue == (PPvoid_t) NULL) // Index is not set. { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } #endif return(1); // single index is set. } // CHECK JRP TYPE: // // Use an if/then for speed rather than a switch, and put the most common cases // first. // // Note: Since even cJU_LEAFW types require counting between two Indexes, // prepare them here for common code below that calls j__udy1LCountSM(), rather // than handling them even more specially here. if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW { Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf. Pjpm = & fakejpm; Pjp = & fakejp; Pjp->jp_Addr = (Word_t) Pjlw; Pjp->jp_Type = cJU_LEAFW; Pjpm->jpm_Pop0 = Pjlw[0]; // from first word of leaf. pop1 = Pjpm->jpm_Pop0 + 1; } else { Pjpm = P_JPM(PArray); Pjp = &(Pjpm->jpm_JP); pop1 = (Pjpm->jpm_Pop0) + 1; // note: can roll over to 0. #if (defined(JUDY1) && (! defined(JU_64BIT))) if (pop1 == 0) // rare special case of full array: { Word_t count = Index2 - Index1 + 1; // can roll over again. if (count == 0) { JU_SET_ERRNO(PJError, JU_ERRNO_FULL); return(C_JERR); } return(count); } #else assert(pop1); // JudyL or 64-bit cannot create a full array! #endif } // COUNT POP1 ABOVE INDEX1, INCLUSIVE: assert(pop1); // just to be safe. if (Index1 == 0) // shortcut, pop1above1 is entire population: { pop1above1 = pop1; } else // find first valid Index above Index1, if any: { #ifdef JUDY1 if ((retcode = Judy1First(PArray, & Index1, PJError)) == JERRI) return(C_JERR); // pass through error. #else if ((PPvalue = JudyLFirst(PArray, & Index1, PJError)) == PPJERR) return(C_JERR); // pass through error. retcode = (PPvalue != (PPvoid_t) NULL); // found a next Index. #endif // If theres no Index at or above Index1, just return C_JERR (early exit): if (retcode == 0) { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } // If a first/next Index was found, call the counting motor starting with that // known valid Index, meaning the return should be positive, not C_JERR except // in case of a real error: if ((pop1above1 = j__udy1LCountSM(Pjp, Index1, Pjpm)) == C_JERR) { JU_COPY_ERRNO(PJError, Pjpm); // pass through error. return(C_JERR); } } // COUNT POP1 ABOVE INDEX2, EXCLUSIVE, AND RETURN THE DIFFERENCE: // // In principle, calculate the ordinal of each Index and take the difference, // with caution about off-by-one errors due to the specified Indexes being set // or unset. In practice: // // - The ordinals computed here are inverse ordinals, that is, the populations // ABOVE the specified Indexes (Index1 inclusive, Index2 exclusive), so // subtract pop1above2 from pop1above1, rather than vice-versa. // // - Index1s result already includes a count for Index1 and/or Index2 if // either is set, so calculate pop1above2 exclusive of Index2. // // TBD: If Index1 and Index2 fall in the same expanse in the top-state // branch(es), would it be faster to walk the SM only once, to their divergence // point, before calling j__udy1LCountSM() or equivalent? Possibly a non-issue // if a top-state pop1 becomes stored with each Judy1 array. Also, consider // whether the first call of j__udy1LCountSM() fills the cache, for common tree // branches, for the second call. // // As for pop1above1, look for shortcuts for special cases when pop1above2 is // zero. Otherwise call the counting "motor". assert(pop1above1); // just to be safe. if (Index2++ == cJU_ALLONES) return(pop1above1); // Index2 at limit. #ifdef JUDY1 if ((retcode = Judy1First(PArray, & Index2, PJError)) == JERRI) return(C_JERR); #else if ((PPvalue = JudyLFirst(PArray, & Index2, PJError)) == PPJERR) return(C_JERR); retcode = (PPvalue != (PPvoid_t) NULL); // found a next Index. #endif if (retcode == 0) return(pop1above1); // no Index above Index2. // Just as for Index1, j__udy1LCountSM() cannot return 0 (locally == C_JERR) // except in case of a real error: if ((pop1above2 = j__udy1LCountSM(Pjp, Index2, Pjpm)) == C_JERR) { JU_COPY_ERRNO(PJError, Pjpm); // pass through error. return(C_JERR); } if (pop1above1 == pop1above2) { JU_SET_ERRNO(PJError, JU_ERRNO_NONE); return(C_JERR); } return(pop1above1 - pop1above2); } // Judy1Count() / JudyLCount()
int JudyLDel(void **PPArray, uint32_t Index, void **PPvalue) { Word_t pop1; int offset; void **PPret; if (PPArray == NULL) { JL_SET_ERRNO(JLE_NULLPPARRAY); return JERR; } if ((PPret = JudyLGet(*PPArray, Index)) == PPJERR) return JERR; if (PPret == NULL) return 0; if (PPvalue) *PPvalue = *PPret; if (JL_LEAFW_POP0(*PPArray) < cJL_LEAFW_MAXPOP1) { Pjv_t Pjv; Pjv_t Pjvnew; Pjlw_t Pjlw = P_JLW(*PPArray); Pjlw_t Pjlwnew; pop1 = Pjlw[0] + 1; if (pop1 == 1) { judyLFreeJLW(Pjlw, /* pop1 = */ 1, NULL); *PPArray = NULL; return 1; } offset = judySearchLeafW(Pjlw + 1, pop1, Index); assert(offset >= 0); Pjv = JL_LEAFWVALUEAREA(Pjlw, pop1); if (JL_LEAFWGROWINPLACE(pop1 - 1)) { JL_DELETEINPLACE(Pjlw + 1, pop1, offset, ignore); JL_DELETEINPLACE(Pjv, pop1, offset, ignore); --(Pjlw[0]); return 1; } Pjlwnew = judyLAllocJLW(pop1 - 1); JL_CHECKALLOC(Pjlw_t, Pjlwnew, JERR); Pjlwnew[0] = (pop1 - 1) - 1; JL_DELETECOPY(Pjlwnew + 1, Pjlw + 1, pop1, offset, ignore); Pjvnew = JL_LEAFWVALUEAREA(Pjlwnew, pop1 - 1); JL_DELETECOPY(Pjvnew, Pjv, pop1, offset, ignore); judyLFreeJLW(Pjlw, pop1, NULL); *PPArray = (void *) Pjlwnew; return 1; } else { Word_t digit; Pjv_t Pjv; Pjlw_t Pjlwnew; Pjpm_t Pjpm = P_JPM(*PPArray); Pjp_t Pjp = &(Pjpm->jpm_JP); assert(((Pjpm->jpm_JP.jp_Type) == cJL_JPBRANCH_L) || ((Pjpm->jpm_JP.jp_Type) == cJL_JPBRANCH_B) || ((Pjpm->jpm_JP.jp_Type) == cJL_JPBRANCH_U)); if (judyDelWalk(Pjp, Index, cJL_ROOTSTATE, Pjpm) == -1) return JERR; --(Pjpm->jpm_Pop0); if ((Pjpm->jpm_Pop0 + 1) != cJL_LEAFW_MAXPOP1) return 1; Pjlwnew = judyLAllocJLW(cJL_LEAFW_MAXPOP1); JL_CHECKALLOC(Pjlw_t, Pjlwnew, JERR); *PPArray = (void *) Pjlwnew; Pjv = JL_LEAFWVALUEAREA(Pjlwnew, cJL_LEAFW_MAXPOP1); *Pjlwnew++ = cJL_LEAFW_MAXPOP1 - 1; switch (JL_JPTYPE(Pjp)) { case cJL_JPBRANCH_L: { Pjbl_t PjblRaw = (Pjbl_t) (Pjp->jp_Addr); Pjbl_t Pjbl = P_JBL(PjblRaw); for (offset = 0; offset < Pjbl->jbl_NumJPs; ++offset) { pop1 = judyLeafM1ToLeafW(Pjlwnew, Pjv, (Pjbl->jbl_jp) + offset, JL_DIGITTOSTATE(Pjbl->jbl_Expanse [offset], cJL_BYTESPERWORD), (void *) Pjpm); Pjlwnew += pop1; Pjv += pop1; } judyLFreeJBL(PjblRaw, Pjpm); break; } case cJL_JPBRANCH_B: { Pjbb_t PjbbRaw = (Pjbb_t) (Pjp->jp_Addr); Pjbb_t Pjbb = P_JBB(PjbbRaw); Word_t subexp; BITMAPB_t bitmap; Pjp_t Pjp2Raw, Pjp2; for (subexp = 0; subexp < cJL_NUMSUBEXPB; ++subexp) { if ((bitmap = JL_JBB_BITMAP(Pjbb, subexp)) == 0) continue; digit = subexp * cJL_BITSPERSUBEXPB; Pjp2Raw = JL_JBB_PJP(Pjbb, subexp); Pjp2 = P_JP(Pjp2Raw); assert(Pjp2 != NULL); for (offset = 0; bitmap != 0; bitmap >>= 1, ++digit) { if (!(bitmap & 1)) continue; pop1 = judyLeafM1ToLeafW(Pjlwnew, Pjv, Pjp2 + offset, JL_DIGITTOSTATE(digit, cJL_BYTESPERWORD), (void *) Pjpm); Pjlwnew += pop1; Pjv += pop1; ++offset; } judyLFreeJBBJP(Pjp2Raw, /* pop1 = */ offset, Pjpm); } judyLFreeJBB(PjbbRaw, Pjpm); break; } case cJL_JPBRANCH_U: { Pjbu_t PjbuRaw = (Pjbu_t) (Pjp->jp_Addr); Pjbu_t Pjbu = P_JBU(PjbuRaw); Word_t ldigit; for (Pjp = Pjbu->jbu_jp, ldigit = 0; ldigit < cJL_BRANCHUNUMJPS; ++Pjp, ++ldigit) { if ((JL_JPTYPE(Pjp)) == cJL_JPNULLMAX) continue; if ((JL_JPTYPE(Pjp)) == cJL_JPIMMED_3_01) { *Pjlwnew++ = JL_DIGITTOSTATE(ldigit, cJL_BYTESPERWORD) | JL_JPDCDPOP0(Pjp); *Pjv++ = Pjp->jp_Addr; continue; } pop1 = judyLeafM1ToLeafW(Pjlwnew, Pjv, Pjp, JL_DIGITTOSTATE(ldigit, cJL_BYTESPERWORD), (void *) Pjpm); Pjlwnew += pop1; Pjv += pop1; } judyLFreeJBU(PjbuRaw, Pjpm); break; } default: JL_SET_ERRNO(JLE_CORRUPT); return JERR; } judyLFreeJPM(Pjpm, NULL); return 1; } }