//
// Created by 马也驰 on 2024/12/29.
//

#ifndef LEVELDB_VLOG_SET_H
#define LEVELDB_VLOG_SET_H

#include <unordered_map>
#include <string>
#include <mutex>
#include <cassert>
#include <condition_variable>
#include "../include/leveldb/slice.h"
#include "../db/shared_lock.h"
#include "../db/vlog.h"
#include "../db/vlog_cache.h"

// 前向声明 VlogGC
class VlogGC;

class VlogSet {
friend class VlogGC;
friend class gc_executor;

#define USING_VLOG_CACHE            true
#define CONFIG_FILE_DELE_MASK       (0x1 << (sizeof(size_t)-1))
#define CONFIG_FILE_VLOG_NUM(v)     ((v) & ~CONFIG_FILE_DELE_MASK)
#define VLOG_GC_THREHOLD            0.5
#define VLOG_GC_VOLUM_THRESHOLD     0.9

 public:
  VlogSet(std::string dbname, VlogGC *vlog_gc);
  ~VlogSet();
  void get_value(const struct slot_content &sc, std::string *value);
  void put_value(struct slot_content &sc, size_t slot_num, const leveldb::Slice &value);
  void del_value(const struct slot_content &sc);

  void set_vlog_gc(VlogGC *vg) { this->vlog_gc = vg; }


 private:
  size_t register_new_vlog();
  void remove_old_vlog(size_t old_vlog_num);
  bool vlog_need_gc(size_t vlog_num);

  void register_inconfig_file(size_t vlog_num);
  void remove_from_config_file(size_t vlog_num);
  void create_vlog(size_t vlog_num);
  struct vlog_info *get_writable_vlog_info(size_t value_size);
  inline void restore_vlog_inmaps(struct vlog_info *vi);
  inline void register_vlog_inmaps(size_t vlog_num, std::string &vlog_name);
  void remove_vlog_file(std::string &vlog_name);
  inline std::string get_config_file_name();
  std::string get_vlog_name(size_t vlog_num);
  struct vlog_info *get_vlog_info(size_t vlog_num);
  struct vlog_handler *get_vlog_handler(size_t vlog_num);
  inline size_t serialize_data(const leveldb::Slice &buff, size_t slot_num, std::string &value);
  inline void deserialize_data(char *buff, std::string &value);
  void read_vlog_value(const struct slot_content &sc, std::string *value);
  void write_vlog_value(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value);
  uint16_t delete_vlog_value(const struct slot_content &sc);
  void mark_del_value(const struct slot_content &sc);

 private:
  void read_vlog_value_direct(const struct slot_content &sc, std::string *value);
  void write_vlog_value_direct(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value);
  uint16_t delete_vlog_value_direct(const struct slot_content &sc);
  void read_vlog_value_cache(const struct slot_content &sc, std::string *value);
  void write_vlog_value_cache(const struct slot_content &sc, size_t slot_num, const leveldb::Slice &value);
  uint16_t delete_vlog_value_cache(const struct slot_content &sc);

 private:
  std::mutex mtx;
  std::string dbname;
  size_t vlog_nums_;
  std::unordered_map<std::string, struct vlog_info *> vlog_info_map_;
  std::unordered_map<std::string, struct vlog_handler *> vlog_handler_map_;
  std::mutex config_file_latch_;
//  std::fstream *config_file_;
  // config_file的处理有问题
  std::string config_file_name;

  int counter = 0;  // 表明当前有多少个gc线程正在进行
  std::mutex counter_latch_;
  std::mutex finished_latch_;
  bool finished = true; // 表明当前是否所有gc线程都已结束

  VlogGC *vlog_gc;  // 仅声明为指针，具体定义放在 vlog_set.cpp

  VlogCache *vlog_cache;
};



#endif  // LEVELDB_VLOG_SET_H
