📄 pager.c
字号:
/**
* @brief 判断页缓存是否在提交前写回了页文件
*/
#define pager_page_is_written_before_page_sync(__pg) pager_page_is_sync_journal(__pg)
/**
* @brief 判断页缓存是否在提交前写回了页文件
*/
#define pager_page_is_clean_not_in_jf(__pg) (PAGE_CLEAN == __pg->pg_state)
/**
* @brief 获取有多少页被缓存
*/
#define pager_get_cached_pages_count(__pgr) MyHashTableGetElementCount(__pgr->hash_page)
/**
* @brief 计算jf日志记录的长度
*/
#define pager_get_journal_rec_len(__pgr) (__pgr->page_size + sizeof(unsigned int) + sizeof(unsigned int))
/**
* @brief 写一个无符号整理数至文件
*/
static __INLINE__ int pager_write_uint_to_file(HOSFILE hf, unsigned int uint_val)
{
unsigned char acVal[sizeof(unsigned int)];
assert(hf);
uint_to_big_endian(uint_val, acVal, sizeof(acVal));
if(0 != OsFileWrite(hf, acVal, sizeof(acVal), NULL))
return -1;
return 0;
}
/**
* @brief 从文件中读出一个整形数
*/
static __INLINE__ int pager_read_uint_from_file(HOSFILE hf, unsigned int * uint_val)
{
unsigned char acVal[sizeof(unsigned int)];
assert(hf && uint_val);
if(0 != OsFileRead(hf, acVal, sizeof(acVal), NULL))
return -1;
array_to_uint_as_big_endian(acVal, sizeof(acVal), *uint_val);
return 0;
}
/**
* @brief 在页缓存哈希表中查找
*/
static __INLINE__ pghd_t * pager_hash_lookup(pager_t * pager, unsigned int pgno)
{
HMYHASHTABLE_ITER it = NULL;
assert(pager && pager->hash_page);
it = MyHashTableSearch(pager->hash_page, (void *)pgno);
if(NULL == it)
return NULL;
assert(MyHashTableGetIterData(it));
assert(((pghd_t *)MyHashTableGetIterData(it))->pager == pager);
return (pghd_t *)MyHashTableGetIterData(it);
}
/**
* @brief 判断某一个是否处于free_list
*/
#define pager_page_is_in_free_list(__pg) (__pg->pg_free_prev || __pg->pg_free_next || __pg == __pg->pager->pg_free_first)
/**
* @brief 判断某一个是否处于sync_jf list
*/
#define pager_page_is_in_syncjf_list(__pg) (__pg->pg_syncjf_next || __pg->pg_syncjf_prev || __pg == __pg->pager->pg_syncjf_first)
/**
* @brief 判断某一个是否处于dirty list中
*/
#define pager_page_is_in_dirty_list(__pg) (__pg->pg_dirty_next || __pg->pg_dirty_prev || __pg == __pg->pager->pg_dirty)
/**
* @brief 判断某一个是否处于所有的页缓存链表中
*/
#define pager_page_is_in_all_list(__pg) (__pg->pg_all_next || __pg->pg_all_prev || __pg == __pg->pager->pg_all)
/**
* @brief 将某一个页缓存置成非dirty状态,并从dirty链表中脱离
*/
static __INLINE__ int pager_page_out_of_dirty_list(pager_t * pager, pghd_t * pg)
{
assert(pager && pg && pager == pg->pager);
assert(pager_page_is_in_dirty_list(pg));
if(pg == pager->pg_dirty)
pager->pg_dirty = pg->pg_dirty_next;
if(pg->pg_dirty_prev)
pg->pg_dirty_prev->pg_dirty_next = pg->pg_dirty_next;
if(pg->pg_dirty_next)
pg->pg_dirty_next->pg_dirty_prev = pg->pg_dirty_prev;
pg->pg_dirty_prev = NULL;
pg->pg_dirty_next = NULL;
return 0;
}
/**
* @brief 将某个页缓存加入dirty list
*/
static __INLINE__ int pager_add_page_to_dirty_list(pager_t * pager, pghd_t * pg)
{
assert(pager && pg && pager == pg->pager);
assert(!pager_page_is_in_dirty_list(pg));
assert(pager_page_is_dirty(pg));
pg->pg_dirty_prev = NULL;
pg->pg_dirty_next = pager->pg_dirty;
if(pager->pg_dirty)
pager->pg_dirty->pg_dirty_prev = pg;
pager->pg_dirty = pg;
return 0;
}
/**
* @brief 将某一个页缓存置成dirty,并加入dirty链表
*/
static __INLINE__ int pager_make_page_dirty(pager_t * pager, pghd_t * pg, PAGE_EVENT evt)
{
assert(!pager_page_is_dirty(pg));
/* 修改页状态 */
pager_change_page_state(pg, evt);
pager_add_page_to_dirty_list(pager, pg);
return 0;
}
/**
* @brief 从sync jf list里脱链
*/
static __INLINE__ int pager_out_syncjf_list(pager_t * pager, pghd_t * pg)
{
assert(pager && pg && pager == pg->pager);
assert(0 == pg->ref_count);
if(pg == pager->pg_syncjf_first)
pager->pg_syncjf_first = pg->pg_syncjf_next;
if(pg == pager->pg_syncjf_last)
pager->pg_syncjf_last = pg->pg_syncjf_prev;
/* 从已同步过日志的链表中脱链 */
if(pg->pg_syncjf_prev)
pg->pg_syncjf_prev->pg_syncjf_next = pg->pg_syncjf_next;
if(pg->pg_syncjf_next)
pg->pg_syncjf_next->pg_syncjf_prev = pg->pg_syncjf_prev;
pg->pg_syncjf_prev = NULL;
pg->pg_syncjf_next = NULL;
return 0;
}
/**
* @brief 从free list里脱链,并从已同步jf页缓存链表中脱链
*/
static __INLINE__ int pager_out_free_list(pager_t * pager, pghd_t * pg)
{
assert(pager && pg && pager == pg->pager);
assert(0 == pg->ref_count);
if(pg == pager->pg_free_first)
pager->pg_free_first = pg->pg_free_next;
if(pg == pager->pg_free_last)
pager->pg_free_last = pg->pg_free_prev;
/* 从空闲页缓存链表中脱链 */
if(pg->pg_free_prev)
pg->pg_free_prev->pg_free_next = pg->pg_free_next;
if(pg->pg_free_next)
pg->pg_free_next->pg_free_prev = pg->pg_free_prev;
pg->pg_free_prev = NULL;
pg->pg_free_next = NULL;
pager_out_syncjf_list(pager, pg);
return 0;
}
/**
* @brief 加入到空闲页缓存链表未尾
*/
static __INLINE__ int pager_add_to_free_list(pager_t * pager, pghd_t * pg)
{
assert(pager && pg && pager == pg->pager);
assert((NULL == pg->pg_free_next && NULL == pg->pg_free_prev) || (pg->pg_free_next && pg->pg_free_prev));
assert(0 == pg->ref_count);
pg->pg_free_prev = pager->pg_free_last;
if(pager->pg_free_last)
pager->pg_free_last->pg_free_next = pg;
pager->pg_free_last = pg;
if(NULL == pager->pg_free_first)
pager->pg_free_first = pg;
return 0;
}
/**
* @brief 将某个页缓存加入到已同步的jf的链表未尾,并加入到空闲页缓存链表未尾
*/
static __INLINE__ int pager_add_to_syncjf_list(pager_t * pager, pghd_t * pg)
{
assert(pager && pg && pager == pg->pager);
assert(NULL == pg->pg_syncjf_next && NULL == pg->pg_syncjf_prev);
assert(0 == pg->ref_count);
pg->pg_syncjf_prev = pager->pg_syncjf_last;
if(pager->pg_syncjf_last)
pager->pg_syncjf_last->pg_syncjf_next = pg;
if(NULL == pager->pg_syncjf_first)
pager->pg_syncjf_first = pg;
pager->pg_syncjf_last = pg;
/* 加入到空闲页缓存链表 */
if(!pager_page_is_in_free_list(pg))
pager_add_to_free_list(pager, pg);
assert(pager_page_is_in_free_list(pg));
return 0;
}
/**
* @brief 将某个页缓存加入页缓存哈希表和总的页缓存链表
*/
static __INLINE__ int pager_add_page_to_hash_and_list(pager_t * pager, pghd_t * pg)
{
assert(pager && pg && pg->pager == pager && pg->page_num);
if(NULL == MyHashTableInsertUnique(pager->hash_page, (void *)pg->page_num, pg))
return -1;
pg->pg_all_next = pager->pg_all;
if(pager->pg_all)
pager->pg_all->pg_all_prev = pg;
pager->pg_all = pg;
return 0;
}
/**
* @brief 将某个页缓存从页缓存哈希表和总的页缓存链表脱离
*/
static __INLINE__ int pager_outof_page_from_hash_and_list(pager_t * pager, pghd_t * pg)
{
assert(pager && pg && pg->pager == pager && pg->page_num);
MyHashTableDelKey(pager->hash_page, (void *)(pg->page_num), NULL, NULL);
if(pg == pager->pg_all)
pager->pg_all = pg->pg_all_next;
if(pg->pg_all_prev)
pg->pg_all_prev->pg_all_next = pg->pg_all_next;
if(pg->pg_all_next)
pg->pg_all_next->pg_all_prev = pg->pg_all_prev;
pg->pg_all_prev = NULL;
pg->pg_all_next = NULL;
return 0;
}
/**
* @brief 增加指定页的引用计数
*/
static __INLINE__ int pager_ref_page(pager_t * pager, pghd_t * pg)
{
assert(pager && pg);
assert(pg->pager == pager);
/* 如果引用计数零,则从空闲链表中除去,引用计数加1 */
if(0 == pg->ref_count)
{
//assert(pager_page_is_in_free_list(pg));
pager_out_free_list(pager, pg);
assert(!pager_page_is_in_free_list(pg));
assert(!pager_page_is_in_syncjf_list(pg));
}
pg->ref_count ++;
pager->ref_count ++;
return 0;
}
/**
* @brief 初始化页缓存
*/
static __INLINE__ int pager_init_page(pager_t * pager, pghd_t * pg, unsigned int pgno)
{
assert(pager && pg && pgno != 0);
memset(pg, 0, sizeof(*pg));
/* 根据injournal着色图初始化相关标识 */
if(pager_page_in_journal(pager, pgno))
pg->pg_state = PAGE_CLEAN_SYNC;
else
pg->pg_state = PAGE_CLEAN;
pg->pager = pager;
pg->page_num = pgno;
memset(pg->pg_buf_start + pager_get_journal_rec_len(pg->pager), 0, pager->extra_size);
return 0;
}
/**
* @brief 分配一个页缓存
*/
static __INLINE__ pghd_t * pager_allocate_page(pager_t * pager, unsigned int pgno)
{
/* 页头信息存储空间 + 页缓存空间 + 用户数据空间 + 页号与校验和存储空间 */
pghd_t * pg = (pghd_t *)MyMemPoolMalloc(pager->hm, sizeof(pghd_t) + pager->extra_size +
pager_get_journal_rec_len(pager));
if(NULL == pg)
return NULL;
pager_init_page(pager, pg, pgno);
return pg;
}
/**
* @brief 释放一个页缓存
*/
static __INLINE__ int pager_free_page(pager_t * pager, pghd_t * pg)
{
assert(pager && pg && pager == pg->pager);
assert(0 == pg->ref_count);
assert(!pager_page_is_in_free_list(pg));
assert(!pager_page_is_in_syncjf_list(pg));
assert(!pager_page_is_in_dirty_list(pg));
pager_outof_page_from_hash_and_list(pager, pg);
MyMemPoolFree(pager->hm, pg);
return 0;
}
/**
* @brief 同步备份日志至外存
*/
static __INLINE__ int pager_sync_journal(pager_t * pager)
{
pghd_t * pg = NULL;
assert(pager && pager->hjf);
/* 如果不需要同步,直接返回 */
if(!pager->need_sync_journal)
return 0;
/* 将日志头写入,主要为备份了多少页 */
if(0 != OsFileSeek(pager->hjf, pager->jouranl_prev_hdr + PAGER_JOURNAL_REC_COUNT_OFFSET))
return -1;
if(0 != pager_write_uint_to_file(pager->hjf, pager->in_journal_pages_count))
return -1;
if(0 != OsFileSeek(pager->hjf, pager->journal_end))
return -1;
/* 调用os的file sync接口同步至外存 */
if(0 != OsFileSyn(pager->hjf))
return -1;
pager->need_sync_journal = 0;
pager->bsync_journal_has_done = 1;
if(NULL == pager->pg_dirty)
return 0;
/* 将所有dirty页的need_sync_journal置成0 */
pg = pager->pg_dirty;
for(; pg; pg = pg->pg_dirty_next)
{
assert(pager_page_is_dirty(pg));
if(!pager_page_is_sync_journal(pg))
pager_change_page_state(pg, PAGE_EVT_SYNC_JOURNAL);
if(pg->ref_count)
{
assert(!pager_page_is_in_free_list(pg));
continue;
}
assert(pager_page_is_in_free_list(pg) && 0 == pg->ref_count);
if(!pager_page_is_in_syncjf_list(pg))
pager_add_to_syncjf_list(pager, pg);
}
return 0;
}
/**
* @brief 获取外存文件包含有多少页
*/
static __INLINE__ unsigned int pager_get_total_pages_count(pager_t * pager)
{
int64 file_size = 0;
assert(pager && pager->hf);
if(pager->total_page_count != (unsigned int)-1)
return pager->total_page_count;
if(0 != OsFileSize(pager->hf, &file_size))
return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -