云备份——数据信息管理模块

一,数据信息管理模块设计

该模块主要用于服务端对备份的文件进行数据信息管理,以便于业务处理模块或者热点管理模随用随取,以及在网页上迅速的显示备份文件列表,因此该模块需要管理的信息也是根据后续业务处理模块以及热点管理模块确定的

根据后续需要我们要管理的信息大概有以下几种

1. 文件的实际存储路径:当用户发出下载请求时,会从该路径读取文件进行响应

2. 文件的压缩包存放路径名:当用户要下载的文件为非热点文件时,需要到该路径下找到目标文件压缩包进行解压,再响应

3. 文件是否压缩标志位:判断文件是否已经被压缩

4. 文件大小

5. 文件最后一次修改时间

6. 文件最后一次访问时间

7. 文件访问中URL的资源路径:/download/a.txt

那么我们如何进行数据管理呢?

1.首先对于数据的访问,最常用的就是查找,如当插入时需要查找资源是否存在,要获取某个备份文件时需要查找资源是否存在,当要更新备份文件时也需要迅速找到目标文件位置;因此我们选择用hash表在内存中管理数据,以URL的下载路径作为key值,对应的信息结构体作为value

2. 持久化存储管理:当服务器关闭或者重启时,我们的文件信息也需要保存到文件中,当服务器再次开始,信息管理模块直接从文件中读取信息即可,因此我们选择用Json序列化将信息保存起来,取出时反序列化即可

数据管理类提供的主要接口如下所示:

#ifndef _MY_MANAGER_
#define _MY_MANAGER_#include "util.hpp"
#include "config.hpp"
#include <unordered_map>namespace mjw_cloud
{struct BackupInfo{BackupInfo(const std::string real_path);BackupInfo& operator=(const BackupInfo& data);//DataManager中的接口需要bool _pack_flag;        // 判断文件是否压缩size_t _fsize;          // 文件大小time_t _atime;          // 文件最后一次访问时间time_t _mtime;          // 文件最后一次修改时间std::string _real_path; // 文件真实存储路径 ./packdir/std::string _pack_path; // 文件压缩包存储路径 ./backdir/std::string _url_path;  // 文件访问中url的资源路径 /download/文件名};class DataManager{public:DataManager();~DataManager();// 存储bool Storage();// 从文件中读取文件信息管理表bool InitTable();// 表中插入数据bool Insert(const BackupInfo &data);// 修改更新表中数据bool Updata(const BackupInfo &data);// 根据url获取对应文件信息,用户根据url请求下载文件时需要bool GetoneByURL(const std::string &url_path, BackupInfo *data);// 根据文件存放路径获取文件信息,服务端检测备份文件时要用bool GetoneByRp(const std::string &real_path, BackupInfo *data);// 获取所有的文件信息,向用户提供一个备份文件表时需要bool GetAll(std::vector<BackupInfo> *arry);private:std::unordered_map<std::string, BackupInfo> _table; // 文件信息管理表std::string _backup_file;                           // 持久化存储文件信息管理表pthread_rwlock_t _rwlock;                           // 读写锁,读共享,写互斥};
}#endif

二,代码实现

代码:

#ifndef _MY_MANAGER_
#define _MY_MANAGER_#include "util.hpp"
#include "config.hpp"
#include <unordered_map>
#include <pthread.h>namespace mjw_cloud
{struct BackupInfo{// 后面数据管理类的InitTable需要用BackupInfo() {}BackupInfo(const std::string real_path){FileUtil fu(real_path);if (fu.Exists() == false){std::cout << "文件不存在" << std::endl;return;}_pack_flag = 0;_fsize = fu.FileSize();_atime = fu.LastATime();_mtime = fu.LastMTime();_real_path = real_path;//"./packdir/a.out" -> "./backdir/a.out.lz"_pack_path = Config::GetInstance().GetPackDir() + fu.FileName() + Config::GetInstance().GetLzPrefix();_url_path = Config::GetInstance().GetUrlPrefix() + fu.FileName();}BackupInfo &operator=(const BackupInfo &data) // DataManager中的接口需要{_pack_flag = data._pack_flag;_fsize = data._fsize;_atime = data._atime;_mtime = data._mtime;_real_path = data._real_path;_pack_path = data._pack_path;_url_path = data._url_path;return *this;}bool _pack_flag;        // 判断文件是否压缩size_t _fsize;          // 文件大小time_t _atime;          // 文件最后一次访问时间time_t _mtime;          // 文件最后一次修改时间std::string _real_path; // 文件真实存储路径名称 ./packdir/a.outstd::string _pack_path; // 文件压缩包存储路径名称 ./backdir/a.out.lzstd::string _url_path;  // 文件访问中url的资源路径 /download/文件名};class DataManager{public:DataManager(){pthread_rwlock_init(&_rwlock, nullptr);_backup_file = Config::GetInstance().GetManagerFile();// 初始化_tableInitTable();}~DataManager(){pthread_rwlock_destroy(&_rwlock);}// 存储bool Storage(){// 1. 将table Json序列化Json::Value root;for (auto t : _table){Json::Value val;val["_pack_flag"] = t.second._pack_flag;// Json支持内置类型,因此size_t和time_t都需强转val["_fsize"] = (Json::Int64)t.second._fsize;val["_atime"] = (Json::Int64)t.second._atime;val["_mtime"] = (Json::Int64)t.second._mtime;val["_real_path"] = t.second._real_path;val["_pack_path"] = t.second._pack_path;val["_url_path"] = t.second._url_path;root.append(val);}std::string str;JsonUtil::Serialize(root, &str);// 2. 写入存储文件FileUtil fu(_backup_file);if (fu.SetContent(str) == false){std::cout << "storage failed" << std::endl;return false;}return true;}// 从文件中读取文件信息管理表bool InitTable(){// 读取信息FileUtil fu(_backup_file);if (fu.Exists() == false)return true;std::string str;if (fu.GetContent(&str) == false){std::cout << "InitTable failed" << std::endl;return false;}// 反序列化Json::Value root;JsonUtil::UnSerialize(str, &root);for (int i = 0; i < root.size(); i++){BackupInfo info;info._atime = root[i]["_atime"].asInt();info._mtime = root[i]["_mtime"].asInt();info._fsize = root[i]["_fsize"].asInt();info._pack_flag = root[i]["_pack_flag"].asBool();info._pack_path = root[i]["_pack_path"].asString();info._real_path = root[i]["_real_path"].asString();info._url_path = root[i]["_url_path"].asString();Insert(info);}return true;}// 表中插入数据bool Insert(const BackupInfo &data){pthread_rwlock_wrlock(&_rwlock);_table[data._url_path] = data;pthread_rwlock_unlock(&_rwlock);//更新数据,持久化存储Storage();return true;}// 修改更新表中数据bool Updata(const BackupInfo &data){pthread_rwlock_wrlock(&_rwlock);_table[data._url_path] = data;pthread_rwlock_unlock(&_rwlock);Storage();return true;}// 根据url获取对应文件信息,用户根据url请求下载文件时需要bool GetoneByURL(const std::string &url_path, BackupInfo *data){pthread_rwlock_rdlock(&_rwlock);auto it = _table.find(url_path);if (it == _table.end()){std::cout << "file unexist" << std::endl;pthread_rwlock_unlock(&_rwlock);return false;}*data = _table[url_path];pthread_rwlock_unlock(&_rwlock);return true;}// 根据文件存放路径获取文件信息,服务端检测备份文件时要用bool GetoneByRp(const std::string &real_path, BackupInfo *data){// 遍历_table,一一比对pthread_rwlock_rdlock(&_rwlock);for (auto t : _table){if (t.second._real_path == real_path){*data = t.second;pthread_rwlock_unlock(&_rwlock);return true;}}pthread_rwlock_unlock(&_rwlock);return false;}// 获取所有的文件信息,向用户提供一个备份文件表时需要bool GetAll(std::vector<BackupInfo> *arry){// 遍历_table,全部插入arrypthread_rwlock_rdlock(&_rwlock);for (auto t : _table){arry->push_back(t.second);}pthread_rwlock_unlock(&_rwlock);return true;}private:std::unordered_map<std::string, BackupInfo> _table; // 文件信息管理表std::string _backup_file;                           // 持久化存储文件信息管理表pthread_rwlock_t _rwlock;                           // 读写锁,读共享,写互斥};
}#endif

测试:

在测试之前我们先将bundle.cpp文件打包成库,因为每次联合编译都很慢,打包成库后编译速度会加快不少。

g++ -c bundle.cpp -o bundle.o
ar -cr libbundle.a bundle.o
mkdir lib//创建lib库
mv libbundle.a lib//将libbnudle.a移动到lib中
//makefile编译指令
g++ -o $@ $^ -L./lib -std=c++11 -lpthread -ljsoncpp -lbundle

测试代码如下

void Managertest(const std::string &real_path)
{std::cout << "-------------BackupInfo test----------------" << std::endl;mjw_cloud::BackupInfo info(real_path);std::cout << info._pack_flag << std::endl;std::cout << info._fsize << std::endl;std::cout << info._atime << std::endl;std::cout << info._mtime << std::endl;std::cout << info._pack_path << std::endl;std::cout << info._real_path << std::endl;std::cout << info._url_path << std::endl;std::cout << std::endl;std::cout << "-------------DataManager test---------------" << std::endl;mjw_cloud::DataManager dm;dm.Insert(info);mjw_cloud::BackupInfo ex1;dm.GetoneByURL(info._url_path, &ex1);std::cout << ex1._pack_flag << std::endl;std::cout << ex1._fsize << std::endl;std::cout << ex1._atime << std::endl;std::cout << ex1._mtime << std::endl;std::cout << ex1._pack_path << std::endl;std::cout << ex1._real_path << std::endl;std::cout << ex1._url_path << std::endl;std::cout << std::endl;mjw_cloud::BackupInfo ex2;dm.GetoneByRp(info._real_path, &ex2);std::cout << ex2._pack_flag << std::endl;std::cout << ex2._fsize << std::endl;std::cout << ex2._atime << std::endl;std::cout << ex2._mtime << std::endl;std::cout << ex2._pack_path << std::endl;std::cout << ex2._real_path << std::endl;std::cout << ex2._url_path << std::endl;std::cout << std::endl;std::vector<mjw_cloud::BackupInfo> arry;dm.GetAll(&arry);for (auto a : arry){std::cout << a._pack_flag << std::endl;std::cout << a._fsize << std::endl;std::cout << a._atime << std::endl;std::cout << a._mtime << std::endl;std::cout << a._pack_path << std::endl;std::cout << a._real_path << std::endl;std::cout << a._url_path << std::endl;std::cout << std::endl;}
}

结果如下

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/100354.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

变电站自动化监控系统

力安科技变电站自动化监控系统是以箱式变电站为管理对象&#xff0c;加装箱变网关&#xff0c;在完成箱变智能化改造的基础上&#xff0c;依托电易云&#xff0c;构建一体化智慧箱变及运维系统。智能箱式变电站被广泛应用于住宅小区、城市公用变压器、工厂、商场、机场、电站等…

服务器数据恢复-阵列崩溃导致LVM结构破坏的数据恢复案例

服务器数据恢复环境&#xff1a; 一台服务器中有两组分别由4块SAS硬盘组建的raid5阵列&#xff0c;两组阵列上层划分LUN组建LVM结构&#xff0c;并被格式化为EXT3文件系统。 服务器故障&检测&#xff1a; RIAD5阵列中有一块硬盘故障离线&#xff0c;热备盘激活上线顶替离线…

pdf怎么合并在一起?几种方法快速合并

pdf怎么合并在一起&#xff1f;在处理PDF文件时&#xff0c;有时需要将多个PDF文件合并成一个文件。这种操作在日常学习、工作和生活中很常见。但是&#xff0c;如果没有专业的PDF工具&#xff0c;这项任务可能会变得非常繁琐、耗时和费力。因此&#xff0c;我们需要一款功能强…

运行Android Automotive模拟器

在windows系统中安装MobaXterm MobaXterm free Xserver and tabbed SSH client for Windows 运行MobaXterm&#xff0c;在宿主机中进入编译后的源码根目录并执行如下命令&#xff0c;若未编译&#xff0c;请参照如下链接&#xff0c;编译车机模拟器Android Automotive编译_IT…

Qt开发_调用OpenCV(3.4.7)设计完成人脸检测系统

一、前言 近年来,人脸识别技术得到了广泛的应用,它可以在各种场景中实现自动化的人脸检测和识别,例如安防监控、人脸解锁、人脸支付等。 该项目的目标是设计一个简单易用但功能强大的人脸检测系统,可以实时从摄像头采集视频,并对视频中的人脸进行准确的检测和框选。通过…

【Mycat1.6】缓存不生效问题处理

背景 系统做读写分离&#xff0c;有大量读需求&#xff0c;基本没有实时获取数据业务需要&#xff0c;所以可以启用缓存来减缓数据库压力&#xff0c;传统使用mybatis的缓存需要大量侵入式声明&#xff0c;所以结合需求使用Mycat中间件来满足 数据库结构 mysql-master&#…

Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin

Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片&#xff0c;Kotlin <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name"android.permission.RE…

linux 内存一致性

linux 出现内存一致性的场景 1、编译器优化 &#xff0c;代码上下没有关联的时候&#xff0c;因为编译优化&#xff0c;会有执行执行顺序不一致的问题&#xff08;多核单核都会出现&#xff09; 2、多核cpu乱序执行&#xff0c;cpu的乱序执行导致内存不一致&#xff08;多核出…

Sui上低Gas费为预言机注入强大动力

在当今世界中&#xff0c;大数据推动了许多真正有用的应用发展&#xff0c;预言机是将这些数据引入区块链的手段。然而&#xff0c;通过预言机进行数据调用需要在区块链上进行交易&#xff0c;并支付相关gas费。Sui保持稳定且低廉gas费的能力&#xff0c;使其成为依赖预言机app…

密码找回安全

文章目录 密码找回安全任意秘密重置 密码找回安全 用户提交修改密码请求;账号认证:服务器发送唯一ID (例如信验证码)只有账户所有者才能看的地方&#xff0c;完成身份验证&#xff1b;身份验证:用户提交验证码完成身份验证;修改密码:用户修改密码。 任意秘密重置 登录metinfo4…

【Node.js】—基本知识点总结

【Node.js】—基本知识总结 一、命令行常用操作 二、Node.js注意点 Node.js中不能使用BOM和DOM操作 总结 三、Buffer buffer是一个类似于数组的对象&#xff0c;用于表示固定长度的字节序列buffer的本质是一段内存空间&#xff0c;专门用来处理二进制数据 特点&#xff1a;…

使用Spring-data-jpa

EnableJpaAuditing 它是用来启动Jpa的审计功能。 jpa querydsl 多表的联合查询 导入依赖 querydsl-jpa 、querydsl-apt Repository接口, 继承QuerydslPredicateExecutor接口 NoRepositoryBean public interface BaseMongoRepository<T> extends MongoRepository<T…