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

📄 hamsterdb.c

📁 About: hamsterdb is a database engine written in ANSI C. It supports a B+Tree index structure, uses
💻 C
📖 第 1 页 / 共 4 页
字号:
    /*     * only a few flags are allowed     */    if (flags&~(HAM_USE_BTREE|HAM_DISABLE_VAR_KEYLEN))        return (HAM_INV_PARAMETER);    /*      * parse parameters     */    if (param) {        for (; param->name; param++) {            switch (param->name) {            case HAM_PARAM_KEYSIZE:                keysize=(ham_u16_t)param->value;                break;            default:                return (HAM_INV_PARAMETER);            }        }    }    /*     * store the env pointer in the database     */    db_set_env(db, env);    /*     * now create the database     */    {    ham_parameter_t full_param[]={        {HAM_PARAM_PAGESIZE,  env_get_pagesize(env)},        {HAM_PARAM_CACHESIZE, env_get_cachesize(env)},        {HAM_PARAM_KEYSIZE,   keysize},        {HAM_PARAM_DBNAME,    name},        {0, 0}};    st=ham_create_ex(db, 0, flags|env_get_rt_flags(env), 0, full_param);    if (st)        return (st);    }    /*     * on success: store the open database in the environment's list of     * opened databases     */    db_set_next(db, env_get_list(env));    env_set_list(env, db);    return (0);}ham_status_tham_env_open_db(ham_env_t *env, ham_db_t *db,        ham_u16_t name, ham_u32_t flags, ham_parameter_t *params){    ham_db_t *head;    ham_status_t st;    ham_parameter_t full_param[]={        {HAM_PARAM_CACHESIZE, env_get_cachesize(env)},        {HAM_PARAM_DBNAME,    name},        {0, 0}};    if (!env || !db)        return (HAM_INV_PARAMETER);    if (!name)        return (HAM_INV_PARAMETER);    if (name!=FIRST_DATABASE_NAME && name>=EMPTY_DATABASE_NAME)        return (HAM_INV_PARAMETER);    /*      * parameters aren't allowed     */    if (params)        return (HAM_INV_PARAMETER);    /*     * make sure that this database is not yet open     */    head=env_get_list(env);    while (head) {        ham_u8_t *ptr=db_get_indexdata(head);        if (ham_db2h16(*(ham_u16_t *)ptr)==name)            return (HAM_DATABASE_ALREADY_OPEN);        head=db_get_next(head);    }    /*     * store the env pointer in the database     */    db_set_env(db, env);    /*     * now open the database     */    st=ham_open_ex(db, 0, flags|env_get_rt_flags(env), full_param);    if (st)        return (st);    /*     * on success: store the open database in the environment's list of     * opened databases     */    db_set_next(db, env_get_list(env));    env_set_list(env, db);    return (0);}ham_status_tham_env_open(ham_env_t *env, const char *filename, ham_u32_t flags){    return (ham_env_open_ex(env, filename, flags, 0));}ham_status_tham_env_open_ex(ham_env_t *env, const char *filename,        ham_u32_t flags, ham_parameter_t *param){    ham_status_t st;    ham_size_t cachesize=0;    ham_device_t *device=0;    if (!env)        return (HAM_INV_PARAMETER);    /*      * cannot open an in-memory-db      */    if (flags&HAM_IN_MEMORY_DB)        return (HAM_INV_PARAMETER);    /*      * parse parameters     */    if (param) {        for (; param->name; param++) {            switch (param->name) {            case HAM_PARAM_CACHESIZE:                cachesize=(ham_size_t)param->value;                break;            default:                return (HAM_INV_PARAMETER);            }        }    }    /*      * 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);    /*      * open the file      */    st=device->open(device, filename, flags);    if (st) {        (void)ham_env_close(env);        return (st);    }    /*     * store the parameters     */    env_set_pagesize(env, 0);    env_set_keysize(env, 0);    env_set_cachesize(env, cachesize);    return (HAM_SUCCESS);}ham_status_tham_env_rename_db(ham_env_t *env, ham_u16_t oldname,                 ham_u16_t newname, ham_u32_t flags){    ham_u16_t i, slot;    ham_u8_t *ptr;    ham_db_t *db;    ham_bool_t owner=HAM_FALSE;    ham_status_t st;    if (!env)        return (HAM_INV_PARAMETER);    if (!oldname || !newname || newname>=EMPTY_DATABASE_NAME)        return (HAM_INV_PARAMETER);    /*     * make sure that the environment was either created or opened, and      * a valid device exists     */    if (!env_get_device(env))        return (HAM_NOT_READY);    /*     * no need to do anything if oldname==newname     */    if (oldname==newname)        return (0);    /*     * !!     * we have to distinguish two cases: in the first case, we have a valid     * ham_db_t pointer, and can therefore access the header page.     *     * In the second case, no db was opened/created, and therefore we      * have to temporarily fetch the header page     */    if (env_get_list(env)) {        db=env_get_list(env);    }    else {        owner=HAM_TRUE;        st=ham_new(&db);        if (st)            return (st);        st=ham_env_open_db(env, db, FIRST_DATABASE_NAME, 0, 0);        if (st) {            ham_delete(db);            return (st);        }    }    /*     * check if a database with the new name already exists; also search      * for the database with the old name     */    slot=db_get_indexdata_size(db);    for (i=0; i<db_get_indexdata_size(db); i++) {        ham_u16_t name=ham_h2db16(*(ham_u16_t *)db_get_indexdata_at(db, i));        if (name==newname) {            if (owner) {                (void)ham_close(db);                (void)ham_delete(db);            }            return (HAM_DATABASE_ALREADY_EXISTS);        }        if (name==oldname)            slot=i;    }    if (slot==db_get_indexdata_size(db)) {        if (owner) {            (void)ham_close(db);            (void)ham_delete(db);        }        return (HAM_DATABASE_NOT_FOUND);    }    /*     * replace the database name with the new name     */    ptr=db_get_indexdata_at(db, slot);    *(ham_u16_t *)ptr=ham_db2h16(newname);    db_set_dirty(db, HAM_TRUE);        if (owner) {        (void)ham_close(db);        (void)ham_delete(db);    }    return (0);}ham_status_tham_env_erase_db(ham_env_t *env, ham_u16_t name, ham_u32_t flags){    ham_db_t *db;    ham_status_t st;    free_cb_context_t context;    ham_txn_t txn;    if (!env || !name)        return (HAM_INV_PARAMETER);    /*     * check if this database is still open     */    db=env_get_list(env);    while (db) {        ham_u16_t dbname=ham_db2h16(*(ham_u16_t *)db_get_indexdata(db));        if (dbname==name)            return (HAM_DATABASE_ALREADY_OPEN);        db=db_get_next(db);    }    /*     * if it's an in-memory environment: no need to go on, if the      * database was closed, it does no longer exist     */    if (env_get_rt_flags(env)&HAM_IN_MEMORY_DB)        return (HAM_DATABASE_NOT_FOUND);    /*     * temporarily load the database     */    st=ham_new(&db);    if (st)        return (st);    st=ham_env_open_db(env, db, name, 0, 0);    if (st) {        (void)ham_delete(db);        return (st);    }    /*     * delete all blobs and extended keys, also from the cache and     * the extkey_cache     *     * also delete all pages and move them to the freelist; if they're      * cached, delete them from the cache     */    if ((st=ham_txn_begin(&txn, db))) {        (void)ham_close(db);        (void)ham_delete(db);        return (st);    }    context.db=db;    st=db_get_backend(db)->_fun_enumerate(db_get_backend(db),             my_free_cb, &context);    if (st) {        (void)ham_txn_abort(&txn);        (void)ham_close(db);        (void)ham_delete(db);        return (st);    }    st=ham_txn_commit(&txn, 0);    if (st) {        (void)ham_close(db);        (void)ham_delete(db);        return (st);    }    /*     * set database name to 0     */    *(ham_u16_t *)db_get_indexdata(db)=ham_h2db16(0);    db_set_dirty(db, HAM_TRUE);    /*     * clean up and return     */    (void)ham_close(db);    (void)ham_delete(db);    return (0);}ham_status_tham_env_close(ham_env_t *env){    if (!env)        return (HAM_INV_PARAMETER);    if (env_get_list(env))        return (HAM_ENV_NOT_EMPTY);    /*     * close the header page     *     * !!     * the last database, which was closed, has set the owner of the      * page to 0, which means that we can't call page_free, page_delete     * etc. We have to use the device-routines.     */    if (env_get_header_page(env)) {        ham_device_t *device=env_get_device(env);        ham_page_t *page=env_get_header_page(env);        if (page_get_pers(page))            (void)device->free_page(device, page);        allocator_free(env_get_allocator(env), page);        env_set_header_page(env, 0);    }    /*      * close the device     */    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);    }    /*      * close the memory allocator      */    if (env_get_allocator(env)) {        env_get_allocator(env)->close(env_get_allocator(env));        env_set_allocator(env, 0);    }    return (HAM_SUCCESS);}ham_status_tham_new(ham_db_t **db){    if (!db)        return (HAM_INV_PARAMETER);    /* allocate memory for the ham_db_t-structure;     * we can't use our allocator because it's not yet created! */    *db=(ham_db_t *)malloc(sizeof(ham_db_t));    if (!(*db))        return (HAM_OUT_OF_MEMORY);    /* reset the whole structure */    memset(*db, 0, sizeof(ham_db_t));    return (0);}ham_status_tham_delete(ham_db_t *db){    if (!db)        return (HAM_INV_PARAMETER);    /* free cached data pointers */    if (db_get_record_allocdata(db))        ham_mem_free(db, db_get_record_allocdata(db));    if (db_get_key_allocdata(db))        ham_mem_free(db, db_get_key_allocdata(db));    /* "free" all remaining memory */    free(db);    return (0);}ham_status_tham_open(ham_db_t *db, const char *filename, ham_u32_t flags){    return (ham_open_ex(db, filename, flags, 0));}ham_status_tham_open_ex(ham_db_t *db, const char *filename,        ham_u32_t flags, ham_parameter_t *param){    ham_status_t st;    ham_cache_t *cache;    ham_backend_t *backend;    ham_u8_t hdrbuf[512];    ham_u16_t dbname=EMPTY_DATABASE_NAME;    ham_size_t i, cachesize=0, pagesize=0;    ham_page_t *page;    ham_device_t *device;    if (!db)        return (HAM_INV_PARAMETER);    db_set_error(db, 0);    /* cannot open an in-memory-db */    if (flags&HAM_IN_MEMORY_DB)        return (db_set_error(db, HAM_INV_PARAMETER));    /* 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_DBNAME:                dbname=(ham_u16_t)param->value;                break;            default:                return (db_set_error(db, HAM_INV_PARAMETER));            }        }    }    if (dbname==EMPTY_DATABASE_NAME && !filename)        return (HAM_INV_PARAMETER);    /*      * if we do not yet have an allocator: create a new one      */    if (!db_get_allocator(db)) {        if (db_get_env(db))            env_set_allocator(db_get_env(db), ham_default_allocator_new());        else            db_set_allocator(db, ham_default_allocator_new());        if (!db_get_allocator(db))            return (db_set_error(db, HAM_OUT_OF_MEMORY));    }    /*      * initialize the device     */    if (!db_get_device(db)) {        device=ham_device_new(db_get_allocator(db), flags&HAM_IN_MEMORY_DB);        if (!device)            return (db_get_error(db));        if (db_get_env(db))            env_set_device(db_get_env(db), device);        else            db_set_device(db, device);        /*          * open the file          */        st=device->open(device, filename, flags);        if (st) {            (void)ham_close(db);            return (db_set_error(db, st));        }        /*         * read the database header         *         * !!!         * now this is an ugly problem - the database header is one page, but         * how large is one page? chances are good that it's the default         * page-size, but we really can't be sure.         *         * read 512 byte and extract the "real" page size, then read          * the real page. (but i really don't like this)

⌨️ 快捷键说明

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