📄 hamsterdb.c
字号:
/* * 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 + -