【云备份】数据管理模块

文章目录

  • 1. 数据管理模块要管理什么数据?
  • 2. 数据管理模块如何管理数据?
  • 3. 数据管理模块的具体实现
    • BackupInfo 数据信息类
      • NewBackupInfo —— 获取各项属性信息
    • DataManager 数据管理类
      • 构造函数
      • 析构函数
      • insert —— 新增
      • update —— 修改
      • GetOneByURL——通过URL获取单个数据
      • GetOneByURL——通过realpath获取单个数据
      • GETALL —— 获取所有
      • Storage —— 持久化存储实现
    • 具体代码实现
      • data.hpp

1. 数据管理模块要管理什么数据?

1.文件实际存储路径
(当客户端下载文件时,则从文件中读取数据进行响应)

2. 文件压缩包存放路径名
(如果一个文件是非热点文件,就会被压缩,则就为压缩包路径名称)

3.文件是否被压缩的标志位
(判断文件是否已经被压缩了)

4.文件大小
5.文件最后一次修改时间
6.文件最后一次访问时间
7. 文件访问URL中的资源路径path


2. 数据管理模块如何管理数据?

1.用于数据信息访问
(使用hash表在内存中管理数据,以url的path作为key值,来查询内部存储的数据,查询速度快)

2.持久化存储管理
使用json序列化 将 所有数据信息 保存在文件中


3. 数据管理模块的具体实现

BackupInfo 数据信息类

数据信息结构体 BackupInfo_t 包含
pack_flag ——是否压缩标志
fsize ——文件大小
latime ——最后一次访问时间
lmtime ——最后一次修改时间
real_path ——文件实际存储路径名称
pack_path ——压缩包存储路径名称
url_path ——请求资源路径


NewBackupInfo —— 获取各项属性信息

将 NewBackupInfo 函数的参数 realpath路径名 传入 ,实例化一个 FileUtil类的对象
由于是新创建的文件,所以不用压缩
分别调用 FileUtil类 中的 Filesize(文件大小) 、 LastMtime( 文件最后一次修改时间)、 LastATime( 文件最后一次访问时间)
传入的 realpath 就为 文件实际存储路径名称


想要获取压缩包存储路径名称(pack_path) 则需将文件的前缀名换为 ./pack 后缀为换为.lz
实例化一个 Config类的对象,借助 Config类 的GetpackDir(压缩包存放路径)、GetPackFileSuffix(压缩包后缀名称)
通过前缀 、后缀 再加上 中间的文件名称 即可 获得 压缩包存储路径名称


借助 Config类 的GetDownloadPrefix(URL前缀路径) ,再加上文件名称 即可获得请求资源路径


DataManager 数据管理类

构造函数

输入 man pthread_rwlock_init 查看锁的初始化

第一个参数为 rwlock 为 读写锁
第二个参数为 attr 为属性


将属性设置为NULL即可

析构函数

输入 man pthread_rwlock_init 也可查看锁的销毁


insert —— 新增

insert插入,想要进行修改就需要 加写锁 即修改table
table作为一个哈希表, info.url 为 key值 info作为value
最后进行解锁即可


update —— 修改

哈希表的数据不会重复,所以当key值相同时,info会覆盖之前的数据
所以插入和修改的代码是相同的


GetOneByURL——通过URL获取单个数据

先加锁
然后再使用find 查找key值为url的数据
若查找到末尾都没有找到 则返回 false
若找到了 先解锁 再返回 url对应的info


GetOneByURL——通过realpath获取单个数据

realpath不是key值,而是info中的一个成员变量, 所以不能使用find来查找
先加锁 再遍历整个哈希表来查找
若找到了对应的realpath ,则将对应的value放入info中 并解锁 返回true
若遍历整个哈希表 都没找到 ,则解锁 返回false


GETALL —— 获取所有

同样是先加锁 再遍历整个哈希表
每遍历一次,就向arry数组中插入当前哈希表数据对应的info
遍历完后 进行解锁 返回 true即可

Storage —— 持久化存储实现

先定义 一个 BackupInfo 类型的 arry数组
并调用 GetAll 获取所有数据 放入 arry数组中


遍历整个arry数组,将当前arry数组中的元素 的 是否压缩标志、 文件大小、最后一次访问时间、 最后一次修改时间、文件实际存储路径名称、 压缩包存储路径名称、请求资源路径 全部放入 item 中
再把 数组元素 item 添加到 root中


定义一个string类型的变量body
通过之前实现好的 Serialize 函数 进行序列化 即将root中的数据 转化到body文件中


通过 _backup_file 数据持久化存储文件 实例化一个对象
再通过FileUtil类中 的 Setcontent 函数 将body写入到 _backup_file 文件中

具体代码实现

data.hpp

#ifndef _MY_DATA_
#define _MY_DATA_
#include<unordered_map>
#include<pthread.h>
#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; //请求资源路径bool  NewBackupInfo(const std::string &realpath)//获取各项属性信息{FileUtil fu(realpath);if(fu.Exists()==false){std::cout<<"new backupinfo file not exists" <<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前缀路径this->pack_flag=false;this->fsize=fu.FileSize();this->mtime=fu.LastMTime();this->atime=fu.LastATime();this->real_path=realpath; this->pack_path  = packdir+fu.FileName()+packsuffix;// ./backdir/a.txt -> ./packdir/a.txt.lzthis->url=download_prefix + fu.FileName();//./backdir/a.txt  -> /download/a.txt return true;}}BackupInfo;class DataManger{private:std::string _backup_file;//数据持久化存储文件 pthread_rwlock_t  _rwlock;//读写锁 std::unordered_map<std::string,BackupInfo> _table;//哈希表public:DataManger()//构造函数{ _backup_file=Config::GetInstance()->GetBackupFile();//数据信息存放文件pthread_rwlock_init(&_rwlock,NULL);//对读写锁初始化}~DataManger()//析构函数{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)//通过URL获取单个数据{pthread_rwlock_wrlock(&_rwlock);//加写锁//因为url是key值 所以可以直接通过key值来进行查找auto it=_table.find(url);if(it==_table.end()){return false;}*info= it->second;//获取url对应的infopthread_rwlock_unlock(&_rwlock);//解锁return true;} bool GetOneByRealPath(const std::string &realpath ,BackupInfo*info)//通过realpath获取单个数据{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()//持久化存储实现{//获取所有数据 std::vector<BackupInfo> arry;this->GetAll(&arry);//获取所有数据放入arry中//添加到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); //添加数组元素item       }  // 对json::value 序列化 std::string body;JsonUtil::Serialize(root,&body);//序列化 //写文件FileUtil fu(_backup_file);//数据持久化存储文件 fu.Setcontent(body);return true;}};}#endif

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

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

相关文章

Portraiture2024最新Photoshop磨皮插件更新啦

Portraiture是一款由Imagenomic公司研发的Photoshop磨皮插件。该插件以其优秀的磨皮效果&#xff0c;成为了众多摄影师和化妆师使用的首选插件。Portraiture主要用于影楼、婚纱、时尚摄影等各个领域。其主要特点是能够轻松地模拟人眼的视觉感受&#xff0c;自然地修饰人像照片。…

netty(三) taskQueue自定义任务,http服务器快速入门,netty核心模块,Unpooled

如果执行某些业务比较复杂&#xff0c;比较耗时&#xff0c;可以使用异步来完成 当然可以有多个任务 上面的结果是&#xff0c;在第一个任务处理完&#xff0c;再等20秒执行&#xff0c;简单来说&#xff0c;就是第一个在10秒执行&#xff0c;第二个在第30秒的时候执行&#…

Linux:通过VMWare,定制化Linux系统

一、原理图 二、新增磁盘&#xff08;对应上图sdb盘&#xff09; 三、挂载磁盘 主要是四步&#xff1a;查看磁盘&#xff0c;分区磁盘&#xff0c;格式化磁盘&#xff0c;挂载磁盘 1、查看磁盘 2、分区磁盘 3、格式化磁盘 4、挂载磁盘 创建两个备用目录&#xff0c;用于磁盘…

Qt_一个由单例引发的崩溃

Qt_一个由单例引发的崩溃 文章目录 Qt_一个由单例引发的崩溃摘要关于 Q_GLOBAL_STATIC代码测试布局管理器源码分析Demo 验证关于布局管理器析构Qt 类声明周期探索更新代码获取父类分析Qt 单例宏源码 关键字&#xff1a; Qt、 Q_GLOBAL_STATIC、 单例、 UI、 崩溃 摘要 今…

网页设计--第5次课后作业

1、快速学习JavaScript的基本知识第11-14章 JavaScript入门 - 绿叶学习网 2、使用所学的知识完成以下练习。 1&#xff09;点击 “点亮”按钮 点亮灯泡&#xff0c;点击“熄灭”按钮 熄灭灯泡 2&#xff09;输入框鼠标聚焦后&#xff0c;展示小写&#xff1b;鼠标离焦后…

【Java】实现一个自己的线程池

上文中我们讲了线程池的简单使用&#xff0c;这里我们来讲一下如何简单实现一个自己的线程池 本文实现这个线程池所达到的效果是&#xff1a;用户给出线程数目&#xff0c;程序根据用户给出的数创建固定数目的线程 1、框架 首先写定义一个线程池类 class MyThreadPool{}pub…

振南技术干货集:znFAT 硬刚日本的 FATFS 历险记(4)

注解目录 1、znFAT 的起源 1.1 源于论坛 &#xff08;那是一个论坛文化兴盛的年代。网友 DIY SDMP3 播放器激起了我的兴趣。&#xff09; 1.2 硬盘 MP3 推了我一把 &#xff08;“坤哥”的硬盘 MP3 播放器&#xff0c;让我深陷 FAT 文件系统不能自拔。&#xff09; 1.3 我…

前端入门(三)Vue生命周期、组件原理、脚手架、插槽插件、存储、组件事件、动画、跨域与代理

文章目录 Vue生命周期Vue 组件化编程 - .vue文件非单文件组件组件的注意点组件嵌套Vue实例对象和VueComponent实例对象Js对象原型与原型链Vue与VueComponent的重要内置关系 应用单文件组件构建 Vue脚手架 - vue.cli项目文件结构组件相关高级属性引用名 - ref数据接入 - props混…

起猛了!自动驾驶可以聊天了

公众号&#xff1a;算法一只狗 一直以来&#xff0c;深度学习模型对于研究者来说是一种“黑盒”模型&#xff0c;我们一般很难分析模型的到底学习到了什么东西&#xff0c;只知道它能够应用于特定的领域。 对比于自动驾驶领域来看&#xff0c;一个黑盒状态的模型&#xff0c;是…

听说你把 ChatGPT 当成搜索引擎用了?

未经作者&#xff08;微信ID&#xff1a;Byte-Flow&#xff09;允许&#xff0c;禁止转载 文章首发于公众号&#xff1a;字节流动 看到一些读者朋友把 ChatGPT 当成搜索引擎使用了&#xff0c;当然这样使用也没有问题&#xff0c;只是并不能发挥出 ChatGPT 背后大型语言模型&am…

​ 云计算的尽头是轻量应用服务器?带你了解亚马逊Lightsail的卓越优势

很多小伙伴可能都在好奇&#xff0c;轻量应用服务器有什么特点&#xff1f;为什么相较于普通的云服务器&#xff0c;很多用户现在都更青睐于轻量应用服务器?这个“轻”就是它独特的优势所在。轻量应用服务器以其“开箱即用、应用优质、轻松上手、投入划算、运维便捷和稳定可靠…

School training competition ( Second )

A. Medium Number 链接 : Problem - 1760A - Codeforces 就是求三个数的中位数 : #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \nusing namespace std; typedef long long LL; const int N 2e510;inline void …