📄 ssl_util_sdbm.c
字号:
db->curbit = dbit; db->hmask = masks[hbit]; pagb = hash & db->hmask;/* * see if the block we need is already in memory. * note: this lookaside cache has about 10% hit rate. */ if (pagb != db->pagbno) {/* * note: here, we assume a "hole" is read as 0s. * if not, must zero pagbuf first. */ if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0 || read(db->pagf, db->pagbuf, PBLKSIZ) < 0) return 0; if (!chkpage(db->pagbuf)) return 0; db->pagbno = pagb; debug(("pag read: %d\n", pagb)); } return 1;}static intgetdbit(db, dbit)register DBM *db;register long dbit;{ register long c; register long dirb; int got; c = dbit / BYTESIZ; dirb = c / DBLKSIZ; if (dirb != db->dirbno) { if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0 || (got = read(db->dirf, db->dirbuf, DBLKSIZ)) < 0) return 0; if (got == 0) memset(db->dirbuf, 0, DBLKSIZ); db->dirbno = dirb; debug(("dir read: %d\n", dirb)); } return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);}static intsetdbit(db, dbit)register DBM *db;register long dbit;{ register long c; register long dirb; int got; c = dbit / BYTESIZ; dirb = c / DBLKSIZ; if (dirb != db->dirbno) { if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0 || (got = read(db->dirf, db->dirbuf, DBLKSIZ)) < 0) return 0; if (got == 0) memset(db->dirbuf, 0, DBLKSIZ); db->dirbno = dirb; debug(("dir read: %d\n", dirb)); } db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);#if 0 if (dbit >= db->maxbno) db->maxbno += DBLKSIZ * BYTESIZ;#else if (OFF_DIR((dirb+1))*BYTESIZ > db->maxbno) db->maxbno = OFF_DIR((dirb+1)) * BYTESIZ;#endif if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0 || write(db->dirf, db->dirbuf, DBLKSIZ) < 0) return 0; return 1;}/* * getnext - get the next key in the page, and if done with * the page, try the next page in sequence */static datumgetnext(db)register DBM *db;{ datum key; for (;;) { db->keyptr++; key = getnkey(db->pagbuf, db->keyptr); if (key.dptr != NULL) return key;/* * we either run out, or there is nothing on this page.. * try the next one... If we lost our position on the * file, we will have to seek. */ db->keyptr = 0; if (db->pagbno != db->blkptr++) if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0) break; db->pagbno = db->blkptr; if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0) break; if (!chkpage(db->pagbuf)) break; } return ioerr(db), nullitem;}/* ************************* *//* * sdbm - ndbm work-alike hashed database library * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978). * author: oz@nexus.yorku.ca * status: public domain. keep it that way. * * hashing routine *//* * polynomial conversion ignoring overflows * [this seems to work remarkably well, in fact better * then the ndbm hash function. Replace at your own risk] * use: 65599 nice. * 65587 even better. */longsdbm_hash(str, len)register char *str;register int len;{ register unsigned long n = 0;#ifdef DUFF#define HASHC n = *str++ + 65599 * n if (len > 0) { register int loop = (len + 8 - 1) >> 3; switch(len & (8 - 1)) { case 0: do { HASHC; case 7: HASHC; case 6: HASHC; case 5: HASHC; case 4: HASHC; case 3: HASHC; case 2: HASHC; case 1: HASHC; } while (--loop); } }#else while (len--) n = *str++ + 65599 * n;#endif return n;}/* ************************* *//* * sdbm - ndbm work-alike hashed database library * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978). * author: oz@nexus.yorku.ca * status: public domain. * * page-level routines */#define exhash(item) sdbm_hash((item).dptr, (item).dsize)/* * forward */static int seepair proto((char *, int, char *, int));/* * page format: * +------------------------------+ * ino | n | keyoff | datoff | keyoff | * +------------+--------+--------+ * | datoff | - - - ----> | * +--------+---------------------+ * | F R E E A R E A | * +--------------+---------------+ * | <---- - - - | data | * +--------+-----+----+----------+ * | key | data | key | * +--------+----------+----------+ * * calculating the offsets for free area: if the number * of entries (ino[0]) is zero, the offset to the END of * the free area is the block size. Otherwise, it is the * nth (ino[ino[0]]) entry's offset. */intfitpair(pag, need)char *pag;int need;{ register int n; register int off; register int avail; register short *ino = (short *) pag; off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ; avail = off - (n + 1) * sizeof(short); need += 2 * sizeof(short); debug(("free %d need %d\n", avail, need)); return need <= avail;}voidputpair(pag, key, val)char *pag;datum key;datum val;{ register int n; register int off; register short *ino = (short *) pag; off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;/* * enter the key first */ off -= key.dsize; (void) memcpy(pag + off, key.dptr, key.dsize); ino[n + 1] = off;/* * now the data */ off -= val.dsize; (void) memcpy(pag + off, val.dptr, val.dsize); ino[n + 2] = off;/* * adjust item count */ ino[0] += 2;}datumgetpair(pag, key)char *pag;datum key;{ register int i; register int n; datum val; register short *ino = (short *) pag; if ((n = ino[0]) == 0) return nullitem; if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0) return nullitem; val.dptr = pag + ino[i + 1]; val.dsize = ino[i] - ino[i + 1]; return val;}#ifdef SEEDUPSintduppair(pag, key)char *pag;datum key;{ register short *ino = (short *) pag; return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;}#endifdatumgetnkey(pag, num)char *pag;int num;{ datum key; register int off; register short *ino = (short *) pag; num = num * 2 - 1; if (ino[0] == 0 || num > ino[0]) return nullitem; off = (num > 1) ? ino[num - 1] : PBLKSIZ; key.dptr = pag + ino[num]; key.dsize = off - ino[num]; return key;}intdelpair(pag, key)char *pag;datum key;{ register int n; register int i; register short *ino = (short *) pag; if ((n = ino[0]) == 0) return 0; if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0) return 0;/* * found the key. if it is the last entry * [i.e. i == n - 1] we just adjust the entry count. * hard case: move all data down onto the deleted pair, * shift offsets onto deleted offsets, and adjust them. * [note: 0 < i < n] */ if (i < n - 1) { register int m; register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]); register char *src = pag + ino[i + 1]; register int zoo = dst - src; debug(("free-up %d ", zoo));/* * shift data/keys down */ m = ino[i + 1] - ino[n];#ifdef DUFF#define MOVB *--dst = *--src if (m > 0) { register int loop = (m + 8 - 1) >> 3; switch (m & (8 - 1)) { case 0: do { MOVB; case 7: MOVB; case 6: MOVB; case 5: MOVB; case 4: MOVB; case 3: MOVB; case 2: MOVB; case 1: MOVB; } while (--loop); } }#else dst -= m; src -= m; memmove(dst, src, m);#endif/* * adjust offset index up */ while (i < n - 1) { ino[i] = ino[i + 2] + zoo; i++; } } ino[0] -= 2; return 1;}/* * search for the key in the page. * return offset index in the range 0 < i < n. * return 0 if not found. */static intseepair(pag, n, key, siz)char *pag;register int n;register char *key;register int siz;{ register int i; register int off = PBLKSIZ; register short *ino = (short *) pag; for (i = 1; i < n; i += 2) { if (siz == off - ino[i] && memcmp(key, pag + ino[i], siz) == 0) return i; off = ino[i + 1]; } return 0;}voidsplpage(pag, new, sbit)char *pag;char *new;long sbit;{ datum key; datum val; register int n; register int off = PBLKSIZ; char cur[PBLKSIZ]; register short *ino = (short *) cur; (void) memcpy(cur, pag, PBLKSIZ); (void) memset(pag, 0, PBLKSIZ); (void) memset(new, 0, PBLKSIZ); n = ino[0]; for (ino++; n > 0; ino += 2) { key.dptr = cur + ino[0]; key.dsize = off - ino[0]; val.dptr = cur + ino[1]; val.dsize = ino[0] - ino[1];/* * select the page pointer (by looking at sbit) and insert */ (void) putpair((exhash(key) & sbit) ? new : pag, key, val); off = ino[1]; n -= 2; } debug(("%d split %d/%d\n", ((short *) cur)[0] / 2, ((short *) new)[0] / 2, ((short *) pag)[0] / 2));}/* * check page sanity: * number of entries should be something * reasonable, and all offsets in the index should be in order. * this could be made more rigorous. */intchkpage(pag)char *pag;{ register int n; register int off; register short *ino = (short *) pag; if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short)) return 0; if (n > 0) { off = PBLKSIZ; for (ino++; n > 0; ino += 2) { if (ino[0] > off || ino[1] > off || ino[1] > ino[0]) return 0; off = ino[1]; n -= 2; } } return 1;}#endif /* SSL_USE_SDBM */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -