server: Use interface::ModuleInfo in module load interface

This commit is contained in:
Perttu Ahola 2014-09-30 14:23:24 +03:00
parent 851cc805a7
commit be719f7eb8
10 changed files with 106 additions and 86 deletions

View File

@ -369,7 +369,7 @@ struct Module: public interface::Module, public loader::Interface
interface::ModuleInfo *info = get_module_info(name);
if(!info)
throw Exception(ss_()+"Couldn't get module info for \""+name+"\"");
if(!m_server->load_module(name, info->path)){
if(!m_server->load_module(*info)){
m_server->shutdown(1, ss_()+"loader: Error loading module "+name);
return;
}
@ -383,7 +383,7 @@ struct Module: public interface::Module, public loader::Interface
log_v(MODULE, "loader::on_module_modified(): %s", cs(event.name));
if(event.name == "loader")
return;
m_server->reload_module(event.name, event.path);
m_server->reload_module(event.name);
}
// Interface

View File

@ -26,4 +26,3 @@ Buildat TODO
- Entity system with automated network sync
- Support Cereal's shared pointer serialization in Lua
- Something in uistack's global nil focus handling has broken
- Use JSON metadata in RCCPP calls (ldflags, cxxflags)

View File

@ -1,5 +1,6 @@
#include "core/log.h"
#include "interface/module.h"
#include "interface/module_info.h"
#include "interface/server.h"
#include "interface/fs.h"
#include "interface/event.h"
@ -45,8 +46,11 @@ struct Module: public interface::Module
void on_load_modules()
{
bool ok = m_server->load_module("loader",
m_server->get_builtin_modules_path()+"/loader");
interface::ModuleInfo info;
info.name = "loader";
info.path = m_server->get_builtin_modules_path()+"/"+info.name;
bool ok = m_server->load_module(info);
if(!ok){
m_shutdown_reason = ss_()+"Error loading builtin/loader";
m_server->shutdown(1);
@ -63,7 +67,7 @@ struct Module: public interface::Module
log_v(MODULE, "__loader::on_module_modified(): %s", cs(event.name));
if(event.name == "__loader")
return;
m_server->reload_module(event.name, event.path);
m_server->reload_module(event.name);
}
};

View File

@ -1,5 +1,6 @@
#include "core/log.h"
#include "interface/module.h"
#include "interface/module_info.h"
#include "interface/server.h"
#include "interface/fs.h"
#include "interface/event.h"
@ -45,8 +46,11 @@ struct Module: public interface::Module
void on_load_modules()
{
bool ok = m_server->load_module("loader",
m_server->get_builtin_modules_path()+"/loader");
interface::ModuleInfo info;
info.name = "loader";
info.path = m_server->get_builtin_modules_path()+"/"+info.name;
bool ok = m_server->load_module(info);
if(!ok){
m_shutdown_reason = ss_()+"Error loading builtin/loader";
m_server->shutdown(1);
@ -63,7 +67,7 @@ struct Module: public interface::Module
log_v(MODULE, "__loader::on_module_modified(): %s", cs(event.name));
if(event.name == "__loader")
return;
m_server->reload_module(event.name, event.path);
m_server->reload_module(event.name);
}
};

View File

@ -1,5 +1,6 @@
#include "core/log.h"
#include "interface/module.h"
#include "interface/module_info.h"
#include "interface/server.h"
#include "interface/fs.h"
#include "interface/event.h"
@ -45,8 +46,11 @@ struct Module: public interface::Module
void on_load_modules()
{
bool ok = m_server->load_module("loader",
m_server->get_builtin_modules_path()+"/loader");
interface::ModuleInfo info;
info.name = "loader";
info.path = m_server->get_builtin_modules_path()+"/"+info.name;
bool ok = m_server->load_module(info);
if(!ok){
m_shutdown_reason = ss_()+"Error loading builtin/loader";
m_server->shutdown(1);
@ -63,7 +67,7 @@ struct Module: public interface::Module
log_v(MODULE, "__loader::on_module_modified(): %s", cs(event.name));
if(event.name == "__loader")
return;
m_server->reload_module(event.name, event.path);
m_server->reload_module(event.name);
}
};

View File

@ -22,6 +22,15 @@ struct CEventRegistry: public EventRegistry
m_types[name] = m_next_type++;
return m_next_type - 1;
}
ss_ name(const Event::Type &type)
{
for(auto &pair : m_types){
if(pair.second == type)
return pair.first;
}
return "";
}
};
EventRegistry* getGlobalEventRegistry()

View File

@ -53,7 +53,10 @@ namespace interface
struct EventRegistry
{
// Allocates new type if needed
virtual Event::Type type(const ss_ &name) = 0;
// Returns "" if type is not allocated to a name
virtual ss_ name(const Event::Type &type) = 0;
};
EventRegistry* getGlobalEventRegistry();

View File

@ -7,6 +7,7 @@
namespace interface
{
struct ModuleInfo;
struct Module;
struct TickEvent: public interface::Event::Private {
@ -42,9 +43,10 @@ namespace interface
virtual void shutdown(int exit_status = 0, const ss_ &reason = "") = 0;
virtual bool load_module(const ss_ &module_name, const ss_ &path) = 0;
virtual bool load_module(const interface::ModuleInfo &info) = 0;
virtual void unload_module(const ss_ &module_name) = 0;
virtual void reload_module(const ss_ &module_name, const ss_ &path) = 0;
virtual void reload_module(const interface::ModuleInfo &info) = 0;
virtual void reload_module(const ss_ &module_name) = 0;
virtual ss_ get_modules_path() = 0;
virtual ss_ get_builtin_modules_path() = 0;
virtual ss_ get_module_path(const ss_ &module_name) = 0;

View File

@ -5,6 +5,7 @@
#include "config.h"
#include "core/log.h"
#include "interface/module.h"
#include "interface/module_info.h"
#include "interface/server.h"
#include "interface/event.h"
#include "interface/file_watch.h"
@ -56,49 +57,23 @@ static sv_<ss_> list_includes(const ss_ &path, const sv_<ss_> &include_dirs)
}
}
if(!found){
// Not a huge problem, just log at verbose
log_v(MODULE, "Include file not found: %s", cs(include));
// Not a huge problem, just log at debug
log_d(MODULE, "Include file not found for watching: %s", cs(include));
}
}
return result;
}
// TODO: Use JSON metadata
struct DepLine {
ss_ type;
ss_ value;
ss_ options;
};
static sv_<DepLine> get_deps(const ss_ &depfile_path)
{
sv_<DepLine> result;
std::ifstream ifs(depfile_path);
if(!ifs.good())
return result;
ss_ line;
while(std::getline(ifs, line)){
c55::Strfnd f(line);
DepLine dep;
dep.type = f.next(":");
if(dep.type == "module"){
dep.value = f.next(" ");
dep.options = f.next("");
} else {
dep.value = f.next("");
}
result.push_back(dep);
}
return result;
}
struct CState: public State, public interface::Server
{
struct ModuleContainer {
interface::Mutex mutex;
interface::Module *module;
ss_ path;
interface::ModuleInfo info;
ModuleContainer(interface::Module *module = NULL): module(module){}
ModuleContainer(interface::Module *module = NULL,
const interface::ModuleInfo &info = interface::ModuleInfo()):
module(module), info(info){}
};
struct SocketState {
@ -176,15 +151,15 @@ struct CState: public State, public interface::Server
return m_shutdown_requested;
}
bool load_module(const ss_ &module_name, const ss_ &path)
bool load_module(const interface::ModuleInfo &info)
{
interface::MutexScope ms(m_modules_mutex);
log_i(MODULE, "Loading module %s from %s", cs(module_name), cs(path));
log_i(MODULE, "Loading module %s from %s", cs(info.name), cs(info.path));
ss_ build_dst = g_server_config.rccpp_build_path +
"/"+module_name+".so";
ss_ init_cpp_path = path+"/"+module_name+".cpp";
"/"+info.name+".so";
ss_ init_cpp_path = info.path+"/"+info.name+".cpp";
// Set up file watch
@ -195,77 +170,77 @@ struct CState: public State, public interface::Server
log_v(MODULE, "Includes: %s", cs(dump(includes)));
files_to_watch.insert(files_to_watch.end(), includes.begin(), includes.end());
if(m_module_file_watches.count(module_name) == 0){
m_module_file_watches[module_name] = sp_<interface::FileWatch>(
if(m_module_file_watches.count(info.name) == 0){
m_module_file_watches[info.name] = sp_<interface::FileWatch>(
interface::createFileWatch(files_to_watch,
[this, module_name, path]()
[this, info]()
{
log_i(MODULE, "Module modified: %s: %s",
cs(module_name), cs(path));
cs(info.name), cs(info.path));
emit_event(Event("core:module_modified",
new interface::ModuleModifiedEvent(module_name, path)));
new interface::ModuleModifiedEvent(info.name, info.path)));
handle_events();
}));
}
// Build
// TODO: Use JSON metadata
sv_<DepLine> deps = get_deps(path+"/deps.txt");
ss_ extra_cxxflags;
ss_ extra_ldflags;
for(const DepLine &dep : deps){
if(dep.type == "cxxflags")
extra_cxxflags += dep.value+" ";
if(dep.type == "ldflags")
extra_ldflags += dep.value+" ";
}
log_v(MODULE, "extra_cxxflags: %s", cs(extra_cxxflags));
log_v(MODULE, "extra_ldflags: %s", cs(extra_ldflags));
ss_ extra_cxxflags = info.meta.cxxflags;
ss_ extra_ldflags = info.meta.ldflags;
log_d(MODULE, "extra_cxxflags: %s", cs(extra_cxxflags));
log_d(MODULE, "extra_ldflags: %s", cs(extra_ldflags));
m_compiler->include_directories.push_back(m_modules_path);
bool build_ok = m_compiler->build(module_name, init_cpp_path, build_dst,
bool build_ok = m_compiler->build(info.name, init_cpp_path, build_dst,
extra_cxxflags, extra_ldflags);
m_compiler->include_directories.pop_back();
if(!build_ok){
log_w(MODULE, "Failed to build module %s", cs(module_name));
log_w(MODULE, "Failed to build module %s", cs(info.name));
return false;
}
// Construct instance
interface::Module *m = static_cast<interface::Module*>(
m_compiler->construct(module_name.c_str(), this));
m_compiler->construct(info.name.c_str(), this));
if(m == nullptr){
log_w(MODULE, "Failed to construct module %s instance",
cs(module_name));
cs(info.name));
return false;
}
m_modules[module_name] = ModuleContainer(m);
m_modules[module_name].path = path;
m_modules[info.name] = ModuleContainer(m, info);
// Call init()
{
ModuleContainer &mc = m_modules[module_name];
ModuleContainer &mc = m_modules[info.name];
interface::MutexScope ms2(mc.mutex);
mc.module->init();
}
emit_event(Event("core:module_loaded",
new interface::ModuleLoadedEvent(module_name)));
new interface::ModuleLoadedEvent(info.name)));
return true;
}
void load_modules(const ss_ &path)
{
m_modules_path = path;
ss_ first_module_path = path+"/__loader";
load_module("__loader", first_module_path);
interface::ModuleInfo info;
info.name = "__loader";
info.path = path+"/"+info.name;
if(!load_module(info)){
shutdown(1, "Failed to load __loader module");
return;
}
// Allow loader to load other modules
emit_event(Event("core:load_modules"));
handle_events();
// Now that everyone is listening, we can fire the start event
emit_event(Event("core:start"));
handle_events();
@ -284,15 +259,32 @@ struct CState: public State, public interface::Server
m_unloads_requested.insert(module_name);
}
void reload_module(const ss_ &module_name, const ss_ &path)
void reload_module(const interface::ModuleInfo &info)
{
log_i(MODULE, "reload_module(%s)", cs(module_name));
log_i(MODULE, "reload_module(%s)", cs(info.name));
{
interface::MutexScope ms(m_modules_mutex);
unload_module_u(module_name);
unload_module_u(info.name);
}
load_module(module_name, path);
load_module(info);
// Send core::continue directly to module
{
interface::MutexScope ms(m_modules_mutex);
auto it = m_modules.find(info.name);
if(it == m_modules.end()){
log_w(MODULE, "reload_module: Module not found: %s",
cs(info.name));
return;
}
ModuleContainer *mc = &it->second;
interface::MutexScope mc_ms(mc->mutex);
mc->module->event(Event::t("core:continue"), nullptr);
}
}
void reload_module(const ss_ &module_name)
{
interface::ModuleInfo info;
{
interface::MutexScope ms(m_modules_mutex);
auto it = m_modules.find(module_name);
@ -302,9 +294,9 @@ struct CState: public State, public interface::Server
return;
}
ModuleContainer *mc = &it->second;
interface::MutexScope mc_ms(mc->mutex);
mc->module->event(Event::t("core:continue"), nullptr);
info = mc->info;
}
reload_module(info);
}
// Direct version; internal and unsafe
@ -366,7 +358,7 @@ struct CState: public State, public interface::Server
if(it == m_modules.end())
throw ModuleNotFoundException(ss_()+"Module not found: "+module_name);
ModuleContainer *mc = &it->second;
return mc->path;
return mc->info.path;
}
interface::Module* get_module(const ss_ &module_name)
@ -444,7 +436,9 @@ struct CState: public State, public interface::Server
log_w(MODULE, "sub_event(): Already on list: %s", cs(module_name));
return;
}
log_v(MODULE, "sub_event(): %s subscribed to %zu", cs(module_name), type);
auto *evreg = interface::getGlobalEventRegistry();
log_v(MODULE, "sub_event(): %s subscribed to %s (%zu)",
cs(module_name), cs(evreg->name(type)), type);
sublist.push_back(mc0);
}

View File

@ -6,6 +6,7 @@
namespace interface
{
struct ModuleInfo;
struct Module;
}
@ -27,7 +28,7 @@ namespace server
virtual void shutdown(int exit_status = 0, const ss_ &reason = "") = 0;
virtual bool is_shutdown_requested(int *exit_status = nullptr,
ss_ *reason = nullptr) = 0;
virtual bool load_module(const ss_ &module_name, const ss_ &path) = 0;
virtual bool load_module(const interface::ModuleInfo &info) = 0;
virtual void load_modules(const ss_ &path) = 0;
virtual interface::Module* get_module(const ss_ &module_name) = 0;
virtual interface::Module* check_module(const ss_ &module_name) = 0;