📄 db.c
字号:
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 + -