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

本文涉及的产品
数据管理 DMS,安全协同 3个实例 3个月
推荐场景:
学生管理系统数据库
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【云备份|| 日志 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;
      }
  };



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1月前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
135 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
1月前
|
SQL Oracle 关系型数据库
【赵渝强老师】Oracle的控制文件与归档日志文件
本文介绍了Oracle数据库中的控制文件和归档日志文件。控制文件记录了数据库的物理结构信息,如数据库名、数据文件和联机日志文件的位置等。为了保护数据库,通常会进行控制文件的多路复用。归档日志文件是联机重做日志文件的副本,用于记录数据库的变更历史。文章还提供了相关SQL语句,帮助查看和设置数据库的日志模式。
【赵渝强老师】Oracle的控制文件与归档日志文件
|
27天前
|
SQL 关系型数据库 MySQL
【赵渝强老师】MySQL的全量日志文件
MySQL全量日志记录所有操作的SQL语句,默认禁用。启用后,可通过`show variables like %general_log%检查状态,使用`set global general_log=ON`临时开启,执行查询并查看日志文件以追踪SQL执行详情。
|
1月前
|
Oracle 关系型数据库 数据库
【赵渝强老师】Oracle的参数文件与告警日志文件
本文介绍了Oracle数据库的参数文件和告警日志文件。参数文件分为初始化参数文件(PFile)和服务器端参数文件(SPFile),在数据库启动时读取并分配资源。告警日志文件记录了数据库的重要活动、错误和警告信息,帮助诊断问题。文中还提供了相关视频讲解和示例代码。
|
2月前
|
监控 Linux 应用服务中间件
系统监控:使用日志文件 journalctl的使用
本文介绍了如何使用`journalctl`命令来监控和查看Linux系统的日志文件,包括查看特定行数、过滤日志级别、实时跟踪日志、按时间段查询日志以及日志轮换和压缩的配置。
89 2
系统监控:使用日志文件 journalctl的使用
|
2月前
|
SQL 数据库
为什么 SQL 日志文件很大,我应该如何处理?
为什么 SQL 日志文件很大,我应该如何处理?
|
2月前
|
存储 数据采集 分布式计算
Hadoop-17 Flume 介绍与环境配置 实机云服务器测试 分布式日志信息收集 海量数据 实时采集引擎 Source Channel Sink 串行复制负载均衡
Hadoop-17 Flume 介绍与环境配置 实机云服务器测试 分布式日志信息收集 海量数据 实时采集引擎 Source Channel Sink 串行复制负载均衡
54 1
|
2月前
|
SQL 数据库
为什么SQL日志文件很大,该如何处理?
为什么SQL日志文件很大,该如何处理?
|
1月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
271 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
6天前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。