C++项目——云备份-⑤-数据管理模块的设计与实现

文章目录

  • 专栏导读
  • 1.要管理的数据有哪些
  • 2.如何管理数据
  • 3.数据信息结构体设计与实现
  • 4.数据管理类设计
  • 5.数据管理类实现
  • 6.数据管理模块整理

专栏导读

🌸作者简介:花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。

🌸专栏简介:本文收录于 C++项目——云备份

🌸相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法Linux
🌸项目Gitee链接:https://gitee.com/li-yuanjiu/cloud-backup

在这里插入图片描述

1.要管理的数据有哪些

  • 文件实际存储路径:当客户要下载文件时,则从这个文件中读取数据进行响应;
  • 文件是否被压缩标志:判断文件是否已经被压缩了;
  • 压缩包存储路径:如果一个文件是非热点文件则会被压缩,这个就是压缩包存储的路径;
    • 如果客户端要下载文件,则需要先解压缩,然后读取解压后的文件数据;

还有各类文件属性信息:

  • 文件大小
  • 文件最后一次修改时间
  • 文件最后一次访问时间
  • 文件访问URL中资源路径path

2.如何管理数据

  • 用于数据信息访问:使用hash表在内存中管理数据,以文件访问URLkey数据信息结构val。访问速度快。以文件访问URL来作为key是因为客户端浏览器下载文件时总是以URL作为请求;

  • 持久化存储管理:使用JSON序列化将所有数据保存到文件中;

3.数据信息结构体设计与实现

  • struct BackupInfo结构中包含要管理的文件各项属性信息;
  • NewBackUpInfo负责将传递进来文件各项属性信息组织起来;
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; // 文件访问URL
    bool NewBackupInfo(const std::string &realpath)
    {
        FileUtil fu(realpath);  
        if(fu.Exists() == false) 
        {
            std::cout << "new backupinfo: file not exit" << std::endl;
            return false;
        }
        Config* config = Config::GetInstance();
        std::string packdir = config->GetPackDir();
        std::string packsuffix = config->GetPackFileSuffix();
        std::string download_prefix = config->GetDownloadPrefix();
        pack_flag = false;
        fsize = fu.FileSize();
        mtime = fu.LastMtime();
        atime = fu.LastATime();
        real_path = realpath;
        pack_path = packdir + fu.FileName() + packsuffix;
        url = download_prefix + fu.FileName();
        return true;
    }
}BackupInfo;

4.数据管理类设计

数据管理类负责将数据信息管理起来。

数据化管理DataManger中包含以下成员:

class DataManager
    {
    public:
        DataManager();
        ~DataManager();
        bool Insert(const BackupInfo &info); // 新增
        bool Updata(const BackupInfo &info); // 更新
        bool GetOneByURL(const std::string &url, BackupInfo* info); // 通过url获取文件信息
        bool GetOneByRealpath(const std::string &realpath, BackupInfo* info); // 通过实际路径获取文件信息
        bool GetAll(std::vector<BackupInfo>* array); // 获取所有文件信息
        bool Storage(); // 每次数据更新或者新增都要持久化存储
        bool InitLoad(); // 初始化加载,在每次系统启动前都要加载以前的数据
    private:
        std::string _backup_file; // 备份信息持久化存储
        pthread_rwlock_t _rwlock; // 读写锁
        std::unordered_map<std::string, BackupInfo> _table // 数据信息组织;
    };

5.数据管理类实现

class DataManager
{
public:
    DataManager() 
    {
        _backup_file = Config::GetInstance()->GetBackupFile(); // 获取备份信息持久化存储的文件
        pthread_rwlock_init(&_rwlock, NULL); // 初始化读写锁
        InitLoad(); // 初始化加载
    }
    ~DataManager()
    {
        pthread_rwlock_destroy(&_rwlock); // 释放读写锁
    }
    bool Insert(const BackupInfo &info)
    {
        pthread_rwlock_wrlock(&_rwlock);
        _table[info.url] = info;
        pthread_rwlock_unlock(&_rwlock);
        return true;
    }
    bool Updata(const BackupInfo &info)
    {
        pthread_rwlock_wrlock(&_rwlock);
        _table[info.url] = info;
        pthread_rwlock_unlock(&_rwlock);
        return true;
    }
    bool GetOneByURL(const std::string &url, BackupInfo* info)
    {
        pthread_rwlock_wrlock(&_rwlock);
        auto it = _table.find(url);
        if(it == _table.end())
        {
            pthread_rwlock_unlock(&_rwlock);
            return false;
        }
        *info = it->second;
        pthread_rwlock_unlock(&_rwlock);
        return true;
    }
    bool GetOneByRealpath(const std::string &realpath, BackupInfo* info)
    {
        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>* array)
    {
        pthread_rwlock_wrlock(&_rwlock);
        auto it = _table.begin();
        for(; it != _table.end(); ++it)
        {
            array->push_back(it->second);
        }
        pthread_rwlock_unlock(&_rwlock);
        return true;
    }
    bool Storage()
    {
        // 1.获取所有数据
        std::vector<BackupInfo> array;
        GetAll(&array);
        // 2.添加到Json::Value中
        Json::Value root;
        for(int i = 0; i < array.size(); i++)
        {
            Json::Value item;
            root["pack_flag"] = array[i].pack_flag;
            root["fize"] = (Json::Int64)array[i].fsize;
            root["atime"] = (Json::Int64)array[i].atime;
            root["mtime"] = (Json::Int64)array[i].mtime;
            root["real_path"] = array[i].real_path;
            root["pack_path"] = array[i].pack_path;
            root["url"] = array[i].url;
            root.append(item); // 添加数组元素
        }
        // 3.对Json::Value序列化
        std::string body;
        JsonUtil::Serialize(root, &body);
        // 4.写文件
        FileUtil fu(_backup_file);
        fu.SetContent(body);
        return true;
    }
    bool InitLoad()
    {
        // 1.将数据从文件中读取出来
        FileUtil fu(_backup_file);
        if(fu.Exists() == false)
        {
            return true;
        }
        std::string body;
        fu.GetContent(&body);
        // 2.反序列化
        Json::Value root;
        JsonUtil::Unserialize(body, &root);
        // 3.将反序列化得到的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;
    }
private:
    std::string _backup_file; // 备份信息持久化存储
    pthread_rwlock_t _rwlock; // 读写锁
    std::unordered_map<std::string, BackupInfo> _table; // 数据信息组织
};

6.数据管理模块整理

我们将BackpInfoDataManger的实现都放到data.hpp中。

// data.hpp
#ifndef __MY_DATA__
#define __MY_DATA__
#include <unordered_map>
#include <pthread.h>
#include "util.hpp"
#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; // 文件访问URL
        bool NewBackupInfo(const std::string &realpath)
        {
            FileUtil fu(realpath);  
            if(fu.Exists() == false) 
            {
                std::cout << "new backupinfo: file not exit" << std::endl;
                return false;
            }
            Config* config = Config::GetInstance();
            std::string packdir = config->GetPackDir();
            std::string packsuffix = config->GetPackFileSuffix();
            std::string download_prefix = config->GetDownloadPrefix();
            pack_flag = false;
            fsize = fu.FileSize();
            mtime = fu.LastMtime();
            atime = fu.LastATime();
            real_path = realpath;
            pack_path = packdir + fu.FileName() + packsuffix;
            url = download_prefix + fu.FileName();
            return true;
        }
    }BackupInfo;
    class DataManager
    {
    public:
        DataManager() 
        {
            _backup_file = Config::GetInstance()->GetBackupFile(); // 获取备份信息持久化存储的文件
            pthread_rwlock_init(&_rwlock, NULL); // 初始化读写锁
            InitLoad(); // 初始化加载
        }
        ~DataManager()
        {
            pthread_rwlock_destroy(&_rwlock); // 释放读写锁
        }
        bool Insert(const BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[info.url] = info;
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool Updata(const BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[info.url] = info;
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool GetOneByURL(const std::string &url, BackupInfo* info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.find(url);
            if(it == _table.end())
            {
                pthread_rwlock_unlock(&_rwlock);
                return false;
            }
            *info = it->second;
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool GetOneByRealpath(const std::string &realpath, BackupInfo* info)
        {
            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>* array)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.begin();
            for(; it != _table.end(); ++it)
            {
                array->push_back(it->second);
            }
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool Storage()
        {
            // 1.获取所有数据
            std::vector<BackupInfo> array;
            GetAll(&array);
            // 2.添加到Json::Value中
            Json::Value root;
            for(int i = 0; i < array.size(); i++)
            {
                Json::Value item;
                root["pack_flag"] = array[i].pack_flag;
                root["fize"] = (Json::Int64)array[i].fsize;
                root["atime"] = (Json::Int64)array[i].atime;
                root["mtime"] = (Json::Int64)array[i].mtime;
                root["real_path"] = array[i].real_path;
                root["pack_path"] = array[i].pack_path;
                root["url"] = array[i].url;
                root.append(item); // 添加数组元素
            }
            // 3.对Json::Value序列化
            std::string body;
            JsonUtil::Serialize(root, &body);
            // 4.写文件
            FileUtil fu(_backup_file);
            fu.SetContent(body);
            return true;
        }
        bool InitLoad()
        {
            // 1.将数据从文件中读取出来
            FileUtil fu(_backup_file);
            if(fu.Exists() == false)
            {
                return true;
            }
            std::string body;
            fu.GetContent(&body);
            // 2.反序列化
            Json::Value root;
            JsonUtil::Unserialize(body, &root);
            // 3.将反序列化得到的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;
        }
    private:
        std::string _backup_file; // 备份信息持久化存储
        pthread_rwlock_t _rwlock; // 读写锁
        std::unordered_map<std::string, BackupInfo> _table; // 数据信息组织
    };
}
#endif

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

05 网络和防火墙等其他

网络和其他 ifconfig : 主机ip地址查询

【Linux】安装VMWare虚拟机(安装配置)和配置Windows Server 2012 R2(安装配置连接vm虚拟机)以及环境配置

前言&#xff1a; 一、操作系统简介 1、什么是操作系统 操作系统是一种软件&#xff0c;它管理计算机系统的硬件和软件资源&#xff0c;并提供给用户和应用程序接口&#xff0c;使它们能够与计算机系统交互和运行。操作系统负责调度和分配系统资源&#xff0c;例如处理器、内存…

【QT】Qt控件不显示图标

问题描述 本人在跟着B站视频学习QT时&#xff0c;遇到了一件十分悲惨的事情&#xff0c;一模一样的步骤&#xff0c;我的图标却不能显示。 于是我上网查询一下解决方案&#xff0c;第一种&#xff0c;亲测没用&#xff1b;第二种亲测可以。 解决方法一 1、构建 -> 清理项目…

java springboot2.7 写一个本地 pdf 预览的接口

依赖方面 创建的是 接口web项目就好了 然后包管理工具打开需要这些 import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; imp…

JavaScript进阶知识汇总~

JavaScript 进阶 给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;web前端面试题库 1.原型链入门 1) 构造函数 当我们自定义一个函数时(箭头函数与生成器函数除外)&#xff0c;这个函…

嵌入式系统设计师考试笔记之操作系统基础复习笔记二

目录 3、任务管理 &#xff08;1&#xff09;嵌入式操作系统的任务管理可以分为 &#xff08;2&#xff09;进程 &#xff08;3&#xff09;线程 &#xff08;4&#xff09;任务 &#xff08;5&#xff09;任务的创建与中止 &#xff08;6&#xff09;任务的状态任务有三…

APP分发-CDN加速原理

摘要 CDN的全称是(Content Delivery Network)&#xff0c;即内容分发网络。其目的是通过在现有的Internet中增加一层新的CACHE(缓存)层&#xff0c;将网站的内容发布到最接近用户的网络”边缘“的节点&#xff0c;使用户可以就近取得所需的内容&#xff0c;提高用户访问网站的…

华为机试题:HJ4 字符串分隔

目录 第一章、算法题1.1&#xff09;题目描述1.2&#xff09;解题思路与答案1.3&#xff09;牛客链接 友情提醒: 先看文章目录&#xff0c;大致了解文章知识点结构&#xff0c;点击文章目录可直接跳转到文章指定位置。 第一章、算法题 1.1&#xff09;题目描述 题目描述&…

Android APK瘦身实践:二次瘦身如何再减少大小?(4M—2.9M)

瘦身前 因为平时就考虑到大小的限制&#xff0c;所以很多工作已经做过了&#xff0c;如下列举现在的状态&#xff1a; 7.3M&#xff08;Debug版本&#xff09;和6.5M&#xff08;Release版本&#xff09; 开启minifyEnabled 开启shrinkResources 已经去除不相关的大型库 图片和…

基于 nodejs+vue旅游推荐系统 mysql

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

三步,金蝶K3的数据可视化了

数据可视化的一大特点就是“一图胜千言”&#xff0c;没什么能比图表更直观展现数据的了。那&#xff0c;金蝶K3系统上那海量数据能不能也做成数据可视化报表&#xff1f;操作复杂吗&#xff0c;难度大吗&#xff1f; 换了别的软件来做&#xff0c;操作多、难度大是板上钉钉&a…

华为数通方向HCIP-DataCom H12-831题库(多选题:81-100)

第81题 经典的网络转发方式是基于路由表转发。OpenFlow交换机的转发方式是基于流表转发。对于这两种转发方式,以下说法正确的有哪些选项? A、流表的匹配方式是同时匹配流量的MAC地址和IP地址。 B、路由表的匹配方式是匹配拥有最长掩码的目的网段路由 C、流表是变长的。一台网…

Openssl数据安全传输平台011:base64的使用

文章目录 1 base641.1 概念1.2 应用场景 2 base64 算法 &#xff08;重要&#xff09;3 openssl 中base64的使用3.1 BIO 操作3.2 base64 编码 -> bio链的写操作3.3 base64 解码 -> bio链的读操作 1 base64 1.1 概念 Base64是一种基于64个可打印字符来表示二进制数据的表…

一文5000字从0到1使用Jmeter实现轻量级的接口自动化测试(图文并茂)

接口测试虽然作为版本的一环&#xff0c;但是也是有一套完整的体系&#xff0c;有接口的功能测试、性能测试、安全测试&#xff1b;同时&#xff0c;由于接口的特性&#xff0c;接口的自动化低成本高收益的&#xff0c;使用一些开源工具或一些轻量级的方法&#xff0c;在测试用…

Win10中Pro/E鼠标滚轮不能缩放该怎么办?

Pro/E安装好后&#xff0c;鼠标滚轮不能缩放模型&#xff0c;该怎么办&#xff1f;问题多发生在win8/win10上&#xff0c;新装了PROE&#xff0c;发现滑动鼠标中键不能放大缩小。 彩虹图纸管理软件_图纸管理系统_图纸文档管理软件系统_彩虹EDM【官网】彩虹EDM图纸管理软件系统…

Android 11.0 禁用插入耳机时弹出的保护听力对话框

1.前言 在11.0的系统开发中,在某些产品中会对耳机音量调节过高限制,在调高到最大音量的70%的时候,会弹出音量过高弹出警告,所以产品 开发的需要要求去掉这个音量弹窗警告功能 2.禁用插入耳机时弹出的保护听力对话框的核心类 frameworks\base\packages\SystemUI\src\com\and…

使用docker部署flask接口服务 一

文章目录 一&#xff1a;说明二&#xff1a;dockerfile 参数说明1. 一般常用的 参数&#xff0c;以及它的含义2. 我自己的 dockerfile 三&#xff1a;示例操作1. Gunicorn Gevent启动服务的好处2. 用Gunicorn Gevent的好处&#xff1a;3. Gunicorn Gevent的 使用示例4. 创建…

【SpringCloudNetflix】一图理解Spring Cloud Netflix解决了那些微服务问题?

什么是微服务理解&#xff1a; SpringCloudNetflix解决的问题理解&#xff1a; SpringCloudNetflix核心点&#xff1a; 注册中心&#xff1a;Eureka负载均衡&#xff1a;Ribbon、Feign服务熔断&#xff1a;Hystrix服务降级&#xff1a;Hystrix服务监控&#xff1a;Hystrix Da…

MySQL多表关联on和where速度对比实测谁更快

MySQL多表关联on和where速度对比实测谁更快 背景 今天发现有人在讨论&#xff1a;两张MySQL的数据表按照某一个字段进行关联的时候查询&#xff0c;我们使用on和where哪种查询方式更快。百闻不如一见&#xff0c;我们来亲自测试下。 先说结论 Where、对等查询的join速度基本…

Android Studio新功能-设备镜像Device mirroring-在电脑侧显示手机实时画面并可控制

下载最新的灰测版本-蜥蜴 成功运行到真机后&#xff0c;点击右侧Running Devices选项卡&#xff0c;再点击号 选中当前设备&#xff1b; 非常丝滑同步&#xff0c;在电脑侧也可以顺畅控制真机 该功能大大方便了我们视线保持在显示器上专注开发&#xff0c;并且便于与UI视觉进行…