【云备份】服务端数据管理模块设计与实现

目录

一、要管理的数据

二、如何管理数据

三.数据管理类的设计

3.1.数据信息结构体的设计

3.2.数据管理类的设计

四.数据管理类实现

4.1.数据信息结构体的数据填充

4.2.数据管理类的实现

五. 源代码+测试 


 

数据管理模块:需要管理的数据有哪些,而我们管理数据是因为后期会用到这些数据。

一、要管理的数据

  1. 文件实际存储路径
    • 描述:当客户端要下载文件时,则从这个路径中读取数据进行响应。
  2. 文件是否被压缩标志
    • 描述:用于判断文件是否已经被压缩。
  3. 文件压缩包存储路径名
    • 描述:如果一个文件是非热点文件,则会被压缩,此路径即为压缩包存储的位置。
    • 如果客户端要下载文件,则需要先解压缩,然后读取解压后的文件数据。
  4. 文件属性信息
    • 文件大小:记录文件的大小。
    • 文件最后一次修改时间:记录文件最后一次被修改的时间。
    • 文件最后一次访问时间:记录文件最后一次被访问的时间。
    • 文件访问 URL 中资源路径(path):记录文件在访问 URL 中的资源路径。比如说/download/a.txt,这个就类似于下载链接,必须得管理好

二、如何管理数据

  • 2.1.用于数据信息访问

方法:使用哈希表(hash 表)在内存中管理数据。

哈希表的键(key):文件访问 URL。

哈希表的值(val):数据信息结构。

优点:访问速度快。因为哈希表的查询时间复杂度都在O(1)。

以文件访问 URL 作为 key,是因为客户端浏览器下载文件时总是以 URL 作为请求。

  • 2.2.用于持久化存储管理

方法:使用 JSON 序列化将所有数据保存到文件中。

三.数据管理类的设计

3.1.数据信息结构体的设计

数据管理类:管理服务端系统中会用到的数据。

数据信息结构体:struct BackupInfo结构中包含要管理的文件各项属性信息;

typedef struct BackupInfo
{
    bool pack_flag; // 文件是否被压缩标志
    size_t fsize; // 文件大小
    time_t mtime; // 文件最后一次修改时间
    time_t atime; // 文件最后一次访问时间
    std::string real_path; // 文件实际存储路径
    std::string pack_path; // 压缩包存储路径
    std::string url; // 文件访问URL
}BackupInfo;

3.2.数据管理类的设计

数据管理类负责将数据信息管理起来。

数据化管理DataManger中包含以下成员:

class DataManager
    {
    public:
        DataManager();
        ~DataManager();

        //持久化存储的接口
        bool Storage(); // 每次数据更新或者新增都要持久化存储,避免数据丢失
        bool InitLoad(); // 初始化加载,在每次系统启动前都要加载以前的数据

        bool Insert(const BackupInfo &info); // 新增
        bool Updata(const BackupInfo &info); // 更新
        
        //数据信息访问的接口
        // 通过url获取文件信息,所有的文件信息都存放到info里面去
        bool GetOneByURL(const std::string &url, BackupInfo* info); 
        // 通过实际路径获取文件信息,这些文件信息都存放到info里面去
        bool GetOneByRealpath(const std::string &realpath, BackupInfo* info); 
        // 获取所有文件信息
        bool GetAll(std::vector<BackupInfo>* array); 

    private:
        std::string _backup_file; // 备份信息持久化存储,从配置文件里面获取
        pthread_rwlock_t _rwlock; //读写锁,读写锁是读共享,写互斥,多个线程可以同时读取数据,但不能同时写
        // 因为我们是使用多线程的,所以需要注意线程安全
        std::unordered_map<std::string, BackupInfo> _table // 哈希表数据信息组织,key是文件访问url,值是数据信息结构;
    };

四.数据管理类实现

4.1.数据信息结构体的数据填充

我们创建一个data.hpp文件,用来数据管理。

首先我们首先需要对 struct BackupInfo结构进行填充,这个需要一个构造函数 NewBackUpInfo。

 NewBackUpInfo负责将传递进来文件各项属性信息组织起来;

本质就是根据配置文件的内容+本文件的属性来更新BackupInfo结构中这些属性。

data.hpp

#ifndef _MY_DATA_
#define _MY_DATA_
#include"util.hpp"
#include<unordered_map>
#include<pthread.h>
#include"conf.hpp"

namespace cloud{
	typedef struct BackupInfo
	{
		bool pack_flag; // 文件是否被压缩标志
		size_t fsize; // 文件大小
		time_t mtime; // 文件最后一次修改时间
		time_t atime; // 文件最后一次访问时间
		std::string real_path; // 文件实际存储路径
		std::string pack_path; // 压缩包存储路径
		std::string url; // 文件访问URL
		bool NewBackupInfo(const std::string &realpath)//填充上面这些数据
		{
			//当前文件的信息的获取
			FileUtil fu(realpath);//文件管理类,方便我们管理文件,获取文件属性
			if(fu.Exists() == false)//当前文件不存在
			{
				std::cout << "new backupinfo: file not exit" << std::endl;
				return false;
			}
			//配置文件信息的获取
			Config* config = Config::GetInstance();//构造我们的配置文件对象
			std::string packdir = config->GetPackDir();//获取配置文件里的压缩路径
			std::string packsuffix = config->GetPackFileSuffix();//获取配置文件里面的压缩文件的后缀名
			std::string download_prefix = config->GetDownloadPrefix();//获取配置文件里面的下载的url前缀
			
			pack_flag = false;//文件没有被压缩
			fsize = fu.FileSize();
			mtime = fu.LastModtime();
			atime = fu.LastAcctime();
			real_path = realpath;//我们传入的参数就是
			//注意我们的文件被压缩时文件路径会从./backdir/a.txt变成./packdir/a.txt.lz,这需要压缩路径,文件名,压缩后缀两个信息,这些都在配置文件里面
			pack_path = packdir + fu.FileName() + packsuffix;
			//我们这个url是从./backdir/a.txt变成./download/a.txt,这就需要下载的url前缀,文件名,这些都在配置文件里面
			url = download_prefix + fu.FileName();
			return true;
		}
	}BackupInfo;
};
#endif

为了检测我们这个代码写的对不对,我们需要来测试一下

cloud.cc

#include"util.hpp"
#include"conf.hpp"
#include"data.hpp"

void DataTest(const std::string & filename)
{
         cloud::BackupInfo info;
        info.NewBackupInfo(filename);
        std::cout<<info.pack_flag<<std::endl;
        std::cout<<info.fsize<<std::endl;
        std::cout<<info.mtime<<std::endl;
        std::cout<<info.atime<<std::endl;
        std::cout<<info.real_path<<std::endl;
        std::cout<<info.pack_path<<std::endl;
        std::cout<<info.url<<std::endl;
}
int main(int argc,char*argv[])
{
        DataTest(argv[1]);
        return 0;
}

我们编译一下,由于我们编译的时候这个bundle头文件啥的太慢了,而且还老是报警,这很不舒服,所以我们将bundle.cpp生成一个静态库好了

g++ -c bundle.cpp -o bundle.o
ar -cr libbundle.a bundle.o
rm -rf bundle.cpp bundle.o

接着修改我们的makefile

cloud:cloud.cc util.hpp 
        g++ $^ -o $@ -L./lib -lpthread -lstdc++fs -ljsoncpp -lbundle
.PHONY:clean
clean:
        rm -f cloud

 这样子就好很多了,编译的很快

 

都没有问题啊!!


这个时候我们git一下

4.2.数据管理类的实现

  • 新增,修改,获取文件属性的接口

我们啥也不多说,直接看代码好吧!!!

class DataManager
	{
	public:
		DataManager()
		{
			_backup_file = Config::GetInstance()->GetBackupFile(); // 获取备份信息持久化存储的文件,也就是获取配置文件里面的内容
			pthread_rwlock_init(&_rwlock, NULL);				   // 初始化读写锁
		}
		~DataManager()
		{
			pthread_rwlock_destroy(&_rwlock); // 释放读写锁
		}


		bool Insert(const BackupInfo &info)//新增
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info.url] = info;//key值是url,值是BackupInfo结构
			pthread_rwlock_unlock(&_rwlock);
			return true;
		}
		bool Updata(const BackupInfo &info)//修改,对于目前来说和新增没有任何区别
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info.url] = info;//当key值相同时,会覆盖之前的文件
			pthread_rwlock_unlock(&_rwlock);
			return true;
		}

		//数据信息访问的接口
        // 通过url获取文件信息,所有的文件信息都存放到info里面去
		//现在传进去的url是哈希表的key值
		bool GetOneByURL(const std::string &url, BackupInfo *info)
		{
			pthread_rwlock_wrlock(&_rwlock);//要访问哈希表,必须加锁
			auto it = _table.find(url);//在哈希表里面寻找匹配的上的url,通过匹配key值来找到BackupInfo结构
			if (it == _table.end())//没找到
			{
				pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
				return false;
			}
			*info = it->second;//用info来获取BackupInfo结构
			pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
			return true;
		}
		// 通过实际路径获取文件信息,这些文件信息都存放到info里面去
		//现在传进去的realpath不是哈希表的key值
		bool GetOneByRealpath(const std::string &realpath, BackupInfo *info)
		{
			pthread_rwlock_wrlock(&_rwlock);//要访问哈希表,必须加锁
			auto it = _table.begin();
			for (; it != _table.end(); ++it)
			{
				if (it->second.real_path == realpath)//通过匹配哈希表里面每个BackupInfo结构里的real_path来找到BackupInfo结构
				{
					*info = it->second;//用info来获取BackupInfo结构
					pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
					return true;
				}
			}
			pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
			return false;//没找到
		}
		// 获取所有文件信息
		bool GetAll(std::vector<BackupInfo> *array)
		{
			pthread_rwlock_wrlock(&_rwlock);//加锁
			auto it = _table.begin();
			for (; it != _table.end(); ++it)
			{
				array->push_back(it->second);//直接填充
			}
			pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
			return true;
		}
		

	private:
		std::string _backup_file;							// 备份信息持久化存储
		pthread_rwlock_t _rwlock;							// 读写锁
		std::unordered_map<std::string, BackupInfo> _table; // 数据信息组织——用哈希表存储
	};

现在我们来测试一下

data.hpp

#ifndef _MY_DATA_
#define _MY_DATA_
#include "util.hpp"
#include <unordered_map>
#include <pthread.h>
#include "conf.hpp"

namespace cloud
{
	typedef struct BackupInfo
	{
		bool pack_flag;									// 文件是否被压缩标志
		size_t fsize;									// 文件大小
		time_t mtime;									// 文件最后一次修改时间
		time_t atime;									// 文件最后一次访问时间
		std::string real_path;							// 文件实际存储路径
		std::string pack_path;							// 压缩包存储路径
		std::string url;								// 文件访问URL
		bool NewBackupInfo(const std::string &realpath) // 填充上面这些数据
		{
			// 当前文件的信息的获取
			FileUtil fu(realpath);	  // 文件管理类,方便我们管理文件,获取文件属性
			if (fu.Exists() == false) // 当前文件不存在
			{
				std::cout << "new backupinfo: file not exit" << std::endl;
				return false;
			}
			// 配置文件信息的获取
			Config *config = Config::GetInstance();					   // 构造我们的配置文件对象
			std::string packdir = config->GetPackDir();				   // 获取配置文件里的压缩路径
			std::string packsuffix = config->GetPackFileSuffix();	   // 获取配置文件里面的压缩文件的后缀名
			std::string download_prefix = config->GetDownloadPrefix(); // 获取配置文件里面的下载的url前缀

			pack_flag = false; // 文件没有被压缩
			fsize = fu.FileSize();
			mtime = fu.LastModtime();
			atime = fu.LastAcctime();
			real_path = realpath; // 我们传入的参数就是
			// 注意我们的文件被压缩时文件路径会从./backdir/a.txt变成./packdir/a.txt.lz,这需要压缩路径,文件名,压缩后缀两个信息,这些都在配置文件里面
			pack_path = packdir + fu.FileName() + packsuffix;
			// 我们这个url是从./backdir/a.txt变成./download/a.txt,这就需要下载的url前缀,文件名,这些都在配置文件里面
			url = download_prefix + fu.FileName();
			return true;
		}
	} BackupInfo;


	class DataManager
	{
	public:
		DataManager()
		{
			_backup_file = Config::GetInstance()->GetBackupFile(); // 获取备份信息持久化存储的文件,也就是获取配置文件里面的内容
			pthread_rwlock_init(&_rwlock, NULL);				   // 初始化读写锁
		}
		~DataManager()
		{
			pthread_rwlock_destroy(&_rwlock); // 释放读写锁
		}


		bool Insert(const BackupInfo &info)//新增
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info.url] = info;//key值是url,值是BackupInfo结构
			pthread_rwlock_unlock(&_rwlock);
			return true;
		}
		bool Updata(const BackupInfo &info)//修改,对于目前来说和新增没有任何区别
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info.url] = info;//当key值相同时,会覆盖之前的文件
			pthread_rwlock_unlock(&_rwlock);
			return true;
		}

		//数据信息访问的接口
        // 通过url获取文件信息,所有的文件信息都存放到info里面去
		//现在传进去的url是哈希表的key值
		bool GetOneByURL(const std::string &url, BackupInfo *info)
		{
			pthread_rwlock_wrlock(&_rwlock);//要访问哈希表,必须加锁
			auto it = _table.find(url);//在哈希表里面寻找匹配的上的url,通过匹配key值来找到BackupInfo结构
			if (it == _table.end())//没找到
			{
				pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
				return false;
			}
			*info = it->second;//用info来获取BackupInfo结构
			pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
			return true;
		}
		// 通过实际路径获取文件信息,这些文件信息都存放到info里面去
		//现在传进去的realpath不是哈希表的key值
		bool GetOneByRealpath(const std::string &realpath, BackupInfo *info)
		{
			pthread_rwlock_wrlock(&_rwlock);//要访问哈希表,必须加锁
			auto it = _table.begin();
			for (; it != _table.end(); ++it)
			{
				if (it->second.real_path == realpath)//通过匹配哈希表里面每个BackupInfo结构里的real_path来找到BackupInfo结构
				{
					*info = it->second;//用info来获取BackupInfo结构
					pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
					return true;
				}
			}
			pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
			return false;//没找到
		}
		// 获取所有文件信息
		bool GetAll(std::vector<BackupInfo> *array)
		{
			pthread_rwlock_wrlock(&_rwlock);//加锁
			auto it = _table.begin();
			for (; it != _table.end(); ++it)
			{
				array->push_back(it->second);//直接填充
			}
			pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
			return true;
		}
		

	private:
		std::string _backup_file;							// 备份信息持久化存储
		pthread_rwlock_t _rwlock;							// 读写锁
		std::unordered_map<std::string, BackupInfo> _table; // 数据信息组织——用哈希表存储
	};

};
#endif

 cloud.cc测试版本1

我们这个函数目前是只测试了那些信息访问的接口,具体接口看下面 

#include "util.hpp"
#include "conf.hpp"
#include "data.hpp"

void DataTest(const std::string &filename)
{
	cloud::BackupInfo info;
	info.NewBackupInfo(filename);
	cloud::DataManager data;

	std::cout<<"---------Insert and GetOneByURL---------"<<std::endl;
	data.Insert(info);
	cloud::BackupInfo tmp;
	data.GetOneByURL("/download/bundle.h", &tmp);
	std::cout << tmp.pack_flag << std::endl;
	std::cout << tmp.fsize << std::endl;
	std::cout << tmp.mtime << std::endl;
	std::cout << tmp.atime << std::endl;
	std::cout << tmp.real_path << std::endl;
	std::cout << tmp.pack_path << std::endl;
	std::cout << tmp.url << std::endl;

	std::cout<<"---------update and GetAll---------"<<std::endl;
	info.pack_flag = true;
	data.Updata(info);
	std::vector<cloud::BackupInfo> arry;
	//获取所有文件
	data.GetAll(&arry);
	for (auto &a : arry)
	{
		std::cout << a.pack_flag << std::endl;
		std::cout << a.fsize << std::endl;
		std::cout << a.mtime << std::endl;
		std::cout << a.atime << std::endl;
		std::cout << a.real_path << std::endl;
		std::cout << a.pack_path << std::endl;
		std::cout << a.url << std::endl;
	}

	//根据实际路径进行查询
	std::cout<<"---------GetOneByRealpath---------"<<std::endl;
	data.GetOneByRealpath(filename,&tmp);
	std::cout << tmp.pack_flag << std::endl;
	std::cout << tmp.fsize << std::endl;
	std::cout << tmp.mtime << std::endl;
	std::cout << tmp.atime << std::endl;
	std::cout << tmp.real_path << std::endl;
	std::cout << tmp.pack_path << std::endl;
	std::cout << tmp.url << std::endl;
}
int main(int argc, char *argv[])
{
	DataTest(argv[1]);
	return 0;
}

 我们编译一下

这个版本很完美


  • 数据持久化存储的接口

其实需要修改的也就是在类里添加或者修改下面三个函数

//用于持久化存储的接口
		bool Storage()//每次数据更新或者新增都要持久化存储,避免数据丢失
		{
			// 1.获取所有文件的数据
			std::vector<BackupInfo> array;
			GetAll(&array);
			// 2.添加到Json::Value中
			Json::Value root;//将需要序列化的信息都放到root里面
			for (int i = 0; i < array.size(); i++)
			{
				Json::Value item;
				item["pack_flag"] = array[i].pack_flag;
				item["fsize"] = (Json::Int64)array[i].fsize;
				item["atime"] = (Json::Int64)array[i].atime;
				item["mtime"] = (Json::Int64)array[i].mtime;
				item["real_path"] = array[i].real_path;
				item["pack_path"] = array[i].pack_path;
				item["url"] = array[i].url;
				root.append(item); // 添加数组元素
			}
			// 3.对Json::Value序列化
			std::string body;
			JsonUtil::Serialize(root, &body);
			// 4.写文件
			FileUtil fu(_backup_file);
			fu.SetContent(body);

			return true;
		}

		

		bool Insert(const BackupInfo &info)//新增
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info.url] = info;//key值是url,值是BackupInfo结构
			pthread_rwlock_unlock(&_rwlock);
			Storage();//新增是需要保存起来的
			return true;
		}
		bool Updata(const BackupInfo &info)//修改,对于目前来说和新增没有任何区别
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info.url] = info;//当key值相同时,会覆盖之前的文件
			pthread_rwlock_unlock(&_rwlock);
			Storage();//修改后的也是需要做持久化存储的
			return true;
		}

 现在所有的信息都存储在这个_backup_file文件里面里面了


  • 初始化加载函数
DataManager()
		{
			_backup_file = Config::GetInstance()->GetBackupFile(); // 获取备份信息持久化存储的文件,也就是获取配置文件里面的内容
			pthread_rwlock_init(&_rwlock, NULL);				   // 初始化读写锁
			InitLoad();// 初始化加载,将json文件里面的数据读取出来
		}


bool InitLoad()// 初始化加载,在每次系统启动前都要加载以前的数据
		{
			// 1.将数据从文件中读取出来
			FileUtil fu(_backup_file);
			if (fu.Exists() == false)//如果文件不存在
			{
				return true;
			}
			std::string body;
			fu.GetContent(&body);//获取文件里面的数据
			// 2.反序列化
			Json::Value root;
			JsonUtil::Unserialize(body, &root);
			// 3.将反序列化得到的Json::Value中的数据添加到table中
			for (int i = 0; i < root.size(); i++)
			{
				BackupInfo info;
				info.pack_flag = root[i]["pack_flag"].asBool();
				info.fsize = root[i]["fsize"].asInt64();
				info.atime = root[i]["atime"].asInt64();
				info.mtime = root[i]["mtime"].asInt64();
				info.pack_path = root[i]["pack_path"].asString();
				info.real_path = root[i]["real_path"].asString();
				info.url = root[i]["url"].asString();
				Insert(info);//将数据添加进哈希表里面去
			}
			return true;
		}

五. 源代码+测试 

data.hpp

#ifndef _MY_DATA_
#define _MY_DATA_
#include "util.hpp"
#include <unordered_map>
#include <pthread.h>
#include "conf.hpp"

namespace cloud
{
	typedef struct BackupInfo
	{
		bool pack_flag;									// 文件是否被压缩标志
		size_t fsize;									// 文件大小
		time_t mtime;									// 文件最后一次修改时间
		time_t atime;									// 文件最后一次访问时间
		std::string real_path;							// 文件实际存储路径
		std::string pack_path;							// 压缩包存储路径
		std::string url;								// 文件访问URL
		bool NewBackupInfo(const std::string &realpath) // 填充上面这些数据
		{
			// 当前文件的信息的获取
			FileUtil fu(realpath);	  // 文件管理类,方便我们管理文件,获取文件属性
			if (fu.Exists() == false) // 当前文件不存在
			{
				std::cout << "new backupinfo: file not exit" << std::endl;
				return false;
			}
			// 配置文件信息的获取
			Config *config = Config::GetInstance();					   // 构造我们的配置文件对象
			std::string packdir = config->GetPackDir();				   // 获取配置文件里的压缩路径
			std::string packsuffix = config->GetPackFileSuffix();	   // 获取配置文件里面的压缩文件的后缀名
			std::string download_prefix = config->GetDownloadPrefix(); // 获取配置文件里面的下载的url前缀

			pack_flag = false; // 文件没有被压缩
			fsize = fu.FileSize();
			mtime = fu.LastModtime();
			atime = fu.LastAcctime();
			real_path = realpath; // 我们传入的参数就是
			// 注意我们的文件被压缩时文件路径会从./backdir/a.txt变成./packdir/a.txt.lz,这需要压缩路径,文件名,压缩后缀两个信息,这些都在配置文件里面
			pack_path = packdir + fu.FileName() + packsuffix;
			// 我们这个url是从./backdir/a.txt变成./download/a.txt,这就需要下载的url前缀,文件名,这些都在配置文件里面
			url = download_prefix + fu.FileName();
			return true;
		}
	} BackupInfo;


	class DataManager
	{
	public:
		DataManager()
		{
			_backup_file = Config::GetInstance()->GetBackupFile(); // 获取备份信息持久化存储的文件,也就是获取配置文件里面的内容
			pthread_rwlock_init(&_rwlock, NULL);				   // 初始化读写锁
			InitLoad();// 初始化加载,将json文件里面的数据读取出来
		}
		~DataManager()
		{
			pthread_rwlock_destroy(&_rwlock); // 释放读写锁
		}

		//用于持久化存储的接口
		bool Storage()//每次数据更新或者新增都要持久化存储,避免数据丢失
		{
			// 1.获取所有文件的数据
			std::vector<BackupInfo> array;
			GetAll(&array);
			// 2.添加到Json::Value中
			Json::Value root;//将需要序列化的信息都放到root里面
			for (int i = 0; i < array.size(); i++)
			{
				Json::Value item;
				item["pack_flag"] = array[i].pack_flag;
				item["fsize"] = (Json::Int64)array[i].fsize;
				item["atime"] = (Json::Int64)array[i].atime;
				item["mtime"] = (Json::Int64)array[i].mtime;
				item["real_path"] = array[i].real_path;
				item["pack_path"] = array[i].pack_path;
				item["url"] = array[i].url;
				root.append(item); // 添加数组元素
			}
			// 3.对Json::Value序列化
			std::string body;
			JsonUtil::Serialize(root, &body);
			// 4.写文件——把序列化后的写进这个_backup_file文件里面
			FileUtil fu(_backup_file);
			fu.SetContent(body);

			return true;
		}

		bool InitLoad()// 初始化加载,在每次系统启动前都要加载以前的数据
		{
			// 1.将数据从文件中读取出来
			FileUtil fu(_backup_file);
			if (fu.Exists() == false)//如果文件不存在
			{
				return true;
			}
			std::string body;
			fu.GetContent(&body);//获取文件里面的数据
			// 2.反序列化
			Json::Value root;
			JsonUtil::Unserialize(body, &root);
			// 3.将反序列化得到的Json::Value中的数据添加到table中
			for (int i = 0; i < root.size(); i++)
			{
				BackupInfo info;
				info.pack_flag = root[i]["pack_flag"].asBool();
				info.fsize = root[i]["fsize"].asInt64();
				info.atime = root[i]["atime"].asInt64();
				info.mtime = root[i]["mtime"].asInt64();
				info.pack_path = root[i]["pack_path"].asString();
				info.real_path = root[i]["real_path"].asString();
				info.url = root[i]["url"].asString();
				Insert(info);//将数据添加进哈希表里面去
			}
			return true;
		}

		bool Insert(const BackupInfo &info)//新增
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info.url] = info;//key值是url,值是BackupInfo结构
			pthread_rwlock_unlock(&_rwlock);
			Storage();//新增是需要保存起来的
			return true;
		}
		bool Updata(const BackupInfo &info)//修改,对于目前来说和新增没有任何区别
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info.url] = info;//当key值相同时,会覆盖之前的文件
			pthread_rwlock_unlock(&_rwlock);
			Storage();//修改后的也是需要做持久化存储的
			return true;
		}

		//数据信息访问的接口
        // 通过url获取文件信息,所有的文件信息都存放到info里面去
		//现在传进去的url是哈希表的key值
		bool GetOneByURL(const std::string &url, BackupInfo *info)
		{
			pthread_rwlock_wrlock(&_rwlock);//要访问哈希表,必须加锁
			auto it = _table.find(url);//在哈希表里面寻找匹配的上的url,通过匹配key值来找到BackupInfo结构
			if (it == _table.end())//没找到
			{
				pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
				return false;
			}
			*info = it->second;//用info来获取BackupInfo结构
			pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
			return true;
		}
		// 通过实际路径获取文件信息,这些文件信息都存放到info里面去
		//现在传进去的realpath不是哈希表的key值
		bool GetOneByRealpath(const std::string &realpath, BackupInfo *info)
		{
			pthread_rwlock_wrlock(&_rwlock);//要访问哈希表,必须加锁
			auto it = _table.begin();
			for (; it != _table.end(); ++it)
			{
				if (it->second.real_path == realpath)//通过匹配哈希表里面每个BackupInfo结构里的real_path来找到BackupInfo结构
				{
					*info = it->second;//用info来获取BackupInfo结构
					pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
					return true;
				}
			}
			pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
			return false;//没找到
		}
		// 获取所有文件信息
		bool GetAll(std::vector<BackupInfo> *array)
		{
			pthread_rwlock_wrlock(&_rwlock);//加锁
			auto it = _table.begin();
			for (; it != _table.end(); ++it)
			{
				array->push_back(it->second);//直接填充
			}
			pthread_rwlock_unlock(&_rwlock);//不要忘记解锁
			return true;
		}
		

	private:
		std::string _backup_file;							// 备份信息持久化存储
		pthread_rwlock_t _rwlock;							// 读写锁
		std::unordered_map<std::string, BackupInfo> _table; // 数据信息组织——用哈希表存储
	};

};
#endif

 cloud.cc

#include "util.hpp"
#include "conf.hpp"
#include "data.hpp"

void DataTest(const std::string &filename)
{
	cloud::DataManager data;//构造之后会默认自动化加载
	std::vector<cloud::BackupInfo> arry;
	//获取所有文件
	data.GetAll(&arry);
	for (auto &a : arry)
	{
		std::cout << a.pack_flag << std::endl;
		std::cout << a.fsize << std::endl;
		std::cout << a.mtime << std::endl;
		std::cout << a.atime << std::endl;
		std::cout << a.real_path << std::endl;
		std::cout << a.pack_path << std::endl;
		std::cout << a.url << std::endl;
	}
}
int main(int argc, char *argv[])
{
	DataTest(argv[1]);
	return 0;
}

现在就是很完美了 


我们git一下

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值