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

news2024/11/19 22:37:43

文章目录

  • 专栏导读
  • 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

在这里插入图片描述

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

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

相关文章

打破尺寸记录!荷兰QuTech研发16量子点阵列新技术

承载16个量子点交叉条阵列的量子芯片&#xff0c;可无缝集成到棋盘图案&#xff08;图片来源&#xff1a;网络&#xff09; 由荷兰代尔夫特理工大学(TU Delft)和荷兰应用科学研究组织(TNO)组建的荷兰量子计算研究中心QuTech的研究人员开发了一种用相对较少的控制线来控制大量量…

【QT】Qt控件不显示图标

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

实战CubeMX配置CAN通讯教程,避免踩坑,cubeMX 回环模式可以但正常模式无法通信

文章目录 实战CubeMX配置CAN通讯教程&#xff0c;避免踩坑&#xff0c;cubeMX 回环模式可以但正常模式无法通信1. 先配置两个LED等的普通IO口&#xff0c;作为通信指示信号2.配置时钟单元3.配置工程文件4.配置代码生成的参数5.配置CAN通信的波特率&#xff0c;注意如果配置成50…

成都瀚网科技有限公司:抖音小店收益计算大揭秘,一招提升你的利润!

你是否曾对抖音小店的收益计算方式感到困惑&#xff1f;想要了解如何提高抖音小店的收益吗&#xff1f;本文将为你揭开抖音小店收益计算的神秘面纱&#xff0c;并分享一些实用的提升利润的方法。 一、抖音小店收益计算方式 抖音小店的收益主要来自于商品销售收入、佣金收入以及…

0146 网络层

目录 4 网络层 4.1 网络层的功能 4.2 路由算法与路由协议 4.3 IPv4 4.4 IPv6 4 网络层 4.1 网络层的功能 4.2 路由算法与路由协议 4.3 IPv4 4.4 IPv6 部分习题 1.网络层的主要目的是&#xff08;&#xff09; A.在邻接结点间进行数据报传输 B.在邻接结点间进行数…

郑州职工注意!郑州市职工数字人才技能竞赛正式启动

10月26日&#xff0c;由郑州市劳动竞赛委员会办公室、郑州市总工会、郑州市大数据管理局、郑州市人力资源和社会保障局、郑州市科学技术局主办&#xff0c;郑东新区总工会、中科大数据研究院联合承办的郑州市职工数字人才技能竞赛在郑东新区顺利举行启动仪式。 河南省总工会副主…

『进阶之路』- 揭开ThreadLocal神秘面纱

阅读本文主要可以解决以下困惑&#xff1a; 什么是ThreadLocal&#xff0c;隔离线程的本地变量ThreadLocal的数据结构是怎么样的&#xff0c;为什么能实现线程隔离ThreadLocal的get和set方法ThreadLocal如何实现的线程安全&#xff1f;结合同步锁机制&#xff0c;空间换取时间…

2023年腾讯云双11服务器活动及价格表

双十一购物狂欢节即将到来&#xff0c;腾讯云作为国内领先的云计算服务提供商&#xff0c;推出了一系列优惠活动&#xff0c;下面给大家详细介绍腾讯云双11服务器活动及价格表。 一、腾讯云双11活动入口 活动入口&#xff1a;txy.ink/1111/ 二、腾讯云双11活动时间 即日起至…

智慧巡查平台(Ionic/Vite/Vue3 移动端) 问题记录

目录 1.环境搭建 1.1 安装 node 16 版本 1.2 安装 ionic7 1.3 创建 vue 项目 2.index.html 3.main.ts 3.1 如何默认使用 ios 样式&#xff1f; 3.2 如何使用 ElmentPlus 国际化&#xff1f; 4.router/xxx 5.打包二三事 5.1 添加打包相关文件 5.1.1 .env.developmen…

3、电路综合原理与实践---单双端口理想微带线(伪)手算S参数与时域波形

电路综合原理与实践—单双端口理想微带线&#xff08;伪&#xff09;手算S参数与时域波形与时域波形 1、单理想微带线&#xff08;UE&#xff09;的S参数理论推导 参考&#xff1a;Design of Ultra Wideband Power Transfer Networks的第四章&#xff0c;之后总结推导过程 自…

Kubernetes中如何使用CNI?

一、CNI 是什么 它的全称是 Container Network Interface&#xff0c;即容器网络的 API 接口。 它是 K8S 中标准的一个调用网络实现的接口。Kubelet 通过这个标准的 API 来调用不同的网络插件以实现不同的网络配置方式。实现了这个接口的就是 CNI 插件&#xff0c;它实现了一…

长连接的原理

Apollo的长连接实现是 Spring的DeferredResult来实现的,先看怎么用 import ...RestController RequestMapping("deferredResult") public class DeferredResultController {private Map<String, Consumer<DeferredResultResponse>> taskMap new HashMa…

如何恢复u盘删除文件?2023最新分享四种方法恢复文件

U盘上删除的文件怎么恢复&#xff1f;使用U盘存储文件是非常方便的&#xff0c;例如&#xff1a;在办公的时候&#xff0c;会使用U盘来存储网络上查找到的资料、产品说明等。在学习的时候&#xff0c;会使用U盘来存储教育机构分享的教学视频、重点知识等。而随着U盘存储文件的概…

[数据结构】二叉树

1.概念 一棵二叉树是结点的一个有限集合&#xff0c;该集合&#xff1a; 1. 或者为空 2. 或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成 从上图我们可以发现&#xff1a; 1.二叉树不存在大于2 的度 2.二叉树的子树有左右之分&#xff0c;次序不能颠倒。是有…

关于内存泄漏的经典面试题

目录 前言 一、内存泄漏基本概念 二、如何判断并查找内存泄漏 1、方案设计 2、方案实现 前言 对于C/C程序员来说&#xff0c;或多或少都会被面试官问到关于内存泄漏的问题&#xff0c;内存泄漏是程序的bug&#xff0c;他会一点一点的侵蚀你的内存&#xff0c;导致程序运行…

jmeter报Java.NET.BindException: Address already in use: connect

1、windows10和window11上&#xff1a; 修改注册表的内容&#xff1a; HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters&#xff1a; 新建dword&#xff08;值&#xff09;的类型&#xff1a; MaxUserPort 65334 TcpTimedWaitDelay 30window

2023年Q3线上生鲜水产数据分析:市场不景气,销额同比下滑44%

事实上&#xff0c;今年线上的生鲜生意市场并不景气。无论是Q1季度还是Q2季度&#xff0c;线上&#xff08;京东平台&#xff09;的销售额均同比去年下滑了10%左右。 然而到了Q3季度&#xff0c;整个下滑态势愈发严峻。可以看到鲸参谋数据显示&#xff0c;7月至9月生鲜水产在京…

腾讯云学生专享云服务器介绍及购买攻略

随着互联网技术的不断发展&#xff0c;越来越多的人开始关注云计算领域。作为国内领先的云计算服务商&#xff0c;腾讯云推出了“云校园”扶持计划&#xff0c;完成学生认证即可购买学生专享云服务器。 一、活动对象 仅限腾讯云官网通过个人认证的35岁以下学生用户参与&#x…

数据结构笔记——树和图(王道408)(持续更新)

文章目录 传送门前言树&#xff08;重点&#xff09;树的数据结构定义性质 二叉树的数据结构定义性质储存结构 二叉树算法先中后序遍历层次展开法递归模拟法 层次遍历遍历序列逆向构造二叉树 线索二叉树&#xff08;难点&#xff09;定义线索化的本质 二叉树线索化线索二叉树中…

Java 使用 poi 和 aspose 实现 word 模板数据写入并转换 pdf 增加水印

本项目所有源码和依赖资源都在文章顶部链接&#xff0c;有需要可以下载使用 1. 需求描述 从指定位置读取一个 word 模板获取业务数据并写入该 word 模板&#xff0c;生成新的 word 文档将新生成的 word 文档转换为 pdf 格式对 pdf 文档添加水印 2. 效果预览 word 模板 带水印的…