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

📄 pager.c

📁 sourceforge历史版本完整下载: http://sourceforge.net/project/showfiles.php?group_id=202044 提供了基于b树索引算法的文件数据数据
💻 C
📖 第 1 页 / 共 5 页
字号:
	MyAlgQuickSort(pg_array, dirty_pages_count, sizeof(pg_array[0]), pager_sort_dirty_compare, NULL, NULL, NULL, NULL, &pg, sizeof(pg));	pager->pg_dirty = NULL;	for(i = 0; i < dirty_pages_count; i ++)	{		pg_array[i]->pg_dirty_next = NULL;		pg_array[i]->pg_dirty_prev = NULL;		pager_add_page_to_dirty_list(pager, pg_array[i]);	}	assert(pg_array);	MyMemPoolFree(pager->hm, pg_array);	return 0;}/** * @brief 同步所有脏缓存页 */static __INLINE__ int pager_syn(pager_t * pager){	pghd_t * pg = NULL;	/*	* 首先将jfd文件同步至外存,将所有页缓存置成同步过jfd	* 将同步过的空闲页缓存加入指定的链表(用于页缓存满时,换页优先从这个链表里取空闲页缓存)	* 将所有的dirty页写入fd中,将dirty链表置空.每页的dirty标识也置空	* 删除份的jfd文件.	* jfd着色表以及页的injournal标识均置成0,因为一个完整提交已经完成了.	*	* 成功之后,将文件的完整性置成1	*	*/	assert((pager->pg_dirty && pager->hjf) || 		(!pager->page_file_is_integrity && pager->hjf) ||		(!pager->hjf && NULL == pager->pg_dirty && pager->page_file_is_integrity));	/* 如果不存在脏页,并且外页的数据是完整的,同步就不需要进行 */	if(NULL == pager->pg_dirty && pager->page_file_is_integrity)		return 0;	/* 将jf同步至外存 */	if(0 != pager_sync_journal(pager))		return -1;	/* 将脏页写回页文件 */	if(pager->pg_dirty)		pager_sort_dirty_list(pager);	for(pg = pager->pg_dirty; pg; pg = pager->pg_dirty)	{		assert(pager_page_is_dirty(pg));		/* 写页缓存写回页文件 */		if(0 != pager_write_page(pager, pg))			return -1;		/* 从dirty list里脱链 */		pager_page_out_of_dirty_list(pager, pg);		/* 改变页状态 */		pager_change_page_state(pg, PAGE_EVT_WRITE_BACK_SYNCJF);	}	assert(NULL == pager->pg_dirty);	/* 同步页文件至外存 */	if(0 != OsFileSyn(pager->hf))		return -1;	/*	* 清除所有页的clean_sync标记	* todo 优先此段代码	*/	for(pg = pager->pg_all; pg; pg = pg->pg_all_next)	{		assert(!pager_page_is_dirty(pg));		if(0 == pg->ref_count)		{			assert(pager_page_is_in_free_list(pg));			if(pager_page_is_sync_journal(pg))			{				assert(pager_page_is_in_syncjf_list(pg));				pager_out_syncjf_list(pager, pg);			}			else				assert(!pager_page_is_in_syncjf_list(pg));		}		else		{			assert(!pager_page_is_in_free_list(pg));			assert(!pager_page_is_in_syncjf_list(pg));		}		assert(!pager_page_is_in_syncjf_list(pg));		if(!pager_page_is_clean_not_in_jf(pg))			pager_change_page_state(pg, PAGE_EVT_SYNC);		assert(pager_page_is_clean_not_in_jf(pg));	}	assert(NULL == pager->pg_syncjf_first && NULL == pager->pg_syncjf_last);	pager->page_file_is_integrity = 1;	/* 关闭jouranl */	if(0 != pager_close_and_del_journal(pager))		return -1;	return 0;}/** * @brief 销毁缓存管理 */static __INLINE__ int pager_destroy(pager_t * pager){	assert(pager);	/* 做回滚操作 */	if(pager->hf && !pager->page_file_is_integrity)		pager_rollback(pager);	if(pager->hjf)		pager_close_and_del_journal(pager);	if(pager->hf)		OsFileClose(pager->hf);	if(pager->hash_page)		MyHashTableDestruct(pager->hash_page);	if(pager->hash_pgno_journal)		MyHashTableDestruct(pager->hash_pgno_journal);	if(pager->hrand)		myrandDestruct(pager->hrand);	if(pager->hb_file_name)		MyBufferDestruct(pager->hb_file_name);	if(pager->hb_jf_name)		MyBufferDestruct(pager->hb_jf_name);	{		/* 依次释放页缓存 */		pghd_t * pg = pager->pg_all;		while(pg)		{			pghd_t * pg_temp = pg->pg_all_next;			MyMemPoolFree(pager->hm, pg);			pg = pg_temp;		}	}	MyMemPoolFree(pager->hm, pager);	return 0;}/** * @brief 页缓存哈希表哈希函数 */static size_t pg_hash_fun(const void * key){	return (size_t)key;}/** * @brief 页缓存哈希表,比较键值是否相等 1:相等 0:不相等 */static int pg_hash_keyequl_fun(const void * key1, const void * key2){	return key1 == key2;}/** * @brief 根据页号,获取一页缓存 */static __INLINE__ pghd_t * pager_get_page(pager_t * pager, unsigned int pgno){	/*	* 如果是第一次获取页,则应判断journal日志文是否存,如果存在则需要执行回滚操作	* 将journal日志文件中的备份,依次读入,检查校验和,如果正确,写入页文件fd	* 回滚结束后,应删除jfd文件	* 首先从页缓存的哈希表里查找,如果找到,页引用计数加1,函数返回	* 如果在缓存中找不到相应的页,则需要分配页缓存,从外存读取,初始化是否injournal的标识	* 此时应注意页缓存满的情况:	* 如果不存在引用计数为零的页缓存,则仍然分配页缓存.	* 如果存在引用计数为零的页缓存,则淘汰该页缓存,用于装载新的页,此时需要将此页写回fd,	* 优先取那些同步过jfd的空闲页缓存,如果没有,则同步jfd,同时从哈希表里删除相应的记录	*  将页号与页缓存指针添加进哈希表	*  如果页处在空闲链表中,脱链	*  如果页处在同步过jfd的空闲链表中,脱链	*  页引用计数加1	*/	pghd_t * pg = NULL;	assert(pager && pager->hash_page);	if(0 == pager->ref_count && NULL == pager->hjf)	{		/*		* 如果是第一次获取页,则应判断journal日志文是否存,如果存在则需要执行回滚操作		* 将journal日志文件中的备份,依次读入,检查校验和,如果正确,写入页文件fd		* 回滚结束后,应删除jfd文件		*/		if(0 != pager_check_and_roll_back(pager))			return NULL;	}	pg = pager_hash_lookup(pager,  pgno);	if(NULL == pg)	{		if((pager->pg_free_first || pager->pg_syncjf_first) && pager_get_cached_pages_count(pager) >= pager->max_cache_pages)			pg = pager_recycle_and_init_page(pager, pgno);/* 回收一页缓存 */		else			pg = pager_allocate_page(pager, pgno);/* 分配一页缓存 */		if(NULL == pg)			goto pager_get_page_err_;		assert(pg->page_num == pgno);		/* 读取页 */		if(0 != pager_read_page(pager, pgno, pg))			goto pager_get_page_err_;		/* 进入哈希表,以及总的页缓存链表 */		if(0 != pager_add_page_to_hash_and_list(pager, pg))			goto pager_get_page_err_;	}	pager_ref_page(pager, pg);	return pg;pager_get_page_err_:	/* 由于没有记录在案,此页缓存必需释放 */	if(pg)		pager_free_page(pager, pg);	return NULL;}/** * @brief 取消对某个页缓存的引用 */static __INLINE__ int pager_release_page(pghd_t * pg){	pager_t * pager = NULL; 	assert(pg && pg->pager);	assert(pg->ref_count > 0);	pager = pg->pager;	/*	* 页引用计数减1,	* 如果页的引用计数为零,则可以将它加入空闲页缓存链表,如果该页并且已经同步过jfd,则可以加入空闲的jfd缓存链表,	*   并且需要调用用户的release回调函数通知上层	*/	/* 引用计数减1 */	assert(pg->ref_count);	pg->ref_count --;	assert(pager->ref_count);	pager->ref_count --;	if(pg->ref_count > 0)		return 0;	assert(!pager_page_is_in_free_list(pg));	assert(!pager_page_is_in_syncjf_list(pg));	/* 如果引用计数为零 */	/* 如果需要同步至jf,加入的free list */	if(pager_page_is_sync_journal(pg))		pager_add_to_syncjf_list(pager, pg);/* 如果不需要同步至jf,加入到syncjf_list,以便优先回收 */	else		pager_add_to_free_list(pager, pg);	/* 调用用户的回调函数 */	if(pager->page_release_cb)		pager->page_release_cb(pg);	return 0;}/** * @brief 写入页头信息 */static __INLINE__ int pager_write_file_page_info(pager_t * pager){	/*	* 页的第一页用于存放页文件本身的信息	* 第一页	*  offset bytes        des	*  0      16           格式版本	*  16     4            页大小	*  20     4            第一个空闲页	*  24     40           保留	*  64   pg_sz - 64     用户数据     	*/	pghd_t * first_pg = NULL;	assert(pager && pager->hf);	assert(0 == pager->ref_count);	first_pg = pager_get_page(pager, PAGER_FIRST_PAGE_NO);	if(NULL == first_pg)		return -1;	if(NULL == pager_make_page_writable(first_pg))		return -1;	memcpy(first_pg->pg_buf_start + PAGER_HDR_VER_OFFSET, VERSION, PAGER_HDR_VER_LEN);	uint_to_big_endian(pager->page_size, first_pg->pg_buf_start + PAGER_HDR_PAGE_SIZE_OFFSET, sizeof(unsigned int));	uint_to_big_endian(0, first_pg->pg_buf_start + PAGER_HDR_FIRST_FREE_OFFSET, sizeof(unsigned int));	pager_release_page(first_pg);	assert(0 == pager->ref_count);	pager_syn(pager);	return 0;}/** * @brief 读取页文件信息,读取页大小,以及包含多少页,并判断文件版本 */static __INLINE__ int pager_read_file_page_info(pager_t * pager){	/*	* 页的第一页用于存放页文件本身的信息	* 第一页	*  offset bytes        des	*  0      16           格式版本	*  16     4            页大小	*  20     4            第一个空闲页	*  24     40           保留	*  64   pg_sz - 64     用户数据     	*/	char ver[sizeof(VERSION)];	unsigned int pg_sz = 0;	int64 pg_file_sz = 0;	assert(pager && pager->hf);	/* 判断页文件大小是否满足一页,否则需要写入页文件头信息 */	if(0 != OsFileSize(pager->hf, &pg_file_sz))		return -1;	if(pg_file_sz < sizeof(ver))	{		/* 无法读到足够的信息,则应认为此页文件是无效的,需要写入头信息 */		if(0 != pager_write_file_page_info(pager))			return -1;		return 0;	}	if(0 != OsFileSeek(pager->hf, 0))		return -1;	if(0 != OsFileRead(pager->hf, ver, sizeof(ver), NULL))		return -1;	if(strncmp(ver, VERSION, strlen(VERSION)) != 0)	{		/* 页文件格式可能是当前程序不支持的 */		LOG_WARN(("page file version err,this page maybe create by the later pager verion,[file version:%s], [program ver:%s]",			ver, VERSION));		return -1;	}	if(0 != OsFileSeek(pager->hf, PAGER_HDR_VER_LEN))		return -1;	/* 读出页的大小 */	if(0 != pager_read_uint_from_file(pager->hf, &pg_sz))		return -1;	if(pg_file_sz < pg_sz)	{		/* 		* 如果页文件的大小于一页的大小 		* 认为是一个新的页文件,需要写入页文件头信息		*/		if(0 != pager_write_file_page_info(pager))			return -1;	}	else	{		pager->page_size = pg_sz;	}	/* 获取当前有多少页 */	pager->total_page_count = pager_get_total_pages_count(pager);	return 0;}/** * @brief 创建一个缓存页管理器 * @param hm:内存池句柄 * @param file_name:辅存的文件名 * @param page_release_cb:页析构回调函数 * @param page_reload_cb:页重载回调函数 * @param extra_size:每页附加的扩展用户数据大小 * @param max_page:缓存中的最大页数 * @param page_size:每一页的大小,如果对应的页文件已存在,则返回页的大小,可为空,默认为1024 * @param used_rate:外存文件使用率, 0:表示不需要进行栽减, 1-9分别表示使用率,一旦低于使用率,则进行自动栽减,>=10表示总是要栽减 * @param rand_seed:随机数初始化种子 * @param rand_seed_size:种子的长度 * @param sector_size:所用系统的扇区大小 */HPAGER PagerConstruct(HMYMEMPOOL hm,					  const char * file_name,					  PAGE_RELEASE page_release_cb,					  PAGE_RELOAD page_reload_cb,					  unsigned int extra_size,					  unsigned int max_cache_pages,					  unsigned int * page_size,					  void * rand_seed,					  unsigned int rand_seed_size,					  unsigned int sector_size){	pager_t * pager = NULL;	if(NULL == page_size || NULL == file_name)	{		LOG_WARN(("param err,page_size:%x, file_name:%x", page_size, file_name));		return NULL;	}	pager = MyMemPoolMalloc(hm, sizeof(*pager));	if(NULL == pager)	{		LOG_WARN(("fail malloc"));		return NULL;	}	memset(pager, 0 ,sizeof(*pager));	pager->hm = hm;	/* 保存日志文件名与外存文件名 */	pager->hb_file_name = MyBufferConstruct(hm, strlen(file_name) + 1);	pager->hb_jf_name = MyBufferConstruct(hm, strlen(file_name) + strlen(JOURNAL) + 1);	pager->ref_count = 0;	if(NULL == pager->hb_file_name || NULL == pager->hb_jf_name)	{		LOG_WARN(("fail malloc"));		goto P

⌨️ 快捷键说明

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