【云备份】服务端数据管理模块设计与实现
目录
一、要管理的数据
二、如何管理数据
三.数据管理类的设计
3.1.数据信息结构体的设计
3.2.数据管理类的设计
四.数据管理类实现
4.1.数据信息结构体的数据填充
4.2.数据管理类的实现
五. 源代码+测试
数据管理模块:需要管理的数据有哪些,而我们管理数据是因为后期会用到这些数据。
一、要管理的数据
- 文件实际存储路径
- 描述:当客户端要下载文件时,则从这个路径中读取数据进行响应。
- 文件是否被压缩标志
- 描述:用于判断文件是否已经被压缩。
- 文件压缩包存储路径名
- 描述:如果一个文件是非热点文件,则会被压缩,此路径即为压缩包存储的位置。
- 如果客户端要下载文件,则需要先解压缩,然后读取解压后的文件数据。
- 文件属性信息
- 文件大小:记录文件的大小。
- 文件最后一次修改时间:记录文件最后一次被修改的时间。
- 文件最后一次访问时间:记录文件最后一次被访问的时间。
- 文件访问 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; // 文件访问URLbool 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; // 文件访问URLbool 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; // 文件访问URLbool 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一下