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

📄 db.c

📁 About: hamsterdb is a database engine written in ANSI C. It supports a B+Tree index structure, uses
💻 C
📖 第 1 页 / 共 2 页
字号:
my_purge_cache(ham_db_t *db){    ham_status_t st;    ham_page_t *page;    /*     * first, try to delete unused pages from the cache     */    if (db_get_cache(db) && !(db_get_rt_flags(db)&HAM_IN_MEMORY_DB)) {        while (cache_too_big(db_get_cache(db))) {            page=cache_get_unused_page(db_get_cache(db));            if (!page) {                if (db_get_rt_flags(db)&HAM_CACHE_STRICT)                     return (db_set_error(db, HAM_CACHE_FULL));                else                    break;            }            st=db_write_page_and_delete(page, 0);            if (st)                return (db_set_error(db, st));        }    }    /*     * then free unused extended keys. We don't do this too often to      * avoid a thrashing of the cache, and freeing unused extkeys     * is more expensive (performance-wise) than freeing unused pages.     */    if (db_get_extkey_cache(db)) {        if (db_get_txn_id(db)%10==0) {            st=extkey_cache_purge(db_get_extkey_cache(db));            if (st)                return (db_set_error(db, st));        }    }    return (HAM_SUCCESS);}ham_page_t *db_page_alloc(ham_db_t *db){    ham_status_t st;    ham_page_t *page=0;    /* purge cache, if necessary */    st=my_purge_cache(db);    if (st)        return (0);    /* try to get an unused page from the cache */    if (db_get_cache(db))        page=cache_get_unused_page(db_get_cache(db));    if (page) {        st=page_flush(page);        if (st) {            db_set_error(db, st);            return (0);        }        st=db_uncouple_all_cursors(page);        if (st) {            db_set_error(db, st);            return (0);        }        st=page_free(page);        if (st) {            db_set_error(db, st);            return (0);        }        memset(page, 0, sizeof(ham_page_t));        page_set_owner(page, db);    }    else {        page=page_new(db);        if (!page) {            db_set_error(db, st);            return (0);        }                st=page_alloc(page, db_get_pagesize(db));        if (st) {            db_set_error(db, st);            return (0);        }    }    if (page && db_get_cache(db)) {        st=cache_put_page(db_get_cache(db), page);        if (st) {            db_set_error(db, st);            return (0);        }    }    return (page);}ham_status_tdb_free_page(ham_page_t *page, ham_u32_t flags){    ham_status_t st;    ham_db_t *db=page_get_owner(page);    st=db_uncouple_all_cursors(page);    if (st)        return (st);    if (db_get_cache(db)) {        st=cache_remove_page(db_get_cache(db), page);        if (st)            return (st);    }    /*     * if this page has a header, and it's either a B-Tree root page or      * a B-Tree index page: remove all extended keys from the cache,      * and/or free their blobs     *     * TODO move this to the backend!     * TODO not necessary, if we come from my_free_cb (hamsterdb)     */    if (page_get_pers(page) && 	    (!(page_get_npers_flags(page)&PAGE_NPERS_NO_HEADER)) &&         (page_get_type(page)==PAGE_TYPE_B_ROOT ||          page_get_type(page)==PAGE_TYPE_B_INDEX)) {        ham_size_t i;        ham_offset_t blobid;        int_key_t *bte;        btree_node_t *node=ham_page_get_btree_node(page);        extkey_cache_t *c=db_get_extkey_cache(page_get_owner(page));        for (i=0; i<btree_node_get_count(node); i++) {            bte=btree_node_get_key(db, node, i);            if (key_get_flags(bte)&KEY_IS_EXTENDED) {                blobid=key_get_extended_rid(db, bte);                if (db_get_rt_flags(db)&HAM_IN_MEMORY_DB) {                    /* delete the blobid to prevent that it's freed twice */                    *(ham_offset_t *)(key_get_key(bte)+                        (db_get_keysize(db)-sizeof(ham_offset_t)))=0;                }                (void)blob_free(db, blobid, 0);                (void)extkey_cache_remove(c, blobid);            }        }    }#if 0    /*     * free the page; this will automatically flush the page, if      * it's dirty     */    st=page_free(page);    if (st)        return (st);#endif    /*     * move the page to the freelist     */    if (flags&DB_MOVE_TO_FREELIST) {        if (!(db_get_rt_flags(db)&HAM_IN_MEMORY_DB))            (void)freel_mark_free(db, page_get_self(page), db_get_pagesize(db));    }    /*     * free the page; since it's deleted, we don't need to flush it     */    page_set_dirty(page, HAM_FALSE);    (void)page_free(page);    (void)page_delete(page);    return (HAM_SUCCESS);}ham_page_t *db_alloc_page(ham_db_t *db, ham_u32_t type, ham_u32_t flags){    ham_status_t st;    ham_offset_t tellpos=0;    ham_page_t *page=0;    /* purge the cache, if necessary */    st=my_purge_cache(db);    if (st)        return (0);    /* first, we ask the freelist for a page */    if (!(flags&PAGE_IGNORE_FREELIST)) {        tellpos=freel_alloc_page(db);        if (tellpos) {            ham_assert(tellpos%db_get_pagesize(db)==0,                    ("page id %llu is not aligned", tellpos));            /* try to fetch the page from the txn */            if (db_get_txn(db)) {                page=txn_get_page(db_get_txn(db), tellpos);                if (page)                    goto done;            }            /* try to fetch the page from the cache */            if (db_get_cache(db)) {                page=cache_get_page(db_get_cache(db), tellpos);                if (page)                    goto done;            }            /* allocate a new page structure */            page=page_new(db);            if (!page)                return (0);            page_set_self(page, tellpos);            /* fetch the page from disk */            st=page_fetch(page, db_get_pagesize(db));            if (st) {                page_delete(page);                return (0);            }            goto done;        }    }    if (!page) {        page=page_new(db);        if (!page)            return (0);    }    st=page_alloc(page, db_get_pagesize(db));    if (st)        return (0);done:    page_set_type(page, type);    page_set_dirty(page, 0);    if (flags&PAGE_CLEAR_WITH_ZERO)        memset(page_get_pers(page), 0, db_get_pagesize(db));    if (db_get_txn(db)) {        st=txn_add_page(db_get_txn(db), page);        if (st) {            db_set_error(db, st);            /* TODO memleak? */            return (0);        }    }    if (db_get_cache(db)) {        st=cache_put_page(db_get_cache(db), page);        if (st) {            db_set_error(db, st);            /* TODO memleak? */            return (0);        }    }    return (page);}ham_page_t *db_fetch_page(ham_db_t *db, ham_offset_t address, ham_u32_t flags){    ham_page_t *page=0;    ham_status_t st;    if (db_get_txn(db)) {        page=txn_get_page(db_get_txn(db), address);        if (page)            return (page);    }    if (db_get_cache(db)) {        page=cache_get_page(db_get_cache(db), address);        if (page) {            if (db_get_txn(db)) {                st=txn_add_page(db_get_txn(db), page);                if (st) {                    db_set_error(db, st);                    return (0);                }            }            st=cache_put_page(db_get_cache(db), page);            if (st) {                db_set_error(db, st);                return (0);            }            return (page);        }    }    if (flags&DB_ONLY_FROM_CACHE)        return (0);    /* check if the cache allows us to allocate another page */    st=my_purge_cache(db);    if (st)        return (0);    page=page_new(db);    if (!page)        return (0);    page_set_self(page, address);    st=page_fetch(page, db_get_pagesize(db));    if (st) {        (void)page_delete(page);        return (0);    }    if (db_get_txn(db)) {        st=txn_add_page(db_get_txn(db), page);        if (st) {            db_set_error(db, st);            (void)page_delete(page);            return (0);        }    }    if (db_get_cache(db)) {        st=cache_put_page(db_get_cache(db), page);        if (st) {            db_set_error(db, st);            (void)page_delete(page);            return (0);        }    }    return (page);}ham_status_tdb_flush_page(ham_db_t *db, ham_page_t *page, ham_u32_t flags){    ham_status_t st;    /* write the page, if it's dirty and if write-through is enabled */    if ((db_get_rt_flags(db)&HAM_WRITE_THROUGH || flags&HAM_WRITE_THROUGH) &&         page_is_dirty(page)) {        st=page_flush(page);        if (st)            return (st);    }    if (db_get_cache(db))        return (cache_put_page(db_get_cache(db), page));    return (0);}ham_status_tdb_flush_all(ham_db_t *db, ham_u32_t flags){    ham_status_t st;    ham_page_t *head;    if (!db_get_cache(db))         return (0);    head=cache_get_totallist(db_get_cache(db));     while (head) {        ham_page_t *next=page_get_next(head, PAGE_LIST_CACHED);        /*         * don't remove the page from the cache, if flag NODELETE         * is set (this flag is used i.e. in ham_flush())         */        if (!(flags&DB_FLUSH_NODELETE)) {            ham_assert(page_get_refcount(head)==0,                 ("page is in use, but database is closing"));            cache_set_totallist(db_get_cache(db),                 page_list_remove(cache_get_totallist(db_get_cache(db)),                 PAGE_LIST_CACHED, head));            cache_set_cur_elements(db_get_cache(db),                 cache_get_cur_elements(db_get_cache(db))-1);        }        st=db_write_page_and_delete(head, flags);        if (st)             ham_log(("failed to flush page (%d) - ignoring error...", st));        head=next;    }    return (HAM_SUCCESS);}ham_status_tdb_write_page_and_delete(ham_page_t *page, ham_u32_t flags){    ham_status_t st;    ham_db_t *db=page_get_owner(page);    /*     * write page to disk if it's dirty (and if we don't have      * an IN-MEMORY DB)     */    if (page_is_dirty(page) && !(db_get_rt_flags(db)&HAM_IN_MEMORY_DB)) {        st=page_flush(page);        if (st)            return (st);    }    /*     * if the page is deleted, uncouple all cursors, then     * free the memory of the page     */    if (!(flags&DB_FLUSH_NODELETE)) {        st=db_uncouple_all_cursors(page);        if (st)            return (st);        st=page_free(page);        if (st)            return (st);        page_delete(page);    }    return (HAM_SUCCESS);}

⌨️ 快捷键说明

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