目录
数据管理模块:需要管理的数据有哪些,而我们管理数据是因为后期会用到这些数据。
一、要管理的数据
- 文件实际存储路径
- 描述:当客户端要下载文件时,则从这个路径中读取数据进行响应。
- 文件是否被压缩标志
- 描述:用于判断文件是否已经被压缩。
- 文件压缩包存储路径名
- 描述:如果一个文件是非热点文件,则会被压缩,此路径即为压缩包存储的位置。
- 如果客户端要下载文件,则需要先解压缩,然后读取解压后的文件数据。
- 文件属性信息
- 文件大小:记录文件的大小。
- 文件最后一次修改时间:记录文件最后一次被修改的时间。
- 文件最后一次访问时间:记录文件最后一次被访问的时间。
- 文件访问 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一下