⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdbm.c

📁 apache的软件linux版本
💻 C
📖 第 1 页 / 共 2 页
字号:
    (void) apr_sdbm_unlock(db);        return status;}/* * makroom - make room by splitting the overfull page * this routine will attempt to make room for SPLTMAX times before * giving up. */static apr_status_t makroom(apr_sdbm_t *db, long hash, int need){    long newp;    char twin[PBLKSIZ];    char *pag = db->pagbuf;    char *new = twin;    register int smax = SPLTMAX;    apr_status_t status;    do {        /*         * split the current page         */        (void) splpage(pag, new, db->hmask + 1);        /*         * address of the new page         */        newp = (hash & db->hmask) | (db->hmask + 1);        /*         * write delay, read avoidence/cache shuffle:         * select the page for incoming pair: if key is to go to the new page,         * write out the previous one, and copy the new one over, thus making         * it the current page. If not, simply write the new page, and we are         * still looking at the page of interest. current page is not updated         * here, as sdbm_store will do so, after it inserts the incoming pair.         */        if (hash & (db->hmask + 1)) {            if ((status = write_page(db, db->pagbuf, db->pagbno))                         != APR_SUCCESS)                return status;                                db->pagbno = newp;            (void) memcpy(pag, new, PBLKSIZ);        }        else {            if ((status = write_page(db, new, newp)) != APR_SUCCESS)                return status;        }        if ((status = setdbit(db, db->curbit)) != APR_SUCCESS)            return status;        /*         * see if we have enough room now         */        if (fitpair(pag, need))            return APR_SUCCESS;        /*         * try again... update curbit and hmask as getpage would have         * done. because of our update of the current page, we do not         * need to read in anything. BUT we have to write the current         * [deferred] page out, as the window of failure is too great.         */        db->curbit = 2 * db->curbit                   + ((hash & (db->hmask + 1)) ? 2 : 1);        db->hmask |= db->hmask + 1;                    if ((status = write_page(db, db->pagbuf, db->pagbno))                    != APR_SUCCESS)            return status;                } while (--smax);    /*     * if we are here, this is real bad news. After SPLTMAX splits,     * we still cannot fit the key. say goodnight.     */#if 0    (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);#endif    /* ### ENOSPC not really appropriate but better than nothing */    return APR_ENOSPC;}/* Reads 'len' bytes from file 'f' at offset 'off' into buf. * 'off' is given relative to the start of the file. * If EOF is returned while reading, this is taken as success. */static apr_status_t read_from(apr_file_t *f, void *buf,              apr_off_t off, apr_size_t len){    apr_status_t status;    if ((status = apr_file_seek(f, APR_SET, &off)) != APR_SUCCESS ||        ((status = apr_file_read_full(f, buf, len, NULL)) != APR_SUCCESS)) {        /* if EOF is reached, pretend we read all zero's */        if (status == APR_EOF) {            memset(buf, 0, len);            status = APR_SUCCESS;        }    }    return status;}/* * the following two routines will break if * deletions aren't taken into account. (ndbm bug) */APU_DECLARE(apr_status_t) apr_sdbm_firstkey(apr_sdbm_t *db,                                             apr_sdbm_datum_t *key){    apr_status_t status;        if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)        return status;    /*     * start at page 0     */    if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(0), PBLKSIZ))                == APR_SUCCESS) {        db->pagbno = 0;        db->blkptr = 0;        db->keyptr = 0;        status = getnext(key, db);    }    (void) apr_sdbm_unlock(db);    return status;}APU_DECLARE(apr_status_t) apr_sdbm_nextkey(apr_sdbm_t *db,                                            apr_sdbm_datum_t *key){    apr_status_t status;        if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)        return status;    status = getnext(key, db);    (void) apr_sdbm_unlock(db);    return status;}/* * all important binary tree traversal */static apr_status_t getpage(apr_sdbm_t *db, long hash){    register int hbit;    register long dbit;    register long pagb;    apr_status_t status;    dbit = 0;    hbit = 0;    while (dbit < db->maxbno && getdbit(db, dbit))    dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);    debug(("dbit: %d...", dbit));    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.         * ### joe: this assumption was surely never correct? but         * ### we make it so in read_from anyway.         */        if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(pagb), PBLKSIZ))                     != APR_SUCCESS)            return status;        if (!chkpage(db->pagbuf))            return APR_ENOSPC; /* ### better error? */        db->pagbno = pagb;        debug(("pag read: %d\n", pagb));    }    return APR_SUCCESS;}static int getdbit(apr_sdbm_t *db, long dbit){    register long c;    register long dirb;    c = dbit / BYTESIZ;    dirb = c / DBLKSIZ;    if (dirb != db->dirbno) {        if (read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ)                    != APR_SUCCESS)            return 0;        db->dirbno = dirb;        debug(("dir read: %d\n", dirb));    }    return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);}static apr_status_t setdbit(apr_sdbm_t *db, long dbit){    register long c;    register long dirb;    apr_status_t status;    apr_off_t off;    c = dbit / BYTESIZ;    dirb = c / DBLKSIZ;    if (dirb != db->dirbno) {        if ((status = read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ))                    != APR_SUCCESS)            return status;        db->dirbno = dirb;                debug(("dir read: %d\n", dirb));    }    db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);    if (dbit >= db->maxbno)        db->maxbno += DBLKSIZ * BYTESIZ;    off = OFF_DIR(dirb);    if ((status = apr_file_seek(db->dirf, APR_SET, &off)) == APR_SUCCESS)        status = apr_file_write_full(db->dirf, db->dirbuf, DBLKSIZ, NULL);    return status;}/** getnext - get the next key in the page, and if done with* the page, try the next page in sequence*/static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db){    apr_status_t status;    for (;;) {        db->keyptr++;        *key = getnkey(db->pagbuf, db->keyptr);        if (key->dptr != NULL)            return APR_SUCCESS;        /*         * 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++) {            apr_off_t off = OFF_PAG(db->blkptr);            if ((status = apr_file_seek(db->pagf, APR_SET, &off)                         != APR_SUCCESS))                return status;        }        db->pagbno = db->blkptr;        /* ### EOF acceptable here too? */        if ((status = apr_file_read_full(db->pagf, db->pagbuf, PBLKSIZ, NULL))                    != APR_SUCCESS)            return status;        if (!chkpage(db->pagbuf))            return APR_EGENERAL;     /* ### need better error */    }    /* NOTREACHED */}APU_DECLARE(int) apr_sdbm_rdonly(apr_sdbm_t *db){    /* ### Should we return true if the first lock is a share lock,     *     to reflect that apr_sdbm_store and apr_sdbm_delete will fail?     */    return (db->flags & SDBM_RDONLY) != 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -