【云备份】数据管理模块

文章目录

  • 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 数据信息类

【云备份】数据管理模块_第1张图片

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


NewBackupInfo —— 获取各项属性信息

【云备份】数据管理模块_第2张图片

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


【云备份】数据管理模块_第3张图片

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


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


【云备份】数据管理模块_第4张图片

DataManager 数据管理类

构造函数

输入 man pthread_rwlock_init 查看锁的初始化

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


【云备份】数据管理模块_第5张图片

将属性设置为NULL即可

析构函数

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


【云备份】数据管理模块_第6张图片

insert —— 新增

【云备份】数据管理模块_第7张图片

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


update —— 修改

【云备份】数据管理模块_第8张图片

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


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

【云备份】数据管理模块_第9张图片

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


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

【云备份】数据管理模块_第10张图片

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


GETALL —— 获取所有

【云备份】数据管理模块_第11张图片

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

Storage —— 持久化存储实现

【云备份】数据管理模块_第12张图片

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


【云备份】数据管理模块_第13张图片

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


【云备份】数据管理模块_第14张图片

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


【云备份】数据管理模块_第15张图片

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

具体代码实现

data.hpp

#ifndef _MY_DATA_
#define _MY_DATA_
#include
#include
#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

你可能感兴趣的:(云备份项目,linux,服务器)