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

📄 pager.c

📁 sourceforge历史版本完整下载: http://sourceforge.net/project/showfiles.php?group_id=202044 提供了基于b树索引算法的文件数据数据
💻 C
📖 第 1 页 / 共 5 页
字号:
	assert(pager && pgno && buf && pager->page_size && buf_len == pager->page_size);	if(pgno > pager_get_total_pages_count(pager))	{		memset(buf, 0, pager->page_size);		return 0;	}	if(0 != OsFileSeek(pager->hf, pager_cal_page_hdr_offset(pager, pgno)))		return -1;	if(0 != OsFileRead(pager->hf, buf, pager->page_size, NULL))		return -1;	return 0;}/** * @brief 根据页号,获取一页至缓存 */static __INLINE__ int pager_read_page(pager_t * pager, unsigned int pgno, pghd_t * pg){	assert(pager && pgno && pg && pg->pager == pager);	assert(pager->hf);	if(0 != pager_read_page_data(pager, pgno, pg->pg_buf_start, pager->page_size))		return -1;	return 0;}/** * @brief 将指定的数据写进某一页 */static __INLINE__ int pager_write_page_data(pager_t * pager, unsigned char * buf, unsigned int buf_size, unsigned int pgno){	assert(pager && buf && buf_size);	assert(pager->hf);	assert(buf_size <= pager->page_size);	/* 将页写入外存页文件 */	if(0 != OsFileSeek(pager->hf, pager_cal_page_hdr_offset(pager, pgno)))		return -1;	if(0 != OsFileWrite(pager->hf, buf, buf_size, NULL))		return -1;	return 0;}/** * @brief 将某一个数据写入页文件 */static __INLINE__ int pager_write_page(pager_t * pager, pghd_t * pg){	assert(pager && pg && pager == pg->pager);	assert(pg->page_num);	assert(pager->hf);	assert(pager_page_is_dirty(pg));	/* 将页写入外存页文件 */	if(0 != pager_write_page_data(pager, pg->pg_buf_start, pager->page_size, pg->page_num))		return -1;	return 0;}/** * @brief 寻找jf头的位置 * jf头的位置应对齐到sector_size的值,假如sector_size为512 * 0 512 1024为jf头的起始位置 */#define pager_locate_jf_hdr_pos(__pgr) \	((__pgr->journal_end % __pgr->sector_size)?(__pgr->journal_end + CAL_ALIGMENT(__pgr->journal_end, __pgr->sector_size)):__pgr->journal_end)/** * @brief 写jf头 */static __INLINE__ int pager_reset_cksum(pager_t * pager){	assert(pager && pager->hrand);	pager->cur_cksum_init = (unsigned int)(myrandGetByte(pager->hrand)) << 24 | 		(unsigned int)(myrandGetByte(pager->hrand)) << 16 |		(unsigned int)(myrandGetByte(pager->hrand)) << 8 | 		(unsigned int)(myrandGetByte(pager->hrand));	return 0;}/** * @brief 写jf头 */static __INLINE__ int pager_write_jf_head(pager_t * pager){	int ret = -1;	unused_journal_hdr * hdr = MyMemPoolMalloc(pager->hm, pager->sector_size);	if(NULL == hdr)		goto pager_write_jf_head_end_;	memset(hdr, 0, pager->sector_size);	assert(pager && pager->hjf && pager->hrand && pager->sector_size >= sizeof(*hdr));	/* 	* journal日志文件头定义	* offset bytes          des	* 0      4              头的大小hd_sz	* 4      16             格式版本	* 20     4              日志里备份了几页	* 24     4              校验和初始随机值	* 28     4              备份日志前页文件的大小	* 32     hd_sz-24       保留	*/	pager->jouranl_prev_hdr = pager_locate_jf_hdr_pos(pager);	assert((pager->jouranl_prev_hdr % pager->sector_size) == 0);	assert(pager->jouranl_prev_hdr >= pager->journal_end);	if(0 != OsFileSeek(pager->hjf, pager->jouranl_prev_hdr))		goto pager_write_jf_head_end_;	/* 写入头的大小 */	uint_to_big_endian(pager->sector_size, hdr->sector_size, sizeof(hdr->sector_size));	/* 拷贝魔法数 */	memcpy(hdr->magic, JOURNAL_MAGIC_STRING, sizeof(hdr->magic));	/* 写记录数,初始应为零 */	uint_to_big_endian(0, hdr->rec_count, sizeof(hdr->rec_count));	/* 写入校验和初始随机值 */	pager_reset_cksum(pager);	uint_to_big_endian(pager->cur_cksum_init, hdr->cksum_init, sizeof(hdr->cksum_init));	/* 写入备份jf前页文件有多少页,用于回滚时栽减 */	uint_to_big_endian(pager->total_page_count, hdr->orig_page_count, sizeof(hdr->orig_page_count));	if(0 != OsFileWrite(pager->hjf, hdr, pager->sector_size, NULL))		goto pager_write_jf_head_end_;	pager->journal_end = pager->jouranl_prev_hdr + pager->sector_size;	ret = 0;pager_write_jf_head_end_:	if(hdr)		MyMemPoolFree(pager->hm, hdr);	return ret;}/** * @brief 读jf头 * @return 0:成功 -1:失败 1:内容不正确,但是操作应结束了 */static __INLINE__ int pager_read_jf_head(pager_t * pager, 										 int64 file_size,										 unsigned int * pin_journal_count,										 unsigned int * porig_pages_count,										 unsigned int * pcksum_init){	unsigned int sector_size = 0;	char magic[JOURNAL_MAGIC_LEN];	assert(pager && pager->hjf && pin_journal_count && porig_pages_count);	/* 	* journal日志文件头定义	* offset bytes          des	* 0      4              头的大小hd_sz	* 4      16             格式版本	* 20     4              日志里备份了几页	* 24     4              校验和初始随机值	* 28     4              备份日志前页文件的大小	* 32     hd_sz-24       保留	*/	/* 定位jf头的偏移 */	pager->journal_end = pager_locate_jf_hdr_pos(pager);	if(pager->journal_end + PAGER_JOURNAL_REC_COUNT_LEN >= file_size)		return RHAPSODY_DONE;	if(OsFileSeek(pager->hjf, pager->journal_end))		return RHAPSODY_FAIL;	/* 读出页头的大小 */	if(0 != pager_read_uint_from_file(pager->hjf, &sector_size))		return RHAPSODY_FAIL;	if(sector_size < PAGER_MIN_SECTOR_SIZE)		return RHAPSODY_DONE;	if(pager->journal_end + PAGER_JOURNAL_REC_COUNT_LEN >= file_size)		return RHAPSODY_DONE;	/* 读出magic字符串,判断它是否合法 */	if(0 != OsFileRead(pager->hjf, magic, sizeof(magic), NULL))		return RHAPSODY_FAIL;	if(memcmp(magic, JOURNAL_MAGIC_STRING, JOURNAL_MAGIC_LEN) != 0)		return RHAPSODY_DONE;	/* 读出日志里备份了几页 */	if(0 != pager_read_uint_from_file(pager->hjf, pin_journal_count))		return RHAPSODY_FAIL;	/* 读出校验和初始值 */	if(0 != pager_read_uint_from_file(pager->hjf, pcksum_init))		return RHAPSODY_FAIL;	/* 读出备份前的页文件大小 */	if(0 != pager_read_uint_from_file(pager->hjf, porig_pages_count))		return RHAPSODY_FAIL;	pager->journal_end += sector_size;	/* 定位文件指针位置 */	if(0 != OsFileSeek(pager->hjf, pager->journal_end))		return RHAPSODY_FAIL;		return RHAPSODY_OK;}/** * @brief 以只读的方式打开journal */static __INLINE__ int pager_open_journal_readonly(pager_t * pager){	assert(pager && NULL ==	pager->hjf);	/* 打开jf文件 */	pager->hjf = OsFileOpenReadOnly((char *)MyBufferGet(pager->hb_jf_name, NULL), pager->hm);	if(NULL == pager->hjf)		return -1;	/* 清空原有的着色表 */	assert(pager->hash_pgno_journal);	MyHashTableClear(pager->hash_pgno_journal);	pager->pg_syncjf_first = NULL;	pager->pg_syncjf_last = NULL;	pager->in_journal_pages_count = 0;	pager->orig_pages_count = pager_get_total_pages_count(pager);	pager->need_sync_journal = 0;	pager->bsync_journal_has_done = 0;		pager->jouranl_prev_hdr = 0;	pager->journal_end = 0;	return 0;}/** * @brief 打开jf */static __INLINE__ int pager_open_journal(pager_t * pager){	assert(pager && NULL ==	pager->hjf);	/* 打开jf文件 */	pager->hjf = OsFileOpenExclusive((char *)MyBufferGet(pager->hb_jf_name, NULL), pager->hm);	if(NULL == pager->hjf)		return -1;	pager->jouranl_prev_hdr = 0;	pager->journal_end = 0;	/* 写入jf头,校验和初始化随机数值,初始数据库的大小 */	if(0 != pager_write_jf_head(pager))		return -1;	/* 清空原有的着色表 */	assert(pager->hash_pgno_journal);	MyHashTableClear(pager->hash_pgno_journal);	pager->pg_syncjf_first = NULL;	pager->pg_syncjf_last = NULL;	pager->in_journal_pages_count = 0;	pager->orig_pages_count = pager_get_total_pages_count(pager);	pager->need_sync_journal = 0;	pager->bsync_journal_has_done = 0;	return 0;}/** * @brief 关闭jf并删除jf文件,清空所有跟jf有关的 */static __INLINE__ int pager_close_and_del_journal(pager_t * pager){	assert(pager && pager->hjf);	if(0 != OsFileClose(pager->hjf))		return -1;	pager->hjf = NULL;	if(0 != OsFileDel(MyBufferGet(pager->hb_jf_name, NULL)))		return -1;	assert(pager->hash_pgno_journal);	MyHashTableClear(pager->hash_pgno_journal);	assert(NULL == pager->pg_syncjf_first && NULL == pager->pg_syncjf_last);	pager->in_journal_pages_count = 0;	pager->orig_pages_count = (unsigned int)-1;	pager->need_sync_journal = 0;	pager->bsync_journal_has_done = 0;	pager->jouranl_prev_hdr = 0;	pager->journal_end = 0;	return 0;}/** * @brief 计算一页数的校验和 */static __INLINE__ unsigned int pager_cal_page_cksum(unsigned char * pg_data, unsigned int pg_sz, unsigned int ckcsum_init){	unsigned int i = pg_sz - 1;	assert(pg_data && pg_sz);	for(; i; i /= 2)		ckcsum_init += *((unsigned char *)pg_data + i);	return ckcsum_init;}/** * @brief 标记一页要jf里s */static __INLINE__ unsigned int pager_mark_page_in_journal(pager_t * pager, pghd_t * pg){	assert(pager && pg && pager == pg->pager);	assert(pg->page_num);	if(NULL == MyHashTableInsertUnique(pager->hash_pgno_journal, (void *)pg->page_num, NULL))		return -1;	return 0;}/** * @brief 回收一页缓存 */static __INLINE__ pghd_t * pager_recycle_page(pager_t * pager){	int need_sync = 0;	pghd_t * pg = NULL;	assert(pager);	assert(pager->pg_free_first);	/*	* 如果存在引用计数为零的页缓存,则淘汰该页缓存,用于装载新的页,此时需要将此页写回fd,	* 优先取那些同步过jfd的空闲页缓存,如果没有,则同步jfd,同时从哈希表里删除相应的记录	*  如果页处在空闲链表中,脱链	*  如果页处在同步过jfd的空闲链表中,脱链	*/	if(pager->pg_syncjf_first)	{		/* 优先取同步过jfd的空闲缓存页 */		pg = pager->pg_syncjf_first;		need_sync = 0;	}	else	{		/* 如果没有,则取没同步过的空闲页缓存 */		pg = pager->pg_free_first;		need_sync = 1;	}	assert(pg);	if(pager_page_is_dirty(pg))	{		if(need_sync)		{			/* 同步jf */			if(0 != pager_sync_journal(pager))				return NULL;			pager->in_journal_pages_count = 0;			if(0 != pager_write_jf_head(pager))				return NULL;		}		/* 写回fd */		if(0 != pager_write_page(pager, pg))			return NULL;		/* 应记录已经有页缓存写入了页文件,但数据还不是完整的 */		pager->page_file_is_integrity = 0;		/* 将页置成干净,并从dirty链表中脱链 */		pager_page_out_of_dirty_list(pager, pg);		/* 将页的状态置成写回状态 */		pager_change_page_state(pg, PAGE_EVT_WRITE_BACK_SYNCJF);	}	else		assert(pager_page_is_clean_not_in_jf(pg) || (pager_page_in_journal(pager, pg->page_num) && pager_page_is_sync_journal(pg)));	/* 如果在空闲链表中则脱链 */	pager_out_free_list(pager, pg);	assert(!pager_page_is_in_free_list(pg));	assert(!pager_page_is_in_syncjf_list(pg));	/* 从哈希表中删除,并从记录所有页缓存的链表中删除 */	pager_outof_page_from_hash_and_list(pager, pg);	return pg;}/** * @brief 回收一页缓存,并初始化 */static __INLINE__ pghd_t * pager_recycle_and_init_page(pager_t * pager, unsigned int pgno){	pghd_t * pg = NULL;	assert(pager && pgno);	pg = pager_recycle_page(pager);	if(NULL == pg)		return NULL;	assert(NULL == pg->pg_all_next && NULL == pg->pg_all_prev &&		!pager_page_is_in_free_list(pg) &&		!pager_page_is_in_syncjf_list(pg) &&		!pager_page_is_in_dirty_list(pg) &&		!pager_page_is_dirty(pg));	pager_init_page(pager, pg, pgno);	return pg;}/** * @brief 将某一个页缓存置成脏,并写入jf */static __INLINE__ void * pager_make_page_writable(pghd_t * pg){	pager_t * pager = NULL;	void * buf_write = NULL;	/*	* 判断jfd机制是否已启用,如果未启用则应该打开jfd文件,并分配着色表	* 判断此页是否已经处在jfd中了(从着色表里查),	*    如果没有则需要写入jfd,先页号,再写页缓存内容,最后写入校验和,并且给该页缓存做上injournal标识,并在着色表相应的位置置标识	*    将页缓存置成dirty,加入dirty链表.	* 如果页号比当前总页数大,	* 此时应将页文件的总页数增1	* 返回页缓存的首地址供上层写入(注意越界检测代码加入)	*/	assert(pg && pg->pager);	assert(pg->ref_count > 0);	buf_write = pager_get_page_bufdata(pg);	pager = pg->pager;	/* 如果未启用jf机制,则应启用 */	if(NULL == pager->hjf)

⌨️ 快捷键说明

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