已经写到后边去了,但是这几天改bug改的很恼火,就没有写项目日志
云备份day4
- 数据管理模块 ------DataManager
数据管理模块 ------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; } };