云备份客户端——数据管理模块

数据管理模块设计之前,我们需要先明确该模块的信息是用来做什么的。根据上文分析该模块信息主要用于判断一个文件是否需要备份,判断条件有两个:1.新增文件 2.被修改过的文件
新增文件好判断,由于我们获得新文件后是先上传文件,再将文件信息插入到数据管理模块中,模块里没有存储该文件信息,则该文件为新增文件
而第二个判断修改文件,我们会设定一个文件的唯一标识,类似于之前服务端构建http协议的ETag关键字,该标识由 文件名-文件大小-文件最后一次修改时间 构成

由上可得,我们文件信息表中需要存储的信息只有两个:文件名-唯一标识

因此内存中存储文件信息表我们选择用unordered_map存储这对KV(文件名-文件唯一标识)值

而对于持久化存储,关键点在于自己完成序列化和反序列化,不过由于存储信息简单因此序列化和反序列化也比较简单,我们序列化方式如下

反序列化则是写一个字符串拆分函数,先拆除一个一个的KV键值对,在将KV值分离

因此,我们接口设置如下

cpp 复制代码
#pragma once
#include "util.hpp"
#include <unordered_map>
namespace mjw_cloud
{
	class FileDatas
	{
	public:
		FileDatas(const std::string& backup_file)
			:_backup_file(backup_file)
		{}
		
		bool InitTable()
		{}
		bool Storage()
		{}
		bool Insert(const std::string& key, const std::string& val)
		{}
		bool Updata(const std::string& key, const std::string& val)
		{}
		bool GetoneByKey(const std::string& key, std::string* val)
		{}
	private:
		//解析序列化字符串时需要
		//字符串分割,对序列化字符串进行分割
		//"key val key" -> "key" "val" "key"
		int Split(const std::string& str, const std::string& seq, std::vector<std::string>* arry)
		{}
	private:
		std::unordered_map<std::string, std::string> _table;//文件信息表
		std::string _backup_file;//备份文件信息 存储文件
	};
}

代码实现如下:

cpp 复制代码
#pragma once
#include "util.hpp"
#include <unordered_map>
namespace mjw_cloud
{
	class FileDatas
	{
	public:
		FileDatas(const std::string& backup_file)
			:_backup_file(backup_file)
		{

			InitTable();
		}
		
		bool InitTable()
		{
			//1.从文件中读取备份文件信息序列化字符串
			std::string body;
			FileUtil fu(_backup_file);
			fu.GetContent(&body);
			if (body.empty()) return true;
			//2.对字符串进行反序列化解析
			std::vector<std::string> arry;
			//"key val\nkey val\n" -> "key val" "key val"
			Split(body, "\n", &arry);
			for (auto a : arry)
			{
				std::vector<std::string> tmp;
				//"key val" -> "key" "val"
				Split(a, " ", &tmp);
				if (tmp.size() != 0) continue;
				_table[tmp[0]] = tmp[1];
			}
			return true;
		}
		bool Storage()
		{
			if (_table.empty()) return true;
			//1.构建序列化字符串
			std::string body;
			for (auto& t : _table)
			{
				body += t.first + " " + t.second + "\n";
			}
			//2.将字符串写入指定文件
			FileUtil fu(_backup_file);
			fu.SetContent(body);
			return true;
		}
		bool Insert(const std::string& key, const std::string& val)
		{
			_table[key] = val;
			return true;
		}
		bool Updata(const std::string& key, const std::string& val)
		{
			_table[key] = val;
			return true;
		}
		bool GetoneByKey(const std::string& key, std::string* val)
		{
			auto it = _table.find(key);
			if (it == _table.end())
			{
				return false;
			}
			*val = _table[key];
			return true;
		}
	private:
		//解析序列化字符串时需要
		//字符串分割,对序列化字符串进行分割
		//"key val key" -> "key" "val" "key"
		int Split(const std::string& str, const std::string& seq, std::vector<std::string>* arry)
		{
			int count = 0;
			int pos = 0, idx = 0;
			while (idx < str.size())
			{
				pos = str.find(seq, idx);
				if (pos == std::string::npos) break;
				arry->push_back(str.substr(idx, pos - idx));
				idx = pos + 1;
				count++;
			}

			if (idx < str.size())
			{
				//说明str还有最后一截字符串没有push_back进arry
				arry->push_back(str.substr(idx));
				count++;
			}
			return count;
		}
	private:
		std::unordered_map<std::string, std::string> _table;//文件信息表
		std::string _backup_file;//备份文件信息 存储文件
	};
}
相关推荐
码客-ygluu13 小时前
一个通用游戏数据服务器
c++·架构
another heaven13 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
星恒随风13 小时前
MySQL 从零入门(六):复合查询详解——多表查询、自连接、子查询与 UNION
linux·服务器·数据库·mysql
少司府13 小时前
嵌入式入门篇(二):初识STM32F103ZET6
linux·python·stm32·单片机·嵌入式硬件·mcu·嵌入式软件
无足鸟ICT14 小时前
【RHCA+】IO调度算法
linux·服务器
wacsii14 小时前
【Linux进程(四)】命令行参数与环境变量
linux·服务器
无奈笑天下14 小时前
银河麒麟上lsblk命令教程详解
linux·运维·服务器·数据库
YLCHUP15 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
xiaoye-duck15 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
科研邪修法15 小时前
培训PDF保护配置:把需求转换成可验收权限
linux·服务器·网络