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

📄 blob.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. * */#include <string.h>#include <ham/hamsterdb.h>#include "os.h"#include "db.h"#include "blob.h"#include "error.h"#include "freelist.h"#include "mem.h"#include "page.h"#define SMALLEST_CHUNK_SIZE  (sizeof(ham_offset_t)+sizeof(blob_t)+1)static ham_bool_tmy_blob_is_small(ham_db_t *db, ham_size_t size){    return (size<(ham_size_t)(db_get_pagesize(db)/3));}static ham_status_tmy_write_chunks(ham_db_t *db, ham_page_t *page,         ham_offset_t addr, ham_u8_t **chunk_data, ham_size_t *chunk_size,         ham_size_t chunks){    ham_size_t i;    ham_status_t st;    ham_offset_t pageid;    ham_device_t *device=db_get_device(db);    /*     * for each chunk...     */    for (i=0; i<chunks; i++) {        while (chunk_size[i]) {            /*             * get the page-ID from this chunk             */            pageid=(addr/db_get_pagesize(db))*db_get_pagesize(db);            /*             * is it the current page? if not, try to fetch the page from             * the cache - but only read the page from disk, if the              * chunk is small             */            if (!(page && page_get_self(page)==pageid) ||                     my_blob_is_small(db, chunk_size[i])) {                page=db_fetch_page(db, pageid,                         my_blob_is_small(db, chunk_size[i])                         ? 0 : DB_ONLY_FROM_CACHE);                /* blob pages don't have a page header */                if (page)                    page_set_npers_flags(page,                         page_get_npers_flags(page)|PAGE_NPERS_NO_HEADER);            }            /*             * if we have a page pointer: use it; otherwise write directly             * to the device             */            if (page) {                ham_size_t writestart=                        (ham_size_t)(addr-page_get_self(page));                ham_size_t writesize =                        (ham_size_t)(db_get_pagesize(db)-writestart);                if (writesize>chunk_size[i])                    writesize=chunk_size[i];                memcpy(&page_get_raw_payload(page)[writestart], chunk_data[i],                            writesize);                page_set_dirty(page, 1);                addr+=writesize;                chunk_data[i]+=writesize;                chunk_size[i]-=writesize;            }            else {                ham_size_t s=chunk_size[i]<db_get_pagesize(db)                         ? chunk_size[i] : db_get_pagesize(db);                /* limit to the next page boundary */                if (s>pageid+db_get_pagesize(db)-addr)                    s=(ham_size_t)(pageid+db_get_pagesize(db)-addr);                st=device->write(device, addr, chunk_data[i], s);                if (st)                    return (st);                addr+=s;                chunk_data[i]+=s;                chunk_size[i]-=s;            }        }    }    return (0);}static ham_status_tmy_read_chunk(ham_db_t *db, ham_offset_t addr,         ham_u8_t *data, ham_size_t size){    ham_status_t st;    ham_page_t *page=0;    ham_offset_t pageid;    ham_device_t *device=db_get_device(db);    while (size) {        /*         * get the page-ID from this chunk         */        pageid=(addr/db_get_pagesize(db))*db_get_pagesize(db);        /*         * is it the current page? if not, try to fetch the page from         * the cache - but only read the page from disk, if the          * chunk is small         */        if (!(page && page_get_self(page)==pageid) ||                 my_blob_is_small(db, size)) {            page=db_fetch_page(db, pageid,                     my_blob_is_small(db, size) ? 0 : DB_ONLY_FROM_CACHE);            /* blob pages don't have a page header */            if (page)                page_set_npers_flags(page,                     page_get_npers_flags(page)|PAGE_NPERS_NO_HEADER);            else                if (db_get_error(db))                    return (db_get_error(db));        }        /*         * if we have a page pointer: use it; otherwise read directly         * from the device         */        if (page) {            ham_size_t readstart=                    (ham_size_t)(addr-page_get_self(page));            ham_size_t readsize =                    (ham_size_t)(db_get_pagesize(db)-readstart);            if (readsize>size)                readsize=size;            memcpy(data, &page_get_raw_payload(page)[readstart], readsize);            addr+=readsize;            data+=readsize;            size-=readsize;        }        else {            ham_size_t s=size<db_get_pagesize(db)                     ? size : db_get_pagesize(db);            /* limit to the next page boundary */            if (s>pageid+db_get_pagesize(db)-addr)                s=(ham_size_t)(pageid+db_get_pagesize(db)-addr);            st=device->read(device, addr, data, s);            if (st)                 return (st);            addr+=s;            data+=s;            size-=s;        }    }    return (0);}ham_status_tblob_allocate(ham_db_t *db, ham_u8_t *data,         ham_size_t size, ham_u32_t flags, ham_offset_t *blobid){    ham_status_t st;    ham_page_t *page=0;    ham_offset_t addr;    blob_t hdr;    ham_u8_t *chunk_data[2];    ham_size_t alloc_size, chunk_size[2];    ham_device_t *device=db_get_device(db);       *blobid=0;    /*     * in-memory-database: the blobid is actually a pointer to the memory     * buffer, in which the blob (with the blob-header) is stored     */    if (db_get_rt_flags(db)&HAM_IN_MEMORY_DB) {        blob_t *hdr;        ham_u8_t *p=(ham_u8_t *)ham_mem_alloc(db, size+sizeof(blob_t));        if (!p) {            db_set_error(db, HAM_OUT_OF_MEMORY);            return (HAM_OUT_OF_MEMORY);        }        memcpy(p+sizeof(blob_t), data, size);        /* initialize the header */        hdr=(blob_t *)p;        memset(hdr, 0, sizeof(&hdr));        blob_set_self(hdr, (ham_offset_t)p);        blob_set_alloc_size(hdr, size+sizeof(blob_t));        blob_set_real_size(hdr, size+sizeof(blob_t));        blob_set_user_size(hdr, size);        *blobid=(ham_offset_t)p;        return (0);    }    memset(&hdr, 0, sizeof(hdr));    /*     * blobs are CHUNKSIZE-allocated      */    alloc_size=sizeof(blob_t)+size;    if (alloc_size%DB_CHUNKSIZE!=0)        alloc_size=((alloc_size/DB_CHUNKSIZE)*DB_CHUNKSIZE)+DB_CHUNKSIZE;    /*      * check if we have space in the freelist      */    addr=freel_alloc_area(db, alloc_size);    if (!addr) {        /*         * if the blob is small, we load the page through the cache         */        if (my_blob_is_small(db, alloc_size)) {            page=db_alloc_page(db, PAGE_TYPE_B_INDEX|PAGE_IGNORE_FREELIST, 0);            if (!page)                return (db_get_error(db));            /* blob pages don't have a page header */            page_set_npers_flags(page,                     page_get_npers_flags(page)|PAGE_NPERS_NO_HEADER);            addr=page_get_self(page);            /* move the remaining space to the freelist */            (void)freel_mark_free(db, addr+alloc_size,                    db_get_pagesize(db)-alloc_size);            blob_set_alloc_size(&hdr, alloc_size);        }        /*         * otherwise use direct IO to allocate the space         */        else {            ham_size_t aligned=alloc_size;            if (aligned%db_get_pagesize(db)) {                aligned+=db_get_pagesize(db);                aligned/=db_get_pagesize(db);                aligned*=db_get_pagesize(db);            }            st=device->alloc(device, aligned, &addr);            if (st)                 return (st);            /* if aligned!=size, and the remaining chunk is large enough:             * move it to the freelist */            if (aligned!=alloc_size) {                ham_size_t diff=aligned-alloc_size;                if (diff>SMALLEST_CHUNK_SIZE) {                    (void)freel_mark_free(db, addr+alloc_size, diff);                    blob_set_alloc_size(&hdr, aligned-diff);                }                else                     blob_set_alloc_size(&hdr, aligned);            }            else                blob_set_alloc_size(&hdr, aligned);

⌨️ 快捷键说明

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