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

📄 pager.c

📁 基于btree索引算法的数据库代码
💻 C
📖 第 1 页 / 共 5 页
字号:

/**
 * @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 + -