len);
其实调用上两个函数的潜台词就是,我现在干了什么事,你给我把他完整的记录下来,如果我这件事没有最终被保存到磁盘的话,我就需要你这个负责记录的模块拿出原来所做的记录,我来进行恢复操作,以确保数据万无一失!
二.如何记录用户操作
在这个模块,用户的操作类型实际上可以归类为两种,一种是基本写操作,一种是非基本写操作。对数据的新增和修改等都可以认为是写操作,而类似与创建文件(FileCreatedOp),删除数据库(DropDbOp)操作都是非基本写操作,这类操作建模为DurOp.最终这两种操作都会在CommitJob:: note()与CommitJob::noteOp()进行内存存储。
基本写操作会被D结构体封装,我们来看下他的结构:
struct D {
void *p;//用户更改的数据源首地址
unsigned len;//用户更改的数据长度
static void go(const D& d);
};
基本写记录会被存储到Writes类在CommitJob类的实例_wi,继而存储到TaskQueue在Writes类的实例_deferred.
非基本写记录会被存储到Writes类的vector< shared_ptr > _ops;
这个流程有很多个类参与,下面用两张顺序图来总结这一流程。
调用getDur().writingPtr的时序图
调用getDur().createdFile的时序图
至此为止,用户操作日志在内存的记录操作就完成了。接下来要讲到如何序列化内存中的记录,以备持久化到磁盘.
今日至此,下面两点下次结合其他的文章一起写。
如何序列化用户操作并持久化
如何根据现有Journal日志恢复数据
后会有期......
博客地址:Zealot Yin
|