专栏导读
1.要管理的数据有哪些
文件实际存储路径
:当客户要下载文件时,则从这个文件中读取数据进行响应;文件是否被压缩标志
:判断文件是否已经被压缩了;压缩包存储路径
:如果一个文件是非热点文件则会被压缩,这个就是压缩包存储的路径;- 如果客户端要下载文件,则需要先解压缩,然后读取解压后的文件数据;
还有各类文件属性信息
:
文件大小
;文件最后一次修改时间
;文件最后一次访问时间
;文件访问URL中资源路径path
;
2.如何管理数据
-
用于数据信息访问
:使用hash
表在内存中管理数据,以文件访问URL
为key
,数据信息结构
为val
。访问速度快。以文件访问URL
来作为key
是因为客户端浏览器下载文件时总是以URL
作为请求; -
持久化存储管理
:使用JSON序列化
将所有数据保存到文件中;
3.数据信息结构体设计与实现
struct BackupInfo
结构中包含要管理的文件各项属性信息;NewBackUpInfo
负责将传递进来文件各项属性信息组织起来;
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();
pack_flag = false;
fsize = fu.FileSize();
mtime = fu.LastMtime();
atime = fu.LastATime();
real_path = realpath;
pack_path = packdir + fu.FileName() + packsuffix;
url = download_prefix + fu.FileName();
return true;
}
}BackupInfo;
4.数据管理类设计
数据管理类负责将数据信息管理起来。
数据化管理DataManger
中包含以下成员:
class DataManager
{
public:
DataManager();
~DataManager();
bool Insert(const BackupInfo &info); // 新增
bool Updata(const BackupInfo &info); // 更新
bool GetOneByURL(const std::string &url, BackupInfo* info); // 通过url获取文件信息
bool GetOneByRealpath(const std::string &realpath, BackupInfo* info); // 通过实际路径获取文件信息
bool GetAll(std::vector<BackupInfo>* array); // 获取所有文件信息
bool Storage(); // 每次数据更新或者新增都要持久化存储
bool InitLoad(); // 初始化加载,在每次系统启动前都要加载以前的数据
private:
std::string _backup_file; // 备份信息持久化存储
pthread_rwlock_t _rwlock; // 读写锁
std::unordered_map<std::string, BackupInfo> _table // 数据信息组织;
};
5.数据管理类实现
class DataManager
{
public:
DataManager()
{
_backup_file = Config::GetInstance()->GetBackupFile(); // 获取备份信息持久化存储的文件
pthread_rwlock_init(&_rwlock, NULL); // 初始化读写锁
InitLoad(); // 初始化加载
}
~DataManager()
{
pthread_rwlock_destroy(&_rwlock); // 释放读写锁
}
bool Insert(const BackupInfo &info)
{
pthread_rwlock_wrlock(&_rwlock);
_table[info.url] = info;
pthread_rwlock_unlock(&_rwlock);
return true;
}
bool Updata(const BackupInfo &info)
{
pthread_rwlock_wrlock(&_rwlock);
_table[info.url] = info;
pthread_rwlock_unlock(&_rwlock);
return true;
}
bool GetOneByURL(const std::string &url, BackupInfo* info)
{
pthread_rwlock_wrlock(&_rwlock);
auto it = _table.find(url);
if(it == _table.end())
{
pthread_rwlock_unlock(&_rwlock);
return false;
}
*info = it->second;
pthread_rwlock_unlock(&_rwlock);
return true;
}
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)
{
*info = it->second;
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;
}
bool Storage()
{
// 1.获取所有数据
std::vector<BackupInfo> array;
GetAll(&array);
// 2.添加到Json::Value中
Json::Value root;
for(int i = 0; i < array.size(); i++)
{
Json::Value item;
root["pack_flag"] = array[i].pack_flag;
root["fize"] = (Json::Int64)array[i].fsize;
root["atime"] = (Json::Int64)array[i].atime;
root["mtime"] = (Json::Int64)array[i].mtime;
root["real_path"] = array[i].real_path;
root["pack_path"] = array[i].pack_path;
root["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 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;
}
private:
std::string _backup_file; // 备份信息持久化存储
pthread_rwlock_t _rwlock; // 读写锁
std::unordered_map<std::string, BackupInfo> _table; // 数据信息组织
};
6.数据管理模块整理
我们将BackpInfo
与DataManger
的实现都放到data.hpp
中。
// data.hpp
#ifndef __MY_DATA__
#define __MY_DATA__
#include <unordered_map>
#include <pthread.h>
#include "util.hpp"
#include "config.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();
pack_flag = false;
fsize = fu.FileSize();
mtime = fu.LastMtime();
atime = fu.LastATime();
real_path = realpath;
pack_path = packdir + fu.FileName() + packsuffix;
url = download_prefix + fu.FileName();
return true;
}
}BackupInfo;
class DataManager
{
public:
DataManager()
{
_backup_file = Config::GetInstance()->GetBackupFile(); // 获取备份信息持久化存储的文件
pthread_rwlock_init(&_rwlock, NULL); // 初始化读写锁
InitLoad(); // 初始化加载
}
~DataManager()
{
pthread_rwlock_destroy(&_rwlock); // 释放读写锁
}
bool Insert(const BackupInfo &info)
{
pthread_rwlock_wrlock(&_rwlock);
_table[info.url] = info;
pthread_rwlock_unlock(&_rwlock);
return true;
}
bool Updata(const BackupInfo &info)
{
pthread_rwlock_wrlock(&_rwlock);
_table[info.url] = info;
pthread_rwlock_unlock(&_rwlock);
return true;
}
bool GetOneByURL(const std::string &url, BackupInfo* info)
{
pthread_rwlock_wrlock(&_rwlock);
auto it = _table.find(url);
if(it == _table.end())
{
pthread_rwlock_unlock(&_rwlock);
return false;
}
*info = it->second;
pthread_rwlock_unlock(&_rwlock);
return true;
}
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)
{
*info = it->second;
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;
}
bool Storage()
{
// 1.获取所有数据
std::vector<BackupInfo> array;
GetAll(&array);
// 2.添加到Json::Value中
Json::Value root;
for(int i = 0; i < array.size(); i++)
{
Json::Value item;
root["pack_flag"] = array[i].pack_flag;
root["fize"] = (Json::Int64)array[i].fsize;
root["atime"] = (Json::Int64)array[i].atime;
root["mtime"] = (Json::Int64)array[i].mtime;
root["real_path"] = array[i].real_path;
root["pack_path"] = array[i].pack_path;
root["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 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;
}
private:
std::string _backup_file; // 备份信息持久化存储
pthread_rwlock_t _rwlock; // 读写锁
std::unordered_map<std::string, BackupInfo> _table; // 数据信息组织
};
}
#endif