//
// Created by 马也驰 on 2025/1/3.
//


#include "gc_executor.h"
#include "vlog_set.h"
#include "vlog_gc.h"


 void gc_executor::exec_gc(VlogGC *vlog_gc_, size_t old_vlog_num, size_t new_vlog_num) {
  auto vlog_set = vlog_gc_->vlog_set;
  auto slot_page_ = vlog_gc_->slot_page_;

  vlog_set->mtx.lock();
  auto old_vlog_name = vlog_set->get_vlog_name(old_vlog_num);
  auto new_vlog_name = vlog_set->get_vlog_name(new_vlog_num);
  auto old_vlog_info = vlog_set->get_vlog_info(old_vlog_num);
  auto new_vlog_info = vlog_set->get_vlog_info(new_vlog_num);
  auto old_vlog_handler = vlog_set->get_vlog_handler(old_vlog_num);
  auto new_vlog_handler = vlog_set->get_vlog_handler(new_vlog_num);

  old_vlog_info->vlog_info_latch_.lock();
  old_vlog_handler->vlog_latch_.soft_lock();
  new_vlog_info->vlog_info_latch_.lock();
  new_vlog_handler->vlog_latch_.hard_lock();
  vlog_set->mtx.unlock();

  auto old_vlog = std::fstream(old_vlog_name, std::ios::in | std::ios::out);
  auto new_vlog = std::fstream(new_vlog_name, std::ios::in | std::ios::out);

//  char old_vlog_buff[VLOG_SIZE];
//  char new_vlog_buff[VLOG_SIZE];
  char *old_vlog_buff = static_cast<char*>(malloc(VLOG_SIZE));
  char *new_vlog_buff = static_cast<char*>(malloc(VLOG_SIZE));
  old_vlog.seekp(0);
  old_vlog.read(old_vlog_buff, VLOG_SIZE);

  size_t value_nums = old_vlog_info->value_nums;
  size_t ovb_off = 2 * sizeof(size_t);
  size_t nvb_off = 2 * sizeof(size_t);
  size_t new_vlog_value_nums = 0;
  for (auto i = 0; i < value_nums; i++) {
    char *value = &old_vlog_buff[ovb_off];
    uint16_t value_len = get_value_len(value);
    size_t slot_num = get_value_slotnum(value);
    if (!value_deleted(value_len)) {
      memcpy(&new_vlog_buff[nvb_off], &old_vlog_buff[ovb_off], value_len);
      memcpy(&new_vlog_buff[nvb_off+sizeof(uint16_t)], &(new_vlog_info->vlog_num), sizeof(size_t));
      struct slot_content scn(new_vlog_info->vlog_num, nvb_off);
      slot_page_->set_slot(slot_num, &scn);
      nvb_off += value_len;
      new_vlog_value_nums ++;
    }
    ovb_off += value_len;
  }
  new_vlog_info->value_nums = new_vlog_value_nums;
  new_vlog_info->curr_size = nvb_off;
  memcpy(new_vlog_buff, &nvb_off, sizeof(size_t));
  memcpy(&new_vlog_buff[sizeof(size_t)], &new_vlog_value_nums, sizeof(size_t));
  new_vlog.seekp(0);
  new_vlog.write(new_vlog_buff, VLOG_SIZE);
  new_vlog.flush();

  free(old_vlog_buff);
  free(new_vlog_buff);

  old_vlog.close();
  new_vlog.close();

  old_vlog_info->vlog_valid_ = false;

  old_vlog_info->vlog_info_latch_.unlock();
  old_vlog_handler->vlog_latch_.soft_unlock();
  new_vlog_info->vlog_info_latch_.unlock();
  new_vlog_handler->vlog_latch_.hard_unlock();

//  vlog_gc_->gc_counter_decrement();
}