void freesuffixarray(Suffixarray *suffixarray) { gt_fa_xmunmap((void *) suffixarray->suftab); suffixarray->suftab = NULL; gt_fa_xmunmap((void *) suffixarray->lcptab); suffixarray->lcptab = NULL; gt_fa_xmunmap((void *) suffixarray->llvtab); suffixarray->llvtab = NULL; gt_fa_xmunmap((void *) suffixarray->bwttab); suffixarray->bwttab = NULL; gt_fa_xfclose(suffixarray->suftabstream.fp); suffixarray->suftabstream.fp = NULL; FREESPACE(suffixarray->suftabstream.bufferedfilespace); gt_fa_xfclose(suffixarray->lcptabstream.fp); suffixarray->lcptabstream.fp = NULL; FREESPACE(suffixarray->lcptabstream.bufferedfilespace); gt_fa_xfclose(suffixarray->llvtabstream.fp); suffixarray->llvtabstream.fp = NULL; FREESPACE(suffixarray->llvtabstream.bufferedfilespace); gt_fa_xfclose(suffixarray->bwttabstream.fp); suffixarray->bwttabstream.fp = NULL; FREESPACE(suffixarray->bwttabstream.bufferedfilespace); encodedsequence_free(&suffixarray->encseq); if (suffixarray->bcktab != NULL) { bcktab_delete(&suffixarray->bcktab); } }
void gt_multimappowerfree(GtCodetype ***multimappower) { if (*multimappower != NULL) { FREESPACE((*multimappower)[0]); FREESPACE((*multimappower)); *multimappower = NULL; } }
static void freeconstructedfmindex(Fmindex *fm) { GT_FREEARRAY (&fm->specpos, GtPairBwtidx); FREESPACE (fm->bfreq); FREESPACE (fm->superbfreq); FREESPACE (fm->tfreq); FREESPACE (fm->markpostable); if (fm->suffixlength > 0) { FREESPACE(fm->boundarray); } }
void gt_makeitmthresholds(Profilematrix *prof, ProfScore minscore) { unsigned long d, a; long ddown; ProfScore partsum, score, *maxscore; ALLOCASSIGNSPACE(maxscore,NULL,ProfScore,prof->dimension); for (d=0; d<prof->dimension; d++) { for (a=0; a<prof->numofcharacters; a++) { score = GETPROFSCORE(prof,a,d); if (a == 0 || maxscore[d] < score) { maxscore[d] = score; } } } partsum = (ProfScore) 0; gt_assert(prof->itmthreshold != NULL); for (ddown = (long) (prof->dimension-1); ddown>=0; ddown--) { prof->itmthreshold[ddown] = minscore - partsum; partsum += maxscore[ddown]; } FREESPACE(maxscore); }
/* * Given the buffer pointer of the first overflow page of a big pair, * find the end of the big pair * * This will set bpp to the buffer header of the last page of the big pair. * It will return the pageno of the overflow page following the last page * of the pair; 0 if there isn't any (i.e. big pair is the last key in the * bucket) */ uint16_t __find_last_page(HTAB *hashp, BUFHEAD **bpp) { BUFHEAD *bufp; uint16_t *bp, pageno; int n; bufp = *bpp; bp = (uint16_t *)(void *)bufp->page; for (;;) { n = bp[0]; /* * This is the last page if: the tag is FULL_KEY_DATA and * either only 2 entries OVFLPAGE marker is explicit there * is freespace on the page. */ if (bp[2] == FULL_KEY_DATA && ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp)))) break; pageno = bp[n - 1]; bufp = __get_buf(hashp, (uint32_t)pageno, bufp, 0); if (!bufp) return (0); /* Need to indicate an error! */ bp = (uint16_t *)(void *)bufp->page; } *bpp = bufp; if (bp[0] > 2) return (bp[3]); else return (0); }
/* * Add the given pair to the page * * Returns: * 0 ==> OK * 1 ==> failure */ extern int __addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val) { u_int16_t *bp, *sop; int do_expand; bp = (u_int16_t *)bufp->page; do_expand = 0; while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY)) /* Exception case */ if (bp[2] == FULL_KEY_DATA && bp[0] == 2) /* This is the last page of a big key/data pair and we need to add another page */ break; else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) { bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); if (!bufp) return (-1); bp = (u_int16_t *)bufp->page; } else /* Try to squeeze key on this page */ if (FREESPACE(bp) > PAIRSIZE(key, val)) { squeeze_key(bp, key, val); return (0); } else { bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); if (!bufp) return (-1); bp = (u_int16_t *)bufp->page; } if (PAIRFITS(bp, key, val)) putpair(bufp->page, key, val); else { do_expand = 1; bufp = __add_ovflpage(hashp, bufp); if (!bufp) return (-1); sop = (u_int16_t *)bufp->page; if (PAIRFITS(sop, key, val)) putpair((char *)sop, key, val); else if (__big_insert(hashp, bufp, key, val)) return (-1); } bufp->flags |= BUF_MOD; /* * If the average number of keys per bucket exceeds the fill factor, * expand the table. */ hashp->NKEYS++; if (do_expand || (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR)) return (__expand_table(hashp)); return (0); }
static void freesimpleoption(Cmppairwiseopt *cmppairwise) { gt_str_array_delete(cmppairwise->strings); gt_str_array_delete(cmppairwise->files); gt_str_delete(cmppairwise->text); if (cmppairwise->charlistlen != NULL) { gt_str_delete(cmppairwise->charlistlen->charlist); FREESPACE(cmppairwise->charlistlen); } }
GtCodetype *gt_initfilltable(unsigned int numofchars,unsigned int prefixlength) { unsigned int i; GtCodetype *filltable, *basepower; basepower = gt_initbasepower(numofchars,prefixlength); ALLOCASSIGNSPACE(filltable,NULL,GtCodetype,prefixlength); for (i=0; i<prefixlength; i++) { filltable[i] = basepower[prefixlength-i]-1; } FREESPACE(basepower); return filltable; }
static unsigned long squarededistunit2 (const GtUchar *u, unsigned long m, const GtUchar *v, unsigned long n) { unsigned long val, we, nw, *ecol, *ecolptr; const GtUchar *uptr, *vptr; ALLOCASSIGNSPACE(ecol,NULL,unsigned long,m+1); for (*ecol = 0, ecolptr = ecol+1, uptr = u; uptr < u + m; ecolptr++, uptr++) { *ecolptr = *(ecolptr-1) + 1; } for (vptr = v; vptr < v + n; vptr++) { nw = *ecol; *ecol = nw + 1; for (ecolptr = ecol+1, uptr = u; uptr < u + m; ecolptr++, uptr++) { we = *ecolptr; *ecolptr = *(ecolptr-1) + 1; if (*uptr == *vptr) { val = nw; } else { val = nw + 1; } if (val < *ecolptr) { *ecolptr = val; } if ((val = we + 1) < *ecolptr) { *ecolptr = val; } nw = we; } } val = *(ecolptr-1); FREESPACE(ecol); return val; }
/* * Given the buffer pointer of the first overflow page of a big pair, * find the end of the big pair * * This will set bpp to the buffer header of the last page of the big pair. * It will return the pageno of the overflow page following the last page * of the pair; 0 if there isn't any (i.e. big pair is the last key in the * bucket) */ extern uint16 dbm_find_last_page(HTAB *hashp, BUFHEAD **bpp) { BUFHEAD *bufp; uint16 *bp, pageno; uint n; bufp = *bpp; bp = (uint16 *)bufp->page; for (;;) { n = bp[0]; /* * This is the last page if: the tag is FULL_KEY_DATA and * either only 2 entries OVFLPAGE marker is explicit there * is freespace on the page. */ if (bp[2] == FULL_KEY_DATA && ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp)))) break; /* LJM bound the size of n to reasonable limits */ if (n > hashp->BSIZE / sizeof(uint16)) return (0); pageno = bp[n - 1]; bufp = dbm_get_buf(hashp, pageno, bufp, 0); if (!bufp) return (0); /* Need to indicate an error! */ bp = (uint16 *)bufp->page; } *bpp = bufp; if (bp[0] > 2) return (bp[3]); else return (0); }
void gt_lookaheadsearchPSSM(const GtEncseq *encseq, const Profilematrix *prof) { unsigned long firstpos, bufsize; GtUchar currentchar; unsigned long pos; GtEncseqReader *esr; unsigned long totallength = gt_encseq_total_length(encseq); GtUchar *buffer; esr = gt_encseq_create_reader_with_readmode(encseq,GT_READMODE_FORWARD,0); ALLOCASSIGNSPACE(buffer,NULL,GtUchar,prof->dimension); firstpos = bufsize = 0; for (pos=0; pos < totallength; pos++) { currentchar = gt_encseq_reader_next_encoded_char(esr); if (ISSPECIAL(currentchar)) { bufsize = firstpos = 0; } else { if (bufsize < prof->dimension) { buffer[bufsize++] = currentchar; } else { buffer[firstpos++] = currentchar; if (firstpos == prof->dimension) { firstpos = 0; } } } } gt_encseq_reader_delete(esr); FREESPACE(buffer); }
void freeTurningwheel(Turningwheel **tw) { FREESPACE(*tw); }
/* * Big_insert * * You need to do an insert and the key/data pair is too big * * Returns: * 0 ==> OK *-1 ==> ERROR */ int __big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val) { uint16_t *p, n; size_t key_size, val_size; uint16_t space, move_bytes, off; char *cp, *key_data, *val_data; size_t temp; cp = bufp->page; /* Character pointer of p. */ p = (uint16_t *)(void *)cp; key_data = (char *)key->data; _DBFIT(key->size, int); key_size = key->size; val_data = (char *)val->data; _DBFIT(val->size, int); val_size = val->size; /* First move the Key */ temp = FREESPACE(p) - BIGOVERHEAD; _DBFIT(temp, uint16_t); space = (uint16_t)temp; while (key_size) { move_bytes = MIN(space, key_size); off = OFFSET(p) - move_bytes; memmove(cp + off, key_data, (size_t)move_bytes); key_size -= move_bytes; key_data += move_bytes; n = p[0]; p[++n] = off; p[0] = ++n; temp = off - PAGE_META(n); _DBFIT(temp, uint16_t); FREESPACE(p) = (uint16_t)temp; OFFSET(p) = off; p[n] = PARTIAL_KEY; bufp = __add_ovflpage(hashp, bufp); if (!bufp) return (-1); n = p[0]; if (!key_size) { space = FREESPACE(p); if (space) { move_bytes = MIN(space, val_size); /* * If the data would fit exactly in the * remaining space, we must overflow it to the * next page; otherwise the invariant that the * data must end on a page with FREESPACE * non-zero would fail. */ if (space == val_size && val_size == val->size) goto toolarge; off = OFFSET(p) - move_bytes; memmove(cp + off, val_data, (size_t)move_bytes); val_data += move_bytes; val_size -= move_bytes; p[n] = off; p[n - 2] = FULL_KEY_DATA; FREESPACE(p) = FREESPACE(p) - move_bytes; OFFSET(p) = off; } else { toolarge: p[n - 2] = FULL_KEY; } } p = (uint16_t *)(void *)bufp->page; cp = bufp->page; bufp->flags |= BUF_MOD; temp = FREESPACE(p) - BIGOVERHEAD; _DBFIT(temp, uint16_t); space = (uint16_t)temp; } /* Now move the data */ temp = FREESPACE(p) - BIGOVERHEAD; _DBFIT(temp, uint16_t); space = (uint16_t)temp; while (val_size) { move_bytes = MIN(space, val_size); /* * Here's the hack to make sure that if the data ends on the * same page as the key ends, FREESPACE is at least one. */ if (space == val_size && val_size == val->size) move_bytes--; off = OFFSET(p) - move_bytes; memmove(cp + off, val_data, (size_t)move_bytes); val_size -= move_bytes; val_data += move_bytes; n = p[0]; p[++n] = off; p[0] = ++n; temp = off - PAGE_META(n); _DBFIT(temp, uint16_t); FREESPACE(p) = (uint16_t)temp; OFFSET(p) = off; if (val_size) { p[n] = FULL_KEY; bufp = __add_ovflpage(hashp, bufp); if (!bufp) return (-1); cp = bufp->page; p = (uint16_t *)(void *)cp; } else p[n] = FULL_KEY_DATA; bufp->flags |= BUF_MOD; temp = FREESPACE(p) - BIGOVERHEAD; _DBFIT(temp, uint16_t); space = (uint16_t)temp; } return (0); }
/* * Returns: * 0 => OK * -1 => error */ int __big_split( HTAB *hashp, BUFHEAD *op, /* Pointer to where to put keys that go in old bucket */ BUFHEAD *np, /* Pointer to new bucket page */ /* Pointer to first page containing the big key/data */ BUFHEAD *big_keyp, int addr, /* Address of big_keyp */ uint32_t obucket,/* Old Bucket */ SPLIT_RETURN *ret ) { BUFHEAD *tmpp; uint16_t *tp; BUFHEAD *bp; DBT key, val; uint32_t change; uint16_t free_space, n, off; size_t temp; bp = big_keyp; /* Now figure out where the big key/data goes */ if (__big_keydata(hashp, big_keyp, &key, &val, 0)) return (-1); change = (__call_hash(hashp, key.data, (int)key.size) != obucket); if ((ret->next_addr = __find_last_page(hashp, &big_keyp)) != 0) { if (!(ret->nextp = __get_buf(hashp, (uint32_t)ret->next_addr, big_keyp, 0))) return (-1); } else ret->nextp = NULL; /* Now make one of np/op point to the big key/data pair */ _DIAGASSERT(np->ovfl == NULL); if (change) tmpp = np; else tmpp = op; tmpp->flags |= BUF_MOD; #ifdef DEBUG1 (void)fprintf(stderr, "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr, (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0)); #endif tmpp->ovfl = bp; /* one of op/np point to big_keyp */ tp = (uint16_t *)(void *)tmpp->page; _DIAGASSERT(FREESPACE(tp) >= OVFLSIZE); n = tp[0]; off = OFFSET(tp); free_space = FREESPACE(tp); tp[++n] = (uint16_t)addr; tp[++n] = OVFLPAGE; tp[0] = n; OFFSET(tp) = off; temp = free_space - OVFLSIZE; _DBFIT(temp, uint16_t); FREESPACE(tp) = (uint16_t)temp; /* * Finally, set the new and old return values. BIG_KEYP contains a * pointer to the last page of the big key_data pair. Make sure that * big_keyp has no following page (2 elements) or create an empty * following page. */ ret->newp = np; ret->oldp = op; tp = (uint16_t *)(void *)big_keyp->page; big_keyp->flags |= BUF_MOD; if (tp[0] > 2) { /* * There may be either one or two offsets on this page. If * there is one, then the overflow page is linked on normally * and tp[4] is OVFLPAGE. If there are two, tp[4] contains * the second offset and needs to get stuffed in after the * next overflow page is added. */ n = tp[4]; free_space = FREESPACE(tp); off = OFFSET(tp); tp[0] -= 2; temp = free_space + OVFLSIZE; _DBFIT(temp, uint16_t); FREESPACE(tp) = (uint16_t)temp; OFFSET(tp) = off; tmpp = __add_ovflpage(hashp, big_keyp); if (!tmpp) return (-1); tp[4] = n; } else tmpp = big_keyp; if (change) ret->newp = tmpp; else ret->oldp = tmpp; return (0); }
/* * Return the data for the key/data pair that begins on this page at this * index (index should always be 1). */ int __big_return(HTAB *hashp, BUFHEAD *bufp, int ndx, DBT *val, int set_current) { BUFHEAD *save_p; uint16_t *bp, len, off, save_addr; char *tp; bp = (uint16_t *)(void *)bufp->page; while (bp[ndx + 1] == PARTIAL_KEY) { bufp = __get_buf(hashp, (uint32_t)bp[bp[0] - 1], bufp, 0); if (!bufp) return (-1); bp = (uint16_t *)(void *)bufp->page; ndx = 1; } if (bp[ndx + 1] == FULL_KEY) { bufp = __get_buf(hashp, (uint32_t)bp[bp[0] - 1], bufp, 0); if (!bufp) return (-1); bp = (uint16_t *)(void *)bufp->page; save_p = bufp; save_addr = save_p->addr; off = bp[1]; len = 0; } else if (!FREESPACE(bp)) { /* * This is a hack. We can't distinguish between * FULL_KEY_DATA that contains complete data or * incomplete data, so we require that if the data * is complete, there is at least 1 byte of free * space left. */ off = bp[bp[0]]; len = bp[1] - off; save_p = bufp; save_addr = bufp->addr; bufp = __get_buf(hashp, (uint32_t)bp[bp[0] - 1], bufp, 0); if (!bufp) return (-1); bp = (uint16_t *)(void *)bufp->page; } else { /* The data is all on one page. */ tp = (char *)(void *)bp; off = bp[bp[0]]; val->data = (uint8_t *)tp + off; val->size = bp[1] - off; if (set_current) { if (bp[0] == 2) { /* No more buckets in * chain */ hashp->cpage = NULL; hashp->cbucket++; hashp->cndx = 1; } else { hashp->cpage = __get_buf(hashp, (uint32_t)bp[bp[0] - 1], bufp, 0); if (!hashp->cpage) return (-1); hashp->cndx = 1; if (!((uint16_t *)(void *) hashp->cpage->page)[0]) { hashp->cbucket++; hashp->cpage = NULL; } } } return (0); } val->size = collect_data(hashp, bufp, (int)len, set_current); if (val->size == (size_t)-1) return (-1); if (save_p->addr != save_addr) { /* We are pretty short on buffers. */ errno = EINVAL; /* OUT OF BUFFERS */ return (-1); } memmove(hashp->tmp_buf, (save_p->page) + off, (size_t)len); val->data = (uint8_t *)hashp->tmp_buf; return (0); }
/* * Called when bufp's page contains a partial key (index should be 1) * * All pages in the big key/data pair except bufp are freed. We cannot * free bufp because the page pointing to it is lost and we can't get rid * of its pointer. * * Returns: * 0 => OK *-1 => ERROR */ int __big_delete(HTAB *hashp, BUFHEAD *bufp) { BUFHEAD *last_bfp, *rbufp; uint16_t *bp, pageno; int key_done, n; size_t temp; rbufp = bufp; last_bfp = NULL; bp = (uint16_t *)(void *)bufp->page; pageno = 0; key_done = 0; while (!key_done || (bp[2] != FULL_KEY_DATA)) { if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) key_done = 1; /* * If there is freespace left on a FULL_KEY_DATA page, then * the data is short and fits entirely on this page, and this * is the last page. */ if (bp[2] == FULL_KEY_DATA && FREESPACE(bp)) break; pageno = bp[bp[0] - 1]; rbufp->flags |= BUF_MOD; rbufp = __get_buf(hashp, (uint32_t)pageno, rbufp, 0); if (last_bfp) __free_ovflpage(hashp, last_bfp); last_bfp = rbufp; if (!rbufp) return (-1); /* Error. */ bp = (uint16_t *)(void *)rbufp->page; } /* * If we get here then rbufp points to the last page of the big * key/data pair. Bufp points to the first one -- it should now be * empty pointing to the next page after this pair. Can't free it * because we don't have the page pointing to it. */ /* This is information from the last page of the pair. */ n = bp[0]; pageno = bp[n - 1]; /* Now, bp is the first page of the pair. */ bp = (uint16_t *)(void *)bufp->page; if (n > 2) { /* There is an overflow page. */ bp[1] = pageno; bp[2] = OVFLPAGE; bufp->ovfl = rbufp->ovfl; } else /* This is the last page. */ bufp->ovfl = NULL; n -= 2; bp[0] = n; temp = hashp->BSIZE - PAGE_META(n); _DBFIT(temp, uint16_t); FREESPACE(bp) = (uint16_t)temp; OFFSET(bp) = hashp->BSIZE; bufp->flags |= BUF_MOD; if (rbufp) __free_ovflpage(hashp, rbufp); if (last_bfp && last_bfp != rbufp) __free_ovflpage(hashp, last_bfp); hashp->NKEYS--; return (0); }
/* * Returns: * 0 ==> OK * -1 ==> Error */ extern int __split_page(HTAB *hashp, uint32 obucket, uint32 nbucket) { register BUFHEAD *new_bufp, *old_bufp; register uint16 *ino; register uint16 *tmp_uint16_array; register char *np; DBT key, val; uint16 n, ndx; int retval; uint16 copyto, diff, moved; size_t off; char *op; copyto = (uint16)hashp->BSIZE; off = (uint16)hashp->BSIZE; old_bufp = __get_buf(hashp, obucket, NULL, 0); if (old_bufp == NULL) return (-1); new_bufp = __get_buf(hashp, nbucket, NULL, 0); if (new_bufp == NULL) return (-1); old_bufp->flags |= (BUF_MOD | BUF_PIN); new_bufp->flags |= (BUF_MOD | BUF_PIN); ino = (uint16 *)(op = old_bufp->page); np = new_bufp->page; moved = 0; for (n = 1, ndx = 1; n < ino[0]; n += 2) { if (ino[n + 1] < REAL_KEY) { retval = ugly_split(hashp, obucket, old_bufp, new_bufp, (int)copyto, (int)moved); old_bufp->flags &= ~BUF_PIN; new_bufp->flags &= ~BUF_PIN; return (retval); } key.data = (uint8 *)op + ino[n]; /* check here for ino[n] being greater than * off. If it is then the database has * been corrupted. */ if (ino[n] > off) return (DATABASE_CORRUPTED_ERROR); key.size = off - ino[n]; #ifdef DEBUG /* make sure the size is positive */ assert(((int)key.size) > -1); #endif if (__call_hash(hashp, (char *)key.data, key.size) == obucket) { /* Don't switch page */ diff = copyto - off; if (diff) { copyto = ino[n + 1] + diff; memmove(op + copyto, op + ino[n + 1], off - ino[n + 1]); ino[ndx] = copyto + ino[n] - ino[n + 1]; ino[ndx + 1] = copyto; } else copyto = ino[n + 1]; ndx += 2; } else { /* Switch page */ val.data = (uint8 *)op + ino[n + 1]; val.size = ino[n] - ino[n + 1]; /* if the pair doesn't fit something is horribly * wrong. LJM */ tmp_uint16_array = (uint16 *)np; if (!PAIRFITS(tmp_uint16_array, &key, &val)) return (DATABASE_CORRUPTED_ERROR); putpair(np, &key, &val); moved += 2; } off = ino[n + 1]; } /* Now clean up the page */ ino[0] -= moved; FREESPACE(ino) = copyto - sizeof(uint16) * (ino[0] + 3); OFFSET(ino) = copyto; #ifdef DEBUG3 (void)fprintf(stderr, "split %d/%d\n", ((uint16 *)np)[0] / 2, ((uint16 *)op)[0] / 2); #endif /* unpin both pages */ old_bufp->flags &= ~BUF_PIN; new_bufp->flags &= ~BUF_PIN; return (0); }
unsigned long greedyunitedist(const GtUchar *useq, unsigned long ulenvalue, const GtUchar *vseq, unsigned long vlenvalue) { unsigned long currentallocated, realdistance; FrontResource gl; Frontspec frontspecspace[2], *fspec, *prevfspec; Frontvalue *fptr; unsigned long kval; long r; #ifdef SKDEBUG printf("unitedistcheckSEPgeneric(ulen=%lu,vlen=%lu)\n",ulenvalue,vlenvalue); #endif gt_assert(ulenvalue < (unsigned long) LONG_MAX); gt_assert(vlenvalue < (unsigned long) LONG_MAX); currentallocated = 1UL; ALLOCASSIGNSPACE(gl.frontspace,NULL,Frontvalue,currentallocated); gl.useq = useq; gl.vseq = vseq; gl.ubound = useq + ulenvalue; gl.vbound = vseq + vlenvalue; gl.ulen = (long) ulenvalue; gl.vlen = (long) vlenvalue; gl.integermin = -MAX(gl.ulen,gl.vlen); prevfspec = &frontspecspace[0]; firstfrontforward(&gl,prevfspec); if (gl.ulen == gl.vlen && ROWVALUE(&gl.frontspace[0]) == gl.vlen) { realdistance = 0; } else { for (kval=1UL, r=1-MIN(gl.ulen,gl.vlen); /* Nothing */ ; kval++, r++) { if (prevfspec == &frontspecspace[0]) { fspec = &frontspecspace[1]; } else { fspec = &frontspecspace[0]; } fspec->offset = prevfspec->offset + prevfspec->width; frontspecparms(&gl,fspec,(long) kval,r); while ((unsigned long) (fspec->offset + fspec->width) >= currentallocated) { currentallocated += (kval+1); ALLOCASSIGNSPACE(gl.frontspace,gl.frontspace, Frontvalue,currentallocated); } (void) evalfrontforward(&gl,prevfspec,fspec,r); fptr = gl.frontspace + fspec->offset - fspec->left; if (accessfront(&gl,fptr,fspec,gl.vlen - gl.ulen) == gl.ulen) { realdistance = kval; break; } if (prevfspec == &frontspecspace[0]) { prevfspec = &frontspecspace[1]; } else { prevfspec = &frontspecspace[0]; } } } #ifdef SKDEBUG printf("unitedistfrontSEP returns %ld\n",realdistance); #endif FREESPACE(gl.frontspace); return realdistance; }
static int ugly_split(HTAB *hashp, uint32 obucket, BUFHEAD *old_bufp, BUFHEAD *new_bufp, /* Same as __split_page. */ int copyto, int moved) /* int copyto; First byte on page which contains key/data values. */ /* int moved; Number of pairs moved to new page. */ { register BUFHEAD *bufp; /* Buffer header for ino */ register uint16 *ino; /* Page keys come off of */ register uint16 *np; /* New page */ register uint16 *op; /* Page keys go on to if they aren't moving */ uint32 loop_detection = 0; BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */ DBT key, val; SPLIT_RETURN ret; uint16 n, off, ov_addr, scopyto; char *cino; /* Character value of ino */ int status; bufp = old_bufp; ino = (uint16 *)old_bufp->page; np = (uint16 *)new_bufp->page; op = (uint16 *)old_bufp->page; last_bfp = NULL; scopyto = (uint16)copyto; /* ANSI */ n = ino[0] - 1; while (n < ino[0]) { /* this function goes nuts sometimes and never returns. * I havent found the problem yet but I need a solution * so if we loop too often we assume a database curruption error * :LJM */ loop_detection++; if (loop_detection > MAX_UGLY_SPLIT_LOOPS) return DATABASE_CORRUPTED_ERROR; if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) { if ((status = __big_split(hashp, old_bufp, new_bufp, bufp, bufp->addr, obucket, &ret))) return (status); old_bufp = ret.oldp; if (!old_bufp) return (-1); op = (uint16 *)old_bufp->page; new_bufp = ret.newp; if (!new_bufp) return (-1); np = (uint16 *)new_bufp->page; bufp = ret.nextp; if (!bufp) return (0); cino = (char *)bufp->page; ino = (uint16 *)cino; last_bfp = ret.nextp; } else if (ino[n + 1] == OVFLPAGE) { ov_addr = ino[n]; /* * Fix up the old page -- the extra 2 are the fields * which contained the overflow information. */ ino[0] -= (moved + 2); FREESPACE(ino) = scopyto - sizeof(uint16) * (ino[0] + 3); OFFSET(ino) = scopyto; bufp = __get_buf(hashp, ov_addr, bufp, 0); if (!bufp) return (-1); ino = (uint16 *)bufp->page; n = 1; scopyto = hashp->BSIZE; moved = 0; if (last_bfp) __free_ovflpage(hashp, last_bfp); last_bfp = bufp; } /* Move regular sized pairs of there are any */ off = hashp->BSIZE; for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) { cino = (char *)ino; key.data = (uint8 *)cino + ino[n]; key.size = off - ino[n]; val.data = (uint8 *)cino + ino[n + 1]; val.size = ino[n] - ino[n + 1]; off = ino[n + 1]; if (__call_hash(hashp, (char *)key.data, key.size) == obucket) { /* Keep on old page */ if (PAIRFITS(op, (&key), (&val))) putpair((char *)op, &key, &val); else { old_bufp = __add_ovflpage(hashp, old_bufp); if (!old_bufp) return (-1); op = (uint16 *)old_bufp->page; putpair((char *)op, &key, &val); } old_bufp->flags |= BUF_MOD; } else { /* Move to new page */ if (PAIRFITS(np, (&key), (&val))) putpair((char *)np, &key, &val); else { new_bufp = __add_ovflpage(hashp, new_bufp); if (!new_bufp) return (-1); np = (uint16 *)new_bufp->page; putpair((char *)np, &key, &val); } new_bufp->flags |= BUF_MOD; } } } if (last_bfp) __free_ovflpage(hashp, last_bfp); return (0); }
void gt_substriter_delete(Substriter **substriter) { gt_multimappowerfree(&(*substriter)->multimappower); FREESPACE(*substriter); }
void gt_tyrsearchinfo_delete(Tyrsearchinfo *tyrsearchinfo) { gt_alphabet_delete(tyrsearchinfo->dnaalpha); FREESPACE(tyrsearchinfo->bytecode); FREESPACE(tyrsearchinfo->rcbuf); }
/* * Returns: * 0 ==> OK * -1 ==> Error */ int __split_page(HTAB *hashp, uint32_t obucket, uint32_t nbucket) { BUFHEAD *new_bufp, *old_bufp; uint16_t *ino; char *np; DBT key, val; int n, ndx, retval; uint16_t copyto, diff, off, moved; char *op; size_t temp; copyto = (uint16_t)hashp->BSIZE; off = (uint16_t)hashp->BSIZE; old_bufp = __get_buf(hashp, obucket, NULL, 0); if (old_bufp == NULL) return (-1); new_bufp = __get_buf(hashp, nbucket, NULL, 0); if (new_bufp == NULL) return (-1); old_bufp->flags |= (BUF_MOD | BUF_PIN); new_bufp->flags |= (BUF_MOD | BUF_PIN); ino = (uint16_t *)(void *)(op = old_bufp->page); np = new_bufp->page; moved = 0; for (n = 1, ndx = 1; n < ino[0]; n += 2) { if (ino[n + 1] < REAL_KEY) { retval = ugly_split(hashp, obucket, old_bufp, new_bufp, (int)copyto, (int)moved); old_bufp->flags &= ~BUF_PIN; new_bufp->flags &= ~BUF_PIN; return (retval); } key.data = (uint8_t *)op + ino[n]; key.size = off - ino[n]; if (__call_hash(hashp, key.data, (int)key.size) == obucket) { /* Don't switch page */ diff = copyto - off; if (diff) { copyto = ino[n + 1] + diff; memmove(op + copyto, op + ino[n + 1], (size_t)(off - ino[n + 1])); ino[ndx] = copyto + ino[n] - ino[n + 1]; ino[ndx + 1] = copyto; } else copyto = ino[n + 1]; ndx += 2; } else { /* Switch page */ val.data = (uint8_t *)op + ino[n + 1]; val.size = ino[n] - ino[n + 1]; putpair(np, &key, &val); moved += 2; } off = ino[n + 1]; } /* Now clean up the page */ ino[0] -= moved; temp = sizeof(uint16_t) * (ino[0] + 3); _DIAGASSERT(copyto >= temp); FREESPACE(ino) = (uint16_t)(copyto - temp); OFFSET(ino) = copyto; #ifdef DEBUG3 (void)fprintf(stderr, "split %d/%d\n", ((uint16_t *)np)[0] / 2, ((uint16_t *)op)[0] / 2); #endif /* unpin both pages */ old_bufp->flags &= ~BUF_PIN; new_bufp->flags &= ~BUF_PIN; return (0); }
/* * Add the given pair to the page * * Returns: * 0 ==> OK * 1 ==> failure */ extern int __addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val) { register uint16 *bp, *sop; int do_expand; bp = (uint16 *)bufp->page; do_expand = 0; while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY)) /* Exception case */ if (bp[2] == FULL_KEY_DATA && bp[0] == 2) /* This is the last page of a big key/data pair and we need to add another page */ break; else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) { bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); if (!bufp) { #ifdef DEBUG assert(0); #endif return (-1); } bp = (uint16 *)bufp->page; } else /* Try to squeeze key on this page */ if (FREESPACE(bp) > PAIRSIZE(key, val)) { { squeeze_key(bp, key, val); /* LJM: I added this because I think it was * left out on accident. * if this isn't incremented nkeys will not * be the actual number of keys in the db. */ hashp->NKEYS++; return (0); } } else { bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); if (!bufp) { #ifdef DEBUG assert(0); #endif return (-1); } bp = (uint16 *)bufp->page; } if (PAIRFITS(bp, key, val)) putpair(bufp->page, key, (DBT *)val); else { do_expand = 1; bufp = __add_ovflpage(hashp, bufp); if (!bufp) { #ifdef DEBUG assert(0); #endif return (-1); } sop = (uint16 *)bufp->page; if (PAIRFITS(sop, key, val)) putpair((char *)sop, key, (DBT *)val); else if (__big_insert(hashp, bufp, key, val)) { #ifdef DEBUG assert(0); #endif return (-1); } } bufp->flags |= BUF_MOD; /* * If the average number of keys per bucket exceeds the fill factor, * expand the table. */ hashp->NKEYS++; if (do_expand || (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR)) return (__expand_table(hashp)); return (0); }
/* * Called when we encounter an overflow or big key/data page during split * handling. This is special cased since we have to begin checking whether * the key/data pairs fit on their respective pages and because we may need * overflow pages for both the old and new pages. * * The first page might be a page with regular key/data pairs in which case * we have a regular overflow condition and just need to go on to the next * page or it might be a big key/data pair in which case we need to fix the * big key/data pair. * * Returns: * 0 ==> success * -1 ==> failure */ static int ugly_split( HTAB *hashp, uint32_t obucket, /* Same as __split_page. */ BUFHEAD *old_bufp, BUFHEAD *new_bufp, int copyto, /* First byte on page which contains key/data values. */ int moved /* Number of pairs moved to new page. */ ) { BUFHEAD *bufp; /* Buffer header for ino */ uint16_t *ino; /* Page keys come off of */ uint16_t *np; /* New page */ uint16_t *op; /* Page keys go on to if they aren't moving */ size_t temp; BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */ DBT key, val; SPLIT_RETURN ret; uint16_t n, off, ov_addr, scopyto; char *cino; /* Character value of ino */ bufp = old_bufp; ino = (uint16_t *)(void *)old_bufp->page; np = (uint16_t *)(void *)new_bufp->page; op = (uint16_t *)(void *)old_bufp->page; last_bfp = NULL; scopyto = (uint16_t)copyto; /* ANSI */ n = ino[0] - 1; while (n < ino[0]) { if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) { if (__big_split(hashp, old_bufp, new_bufp, bufp, (int)bufp->addr, obucket, &ret)) return (-1); old_bufp = ret.oldp; if (!old_bufp) return (-1); op = (uint16_t *)(void *)old_bufp->page; new_bufp = ret.newp; if (!new_bufp) return (-1); np = (uint16_t *)(void *)new_bufp->page; bufp = ret.nextp; if (!bufp) return (0); cino = (char *)bufp->page; ino = (uint16_t *)(void *)cino; last_bfp = ret.nextp; } else if (ino[n + 1] == OVFLPAGE) { ov_addr = ino[n]; /* * Fix up the old page -- the extra 2 are the fields * which contained the overflow information. */ ino[0] -= (moved + 2); temp = sizeof(uint16_t) * (ino[0] + 3); _DIAGASSERT(scopyto >= temp); FREESPACE(ino) = (uint16_t)(scopyto - temp); OFFSET(ino) = scopyto; bufp = __get_buf(hashp, (uint32_t)ov_addr, bufp, 0); if (!bufp) return (-1); ino = (uint16_t *)(void *)bufp->page; n = 1; scopyto = hashp->BSIZE; moved = 0; if (last_bfp) __free_ovflpage(hashp, last_bfp); last_bfp = bufp; } /* Move regular sized pairs of there are any */ off = hashp->BSIZE; for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) { cino = (char *)(void *)ino; key.data = (uint8_t *)cino + ino[n]; key.size = off - ino[n]; val.data = (uint8_t *)cino + ino[n + 1]; val.size = ino[n] - ino[n + 1]; off = ino[n + 1]; if (__call_hash(hashp, key.data, (int)key.size) == obucket) { /* Keep on old page */ if (PAIRFITS(op, (&key), (&val))) putpair((char *)(void *)op, &key, &val); else { old_bufp = __add_ovflpage(hashp, old_bufp); if (!old_bufp) return (-1); op = (uint16_t *)(void *)old_bufp->page; putpair((char *)(void *)op, &key, &val); } old_bufp->flags |= BUF_MOD; } else { /* Move to new page */ if (PAIRFITS(np, (&key), (&val))) putpair((char *)(void *)np, &key, &val); else { new_bufp = __add_ovflpage(hashp, new_bufp); if (!new_bufp) return (-1); np = (uint16_t *)(void *)new_bufp->page; putpair((char *)(void *)np, &key, &val); } new_bufp->flags |= BUF_MOD; } } } if (last_bfp) __free_ovflpage(hashp, last_bfp); return (0); }
/* * Big_insert * * You need to do an insert and the key/data pair is too big * * Returns: * 0 ==> OK *-1 ==> ERROR */ extern int dbm_big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val) { register uint16 *p; uint key_size, n, val_size; uint16 space, move_bytes, off; char *cp, *key_data, *val_data; cp = bufp->page; /* Character pointer of p. */ p = (uint16 *)cp; key_data = (char *)key->data; key_size = key->size; val_data = (char *)val->data; val_size = val->size; /* First move the Key */ for (space = FREESPACE(p) - BIGOVERHEAD; key_size; space = FREESPACE(p) - BIGOVERHEAD) { move_bytes = PR_MIN(space, key_size); off = OFFSET(p) - move_bytes; memmove(cp + off, key_data, move_bytes); key_size -= move_bytes; key_data += move_bytes; n = p[0]; p[++n] = off; p[0] = ++n; FREESPACE(p) = off - PAGE_META(n); OFFSET(p) = off; p[n] = PARTIAL_KEY; bufp = dbm_add_ovflpage(hashp, bufp); if (!bufp) return (-1); n = p[0]; if (!key_size) { if (FREESPACE(p)) { move_bytes = PR_MIN(FREESPACE(p), val_size); off = OFFSET(p) - move_bytes; p[n] = off; memmove(cp + off, val_data, move_bytes); val_data += move_bytes; val_size -= move_bytes; p[n - 2] = FULL_KEY_DATA; FREESPACE(p) = FREESPACE(p) - move_bytes; OFFSET(p) = off; } else p[n - 2] = FULL_KEY; } p = (uint16 *)bufp->page; cp = bufp->page; bufp->flags |= BUF_MOD; } /* Now move the data */ for (space = FREESPACE(p) - BIGOVERHEAD; val_size; space = FREESPACE(p) - BIGOVERHEAD) { move_bytes = PR_MIN(space, val_size); /* * Here's the hack to make sure that if the data ends on the * same page as the key ends, FREESPACE is at least one. */ if (space == val_size && val_size == val->size) move_bytes--; off = OFFSET(p) - move_bytes; memmove(cp + off, val_data, move_bytes); val_size -= move_bytes; val_data += move_bytes; n = p[0]; p[++n] = off; p[0] = ++n; FREESPACE(p) = off - PAGE_META(n); OFFSET(p) = off; if (val_size) { p[n] = FULL_KEY; bufp = dbm_add_ovflpage(hashp, bufp); if (!bufp) return (-1); cp = bufp->page; p = (uint16 *)cp; } else p[n] = FULL_KEY_DATA; bufp->flags |= BUF_MOD; } return (0); }