Ferenc Szontágh
2024-06-27 0c428a79ef2379c6c7be29712e83f8c39e43c580
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "Server.h"
#include <iostream>
#include <csignal>
#include <chrono>
 
// Initialize the static instance pointer
Server *Server::instance = nullptr;
 
Server::Server() : reloadConfigFlag(false)
{
    instance = this; // Set the instance pointer
    ipc = std::make_unique<IPC>();
    signal(SIGUSR1, Server::handleSignal);
    if (!config.loadFromFile("/etc/fserver/config.json"))
    {
        LOG(ERROR) << "Failed to load /etc/fserver/config.json";
    }
    loadPlugins();
    for (int i = 0; i < 4; ++i)
    {
        threadPool.emplace_back(&Server::handleIPC, this);
    }
}
 
Server::~Server()
{
    // Join all threads
    for (auto &thread : threadPool)
    {
        if (thread.joinable())
        {
            thread.join();
        }
    }
 
    // Close all plugin handles
    for (auto &handle : pluginHandles)
    {
        dlclose(handle);
    }
}
 
Server &Server::getInstance()
{
    return *instance;
}
 
void Server::run()
{
    mainLoop();
}
 
void Server::reloadConfig()
{
    if (config.loadFromFile("/etc/fserver/config.json"))
    {
        LOG(INFO) << "Configuration reloaded /etc/fserver/config.json";
 
        // Stop and clear existing plugins
        for (auto &plugin : plugins)
        {
            plugin->updateConfig({}); // Optionally reset plugin config
        }
        plugins.clear();
 
        // Close and clear plugin handles
        for (auto &handle : pluginHandles)
        {
            dlclose(handle);
        }
        pluginHandles.clear();
 
        loadPlugins();
    }
    else
    {
        LOG(ERROR) << "Failed to reload configuration";
    }
}
 
void Server::loadPlugins()
{
    auto configData = config.getConfig();
    auto pluginsArray = configData["plugins"];
    for (const auto &pluginName : pluginsArray)
    {
        std::string pluginPath = "./plugins/" + pluginName.get<std::string>();
        void *handle = dlopen(pluginPath.c_str(), RTLD_LAZY);
        if (!handle)
        {
            LOG(WARNING) << "Can not open lib: " << dlerror();
            continue;
        }
        pluginHandles.push_back(handle);
 
        typedef IPlugin *(*create_t)(IPC *);
        create_t create_plugin = (create_t)dlsym(handle, "create");
        const char *dlsym_error = dlerror();
        if (dlsym_error)
        {
            LOG(ERROR) << "Cannot load symbol create: " << dlsym_error;
            dlclose(handle);
            continue;
        }
 
        std::shared_ptr<IPlugin> plugin(create_plugin(ipc.get()));
        plugins.push_back(plugin);
        ipc->registerHandler(plugin);
        plugin->updateConfig(config.getConfig()); // Forward the config to the plugin
        LOG(INFO) << "Plugin loaded: " << plugin->getPluginName();
    }
}
 
void Server::mainLoop()
{
    while (true)
    {
        if (reloadConfigFlag.load())
        {
            reloadConfig();
            reloadConfigFlag.store(false);
        }
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}
 
void Server::handleIPC()
{
    while (true)
    {
        auto message = ipc->receiveMessage();
        if (message.has_value())
        {
            for (auto &plugin : plugins)
            {
                plugin->handleMessage(message.value());
            }
        }
    }
}
 
void Server::handleSignal(int signal)
{
    if (signal == SIGUSR1)
    {
        LOG(INFO) << "Reloading config file by SIGUSR1";
        Server::getInstance().reloadConfigFlag.store(true);
    }
}