已经写到后边去了,但是这几天改bug改的很恼火,就没有写项目日志
云备份day4
数据管理模块 ------DataManager
我们要对服务器上存在的文件进行数据管理,就要遵循
先描述,后组织的 的原则,我们需要知道文件的状态和信息,将其描述成为一个结构体,然后在对其进行管理。
服务端模块实现-管理的数据信息
文件实际存储路径
文件是否压缩标志
压缩包存储路径
文件访问URL
文件最后一次修改时间
文件最后一次访问时间
文件大小
服务端数据管理模块实现-如何管理数据
内存中以文件访问URL为key,数据信息结构为val,使用哈希表进行管理,查询速度快。使用url作为key是因为往后客户端浏览器下载文件的时候总是以 url 作为请求。
采用文件形式对数据进行持久化存储(序列化方式采用 json 格式或者自定义方式)
文件信息:
typedef struct BackupInfo{
int pack_flag;
time_t mtime;
time_t atime;
size_t fsize;
std::string realpath;
std::string url;
std::string packpath;
bool NewBackupInfo(const std::string &realpath);
}BackupInfo;
管理模块:
无非就是对数据的增删查改
class DataManager{
private:
FileUtil _backup_file;
pthread_rwlock_t _rwlock;
std::unordered_map<std::string, BackupInfo> _table;
public:
DataManager();
bool InitLoad();//初始化程序运行时从文件读取数据
bool Storage(); //每次有信息改变则需要持久化存储一次
bool Insert(const std::string &key, const BackupInfo &val);
bool Update(const std::string &key, const BackupInfo &val);
bool GetOneByURL(const std::string &key, BackupInfo *info);
bool GetOneByRealPath(const std::string &key, BackupInfo *info);
bool GetAll(std::vector<BackupInfo> *arry);
};
代码:
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;
bool NewBackupInfo(const std::string &realpath){
FileUtil fu(realpath);
if (fu.Exists() == false) {
std::cout << "new backupinfo: file not exists!\n";
return false;
}
Config *config = Config::GetInstance();
std::string packdir = config->GetPackDir();
std::string packsuffix = config->GetPackFileSuffix();
std::string download_prefix = config->GetDownloadPrefix();
this->pack_flag = false;
this->fsize = fu.FileSize();
this->mtime = fu.LastMTime();
this->atime = fu.LastATime();
this->real_path = realpath;
// ./backdir/a.txt -> ./packdir/a.txt.lz
this->pack_path = packdir + fu.FileName() + packsuffix;
// ./backdir/a.txt -> /download/a.txt
this->url = download_prefix + fu.FileName();
return true;
}
}BackupInfo;
class DataManager{
private:
std::string _backup_file;
pthread_rwlock_t _rwlock;
std::unordered_map<std::string, BackupInfo> _table;
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);
Storage();
return true;
}
bool Update(const BackupInfo &info) {
pthread_rwlock_wrlock(&_rwlock);
_table[info.url] = info;
pthread_rwlock_unlock(&_rwlock);
Storage();
return true;
}
bool GetOneByURL(const std::string &url, BackupInfo *info) {
pthread_rwlock_wrlock(&_rwlock);
//因为url是key值,所以直接通过find进行查找
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> *arry) {
pthread_rwlock_wrlock(&_rwlock);
auto it = _table.begin();
for (; it != _table.end(); ++it){
arry->push_back(it->second);
}
pthread_rwlock_unlock(&_rwlock);
return true;
}
bool Storage(){
//1. 获取所有数据
std::vector<BackupInfo> arry;
this->GetAll(&arry);
//2. 添加到Json::Value
Json::Value root;
for (int i = 0; i < arry.size(); i++){
Json::Value item;
item["pack_flag"] = arry[i].pack_flag;
item["fsize"] = (Json::Int64)arry[i].fsize;
item["atime"] = (Json::Int64)arry[i].atime;
item["mtime"] = (Json::Int64)arry[i].mtime;
item["real_path"] = arry[i].real_path;
item["pack_path"] = arry[i].pack_path;
item["url"] = arry[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;
}
};