如何做一个国产数据库(三)

11 篇文章 0 订阅

一和二

如何做一个国产数据库一
如何做一个国产数据库二

1、数据结构重新定义

再次重新定义数据结构

typedef struct sdata
{
	uint32_t index;
	char vardata[128];
}sdata;

typedef struct sdata_index
{
	uint32_t index;
	uint32_t offset;
}sdata_index;


//增加的数据库上下文环境结构体
typedef struct db_context
{
	char v_tablename[256];
	sdata_index *v_index = NULL;
	uint32_t v_tindex = 0;
	uint32_t v_nindex = 0;
}db_context;

2、增删改查

此次增加了一个数据库的db_context 结构体,包含文件名称,索引内存保存,两个index的内存保存,在增加四个api函数,以前的函数变成工具,定义tool.h 和tool.cpp.

增加api.h 和api.cpp,增加四个函数声明:

int   Insert(void *data,db_context *v_context);
int   Delete(void *key, db_context *v_context);
int   Update(void *key, void *data, db_context *v_context);
void *Select(void *key, db_context *v_context);

今天实现Insert 函数,暂不测试,因为单元测试需要单独一个教程才行

xx xx xx xx | xx xx xx xx | xx xx xx xx – xx xx xx xx
4字节最大索引| 4字节当前索引 4bytes index 4bytes offset
data

*/
//2M的空间做索引
//uint32_t indext;//索引总长度
//uint32_t indexn;//索引长度,内容为x个索引 indexn <= indext

2.1 实现索引读的函数

#define INDEX_BYTES 2 * 1024 * 1024
//int index_num = INDEX_BYTES / sizeof(int) * 2; //max index number is 162144


sdata_index* bfile_read_index(const char * file, uint32_t &indext,uint32_t &indexn)
{
	size_t nr;
	indext = 0;
	indexn = 0;
	FILE * fp = fopen(file, "rb");
	if (fp == NULL)
		return NULL;
	//读取最大的index值容量
	nr = fread(&indext, sizeof(uint32_t), 1, fp);
	if (nr == 0)
	{
		fclose(fp);
		return NULL;
	}
	//读取存储的索引值
	nr = fread(&indexn, sizeof(uint32_t), 1, fp);
	if (nr == 0)
	{
		fclose(fp);
		return NULL;
	}

	//4字节索引号 4字节偏移地址
	uint8_t * index = (uint8_t*)malloc(indexn * sizeof(uint32_t) * 2);
	nr = fread(index, indexn * sizeof(uint32_t) * 2, 1, fp);
	if (nr == 0)
	{
		fclose(fp);
		free(index);
		return NULL;
	}
	return (sdata_index*)index;
}

2.2 实现初始化数据库的函数

该函数并不完整,等待完善,有很多需要注意的地方

int Initialize(const char *tname, db_context *context)
{

	if (context == NULL)
		return -1;
	strcpy(context->v_tablename,tname);

	if (context->v_index == NULL)
		context->v_index = bfile_read_index(
			tname,             /*filename*/
			context->v_tindex, 
			context->v_nindex
		);

	if (context->v_index == NULL)
		return -1;
	return 0;
}

2.3实现插入

整个增加的流程为:

打开数据库
初始化读取
读取上次索引信息
写入当次索引+偏移
写入索引量last+1
int Insert(void *data, db_context *context)
{
	if (context->v_nindex < context->v_tindex)
	{
		FILE * fp = fopen(context->v_tablename, "wb");
		if (fp == NULL)
			return -1;


		fpos_t pos = 4 + 4 + (context->v_nindex) * (8);
		fsetpos(fp, &pos);
		//int last_index = context->v_nindex - 1;
		uint32_t  indexlast = context->v_index[context->v_nindex - 1].index ;
		uint32_t  indexinsert = indexlast + 1;
		size_t n = fwrite(&indexinsert, sizeof(uint32_t), 1, fp);
		if (n != sizeof(uint32_t))
		{
			fclose(fp);
			return -1;
		}

		sdata *pdata = (sdata*)data;

		size_t vsize = sizeof(pdata->vardata);
		uint32_t datasize = vsize * indexlast;
		fpos_t offset = 4 + 4 + INDEX_BYTES + datasize;
		n = fwrite(&offset, sizeof(uint32_t), 1, fp);
		if (n != sizeof(uint32_t))
		{
			fclose(fp);
			return -1;
		}

		fsetpos(fp, &offset);
		n = fwrite(data, vsize, 1, fp);
		if (n != vsize)
		{
			fclose(fp);
			return -1;
		}
		fpos_t index = sizeof(uint32_t);
		fsetpos(fp, &index);
		uint32_t newnindex = context->v_nindex + 1;
		n = fwrite(&newnindex, sizeof(uint32_t), 1, fp);
		if (n != sizeof(int))
		{
			fclose(fp);
			return -1;
		}
		fclose(fp);
		return 0;
	}
	return -1;
}


int   Delete(void *key, db_context *v_context)
{

}
int   Update(void *key, void *data, db_context *v_context)
{

}
void *Select(void *key, db_context *v_context)
{

}

上面说了,先实现增加函数,其他先不实现,也不测试,单元测试需要一个严格的定义和测试用例,此次先为增加流程的初步代码实现,有待完善。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qianbo_insist

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值