#pragma once
#include "../../../include/common/ICollector.hpp"
#include "../../../include/common/constant.h"
#include "../../../include/log/logging.h"
#include "../../../include/utils/ElfUtils.hpp"
#include "../../../include/utils/FileWriterUtil.hpp"
#include "../../../include/utils/PluginUtils.hpp"
#include "../../../include/utils/TimeUtil.hpp"
#include "../../../include/utils/TimerManager.hpp"
#include "../../../include/utils/util.h"
#include "../ebpfPluginBase/EbpfCollectorBase.h"
#include <algorithm>
#include <atomic>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <fcntl.h>
#include <gelf.h>
#include <iomanip>
#include <iostream>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <thread>
#include <unistd.h>
#include <unordered_map>
#include <vector>
typedef uint32_t u32;
struct python_gil_bpf;
struct ring_buffer;
struct bpf_link;
using PluginNameType = systrace::constant::Plugin;
class GILPlugin : public EbpfCollectorBase, public ICollector {
public:
GILPlugin();
~GILPlugin();
bool start(const json ¶ms, int duration) override;
void stop() override;
private:
void consume_perf_events();
void process_raw_event(void *data);
void attach_all_probes(std::vector<int> pids, const std::string &path);
bool try_bind_uprobe(struct bpf_program *prog, int pid,
const std::string &path,
const std::vector<std::string> &funcs, bool is_ret);
void register_target_process_to_bpf();
std::string auto_find_libpython();
void clean_ringbuffer();
void cleanup_skel();
void clear_gil_maps();
void set_gil_trace_enabled(bool enabled);
const size_t BUF_CHUNK_SIZE = 256 * 1024;
std::atomic_flag stop_latched_ = ATOMIC_FLAG_INIT;
struct python_gil_bpf *bpf_skeleton_ = nullptr;
std::thread poll_thread_;
FILE *trace_output_stream_ = nullptr;
bool first_event_ = true;
systrace::fileWriterUtil::strbuf_t json_buf_;
std::unordered_map<int, int> host_pid_to_rank_mapping_;
struct ring_buffer *rb_ = nullptr;
std::mutex rb_mutex_;
std::vector<struct bpf_link *> links_;
std::mutex link_mutex_;
std::string output_;
const std::vector<std::string> gil_acquire_symbols = {
"take_gil", "PyEval_RestoreThread"};
const std::vector<std::string> gil_release_symbols = {"drop_gil",
"PyEval_SaveThread"};
};