当前位置: 首页 > java >正文

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

目录

一、要管理的数据

二、如何管理数据

三.数据管理类的设计

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; // 文件访问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一下

 

http://www.xdnf.cn/news/3715.html

相关文章:

  • 嵌入式 GCC 编译工具链:32 位与 64 位助力高效开发
  • [UVM]UVM中reg_map的作用及多个rem_map的使用案例
  • 【C++篇】类和对象(上)
  • 饱和蒸汽再生数据采集挥发性有机物(VOCs)吸附脱附实验装置
  • Pillow 玩图术:轻松获取图片尺寸和颜色模式
  • 肥胖风险的多类预测——CatBoost模型的89%
  • 《MATLAB实战训练营:从入门到工业级应用》趣味入门篇-用声音合成玩音乐:MATLAB电子琴制作(超级趣味实践版)
  • 用可视化学习逆置法
  • 【Linux】Linux应用开发小经验
  • 信息安全导论 第七章 网络边界防御技术
  • 前端面经-VUE3篇(二)--vue3组件知识(二)依赖注入、异步组件、生命周期、组合式函数、插件
  • piccolo-large-zh-v2 和 bge-m3哪个效果好?
  • 【Mytais系列】SqlSession
  • 经典算法 求解硬币组成问题
  • 【Mytais系列】Select语句执行流程
  • 学习笔记:Qlib 量化投资平台框架 — FOR DEVELOPERS
  • 使用线性表实现通讯录管理
  • MySQL表的约束
  • Yocto介绍
  • 【C语言练习】018. 定义和初始化结构体
  • 【c++】模板详解
  • [android]MT6835 Android 移植brctl指令
  • PowerShell从5.1升级到7.X
  • 深挖Java之:运算符与输入器
  • #Paper Reading# DeepSeek-R1
  • DeepSeek与MySQL:开启数据智能新时代
  • Java SE(7)——类和对象(二)
  • 【Java Stream流-59】Java Stream流式编程:高效、优雅的数据处理之道
  • [案例二] 菜单条制作(Menuscript)与工具条制作(Toolbar)
  • Python基础语法