本文介绍: 分别调用 FileUtil类 中的 Filesize(文件大小) 、 LastMtime( 文件最后一次修改时间)、 LastATime( 文件最后一次访问时间)实例一个 Config类的对象,借助 Config类 的GetpackDir(压缩包存放路径)、GetPackFileSuffix(压缩包后缀名称)(使用hash表在内存管理数据,以urlpath作为key值,来查询内部存储数据,查询速度快)哈希表的数据不会重复,所以当key值相同时,info覆盖之前的数据

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

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

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

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

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


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

1.用于数据信息访问
(使用hash表在内存管理数据,以urlpath作为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.urlkeyinfo作为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 文件中

Initload ——初始化加载

通过_backup_file 数据持久化存储文件实例化一个 FileUtil类的对象 fu
判断实例对象是否成功,若成功则继续加载,若失败则直接返回true
定义一个string类型body字符串
通过 GetContent函数 将_backup_file文件中的数据 读取body


通过JsonUtil类中的 UnSerialize 反序列化函数
body字符串转化为 root结构化数据


通过遍历root结构化数据,将root中的数组元素对应的是否压缩标志、 文件大小、最后一次访问时间、 最后一次修改时间、文件实际存储路径名称、 压缩包存储路径名称、请求资源路径 添加到 临时定义的 BackupInfo类型info中

再通过调用 Insert 函数 将 info 插入到 _tables哈希表中


具体代码实现

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 &amp;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(&amp;_rwlock,NULL);//对读写初始化
            InitLoad();

          }
          ~DataManger()//析构函数
          {
             pthread_rwlock_destroy(&amp;_rwlock);//对读写锁进行销毁
          }

          bool Insert(const BackupInfo &amp;info)//新增
          { 
               pthread_rwlock_wrlock(&amp;_rwlock);//加写锁
               _table[info.url]=info;
               pthread_rwlock_unlock(&amp;_rwlock);//解锁
               Storage();
               return true;
          }
          bool update(const BackupInfo&amp; info)//更新
          {
               pthread_rwlock_wrlock(&amp;_rwlock);//加写锁
               _table[info.url]=info;
               pthread_rwlock_unlock(&amp;_rwlock);//解锁
               Storage();
               return true;
          }
          bool GetOneByURL(const std::string &amp;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;
           }
          
          
           bool InitLoad()//初始化加载
           {
              //将数据文件中的数据读取出来
               FileUtil fu(_backup_file);//数据持久化存储文件   
               if(fu.Exists()==false)//若没有数据 则直接返回true 就不用进行加载
               {
                return true;
               }              
               std::string body;
               fu.GetContent(&body);//将_backup_file文件中的数据 全部读取到body中

               //反序列
               Json::Value root;
               JsonUtil::UnSerialize(body,&root);//反序列化  将body字符串转化为 root结构化数据
                
               //将反序列化得到的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;
           }
           
    };
}


#endif

原文地址:https://blog.csdn.net/qq_62939852/article/details/134651066

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_18303.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注