【云备份|| 日志 day4】文件信息管理模块

简介: 【云备份|| 日志 day4】文件信息管理模块

已经写到后边去了,但是这几天改bug改的很恼火,就没有写项目日志

image.png

云备份day4

  • 数据管理模块 ------DataManager

数据管理模块 ------DataManager

我们要对服务器上存在的文件进行数据管理,就要遵循

先描述,后组织的 的原则,我们需要知道文件的状态和信息,将其描述成为一个结构体,然后在对其进行管理。

服务端模块实现-管理的数据信息

文件实际存储路径

文件是否压缩标志

压缩包存储路径

文件访问URL

文件最后一次修改时间

文件最后一次访问时间

文件大小

服务端数据管理模块实现-如何管理数据

内存中以文件访问URL为key,数据信息结构为val,使用哈希表进行管理,查询速度快。使用url作为key是因为往后客户端浏览器下载文件的时候总是以 url 作为请求。

采用文件形式对数据进行持久化存储(序列化方式采用 json 格式或者自定义方式)

文件信息:

typedef struct BackupInfo{
  int pack_flag;
  time_t mtime;
  time_t atime;
  size_t fsize;
  std::string realpath;
  std::string url;
  std::string packpath;
  bool NewBackupInfo(const std::string &realpath);
}BackupInfo;

管理模块:

无非就是对数据的增删查改

class DataManager{
private:
  FileUtil _backup_file;
  pthread_rwlock_t _rwlock;
  std::unordered_map<std::string, BackupInfo> _table;
public:
  DataManager();
  bool InitLoad();//初始化程序运行时从文件读取数据
  bool Storage(); //每次有信息改变则需要持久化存储一次
  bool Insert(const std::string &key, const BackupInfo &val);
  bool Update(const std::string &key, const BackupInfo &val);
  bool GetOneByURL(const std::string &key, BackupInfo *info);
  bool GetOneByRealPath(const std::string &key, BackupInfo *info);
  bool GetAll(std::vector<BackupInfo> *arry);
};

代码:

  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;
    bool NewBackupInfo(const std::string &realpath){
      FileUtil fu(realpath);
      if (fu.Exists() == false) {
        std::cout << "new backupinfo: file not exists!\n";
        return false;
      }
      Config *config = Config::GetInstance();
      std::string packdir = config->GetPackDir();
      std::string packsuffix = config->GetPackFileSuffix();
      std::string download_prefix = config->GetDownloadPrefix();
      this->pack_flag = false;
      this->fsize = fu.FileSize();
      this->mtime = fu.LastMTime();
      this->atime = fu.LastATime();
      this->real_path = realpath;
      // ./backdir/a.txt   ->   ./packdir/a.txt.lz
      this->pack_path = packdir + fu.FileName() + packsuffix;
      // ./backdir/a.txt   ->   /download/a.txt
      this->url = download_prefix + fu.FileName();
      return true;
    }
  }BackupInfo;
  class DataManager{
    private:
      std::string _backup_file;
      pthread_rwlock_t _rwlock;
      std::unordered_map<std::string, BackupInfo> _table;
    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);
        Storage();
        return true;
      }
      bool Update(const BackupInfo &info) {
        pthread_rwlock_wrlock(&_rwlock);
        _table[info.url] = info;
        pthread_rwlock_unlock(&_rwlock);
        Storage();
        return true;
      }
      bool GetOneByURL(const std::string &url, BackupInfo *info) {
        pthread_rwlock_wrlock(&_rwlock);
        //因为url是key值,所以直接通过find进行查找
        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> *arry) {
        pthread_rwlock_wrlock(&_rwlock);
        auto it = _table.begin();
        for (; it != _table.end(); ++it){
          arry->push_back(it->second);
        }
        pthread_rwlock_unlock(&_rwlock);
        return true;
      }
      bool Storage(){
        //1. 获取所有数据
        std::vector<BackupInfo> arry;
        this->GetAll(&arry);
        //2. 添加到Json::Value
        Json::Value root;
        for (int i = 0; i < arry.size(); i++){
          Json::Value item;
          item["pack_flag"] = arry[i].pack_flag;
          item["fsize"] = (Json::Int64)arry[i].fsize;
          item["atime"] = (Json::Int64)arry[i].atime;
          item["mtime"] = (Json::Int64)arry[i].mtime;
          item["real_path"] = arry[i].real_path;
          item["pack_path"] = arry[i].pack_path;
          item["url"] = arry[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;
      }
  };



相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
相关文章
|
4月前
|
存储 监控 算法
防止员工泄密软件中文件访问日志管理的 Go 语言 B + 树算法
B+树凭借高效范围查询与稳定插入删除性能,为防止员工泄密软件提供高响应、可追溯的日志管理方案,显著提升海量文件操作日志的存储与检索效率。
156 2
|
4月前
|
监控 安全 程序员
Python日志模块配置:从print到logging的优雅升级指南
从 `print` 到 `logging` 是 Python 开发的必经之路。`print` 调试简单却难维护,日志混乱、无法分级、缺乏上下文;而 `logging` 支持级别控制、多输出、结构化记录,助力项目可维护性升级。本文详解痛点、优势、迁移方案与最佳实践,助你构建专业日志系统,让程序“有记忆”。
398 0
|
10月前
|
存储 监控 API
【Azure App Service】分享使用Python Code获取App Service的服务器日志记录管理配置信息
本文介绍了如何通过Python代码获取App Service中“Web服务器日志记录”的配置状态。借助`azure-mgmt-web` SDK,可通过初始化`WebSiteManagementClient`对象、调用`get_configuration`方法来查看`http_logging_enabled`的值,从而判断日志记录是否启用及存储方式(关闭、存储或文件系统)。示例代码详细展示了实现步骤,并附有执行结果与官方文档参考链接,帮助开发者快速定位和解决问题。
309 22
|
11月前
|
SQL 缓存
【YashanDB知识库】YashanDB run.log中有slow log queue is full信息
【YashanDB知识库】YashanDB run.log中有slow log queue is full信息
|
运维 应用服务中间件 nginx
docker运维查看指定应用log文件位置和名称
通过本文的方法,您可以更高效地管理和查看Docker容器中的日志文件,确保应用运行状态可控和可监测。
2013 28
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
409 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
存储 SQL 关系型数据库
【赵渝强老师】PostgreSQL的运行日志文件
PostgreSQL的物理存储结构包括数据文件、日志文件等。运行日志默认未开启,需配置`postgresql.conf`文件中的相关参数如`log_destination`、`log_directory`等,以记录数据库状态、错误信息等。示例配置中启用了CSV格式日志,便于管理和分析。通过创建表操作,可查看生成的日志文件,了解具体日志内容。
430 3
|
SQL 关系型数据库 MySQL
【赵渝强老师】MySQL的全量日志文件
MySQL全量日志记录所有操作的SQL语句,默认禁用。启用后,可通过`show variables like %general_log%检查状态,使用`set global general_log=ON`临时开启,执行查询并查看日志文件以追踪SQL执行详情。
242 4
|
Oracle 关系型数据库 数据库
【赵渝强老师】Oracle的参数文件与告警日志文件
本文介绍了Oracle数据库的参数文件和告警日志文件。参数文件分为初始化参数文件(PFile)和服务器端参数文件(SPFile),在数据库启动时读取并分配资源。告警日志文件记录了数据库的重要活动、错误和警告信息,帮助诊断问题。文中还提供了相关视频讲解和示例代码。
319 1