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

📄 hamsterdb.c

📁 About: hamsterdb is a database engine written in ANSI C. It supports a B+Tree index structure, uses
💻 C
📖 第 1 页 / 共 4 页
字号:
/** * Copyright (C) 2005-2007 Christoph Rupp (chris@crupp.de). * All rights reserved. See file LICENSE for licence and copyright * information. * */#ifdef HAVE_MALLOC_H#  include <malloc.h>#else#  include <stdlib.h>#endif#include <string.h>#include <ham/hamsterdb.h>#include "config.h"#include "error.h"#include "mem.h"#include "env.h"#include "db.h"#include "page.h"#include "version.h"#include "txn.h"#include "cache.h"#include "blob.h"#include "freelist.h"#include "extkeys.h"#include "btree_cursor.h"#include "cursor.h"#include "util.h"#include "keys.h"/* private parameter list entry for ham_create_ex */#define HAM_PARAM_DBNAME          (1000)/* a reserved database name for those databases, who're created without * an environment (and therefore don't have a name) */#define EMPTY_DATABASE_NAME       (0xf000)/* a reserved database name for the first database in an environment */#define FIRST_DATABASE_NAME       (0xf001)typedef struct free_cb_context_t{    ham_db_t *db;    ham_bool_t is_leaf;} free_cb_context_t;/* * callback function for ham_dump */#ifdef HAM_ENABLE_INTERNALstatic voidmy_dump_cb(int event, void *param1, void *param2, void *context){    ham_size_t i, limit, keysize;    ham_page_t *page;    int_key_t *key;    ham_u8_t *data;    ham_dump_cb_t cb=(ham_dump_cb_t)context;    switch (event) {    case ENUM_EVENT_DESCEND:        break;    case ENUM_EVENT_PAGE_START:        page=(ham_page_t *)param1;        printf("\n------ page 0x%llx ---------------------------------------\n",				(long long unsigned)page_get_self(page));        break;    case ENUM_EVENT_ITEM:        key=(int_key_t *)param1;        data=key_get_key(key);        keysize=key_get_size(key);        if (cb) {            cb(data, keysize);        }        else {            printf(" %02d: ", *(int *)param2);            printf(" key (%2d byte): ", key_get_size(key));            if (keysize>16)                limit=16;            else                limit=keysize;            for (i=0; i<limit; i++)                printf("%02x ", data[i]);            if (keysize>limit)                printf("... (%d more bytes)\n", keysize-limit);            else                printf("\n");            printf("      ptr: 0x%llx\n",                    (long long unsigned)key_get_ptr(key));        }        break;    default:        ham_assert(!"unknown callback event", (""));        break;    }}#endif /* HAM_ENABLE_INTERNAL *//* * callback function for freeing blobs of an in-memory-database */static voidmy_free_cb(int event, void *param1, void *param2, void *context){    int_key_t *key;    free_cb_context_t *c;    c=(free_cb_context_t *)context;    switch (event) {    case ENUM_EVENT_DESCEND:        break;    case ENUM_EVENT_PAGE_START:        c->is_leaf=*(ham_bool_t *)param2;        break;    case ENUM_EVENT_PAGE_STOP:        /*         * if this callback function is called from ham_env_erase_db:         * move the page to the freelist         */        if (!db_get_rt_flags(c->db)&HAM_IN_MEMORY_DB) {            ham_page_t *page=(ham_page_t *)param1;            (void)txn_free_page(db_get_txn(c->db), page);        }        break;    case ENUM_EVENT_ITEM:        key=(int_key_t *)param1;        if (key_get_flags(key)&KEY_IS_EXTENDED) {            ham_offset_t blobid=key_get_extended_rid(c->db, key);            /*             * delete the cached extended key             */            if (db_get_extkey_cache(c->db))                (void)extkey_cache_remove(db_get_extkey_cache(c->db), blobid);            /*             * then delete the blob             */            (void)blob_free(c->db, blobid, 0);        }        if (key_get_flags(key)&KEY_BLOB_SIZE_TINY ||            key_get_flags(key)&KEY_BLOB_SIZE_SMALL ||            key_get_flags(key)&KEY_BLOB_SIZE_EMPTY)            break;        /*         * if we're in the leaf page, delete the blob         */        if (c->is_leaf)             (void)blob_free(c->db, key_get_ptr(key), 0);        break;    default:        ham_assert(!"unknown callback event", (""));        break;    }}const char *ham_strerror(ham_status_t result){    switch (result) {        case HAM_SUCCESS:            return ("Success");        case HAM_SHORT_READ:            return ("Short read");        case HAM_SHORT_WRITE:            return ("Short write");        case HAM_INV_KEYSIZE:            return ("Invalid key size");        case HAM_INV_PAGESIZE:            return ("Invalid page size");        case HAM_DB_ALREADY_OPEN:            return ("Db already open");        case HAM_OUT_OF_MEMORY:            return ("Out of memory");        case HAM_INV_INDEX:            return ("Invalid index structure");        case HAM_INV_PARAMETER:            return ("Invalid parameter");        case HAM_INV_FILE_HEADER:            return ("Invalid database file header");        case HAM_INV_FILE_VERSION:            return ("Invalid database file version");        case HAM_KEY_NOT_FOUND:            return ("Key not found");        case HAM_DUPLICATE_KEY:            return ("Duplicate key");        case HAM_INTEGRITY_VIOLATED:            return ("Internal integrity violated");        case HAM_INTERNAL_ERROR:            return ("Internal error");        case HAM_DB_READ_ONLY:            return ("Database opened in read-only mode");        case HAM_BLOB_NOT_FOUND:            return ("Data blob not found");        case HAM_PREFIX_REQUEST_FULLKEY:            return ("Comparator function needs more data");        case HAM_IO_ERROR:            return ("System I/O error");        case HAM_CACHE_FULL:            return ("Database cache is full");        case HAM_NOT_IMPLEMENTED:            return ("Operation not implemented");        case HAM_FILE_NOT_FOUND:            return ("File not found");        case HAM_WOULD_BLOCK:            return ("Operation would block");        case HAM_NOT_READY:            return ("Object was not initialized correctly");        case HAM_CURSOR_IS_NIL:            return ("Cursor points to NIL");        case HAM_ENV_NOT_EMPTY:            return ("Not all databases were closed before "                    "closing the environment");        case HAM_DATABASE_NOT_FOUND:            return ("Database not found");        case HAM_DATABASE_ALREADY_EXISTS:            return ("Database name already exists");        case HAM_DATABASE_ALREADY_OPEN:            return ("Database already open");        case HAM_ENV_FULL:            return ("Environment is full");        default:            return ("Unknown error");    }}static void__prepare_db(ham_db_t *db){    ham_env_t *env=db_get_env(db);    ham_assert(db_get_env(db)!=0, (""));    if (env_get_header_page(env))        page_set_owner(env_get_header_page(env), db);    if (env_get_extkey_cache(env))        extkey_cache_set_db(env_get_extkey_cache(env), db);    if (env_get_txn(env))        txn_set_db(env_get_txn(env), db);}static ham_status_t __check_create_parameters(ham_bool_t is_env, const char *filename,         ham_u32_t *flags, ham_parameter_t *param, ham_size_t *ppagesize,         ham_u16_t *pkeysize, ham_size_t *pcachesize, ham_u16_t *pdbname){    ham_u32_t pagesize=0;    ham_u16_t keysize=0, dbname=EMPTY_DATABASE_NAME;    ham_size_t cachesize=0;    ham_bool_t no_mmap=HAM_FALSE;    /*      * parse parameters      */    if (param) {        for (; param->name; param++) {            switch (param->name) {            case HAM_PARAM_CACHESIZE:                cachesize=(ham_size_t)param->value;                break;            case HAM_PARAM_KEYSIZE:                if (is_env) /* calling from ham_env_create_ex? */                    return (HAM_INV_PARAMETER);                else                    keysize=(ham_u16_t)param->value;                break;            case HAM_PARAM_PAGESIZE:                pagesize=(ham_u32_t)param->value;                break;            case HAM_PARAM_DBNAME:                dbname=(ham_u16_t)param->value;                break;            default:                return (HAM_INV_PARAMETER);            }        }    }    if (dbname==EMPTY_DATABASE_NAME) {        if (!filename && !((*flags)&HAM_IN_MEMORY_DB))            return (HAM_INV_PARAMETER);    }    /*     * make sure that the pagesize is aligned to 1024k     */    if (pagesize) {        if (pagesize%1024)            return (HAM_INV_PAGESIZE);    }    /*     * in-memory-db? don't allow cache limits!     */    if ((*flags)&HAM_IN_MEMORY_DB) {        if (((*flags)&HAM_CACHE_STRICT) || cachesize!=0)            return (HAM_INV_PARAMETER);    }    /*     * in-memory-db? use the default pagesize of the system     */    if ((*flags)&HAM_IN_MEMORY_DB) {        if (!pagesize) {            pagesize=os_get_pagesize();            if (!pagesize) {                pagesize=1024*4;                no_mmap=HAM_TRUE;            }        }    }    /*     * can we use mmap?     */#if HAVE_MMAP    if (!((*flags)&HAM_DISABLE_MMAP)) {        if (pagesize) {            if (pagesize%os_get_pagesize()!=0)                no_mmap=HAM_TRUE;        }        else {            pagesize=os_get_pagesize();            if (!pagesize) {                pagesize=1024*4;                no_mmap=HAM_TRUE;            }        }    }#else    no_mmap=HAM_TRUE;#endif    /*     * if we still don't have a pagesize, try to get a good default value     */    if (!pagesize) {        pagesize=os_get_pagesize();        if (!pagesize) {            pagesize=1024*4;            no_mmap=HAM_TRUE;        }    }    /*     * set the database flags if we can't use mmapped I/O     */    if (no_mmap) {        (*flags)&=~DB_USE_MMAP;        (*flags)|=HAM_DISABLE_MMAP;    }    /*     * make sure that the pagesize is big enough for at least 5 keys     */    if (keysize)        if (pagesize/keysize<5)            return (HAM_INV_KEYSIZE);    /*     * initialize the database with a good default value;     * 32byte is the size of a first level cache line for most modern     * processors; adjust the keysize, so the keys are aligned to     * 32byte     */    if (keysize==0)        keysize=32-(sizeof(int_key_t)-1);    /*     * return the fixed parameters     */    *pcachesize=cachesize;    *pkeysize  =keysize;    *ppagesize =pagesize;    if (pdbname)        *pdbname=dbname;    return (0);}voidham_get_version(ham_u32_t *major, ham_u32_t *minor,                ham_u32_t *revision){    if (major)        *major=HAM_VERSION_MAJ;    if (minor)        *minor=HAM_VERSION_MIN;    if (revision)        *revision=HAM_VERSION_REV;}ham_status_tham_env_new(ham_env_t **env){    if (!env)        return (HAM_INV_PARAMETER);    /* allocate memory for the ham_db_t-structure;     * we can't use our allocator because it's not yet created! */    *env=(ham_env_t *)malloc(sizeof(ham_env_t));    if (!(*env))        return (HAM_OUT_OF_MEMORY);    /* reset the whole structure */    memset(*env, 0, sizeof(ham_env_t));    return (0);}ham_status_tham_env_delete(ham_env_t *env){    if (!env)        return (HAM_INV_PARAMETER);    /*     * close the device     */    if (env_get_allocator(env)) {        env_get_allocator(env)->close(env_get_allocator(env));        env_set_allocator(env, 0);    }    /*      * close the allocator     */    if (env_get_device(env)) {        if (env_get_device(env)->is_open(env_get_device(env))) {            (void)env_get_device(env)->flush(env_get_device(env));            (void)env_get_device(env)->close(env_get_device(env));        }        (void)env_get_device(env)->destroy(env_get_device(env));        env_set_device(env, 0);    }    free(env);    return (0);}ham_status_tham_env_create(ham_env_t *env, const char *filename,        ham_u32_t flags, ham_u32_t mode){    return (ham_env_create_ex(env, filename, flags, mode, 0));}ham_status_tham_env_create_ex(ham_env_t *env, const char *filename,        ham_u32_t flags, ham_u32_t mode, ham_parameter_t *param){    ham_status_t st;    ham_size_t pagesize;    ham_u16_t keysize;    ham_size_t cachesize;    ham_device_t *device;    if (!env)        return (HAM_INV_PARAMETER);    /*     * check (and modify) the parameters     */    st=__check_create_parameters(HAM_TRUE, filename, &flags, param,             &pagesize, &keysize, &cachesize, 0);    if (st)        return (st);    /*      * if we do not yet have an allocator: create a new one      */    if (!env_get_allocator(env)) {        env_set_allocator(env, ham_default_allocator_new());        if (!env_get_allocator(env))            return (HAM_OUT_OF_MEMORY);    }    /*      * initialize the device      */    device=ham_device_new(env_get_allocator(env), flags&HAM_IN_MEMORY_DB);    if (!device)        return (HAM_OUT_OF_MEMORY);    env_set_device(env, device);    /*      * create the file      */    st=device->create(device, filename, flags, mode);    if (st) {        (void)ham_env_close(env);        return (st);    }    /*     * store the parameters     */    env_set_rt_flags(env, flags);    env_set_pagesize(env, pagesize);    env_set_keysize(env, keysize);    env_set_cachesize(env, cachesize);    return (HAM_SUCCESS);}ham_status_tham_env_create_db(ham_env_t *env, ham_db_t *db,        ham_u16_t name, ham_u32_t flags, ham_parameter_t *param){    ham_status_t st;    ham_u16_t keysize=env_get_keysize(env);    if (!env || !db)        return (HAM_INV_PARAMETER);    if (!name || name>=EMPTY_DATABASE_NAME)        return (HAM_INV_PARAMETER);

⌨️ 快捷键说明

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