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位置

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NUC_Dodamce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值