//
// 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 "../include/leveldb/slice.h"
#include "../db/shared_lock.h"
#include "../db/vlog.h"

// 前向声明 VlogGC
class VlogGC;

class VlogSet {
friend class VlogGC;

#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.8
 public:
  VlogSet(std::string dbname, VlogGC *vlog_gc);
  ~VlogSet();
  void get_value(uint32_t vlog_num, uint32_t value_offset, std::string *value);
  void put_value(uint32_t *vlog_num, uint32_t *value_offset, const leveldb::Slice &value);
  void del_value(uint32_t vlog_num, uint32_t value_offset);

  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);
  inline void remove_vlog_from_maps(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);
  void read_vlog_value(uint32_t vlog_num, uint32_t value_offset, std::string *value);
  void write_vlog_value(uint32_t vlog_num, uint32_t value_offset, const leveldb::Slice &value);
  void mark_del_value(uint32_t vlog_num, uint32_t value_offset);

 private:
  std::mutex mtx;
  std::string dbname;
  size_t vlog_nums_;
//  size_t vlog_count_;
  std::unordered_map<std::string, struct vlog_info *> vlog_info_map_;
  std::unordered_map<std::string, struct vlog_handler *> vlog_handler_map_;
  std::fstream *config_file_;

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



#endif  // LEVELDB_VLOG_SET_H
