前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Zookeeper之FileSnap源码分析

Zookeeper之FileSnap源码分析

作者头像
tunsuy
发布2022-10-27 09:29:10
1910
发布2022-10-27 09:29:10
举报
文章被收录于专栏:有文化的技术人

FileSnap实现了SnapShot接口,主要用作存储、序列化、反序列化、访问相应snapshot文件。

1. deserialize函数

代码语言:javascript
复制
public long deserialize(DataTree dt, Map<Long, Integer> sessions) throws IOException {
	// we run through 100 snapshots (not all of them)
	// if we cannot get it running within 100 snapshots
	// we should  give up
	List<File> snapList = findNValidSnapshots(100);
	if (snapList.size() == 0) {
		return -1L;
	}
	File snap = null;
	long snapZxid = -1;
	boolean foundValid = false;
	for (int i = 0, snapListSize = snapList.size(); i < snapListSize; i++) {
		snap = snapList.get(i);
		LOG.info("Reading snapshot {}", snap);
		snapZxid = Util.getZxidFromName(snap.getName(), SNAPSHOT_FILE_PREFIX);
		try (CheckedInputStream snapIS = SnapStream.getInputStream(snap)) {
			InputArchive ia = BinaryInputArchive.getArchive(snapIS);
			deserialize(dt, sessions, ia);
			SnapStream.checkSealIntegrity(snapIS, ia);

			// Digest feature was added after the CRC to make it backward
			// compatible, the older code can still read snapshots which
			// includes digest.
			//
			// To check the intact, after adding digest we added another
			// CRC check.
			if (dt.deserializeZxidDigest(ia, snapZxid)) {
				SnapStream.checkSealIntegrity(snapIS, ia);
			}

			foundValid = true;
			break;
		} catch (IOException e) {
			LOG.warn("problem reading snap file {}", snap, e);
		}
	}
	if (!foundValid) {
		throw new IOException("Not able to find valid snapshots in " + snapDir);
	}
	dt.lastProcessedZxid = snapZxid;
	lastSnapshotInfo = new SnapshotInfo(dt.lastProcessedZxid, snap.lastModified() / 1000);

	// compare the digest if this is not a fuzzy snapshot, we want to compare
	// and find inconsistent asap.
	if (dt.getDigestFromLoadedSnapshot() != null) {
		dt.compareSnapshotDigests(dt.lastProcessedZxid);
	}
	return dt.lastProcessedZxid;
}

说明:deserialize主要用作反序列化,并将反序列化结果保存至dt和sessions中。其大致步骤如下

  • 获取100个合法的snapshot文件,并且snapshot文件已经通过zxid进行降序排序
  • 遍历100个snapshot文件,从zxid最大的开始,读取该文件,并创建相应的InputArchive
  • 调用deserialize(dt,sessions, ia)函数完成反序列化操作
  • 验证从文件中读取的Checksum是否与新生的Checksum相等,若不等,则抛出异常
  • 跳出循环并关闭相应的输入流,并从文件名中解析出相应的zxid返回。
  • 在遍历100个snapshot文件后仍然无法找到通过验证的文件,则抛出异常。

在deserialize函数中,会调用findNValidSnapshots以及同名的deserialize(dt,sessions, ia)函数。findNValidSnapshots函数主要是查找N个合法的snapshot文件并进行降序排序后返回。deserialize(dt,sessions, ia)函数主要作用反序列化,并将反序列化结果保存至header和sessions中。其中会验证header的魔数是否相等。

2. serialize函数

代码语言:javascript
复制
public synchronized void serialize(
	DataTree dt,
	Map<Long, Integer> sessions,
	File snapShot,
	boolean fsync) throws IOException {
	if (!close) {
		try (CheckedOutputStream snapOS = SnapStream.getOutputStream(snapShot, fsync)) {
			OutputArchive oa = BinaryOutputArchive.getArchive(snapOS);
			FileHeader header = new FileHeader(SNAP_MAGIC, VERSION, dbId);
			serialize(dt, sessions, oa, header);
			SnapStream.sealStream(snapOS, oa);

			// Digest feature was added after the CRC to make it backward
			// compatible, the older code cal still read snapshots which
			// includes digest.
			//
			// To check the intact, after adding digest we added another
			// CRC check.
			if (dt.serializeZxidDigest(oa)) {
				SnapStream.sealStream(snapOS, oa);
			}

			lastSnapshotInfo = new SnapshotInfo(
				Util.getZxidFromName(snapShot.getName(), SNAPSHOT_FILE_PREFIX),
				snapShot.lastModified() / 1000);
		}
	}
}

该函数用于将header、sessions、dt序列化至本地snapshot文件中,并且在最后会写入"/"字符。该方法是同步的,即是线程安全的。 FileHeader header = new FileHeader(SNAP_MAGIC, VERSION, dbId);可以看出写入了magic、version、dbid,也就是在之前的文章中介绍的,snapshot文件解析之后的第一行。另外还会序列号摘要

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 有文化的技术人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. deserialize函数
  • 2. serialize函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档