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

📄 btree_insert.c

📁 About: hamsterdb is a database engine written in ANSI C. It supports a B+Tree index structure, uses
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * Copyright (C) 2005-2007 Christoph Rupp (chris@crupp.de). * All rights reserved. See file LICENSE for licence and copyright * information. * * btree inserting * */#include <string.h>#include "db.h"#include "error.h"#include "keys.h"#include "page.h"#include "btree.h"#include "blob.h"#include "mem.h"#include "util.h"#include "btree_cursor.h"/* * the insert_scratchpad_t structure helps us to propagate return values * from the bottom of the tree to the root. */typedef struct{    /*     * the backend pointer     */    ham_btree_t *be;    /*     * the flags of the ham_insert()-call     */    ham_u32_t flags;    /*     * the record which is inserted     */    ham_record_t *record;    /*     * a key; this is used to propagate SMOs (structure modification     * operations) from a child page to a parent page     */    ham_key_t key;    /*     * a RID; this is used to propagate SMOs (structure modification     * operations) from a child page to a parent page     */    ham_offset_t rid;    /*     * a pointer to a cursor; if this is a valid pointer, then this      * cursor will point to the new inserted item     */    ham_bt_cursor_t *cursor;} insert_scratchpad_t;/* * return values */#define SPLIT     1/* * flags for my_insert_nosplit() */#define NOFLUSH   0x1000    /* avoid conflicts with public flags */#define OVERWRITE HAM_OVERWRITE/* * this is the function which does most of the work - traversing to a  * leaf, inserting the key using my_insert_in_page()  * and performing necessary SMOs. it works recursive. */static ham_status_tmy_insert_recursive(ham_page_t *page, ham_key_t *key,         ham_offset_t rid, insert_scratchpad_t *scratchpad);/* * this function inserts a key in a page */static ham_status_tmy_insert_in_page(ham_page_t *page, ham_key_t *key,         ham_offset_t rid, ham_u32_t flags,         insert_scratchpad_t *scratchpad);/* * insert a key in a page; the page MUST have free slots */static ham_status_tmy_insert_nosplit(ham_page_t *page, ham_key_t *key,         ham_offset_t rid, ham_record_t *record,         ham_bt_cursor_t *cursor, ham_u32_t flags);/* * split a page and insert the new element */static ham_status_tmy_insert_split(ham_page_t *page, ham_key_t *key,         ham_offset_t rid, ham_u32_t flags,         insert_scratchpad_t *scratchpad);ham_status_tbtree_insert_cursor(ham_btree_t *be, ham_key_t *key,         ham_record_t *record, ham_bt_cursor_t *cursor, ham_u32_t flags){    ham_status_t st;    ham_page_t *root;    ham_db_t *db=btree_get_db(be);    insert_scratchpad_t scratchpad;    /*      * initialize the scratchpad      */    memset(&scratchpad, 0, sizeof(scratchpad));    scratchpad.be=be;    scratchpad.flags=flags;    scratchpad.record=record;    scratchpad.cursor=cursor;    /*      * get the root-page...     */    ham_assert(btree_get_rootpage(be)!=0, ("btree has no root page"));    root=db_fetch_page(db, btree_get_rootpage(be), 0);    /*      * ... and start the recursion      */    st=my_insert_recursive(root, key, 0, &scratchpad);    /*     * if the root page was split, we have to create a new     * root page.     */    if (st==SPLIT) {        ham_page_t *newroot;        btree_node_t *node;        /*         * allocate a new root page         */        newroot=db_alloc_page(db, PAGE_TYPE_B_ROOT, 0);         if (!newroot)            return (db_get_error(db));        /* clear the node header */        memset(page_get_payload(newroot), 0, sizeof(btree_node_t));        /*          * insert the pivot element and the ptr_left         */         node=ham_page_get_btree_node(newroot);        btree_node_set_ptr_left(node, btree_get_rootpage(be));        st=my_insert_nosplit(newroot, &scratchpad.key,                 scratchpad.rid, scratchpad.record, scratchpad.cursor,                 flags|NOFLUSH);        scratchpad.cursor=0; /* don't overwrite cursor if my_insert_nosplit                                is called again */        if (st) {            if (scratchpad.key.data)                ham_mem_free(db, scratchpad.key.data);            return (st);        }        /*         * set the new root page         *         * !!         * do NOT delete the old root page - it's still in use!         */        btree_set_rootpage(be, page_get_self(newroot));        btree_set_dirty(be, HAM_TRUE);        db_set_dirty(db, 1);        page_set_type(root, PAGE_TYPE_B_INDEX);    }    /*     * release the scratchpad-memory and return to caller     */    if (scratchpad.key.data)        ham_mem_free(db, scratchpad.key.data);    return (st);}ham_status_tbtree_insert(ham_btree_t *be, ham_key_t *key,         ham_record_t *record, ham_u32_t flags){    return (btree_insert_cursor(be, key, record, 0, flags));}static ham_status_tmy_insert_recursive(ham_page_t *page, ham_key_t *key,         ham_offset_t rid, insert_scratchpad_t *scratchpad){    ham_status_t st;    ham_page_t *child;    ham_db_t *db=page_get_owner(page);    btree_node_t *node=ham_page_get_btree_node(page);    /*     * if we've reached a leaf: insert the key     */    if (btree_node_is_leaf(node))         return (my_insert_in_page(page, key, rid,                     scratchpad->flags, scratchpad));    /*     * otherwise traverse the root down to the leaf     */    child=btree_traverse_tree(db, page, key, 0);    if (!child)        return (db_get_error(db));    /*     * and call this function recursively     */    st=my_insert_recursive(child, key, rid, scratchpad);    switch (st) {        /*         * if we're done, we're done         */        case HAM_SUCCESS:            break;        /*         * if we tried to insert a duplicate key, we're done, too         */        case HAM_DUPLICATE_KEY:            break;        /*         * the child was split, and we have to insert a new (key/rid)-tuple.         */        case SPLIT:            st=my_insert_in_page(page, &scratchpad->key,                         scratchpad->rid, scratchpad->flags|HAM_OVERWRITE,                         scratchpad);            break;        /*         * every other return value is unexpected and shouldn't happen         */        default:            db_set_error(db, st);            break;    }    return (st);}static ham_status_tmy_insert_in_page(ham_page_t *page, ham_key_t *key,         ham_offset_t rid, ham_u32_t flags,         insert_scratchpad_t *scratchpad){    ham_size_t maxkeys=btree_get_maxkeys(scratchpad->be);    btree_node_t *node=ham_page_get_btree_node(page);    ham_assert(maxkeys>1,             ("invalid result of db_get_maxkeys(): %d", maxkeys));    /*     * if we can insert the new key without splitting the page:      * my_insert_nosplit() will do the work for us     */    if (btree_node_get_count(node)<maxkeys) {        ham_status_t st=my_insert_nosplit(page, key, rid,                     scratchpad->record, scratchpad->cursor, flags);        scratchpad->cursor=0; /* don't overwrite cursor if my_insert_nosplit                                 is called again */        return (st);    }    /*     * otherwise, we have to split the page.     * but BEFORE we split, we check if the key already exists!     */    if (btree_node_is_leaf(node)) {        if (btree_node_search_by_key(page_get_owner(page), page, key)>=0) {            if (flags&HAM_OVERWRITE) {                ham_status_t st=my_insert_nosplit(page, key, rid,                         scratchpad->record, scratchpad->cursor, flags);                /* don't overwrite cursor if my_insert_nosplit                   is called again */                scratchpad->cursor=0;                 return (st);            }            else                return (HAM_DUPLICATE_KEY);        }    }    return (my_insert_split(page, key, rid, flags, scratchpad));}static ham_status_tmy_insert_nosplit(ham_page_t *page, ham_key_t *key,         ham_offset_t rid, ham_record_t *record,         ham_bt_cursor_t *cursor, ham_u32_t flags){    int cmp;    ham_status_t st;    ham_bool_t overwrite=HAM_FALSE;    ham_size_t i, count, keysize;    int_key_t *bte=0;    btree_node_t *node;    ham_db_t *db=page_get_owner(page);    ham_s32_t slot;    ham_u32_t oldflags;    node=ham_page_get_btree_node(page);    count=btree_node_get_count(node);    keysize=db_get_keysize(db);    /*     * uncouple all cursors     */    st=db_uncouple_all_cursors(page);    if (st)        return (db_set_error(db, st));    if (btree_node_get_count(node)==0)        slot=0;    else {        st=btree_get_slot(db, page, key, &slot);        if (st)            return (db_set_error(db, st));        /* insert the new key at the beginning? */        if (slot==-1) {            slot++;            bte=btree_node_get_key(db, node, slot);            goto shift_elements;        }        cmp=key_compare_int_to_pub(page, (ham_u16_t)slot, key);        if (db_get_error(db))            return (db_get_error(db));        bte=btree_node_get_key(db, node, slot);        /*         * key exists already         */        if (cmp==0) {            if (flags&HAM_OVERWRITE) {                /*                  * no need to overwrite the key - it already exists!                  * however, we have to overwrite the data!                 */                if (btree_node_is_leaf(node))                     overwrite=HAM_TRUE;                else                    return (HAM_SUCCESS);            }            else                return (HAM_DUPLICATE_KEY);        }        /*         * otherwise, if the new key is < then the slot key, move to          * the next slot         */

⌨️ 快捷键说明

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