Linux(CentOS)/Windows-C++ 云备份项目(服务器数据管理模块设计)

数据管理模块功能:
后续项目需要使用的数据如下

  1. 文件实际存储路径:当客户端需要下载文件时,从这个文件中进行读取响应
  2. 文件压缩包存放路径名:如果文件是非热点文件会被压缩
    如果客户端需要下载这些文件,需要先进行解压缩,然后返回
  3. 文件是否被压缩的标记位:判断文件是否被压缩了
  4. 文件大小,文件最后一次修改时间,文件最后一次访问时间
  5. 文件访问url中的资源路径path

数据管理模块管理数据方式:

  1. 用于数据信息访问:使用哈希表,在内存中管理数据,url的path作为key值
  2. 持久化存储管理:使用json序列化,将所有数据信息保存在文件中(不使用数据库)

数据管理模块被多个线程共享,使用读写锁更好(读共享,写互斥)。每次数据更新都要重新持久化存储,避免数据丢失。每次服务器重启都要加载以前的数据

文件数据结构体设计如下:

#pragma once
#include "./util/fileutil.hpp"
#include <unordered_map>
#include <pthread.h>
#include "./config/config.hpp"
namespace CloudBackups
{
    struct BackupInfo
    {
        bool packflag;         // 压缩标记
        size_t size;           // 文件大小
        time_t mtime;          // 最后一次修改时间
        time_t atime;          // 最后一次访问时间
        std::string real_path; // 实际文件存储位置
        std::string pack_path; // 文件压缩存储位置
        std::string url;
        // 打开文件初始化BackInfo
        BackupInfo(const std::string &real_path)
        {
            this->packflag = false;
            FileUtil file(real_path);
            if (file.isExit()) // 文件存在时才可以获取下面的信息
            {
                this->size = file.filesize();
                this->mtime = file.last_modify_time();
                this->atime = file.last_visit_time();
                this->real_path = real_path;
                // 获取配置文件的压缩文件路径
                Config *config = Config::GetInstance();
                std::string packdir = config->GetPackfileDir();   // 压缩文件根目录
                std::string suffix = config->GetPackfileSuffix(); // 压缩文件后缀
                std::string zipname = file.filename() + suffix;
                this->pack_path = packdir + "/" + zipname; // 压缩文件路径
                std::string download = config->GetDownloadPrefix();
                this->url = download + "/" + file.filename(); // 下载请求路径
            }
            else
            {
                LOG(FATAL, "file not found");
            }
        }
    };
}

数据管理模块设计如下:

#pragma once
#include "./util/fileutil.hpp"
#include <unordered_map>
#include <pthread.h>
#include "./config/config.hpp"
#include "./util/json.hpp"
namespace CloudBackups
{
    class DataMange
    {
    private:
        pthread_rwlock_t rwlock;                               // 读写锁,读共享,写互斥
        std::unordered_map<std::string, BackupInfo> backupMap; // 文件请求路径和对应信息的哈希表
        std::string backupFile;                                // 数据持久化信息文件,文件格式为json
    public:
        // 将backupMap持久化存储
        bool Storage()
        {
            // 获取所有数据
            std::vector<BackupInfo> backups;
            this->GetAll(backups);
            // 添加到Json::Value中
            Json::Value root;
            for (size_t i = 0; i < backups.size(); i++)
            {
                Json::Value backup;
                backup["packflag"] = backups[i].packflag;
                backup["size"] = Json::Int64(backups[i].size);
                backup["mtime"] = Json::Int64(backups[i].mtime);
                backup["atime"] = Json::Int64(backups[i].atime);
                backup["real_path"] = backups[i].real_path;
                backup["pack_path"] = backups[i].pack_path;
                backup["url"] = backups[i].url;
                root.append(backup);
            }
            // 持久化 序列化+保存
            //  序列化
            std::string body;
            JsonUtil::serialize(root, body);
            // 保存文件
            FileUtil file(backupFile);
            file.setContent(body);
            return true;
        }
        // 加载配置信息,初始化backupMap
        bool InitLoad()
        {
            // 读取Json文件
            FileUtil file(backupFile);
            if (file.isExit() == false)
            {
                // 服务器文件信息不存在,无需初始化
                return true;
            }
            std::string body;
            file.getContent(body);
            // 反序列化
            Json::Value root;
            if (JsonUtil::unserialize(body, root) == true)
            {
                // 将反序列化的数据写到map上
                for (int i = 0; i < root.size(); i++)
                {
                    BackupInfo backupInfo;
                    backupInfo.packflag = root[i]["packflag"].asBool();
                    backupInfo.size = root[i]["size"].asInt64();
                    backupInfo.mtime = root[i]["mtime"].asInt64();
                    backupInfo.atime = root[i]["atime"].asInt64();
                    backupInfo.real_path = root[i]["real_path"].asString();
                    backupInfo.pack_path = root[i]["pack_path"].asString();
                    backupInfo.url = root[i]["url"].asString();
                    Insert(backupInfo);
                }
                return true;
            }
            return false;
        }
        DataMange()
        {
            backupFile = Config::GetInstance()->GetBackupFile();
            pthread_rwlock_init(&rwlock, nullptr);
            InitLoad();
        }
        ~DataMange()
        {
            pthread_rwlock_destroy(&rwlock);
        }
        // 数据管理模块插入信息
        bool Insert(const BackupInfo &backupInfo)
        {
            pthread_rwlock_wrlock(&rwlock);
            backupMap[backupInfo.url] = backupInfo;
            pthread_rwlock_unlock(&rwlock);
            Storage();
            return true;
        }
        // 更新数据管理模块
        bool UpDate(const BackupInfo &backupInfo)
        {
            pthread_rwlock_wrlock(&rwlock);
            backupMap[backupInfo.url] = backupInfo;
            pthread_rwlock_unlock(&rwlock);
            Storage();
            return true;
        }
        // 通过url获取这个文件
        bool GetByUrl(const std::string &url, BackupInfo &backupInfo)
        {
            pthread_rwlock_wrlock(&rwlock);
            auto pos = backupMap.find(url);
            if (pos == backupMap.end())
            {
                LOG(WARNING, "url map not found you url is: " + url);
                pthread_rwlock_unlock(&rwlock);
                return false;
            }
            backupInfo = pos->second;
            pthread_rwlock_unlock(&rwlock);
            return true;
        }
        // 通过http uri 获取文件信息
        bool GetByRealPath(const std::string &real_url, BackupInfo &backupInfo)
        {
            pthread_rwlock_wrlock(&rwlock);
            auto pos = backupMap.begin();
            while (pos != backupMap.end())
            {
                if (pos->second.real_path == real_url)
                {
                    backupInfo = pos->second;
                    pthread_rwlock_unlock(&rwlock);
                    return true;
                }
                pos++;
            }
            LOG(WARNING, "http uti not found you uri is: " + real_url);
            pthread_rwlock_unlock(&rwlock);
            return false;
        }
        // 获取请求映射下所有文件信息
        bool GetAll(std::vector<BackupInfo> &backups)
        {
            pthread_rwlock_wrlock(&rwlock);
            backups.clear();
            for (auto &backup : backupMap)
            {
                backups.push_back(backup.second);
            }
            pthread_rwlock_unlock(&rwlock);
            return true;
        }
    };
}

Gitee位置
Github位置

相关推荐

  1. Linux(CentOS)/Windows-C++ 备份项目(结项,项目总结)

    2024-03-31 01:28:01       17 阅读
  2. 备份服务器数据的重要

    2024-03-31 01:28:01       27 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-31 01:28:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-31 01:28:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-31 01:28:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-31 01:28:01       18 阅读

热门阅读

  1. 每日一题 --- 四数相加 II[力扣][Go]

    2024-03-31 01:28:01       23 阅读
  2. 什么是ac

    2024-03-31 01:28:01       19 阅读
  3. kubernetes(K8S)学习(八):K8S之常见部署方案

    2024-03-31 01:28:01       19 阅读
  4. PreparedStatement对象

    2024-03-31 01:28:01       16 阅读
  5. Acwing 1238.日志统计 双指针

    2024-03-31 01:28:01       17 阅读
  6. 对象数组与指针与引用

    2024-03-31 01:28:01       19 阅读
  7. css之flex布局文本不换行不显示省略号的解决方法

    2024-03-31 01:28:01       18 阅读
  8. 09、Lua 运算符

    2024-03-31 01:28:01       16 阅读