【云备份】数据管理模块

news2024/11/27 10:27:33

文章目录

  • 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.lz
         
          this->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对应的info
                pthread_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.coloradmin.cn/o/1259631.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言——标识符

一、标识符是什么 标识符是C程序的最基本组成部分&#xff0c;例如&#xff1a;变量名称、函数名称、数据类型等等&#xff0c;都是一个标识符。标识符的要求是&#xff1a;必须由字母&#xff08;区分大小写&#xff09;、数字、下划线组成。而且&#xff0c;标识符的第一个字…

JDBC编程基础

JDBC编程基础 JDBC介绍创建JDBC项目的步骤1.引入依赖2.注册驱动3.获取数据库连接4.获取sql执行对象 JDBC 常用 API 详解sql执行对象PreparedStatement作用 事务管理结果集对象 JDBC项目demo测试 JDBC介绍 每个数据库都会提供一组API来支持程序员实现自己客户端&#xff0c;自己…

SQL Server:流程控制语言详解

文章目录 一、批处理、脚本和变量局部变量和全局变量1、局部变量2、全局变量 二、顺序、分支和循环结构语句1、程序注释语句2、BEGIN┅END语句块3、IF┅ELSE语句4、CASE语句5、WHILE语句6、BREAK和CONTINUE语句BREAK语句CONTINUE语句 三、程序返回、屏幕显示等语句1、RETURN语句…

通义灵码,你的智能编码助手,免费公测啦!

目录 ​编辑 1、介绍 2、安装 3、功能介绍 行/函数级实时续写 自然语言生成代码 单元测试生成 代码注释生成 代码解释 研发智能问答 多编程语言、多编辑器全方位支持 4、视频 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家…

TopK问题(用堆解决)

我们继续来延续我们上面的TopK问题&#xff0c;TopK问题一般是在解决有很多数的情况下&#xff0c;我们的k是个和小的值&#xff0c;然后我们是要找到最小或者最大的K个数&#xff0c;这类问题我们也称之为TopK问题&#xff0c;面对这种的问题&#xff0c;如果数字不是很大的情…

java--子类中访问其他成员的特点

1.在子类方法中访问其他成员(成员变量、成员方法)&#xff0c;是依照就近原则的。 ①先子类局部范围找。 ②然后子类成员范围找。 ③然后父类成员范围找&#xff0c;如果父类范围还没有找到则报错。 2.如果父类中&#xff0c;出现了重名的成员&#xff0c;会优先使用子类的…

linux 磁盘管理、分区管理常用命令

文章目录 基础命令挂载新硬盘/分区添加内存交换分区swaplvm分区管理模式 基础命令 查看目录文件大小 du -sh /backup du -sh /backup/* du -sh *查看磁盘挂载信息 df -lhT查看某个目录挂载在哪个分区&#xff0c;以及分区的磁盘使用情况 df [目录] #例如&#xff1a;df /ho…

【Linux】cd 命令使用

cd&#xff08;英文全拼&#xff1a;change directory&#xff09;命令用于改变当前工作目录的命令&#xff0c;切换到指定的路径。 ~ 也表示为 home 目录 的意思。. 则是表示目前所在的目录。.. 则表示目前目录位置的上一层目录。 语法 cd [目录] 命令选项及作用 执行令 …

平均模式恒流控制的LED驱动器:FP7122,打造舒适照明环境的绝佳选择

目录 一、 FP7122概述 二、 FP7122特点 三、 FP7122应用 近年来&#xff0c;随着LED照明技术的迅猛发展&#xff0c;LED驱动器在家庭照明、商业照明以及植物灯等领域扮演着至关重要的角色。其中&#xff0c;平均模式恒流控制的LED驱动器已经成为人们追求舒适照明环境的首选。…

齐活!Spring工程整合Redis实战汇总

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349;本篇记录Spring工程整合Redis实战汇总操作&#xff0…

经典神经网络——GoogLeNet模型论文详解及代码复现

论文地址&#xff1a;[1409.4842] Going Deeper with Convolutions (arxiv.org) 一、GoogLeNet概述 创新点 我认为&#xff0c;这篇文章最大的创新点是引入了一个名为Inception块的结构&#xff0c;能够增加神经网络模型大小的同时&#xff0c;减缓参数量的爆炸式增长&#x…

Java第二十章 ——多线程

本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 在这之前&#xff0c;首先让我们来了解下在操作系统中进程和线程的区别&#xff1a;   进程&#xff1a;每个进程都有独立的代码和数据空间&#xff08;进程上下文…

服务化通信OPC实操

实操也是基于视频进行一些笔记&#xff0c;没得写就少写了 准备 Nuget包准备&#xff1a;OPCfoundation 一般都是使用Ua&#xff0c;当然也是有&#xff1a; 客户端链接服务器参数&#xff1a;IP Port 认证 登录用户名 Session 的实例化创建 进行使用&#xff1a; 因为Ses…

NAS层协议学习(三)

消息结构 每个NAS消息包含一个协议鉴别符和一个消息标识。协议鉴别符是一个 4 位值&#xff0c;指示正在使用的协议&#xff0c;即对于 EPS NAS 消息是 EMM 或 ESM。消息标识指示发送的特定消息。 EMM 消息还包含一个安全标头&#xff0c;指示消息是否受到完整性保护和/或加密…

AI视觉识别有哪些工业应用

AI视觉识别&#xff0c;主要是利用人工智能算法对图像或视频数据进行分析和处理&#xff0c;以提取关键信息并执行筛选、判断、预警等任务。AI视觉识别涵盖多种应用&#xff0c;如人脸识别、目标检测和识别、图像分割、行为识别、视频分析等。本篇就简单介绍一下AI视觉识别的应…

Dockerfile讲解

Dockerfile 1. 构建过程解析2. Dockerfile常用保留字指令3. 案例3.1. 自定义镜像mycentosjava83.2. 虚悬镜像 4. Docker微服务实战 dockerfile是用来构建docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚本。 dockerfile定义了进程需要的一切东西&…

OpenAI神秘项目Q-star曝光,人类永生或灭绝,将在我们有生之年发生

上周&#xff0c;OpenAI人事风波暂停的尾声中&#xff0c;有个“可能威胁人类”的、代号为“Q*”的神秘项目被抛掷出来。 传言中&#xff0c;Sam Altman被解雇前&#xff0c;几名研究人员向董事会发了一封信&#xff0c;警告一项强大的人工智能发现可能威胁到人类&#xff0c;而…

网络渗透测试(认识)

ARP协议 逻辑地址变成物理地址 32bit的IP地址变换成48bit的mac地址 ARP两个字节&#xff08;0x0806&#xff09; ARP解析协议 每一个主机都有ARP高速缓存&#xff0c;此缓存中记录了最近一段时间的内其他IP地址与其MAC地址的对应关系 如果本机想与某台主机通信&#xff0c;首先…

某医生用 ChatGPT 在 4 个月内狂写 16 篇论文,其中 5 篇已发表,揭密ChatGPT进行论文润色与改写的秘籍

如果写过学术论文&#xff0c;想必会有这样的感受&#xff1a; 绞尽脑汁、茶饭不思、夜不能寐、废寝忘食、夜以继日&#xff0c;赶出一篇论文&#xff0c;然后还被导师点评&#xff0c;“写得就是一坨&#xff01;” 可是&#xff0c;却有人4个月产出了16篇论文&#xff0c;成功…

03、K-means聚类实现步骤与基于K-means聚类的图像压缩

03、K-means聚类实现步骤与基于K-means聚类的图像压缩&#xff08;1&#xff09; K-means聚类实现步骤 开始学习机器学习啦&#xff0c;已经把吴恩达的课全部刷完了&#xff0c;现在开始熟悉一下复现代码。对这个手写数字实部比较感兴趣&#xff0c;作为入门的素材非常合适。…