📄 hamsterdb.c
字号:
*/ st=device->read(device, 0, hdrbuf, sizeof(hdrbuf)); if (st) { ham_log(("os_pread of %s failed with status %d (%s)", filename, st, ham_strerror(st))); (void)ham_close(db); return (db_set_error(db, st)); } pagesize=ham_db2h32(((db_header_t *)&hdrbuf[12])->_pagesize); device_set_pagesize(device, pagesize); /* * can we use mmap? */#if HAVE_MMAP if (!(flags&HAM_DISABLE_MMAP)) { if (pagesize%os_get_pagesize()==0) flags|=DB_USE_MMAP; else device->set_flags(device, flags|HAM_DISABLE_MMAP); } else device->set_flags(device, flags|HAM_DISABLE_MMAP); flags&=~HAM_DISABLE_MMAP; /* don't store this flag */#else device->set_flags(device, flags|HAM_DISABLE_MMAP);#endif /* * create the freelist - not needed for in-memory-databases */ if (!(flags&HAM_IN_MEMORY_DB)) { st=freel_create(db); if (st) { ham_log(("unable to create freelist")); (void)ham_close(db); return (st); } } } db_set_error(db, HAM_SUCCESS); /* * read the header page */ if (!db_get_header_page(db)) { page=page_new(db); if (!page) { (void)ham_close(db); return (db_get_error(db)); } st=page_fetch(page, pagesize); if (st) { if (page_get_pers(page)) (void)page_free(page); (void)page_delete(page); (void)ham_close(db); return (st); } page_set_type(page, PAGE_TYPE_HEADER); if (db_get_env(db)) env_set_header_page(db_get_env(db), page); else db_set_header_page(db, page); } /* * otherwise, if a header page already exists (which means that we're * in an environment), we transfer the ownership of the header * page to this database */ else { page_set_owner(db_get_header_page(db), db); } /* * check the file magic */ if (db_get_magic(db, 0)!='H' || db_get_magic(db, 1)!='A' || db_get_magic(db, 2)!='M' || db_get_magic(db, 3)!='\0') { ham_log(("invalid file type - %s is not a hamster-db", filename)); (void)ham_close(db); db_set_error(db, HAM_INV_FILE_HEADER); return (HAM_INV_FILE_HEADER); } /* * check the database version */ if (db_get_version(db, 0)!=HAM_VERSION_MAJ || db_get_version(db, 1)!=HAM_VERSION_MIN) { ham_log(("invalid file version")); (void)ham_close(db); db_set_error(db, HAM_INV_FILE_VERSION); return (HAM_INV_FILE_VERSION); } /* * search for a database with this name */ for (i=0; i<db_get_indexdata_size(db); i++) { ham_u8_t *ptr=db_get_indexdata_at(db, i); if (dbname==FIRST_DATABASE_NAME || dbname==ham_h2db16(*(ham_u16_t *)ptr)) { db_set_indexdata_offset(db, i); break; } } if (i==db_get_indexdata_size(db)) { (void)ham_close(db); return (db_set_error(db, HAM_DATABASE_NOT_FOUND)); } /* * create the backend */ backend=db_create_backend(db, flags); if (!backend) { ham_log(("unable to create backend with flags 0x%x", flags)); (void)ham_close(db); db_set_error(db, HAM_INV_INDEX); return (HAM_INV_INDEX); } db_set_backend(db, backend); /* * initialize the backend */ st=backend->_fun_open(backend, flags); if (st) { ham_log(("backend create() failed with status %d (%s)", st, ham_strerror(st))); db_set_error(db, st); (void)ham_close(db); return (st); } /* * set the database flags */ db_set_rt_flags(db, flags|be_get_flags(backend)); ham_assert(!(be_get_flags(backend)&HAM_DISABLE_VAR_KEYLEN), ("invalid persistent database flags 0x%x", be_get_flags(backend))); ham_assert(!(be_get_flags(backend)&HAM_CACHE_STRICT), ("invalid persistent database flags 0x%x", be_get_flags(backend))); ham_assert(!(be_get_flags(backend)&HAM_DISABLE_MMAP), ("invalid persistent database flags 0x%x", be_get_flags(backend))); ham_assert(!(be_get_flags(backend)&HAM_WRITE_THROUGH), ("invalid persistent database flags 0x%x", be_get_flags(backend))); ham_assert(!(be_get_flags(backend)&HAM_READ_ONLY), ("invalid persistent database flags 0x%x", be_get_flags(backend))); ham_assert(!(be_get_flags(backend)&HAM_DISABLE_FREELIST_FLUSH), ("invalid persistent database flags 0x%x", be_get_flags(backend))); ham_assert(!(be_get_flags(backend)&DB_USE_MMAP), ("invalid persistent database flags 0x%x", be_get_flags(backend))); /* * initialize the cache */ if (!db_get_cache(db)) { if (cachesize==0) cachesize=HAM_DEFAULT_CACHESIZE; cache=cache_new(db, cachesize/db_get_pagesize(db)); if (!cache) { (void)ham_close(db); return (db_get_error(db)); } if (db_get_env(db)) env_set_cache(db_get_env(db), cache); else db_set_cache(db, cache); } /* * set the key compare function */ ham_set_compare_func(db, db_default_compare); ham_set_prefix_compare_func(db, db_default_prefix_compare); return (HAM_SUCCESS);}ham_status_tham_create(ham_db_t *db, const char *filename, ham_u32_t flags, ham_u32_t mode){ return (ham_create_ex(db, filename, flags, mode, 0));}ham_status_tham_create_ex(ham_db_t *db, const char *filename, ham_u32_t flags, ham_u32_t mode, ham_parameter_t *param){ ham_status_t st; ham_cache_t *cache; ham_backend_t *backend; ham_page_t *page; ham_u32_t pflags; ham_device_t *device; ham_size_t pagesize; ham_u16_t keysize, dbname=0, i; ham_size_t cachesize; if (!db) return (HAM_INV_PARAMETER); db_set_error(db, 0); /* * check (and modify) the parameters */ st=__check_create_parameters(HAM_FALSE, filename, &flags, param, &pagesize, &keysize, &cachesize, &dbname); if (st) return (db_set_error(db, st)); /* * if we do not yet have an allocator: create a new one */ if (!db_get_allocator(db)) { 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 it does not yet exist */ 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); device->set_flags(device, flags); device_set_pagesize(device, pagesize); /* * create the file */ st=device->create(device, filename, flags, mode); if (st) { (void)ham_close(db); return (db_set_error(db, st)); } } else device=db_get_device(db); /* * set the flags */ pflags=flags; pflags&=~HAM_DISABLE_VAR_KEYLEN; pflags&=~HAM_CACHE_STRICT; pflags&=~HAM_DISABLE_MMAP; pflags&=~HAM_WRITE_THROUGH; pflags&=~HAM_READ_ONLY; pflags&=~HAM_DISABLE_FREELIST_FLUSH; pflags&=~DB_USE_MMAP; db_set_rt_flags(db, flags); /* * if there's no header page, allocate one */ if (!db_get_header_page(db)) { page=page_new(db); if (!page) { ham_log(("unable to allocate the header page")); (void)ham_close(db); return (db_get_error(db)); } st=page_alloc(page, pagesize); if (st) { page_delete(page); (void)ham_close(db); return (st); } memset(page_get_pers(page), 0, pagesize); page_set_type(page, PAGE_TYPE_HEADER); if (db_get_env(db)) env_set_header_page(db_get_env(db), page); else db_set_header_page(db, page); page_set_dirty(page, 1); /* initialize the header */ db_set_magic(db, 'H', 'A', 'M', '\0'); db_set_version(db, HAM_VERSION_MAJ, HAM_VERSION_MIN, HAM_VERSION_REV, 0); db_set_serialno(db, HAM_SERIALNO); db_set_error(db, HAM_SUCCESS); db_set_pagesize(db, pagesize); db_set_indexdata_size(db, DB_MAX_INDICES); /* * initialize the freelist structure in the header page; * the freelist starts _after_ the header-page, therefore * the start-address of the freelist is the pagesize */ st=freel_prepare(db, db_get_freelist(db), db_get_pagesize(db), db_get_usable_pagesize(db)- (OFFSET_OF(db_header_t, _freelist_start)+1)); if (st) { ham_log(("unable to setup the freelist")); (void)ham_close(db); return (db_set_error(db, st)); } /* * create the freelist - not needed for in-memory-databases */ if (!(flags&HAM_IN_MEMORY_DB)) { st=freel_create(db); if (st) { ham_log(("unable to create freelist")); (void)ham_close(db); return (db_set_error(db, st)); } } } /* * otherwise, if a header page already exists (which means that we're * in an environment), we transfer the ownership of the header * page to this database */ else { page_set_owner(db_get_header_page(db), db); } /* * check if this database name is unique */ 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==dbname) { (void)ham_close(db); return (db_set_error(db, HAM_DATABASE_ALREADY_EXISTS)); } } /* * find a free slot in the indexdata array and store the * database name */ for (i=0; i<db_get_indexdata_size(db); i++) { ham_u8_t *ptr=db_get_indexdata_at(db, i); ham_u16_t name=ham_h2db16(*(ham_u16_t *)ptr); if (!name) { *(ham_u16_t *)ptr=ham_db2h16(dbname); db_set_indexdata_offset(db, i); break; } } if (i==db_get_indexdata_size(db)) { (void)ham_close(db); return (db_set_error(db, HAM_INTERNAL_ERROR)); /* TODO */ } /* * initialize the cache */ if (!db_get_cache(db)) { if (cachesize==0) cachesize=HAM_DEFAULT_CACHESIZE; cache=cache_new(db, cachesize/db_get_pagesize(db)); if (!cache) { (void)ham_close(db); return (db_get_error(db)); } if (db_get_env(db)) env_set_cache(db_get_env(db), cache); else db_set_cache(db, cache); } /* * create the backend */ backend=db_create_backend(db, flags); if (!backend) { ham_log(("unable to create backend with flags 0x%x", flags)); (void)ham_close(db); return (db_set_error(db, HAM_INV_INDEX)); } /* * initialize the backend */ st=backend->_fun_create(backend, keysize, pflags); if (st) { ham_log(("unable to create the backend")); (void)ham_close(db); db_set_error(db, st); return (st); } /* * store the backend in the database */ db_set_backend(db, backend); /* * set the default key compare functions */ ham_set_compare_func(db, db_default_compare); ham_set_prefix_compare_func(db, db_default_prefix_compare); db_set_dirty(db, HAM_TRUE); return (HAM_SUCCESS);}ham_status_tham_get_error(ham_db_t *db){ if (!db) return (0); return (db_get_error(db));}ham_status_tham_set_prefix_compare_func(ham_db_t *db, ham_prefix_compare_func_t foo){ if (!db) return (HAM_INV_PARAMETER); db_set_error(db, 0); db_set_prefix_compare_func(db, foo); return (HAM_SUCCESS);}ham_status_tham_set_compare_func(ham_db_t *db, ham_compare_func_t foo){ if (!db) return (HAM_INV_PARAMETER); db_set_error(db, 0); db_set_compare_func(db, foo); return (HAM_SUCCESS);}ham_status_tham_find(ham_db_t *db, void *reserved, ham_key_t *key, ham_record_t *record, ham_u32_t flags){ ham_txn_t txn; ham_status_t st; ham_backend_t *be; if (!db || !key || !record) return (HAM_INV_PARAMETER); if (db_get_env(db)) __prepare_db(db); db_set_error(db, 0); be=db_get_backend(db); if (!be) return (db_set_error(db, HAM_INV_INDEX)); if ((st=ham_txn_begin(&txn, db))) return (st); /* * first look up the blob id, then fetch the blob */ st=be->_fun_find(be, key, record, flags); if (st==HAM_SUCCESS) st=util_read_record(db, record, flags); if (st) { (void)ham_txn_abort(&txn); return (st); } return (ham_txn_commit(&txn, 0));}ham_status_tham_insert(ham_db_t *db, void *reserved, ham_key_t *key, ham_record_t *record, ham_u32_t flags){ ham_txn_t txn; ham_status_t st; ham_backend_t *be; if (!db || !key || !record) return (HAM_INV_PARAMETER); if (db_get_env(db)) __prepare_db(db); db_set_error(db, 0); be=db_get_backend(db); if (!be) return (db_set_error(db, HAM_INV_INDEX)); if (db_get_rt_flags(db)&HAM_READ_ONLY) return (db_set_error(db, HAM_DB_READ_ONLY)); if ((db_get_rt_flags(db)&HAM_DISABLE_VAR_KEYLEN) && (key->size>db_get_keysize(db))) return (db_set_error(db, HAM_INV_KEYSIZE)); if ((db_get_keysize(db)<sizeof(ham_offset_t)) && (key->size>db_get_keysize(db))) return (db_set_error(db, HAM_INV_KEYSIZE)); if ((st=ham_txn_begin(&txn, db))) return (st); /* * store the index entry; the backend will store the blob */ st=be->_fun_insert(be, key, record, flags); if (st) {#if 0 (void)ham_txn_abort(&txn);#endif (void)ham_txn_commit(&txn, 0); return (st); } return (ham_txn_commit(&txn, 0));}ham_status_tham_erase(ham_db_t *db, void *reserved, ham_key_t *key, ham_u32_t flags){ ham_txn_t txn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -