【云备份|| 日志 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日志并进行多维度分析。
相关文章
|
9天前
|
监控 Java API
如何将不同业务模块产生的日志 分多文件记录
如何将不同业务模块产生的日志 分多文件记录
10 0
|
6天前
|
SQL 监控 Java
在IDEA 、springboot中使用切面aop实现日志信息的记录到数据库
这篇文章介绍了如何在IDEA和Spring Boot中使用AOP技术实现日志信息的记录到数据库的详细步骤和代码示例。
在IDEA 、springboot中使用切面aop实现日志信息的记录到数据库
|
1天前
|
Ubuntu Java Linux
查看Linux系统中日志文件
查看Linux系统中日志文件
|
1天前
|
存储 监控 应用服务中间件
查看nginx日志文件
器性能和提高网站可用性。掌握日志文件的路径、查看方法和基本分析技能对于任何服务器管理员来说都是必备技能。
7 1
|
2天前
|
SQL Oracle NoSQL
实时计算 Flink版操作报错合集之报错“找不到对应的归档日志文件”,怎么处理
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
7天前
|
存储 监控 Java
|
5天前
|
XML Java Maven
logback在springBoot项目中的使用 springboot中使用日志进行持久化保存日志信息
这篇文章详细介绍了如何在Spring Boot项目中使用logback进行日志记录,包括Maven依赖配置、logback配置文件的编写,以及实现的日志持久化和控制台输出效果。
logback在springBoot项目中的使用 springboot中使用日志进行持久化保存日志信息
|
12天前
|
存储 安全 Python
[python]使用标准库logging实现多进程安全的日志模块
[python]使用标准库logging实现多进程安全的日志模块
|
6天前
|
应用服务中间件 Linux nginx
Nginx log 日志文件较大,按日期生成 实现日志的切割
Nginx log 日志文件较大,按日期生成 实现日志的切割
27 0
|
6天前
|
C#
C# 写日志文件
C# 写日志文件
12 0

热门文章

最新文章