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

📄 sdbm.c

📁 apache的软件linux版本
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * sdbm - ndbm work-alike hashed database library * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978). * author: oz@nexus.yorku.ca * ex-public domain, ported to APR for Apache 2 * core routines */#include "apr.h"#include "apr_file_io.h"#include "apr_strings.h"#include "apr_errno.h"#include "apr_sdbm.h"#include "sdbm_tune.h"#include "sdbm_pair.h"#include "sdbm_private.h"#include <string.h>     /* for memset() */#include <stdlib.h>     /* for malloc() and free() *//* * forward */static int getdbit (apr_sdbm_t *, long);static apr_status_t setdbit(apr_sdbm_t *, long);static apr_status_t getpage(apr_sdbm_t *db, long);static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db);static apr_status_t makroom(apr_sdbm_t *, long, int);/* * useful macros */#define bad(x)		((x).dptr == NULL || (x).dsize <= 0)#define exhash(item)	sdbm_hash((item).dptr, (item).dsize)/* ### Does anything need these externally? */#define sdbm_dirfno(db)	((db)->dirf)#define sdbm_pagfno(db)	((db)->pagf)#define OFF_PAG(off)	(apr_off_t) (off) * PBLKSIZ#define OFF_DIR(off)	(apr_off_t) (off) * DBLKSIZstatic long masks[] = {        000000000000, 000000000001, 000000000003, 000000000007,        000000000017, 000000000037, 000000000077, 000000000177,        000000000377, 000000000777, 000000001777, 000000003777,        000000007777, 000000017777, 000000037777, 000000077777,        000000177777, 000000377777, 000000777777, 000001777777,        000003777777, 000007777777, 000017777777, 000037777777,        000077777777, 000177777777, 000377777777, 000777777777,        001777777777, 003777777777, 007777777777, 017777777777};const apr_sdbm_datum_t sdbm_nullitem = { NULL, 0 };static apr_status_t database_cleanup(void *data){    apr_sdbm_t *db = data;    /*     * Can't rely on apr_sdbm_unlock, since it will merely     * decrement the refcnt if several locks are held.     */    if (db->flags & (SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK))        (void) apr_file_unlock(db->dirf);    (void) apr_file_close(db->dirf);    (void) apr_file_close(db->pagf);    free(db);    return APR_SUCCESS;}static apr_status_t prep(apr_sdbm_t **pdb, const char *dirname, const char *pagname,                         apr_int32_t flags, apr_fileperms_t perms, apr_pool_t *p){    apr_sdbm_t *db;    apr_status_t status;    *pdb = NULL;    db = malloc(sizeof(*db));    memset(db, 0, sizeof(*db));    db->pool = p;    /*     * adjust user flags so that WRONLY becomes RDWR,      * as required by this package. Also set our internal     * flag for RDONLY if needed.     */    if (!(flags & APR_WRITE)) {        db->flags |= SDBM_RDONLY;    }    /*     * adjust the file open flags so that we handle locking     * on our own (don't rely on any locking behavior within     * an apr_file_t, in case it's ever introduced, and set     * our own flag.     */    if (flags & APR_SHARELOCK) {        db->flags |= SDBM_SHARED;        flags &= ~APR_SHARELOCK;    }    flags |= APR_BINARY | APR_READ;    /*     * open the files in sequence, and stat the dirfile.     * If we fail anywhere, undo everything, return NULL.     */    if ((status = apr_file_open(&db->dirf, dirname, flags, perms, p))                != APR_SUCCESS)        goto error;    if ((status = apr_file_open(&db->pagf, pagname, flags, perms, p))                != APR_SUCCESS)        goto error;    if ((status = apr_sdbm_lock(db, (db->flags & SDBM_RDONLY)                                         ? APR_FLOCK_SHARED                                        : APR_FLOCK_EXCLUSIVE))                != APR_SUCCESS)        goto error;    /* apr_pcalloc zeroed the buffers     * apr_sdbm_lock stated the dirf->size and invalidated the cache     */    /*     * if we are opened in SHARED mode, unlock ourself      */    if (db->flags & SDBM_SHARED)        if ((status = apr_sdbm_unlock(db)) != APR_SUCCESS)            goto error;    /* make sure that we close the database at some point */    apr_pool_cleanup_register(p, db, database_cleanup, apr_pool_cleanup_null);    /* Done! */    *pdb = db;    return APR_SUCCESS;error:    if (db->dirf && db->pagf)        (void) apr_sdbm_unlock(db);    if (db->dirf != NULL)        (void) apr_file_close(db->dirf);    if (db->pagf != NULL) {        (void) apr_file_close(db->pagf);    }    free(db);    return status;}APU_DECLARE(apr_status_t) apr_sdbm_open(apr_sdbm_t **db, const char *file,                                         apr_int32_t flags,                                         apr_fileperms_t perms, apr_pool_t *p){    char *dirname = apr_pstrcat(p, file, APR_SDBM_DIRFEXT, NULL);    char *pagname = apr_pstrcat(p, file, APR_SDBM_PAGFEXT, NULL);        return prep(db, dirname, pagname, flags, perms, p);}APU_DECLARE(apr_status_t) apr_sdbm_close(apr_sdbm_t *db){    return apr_pool_cleanup_run(db->pool, db, database_cleanup);}APU_DECLARE(apr_status_t) apr_sdbm_fetch(apr_sdbm_t *db, apr_sdbm_datum_t *val,                                         apr_sdbm_datum_t key){    apr_status_t status;        if (db == NULL || bad(key))        return APR_EINVAL;    if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)        return status;    if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {        *val = getpair(db->pagbuf, key);        /* ### do we want a not-found result? */    }    (void) apr_sdbm_unlock(db);    return status;}static apr_status_t write_page(apr_sdbm_t *db, const char *buf, long pagno){    apr_status_t status;    apr_off_t off = OFF_PAG(pagno);        if ((status = apr_file_seek(db->pagf, APR_SET, &off)) == APR_SUCCESS)        status = apr_file_write_full(db->pagf, buf, PBLKSIZ, NULL);    return status;}APU_DECLARE(apr_status_t) apr_sdbm_delete(apr_sdbm_t *db,                                           const apr_sdbm_datum_t key){    apr_status_t status;        if (db == NULL || bad(key))        return APR_EINVAL;    if (apr_sdbm_rdonly(db))        return APR_EINVAL;        if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)        return status;    if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {        if (!delpair(db->pagbuf, key))            /* ### should we define some APRUTIL codes? */            status = APR_EGENERAL;        else            status = write_page(db, db->pagbuf, db->pagbno);    }    (void) apr_sdbm_unlock(db);    return status;}APU_DECLARE(apr_status_t) apr_sdbm_store(apr_sdbm_t *db, apr_sdbm_datum_t key,                                         apr_sdbm_datum_t val, int flags){    int need;    register long hash;    apr_status_t status;        if (db == NULL || bad(key))        return APR_EINVAL;    if (apr_sdbm_rdonly(db))        return APR_EINVAL;    need = key.dsize + val.dsize;    /*     * is the pair too big (or too small) for this database ??     */    if (need < 0 || need > PAIRMAX)        return APR_EINVAL;    if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)        return status;    if ((status = getpage(db, (hash = exhash(key)))) == APR_SUCCESS) {        /*         * if we need to replace, delete the key/data pair         * first. If it is not there, ignore.         */        if (flags == APR_SDBM_REPLACE)            (void) delpair(db->pagbuf, key);        else if (!(flags & APR_SDBM_INSERTDUP) && duppair(db->pagbuf, key)) {            status = APR_EEXIST;            goto error;        }        /*         * if we do not have enough room, we have to split.         */        if (!fitpair(db->pagbuf, need))            if ((status = makroom(db, hash, need)) != APR_SUCCESS)                goto error;        /*         * we have enough room or split is successful. insert the key,         * and update the page file.         */        (void) putpair(db->pagbuf, key, val);        status = write_page(db, db->pagbuf, db->pagbno);    }error:

⌨️ 快捷键说明

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