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


    专栏导读

    🌸作者简介:花想云 ,在读本科生一枚,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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    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 // 数据信息组织;
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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["fsize"] = (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; // 数据信息组织
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127

    6.数据管理模块整理

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

    // data.hpp
    #ifndef __MY_DATA__
    #define __MY_DATA__
    #include 
    #include 
    #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["fsize"] = (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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170

    在这里插入图片描述

  • 相关阅读:
    使用 Python 和 AI 将自己卡通化VToonify(教程含源码)
    案例分享 | 数字化综合人才管理平台
    鸿蒙入门-13Gauge组件
    ChatGPT从⼊⻔到精通
    Node.js 模块系统
    Python教程之深度比较Python移动应用框架
    【目标定位】基于matlab多机EKF+时差和频差无源定位【含Matlab源码 2057期】
    Java遍历集合元素并修改
    【数据结构】链表的学习总结
    docker修改mysql数据库密码,redis密码
  • 原文地址:https://blog.csdn.net/gllll_yu/article/details/134063090