Method---wal.go Description
func Create(lg *zap.Logger, dirpath string, metadata []byte) (*WAL, error) 初次启动raftNode时调用WAL.Create方法。创建WAL对象用于记录追加 :判断是否存在dirpath路径,如果已存在则不是初次启动raftNode,返回os.ErrExist。创建临时目录和初始上锁的wal文件—walName(seq=0 & index=0),seek到文件末尾(why?),预分配该wal文件大小(SegmentSizeBytes=64MB,优化追加速度),创建WAL对象并设定路径、 metadata(NodeID和ClusterID)、编码器,将上锁的WAL文件追加到锁表内,然后依次写入crc、metadata和空snapshot,重命名临时目录,同步临时目录的父目录(fsync)使得重命名持久化。
func (w *WAL) renameWAL(tmpdirpath string) (*WAL, error) 移除w.dir目录及目录下所有文件和文件夹,调用os.Rename(tmpdirpath, w.dir)将Create方法内创建的临时目录重命名,创建FilePipeline和dirFile *os.File,dirFile is a fd for the wal directory for syncing on Rename
func (w *WAL) SaveSnapshot(e walpb.Snapshot) error 检验snapshot是否合法(Since etcd>=3.5.0),pb序列化snapshot得到data字段,加锁,调用w.encoder.encode方法写入record,更新w.enti如果snapshot index > 原w.enti,解锁。
func (w *WAL) saveCrc(prevCrc uint32) error 写入crcType的记录
func (w *WAL) Save(st raftpb.HardState, ents []raftpb.Entry) error 加锁,如果hardstate和entries为空,返回。判断是否需要sync(entries长度不为0||vote改变||term改变),写入entries和hardstate,判断文件当前位置是否小于SegmentSizeBytes(默认64M),如果小于判断是否需要sync数据,如果不小于,返回cut操作结果,解锁。
func (w *WAL) saveEntry(e *raftpb.Entry) error 写入一条entry记录并更新WAL对象的enti值
func (w *WAL) saveState(s *raftpb.HardState) error 判断是否为空,不为空写入HardState并更新WAL对象的state值
func (w *WAL) cut() error 关闭当前文件并创建一个新的文件用于追加记录:首先移动到锁表最后一个wal文件的当前位置截断文件然后执行sync,调用FilePipeline对象的Open方法创建一个新文件并加入锁表,首先保存旧的encoder的crc,然后创建新的encoder对象替换旧的encoder对象,保存头信息crc、metadata和hardstate,原子重命名文件之前先执行sync和保存当前位置偏移,重命名后对WAL对象的dirFile执行fsync持久化wal目录的变化。关闭文件重新以LockFile方式打开文件并seek到文件末尾,替换锁表尾文件,再次进行新旧encoder替换。
func (w *WAL) tail() *fileutil.LockedFile WAL对象的锁表如果不为空,返回最后一个上锁文件,否则返回空。
func (w *WAL) sync() error 如果encoder存在,则将encoder pageWriter缓冲区的数据写入,锁表尾文件执行fdatasync,将fdatasync延时上报监控prometheus。
func ValidSnapshotEntries(lg *zap.Logger, walDir string) ([]walpb.Snapshot, error) 寻找所有wal文件中snapshot条目,有效的snapshot条目index必须小于等于最新的hardstate。步骤:找到目录下所有带有合法名称的wal文件名,以只读模式打开这些wal文件,根据以读模式打开的这些wal文件创建decoder,循环解码每个文件的record:若为snapshotType,追加到snaps中;若为stateType,更新hardstate;若为crcType(wal文件开头),验证是否和decoder.crc相同(上一个文件末尾的crc)。返回所有index小于最新hardstate.Commit的walpb.snap条目。
func readWALNames(lg *zap.Logger, dirpath string) ([]string, error) 从指定目录读取所有wal文件name,并检查name合法性(.wal结尾)
func openWALFiles(lg *zap.Logger, dirpath string, names []string, nameIndex int, write bool) ([]fileutil.FileReader, []*fileutil.LockedFile, func() error, error) 根据write标志选择以读模式还是写模式打开文件,步骤:从nameIndex指定的索引开始打开文件。若写模式:打开上锁的wal文件,将该文件添加到锁表、文件关闭表、读文件表;若读模式:以os.O_RDONLY打开文件,将该文件添加到文件关闭表、读文件表,添加nil到锁表(锁表只在写模式下用到)。
func Open(lg zap.Logger, dirpath string, snap walpb.Snapshot) (WAL, error) 写模式调用openAtIndex。Open opens the WAL at the given snap,The returned WAL is ready to read and the first record will be the one after the given snap. The WAL cannot be appended to before reading out all of its previous records.
func OpenForRead(lg zap.Logger, dirpath string, snap walpb.Snapshot) (WAL, error) 读模式调用openAtIndex。
func openAtIndex(lg zap.Logger, dirpath string, snap walpb.Snapshot, write bool) (WAL, error) 遍历wal目录,找到snap所在位置index,依次打开index后续所有的wal文件并加锁(调用openWALFiles),创建WAL对象并设定解码器、readClose(调用closeAll关闭已打开文件)和锁表,若写模式:readClose置空(写模式下还要继续对wal文件进行append操作,等到读完后不用进行关闭操作),测试锁表最后一个上锁文件是否是合法wal文件(通过是否符合命名规范判断),如果不合法,关闭所有文件返回错误,否则,设定FilePipeline对象(大小超过64M时用于截断并切换到新文件),返回WAL对象 。
func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb.Entry, err error) 读取WAL对象的所有记录 ,对于不同类型记录做不同处理: 判断锁表尾文件如为空(读模式):如果不是读到EOF或ErrUnexpectedEOF则重置state返回;对于写模式,如果err不是EOF,重置状态返回,然后锁表尾文件Seek到lastOffset位置, 将后续内容清零(目的是处理遇到0记录后接非0记录时,非0记录又没有被全部重写,再次打开的时候会出现 CRC错误,由于数据从不会一开始就完全同步到磁盘,因此进行清零操作是安全的 ?暂时没懂),然后判断snapshot是否匹配,关闭decoder实现禁读,重置WAL对象的start为一个空snapshot对象,创建encoder并将decoder设空,返回metadata,state,ents和err。
Method---encoder.go Description
func (e *encoder) encode(rec *walpb.Record) error 加锁,根据record.data计算crc,序列化record得data,根据len(data)计算出lenField和padBytes(需要填充字节数使得8字节对齐),写入lenField到文件,如果padBytes!=0,则给data填充padBytes字节,写入到pageWriter缓冲区。
func encodeFrameSize(dataBytes int) (lenField uint64, padBytes int) 计算出lenField, padBytes
func (e *encoder) flush() error 加锁,将pageWriter缓冲区内数据写入文件,解锁
func writeUint64(w io.Writer, n uint64, buf []byte) error 将uint64类型n写入到[]byte内,再写入文件
Method---pagewriter.go Description
func (pw *PageWriter) Write(p []byte) (n int, err error) 若未超出缓冲区最大容量,则将数据复制到缓冲区并更新当前缓冲字节数返回。若超出,计算出一页还空闲多少字节数slack,若还有空闲:
func (pw *PageWriter) flush() (int, error) 将缓冲区内的所有数据写入文件,重新计算页内偏移量(pageBytes=4KB),将已缓存字节数重置为0
Method---decoder.go Description
func (d *decoder) decodeRecord(rec *walpb.Record) error 首先读取一个int64变量,算出recBytes,和padBytes,读取recBytes+padBytes大小的数据,将前recBytes大小的数据反序列化,如果不是crcType,验证crc是否一致,更新lastOffset = 8 + recBytes + padBytes。
func decodeFrameSize(lenField int64) (recBytes int64, padBytes int64) 根据lenField,算出实际数据大小和填充数据大小
func (d *decoder) isTornEntry(data []byte) bool 还没看
func readInt64(r io.Reader) (int64, error) 从文件中读取一个int64变量

WAL模块主要方法简述的更多相关文章

  1. thinkphp访问不存在的模块或者方法跳转到404页面

    使用的thinkphp 版本是3.2.0, 在config.php中配置 404地址,即可: 'TMPL_EXCEPTION_FILE' => './Application/Home/View/ ...

  2. Android中View的绘制过程 onMeasure方法简述 附有自定义View例子

    Android中View的绘制过程 onMeasure方法简述 附有自定义View例子 Android中View的绘制过程 当Activity获得焦点时,它将被要求绘制自己的布局,Android fr ...

  3. ThinkPHP3.2判断手机端访问并设置默认访问模块的方法

    ThinkPHP3.2判断是否为手机端访问并跳转到另一个模块的方法 目录结构 公共模块Common,Home模块,Mobile模块 配置Application/Common/Conf/config.p ...

  4. apache2服务器mod_rewrite模块 开启方法[linux, ubuntu]

    在UBUNTU系统中要启用mod_rewrite的方法有两种: 第一种: 在终端中执行 sudo a2enmod rewrite 指 令后,即启用了 Mod_rewrite 模块, apache2服务 ...

  5. python在不同层级目录import模块的方法

    使用python进行程序编写时,经常会使用第三方模块包.这种包我们可以通过python setup install 进行安装后,通过import XXX或from XXX import yyy 进行导 ...

  6. Python学习笔记4-如何快速的学会一个Python的模块、方法、关键字

    想要快速的学会一个Python的模块和方法,两个函数必须要知道,那就是dir()和help() dir():能够快速的以集合的型式列出该模块下的所有内容(类.常量.方法)例: #--encoding: ...

  7. 【转】关于python中re模块split方法的使用

    注:最近在研究文本处理,需要用到正则切割文本,所以收索到了这篇文章,很有用,谢谢原作者. 原址:http://blog.sciencenet.cn/blog-314114-775285.html 关于 ...

  8. python有三种导入模块的方法(转)

    原文:http://www.cnblogs.com/allenblogs/archive/2011/11/15/2055149.html python有三种导入模块的方法 其一, import mod ...

  9. Python中os和shutil模块实用方法集…

    Python中os和shutil模块实用方法集锦 类型:转载 时间:2014-05-13 这篇文章主要介绍了Python中os和shutil模块实用方法集锦,需要的朋友可以参考下 复制代码代码如下: ...

  10. Python中os和shutil模块实用方法集锦

    Python中os和shutil模块实用方法集锦 类型:转载 时间:2014-05-13 这篇文章主要介绍了Python中os和shutil模块实用方法集锦,需要的朋友可以参考下 复制代码代码如下: ...

随机推荐

  1. EBI数据库下载数据

    EBI网址链接: https://www.ebi.ac.uk 方法:直接从ncbi上面找到想要下载数据的SRR号然后去EBI里面直接搜索即可得到. 底部就是想要下载的fastq文件了: 然后右键复制链 ...

  2. angular请求头部加XSRF-TOKEN

    1.创建拦截器 import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, } from '@angular/common/http' ...

  3. python 购物小程序

    要求:  1.启动程序后,让用户输入预算,然后打印商品列表  2.允许用户根据商品编号购买商品 3.用户选择商品后,检测余额够不够,够就直接付款,不够就提醒 4.可随时退出,推出时打印已购买商品和余额 ...

  4. api进阶Day1文件的创建、删除、访问、设置过滤器并查询。目录的删除、创建。

    文件的创建: package file; import java.io.File; import java.io.IOException; /* create:创建 new:新 file:文件 使用F ...

  5. centos7 升级gcc

    #安装gcc yum install -y gcc-c++ autoconf automake ​ #centos7 默认的 gcc 默认是4.8.5,版本小于 5.3 无法编译,需要先安装gcc新版 ...

  6. swftools工具将pdf文件转换为swf文件 文字丢失

    开发客户网站时遇到了一个需求,客户要求后台上传pdf文件,前台能以翻书的形式直接访问. 首先想到的是使用js解决,用户访问前端页面时,php将文件路径发送给js,让js呈现出来翻书的效果.在网上百度了 ...

  7. 问题积累 - IAR - ErrorTa97:Cannot callintrinsic functionnounwwind _DSBfrom Thumb mode in this architecture

    IAR编译工程时报错: ErrorTa97:Cannot callintrinsic functionnounwwind _DSBfrom Thumb mode in this architectur ...

  8. antd动态tree 自定义样式

    import React, { useEffect, useState } from 'react';import { Tree } from 'antd';import './index.less' ...

  9. 基于工业4g网关的危化品运输车监控方案

    工业的发展立足于各种各样原材料的加工和应用,而其中就包括一些油料.化学品和易燃易爆货物,针对此类货物的运输,需要着重关注其安全性和稳定性,否则就容易造成严重的人身和财产损失.得益于物联网技术的发展,现 ...

  10. windows电脑设置【定时任务】开机、关机、启动程序

    windows电脑设置[定时任务]开机.关机.启动程序 shutdown -s -t **(延时秒数):关机 shutdown -r -t **(延时秒数):重启 gina -s -t 36 (开机) ...