mirror of
https://github.com/Telecominfraproject/oopt-tai-implementations.git
synced 2025-10-29 09:12:34 +00:00
Merge pull request #13 from Telecominfraproject/exec
mux: add exec platform adapter
This commit is contained in:
@@ -16,7 +16,9 @@ modules and decides which `libtai.so` to use for detected modules.
|
||||
platform adapter. User can choose which platform adapter to use by
|
||||
passing an environment variable `TAI_MUX_PLATFORM_ADAPTER`.
|
||||
|
||||
Currently, only `static` platform adapter is supported.
|
||||
Currently, `static` platform adapter and `exec` platform adapter is supported.
|
||||
|
||||
By default, `TAI_MUX_PLATFORM_ADAPTER` is set to `static`.
|
||||
|
||||
#### static platform adapter
|
||||
|
||||
@@ -48,6 +50,24 @@ is 5,6,7,8.
|
||||
An environment variable `TAI_MUX_STATIC_CONFIG_FILE` is used to let the
|
||||
static platform adapter know the location of the configuration file.
|
||||
|
||||
#### exec platform adapter
|
||||
|
||||
exec platform adapter is a platform adapter which executes a prespecified script.
|
||||
|
||||
User can choose what script to execute by using an environment variable `TAI_MUX_EXEC_SCRIPT`.
|
||||
|
||||
By default, `TAI_MUX_EXEC_SCRIPT` is set to `/etc/tai/mux/exec.sh`.
|
||||
|
||||
exec platform adapter executes this script in two ways.
|
||||
|
||||
The first way is to get the list of modules during the initialization phase.
|
||||
In this case, exec platform adapter passes 'list' as the first argument.
|
||||
The script must return the list of modules which is separated by a newline, or "\n".
|
||||
|
||||
The second way is to get the actual TAI library to use for a module when TAI adapter host tries to create a module.
|
||||
In this case, exec platform adapter passes the module location as the first argument.
|
||||
The script must return the TAI library name. If the module doesn't exist in the specified location, the script must exit with non-zero value.
|
||||
|
||||
### HOW TO BUILD
|
||||
|
||||
```
|
||||
|
||||
@@ -7,6 +7,7 @@ typedef enum _tai_mux_platform_adapter_type_t
|
||||
{
|
||||
TAI_MUX_PLATFORM_ADAPTER_TYPE_UNKNOWN,
|
||||
TAI_MUX_PLATFORM_ADAPTER_TYPE_STATIC,
|
||||
TAI_MUX_PLATFORM_ADAPTER_TYPE_EXEC,
|
||||
TAI_MUX_PLATFORM_ADAPTER_TYPE_MAX,
|
||||
} tai_mux_platform_adapter_type_t;
|
||||
|
||||
|
||||
92
tai_mux/exec_platform_adapter.cpp
Normal file
92
tai_mux/exec_platform_adapter.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "exec_platform_adapter.hpp"
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
|
||||
namespace tai::mux {
|
||||
|
||||
// trim from end (in place)
|
||||
static inline void rtrim(std::string &s) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
|
||||
return std::isgraph(ch);
|
||||
}).base(), s.end());
|
||||
}
|
||||
|
||||
static int exec(const std::string& cmd, std::string& output) {
|
||||
FILE* pipe = popen(cmd.c_str(), "r");
|
||||
if (!pipe) return -1;
|
||||
char buffer[128] = {};
|
||||
while (!feof(pipe)) {
|
||||
if (fgets(buffer, 128, pipe) != NULL)
|
||||
output += buffer;
|
||||
}
|
||||
return WEXITSTATUS(pclose(pipe));
|
||||
}
|
||||
|
||||
static int exec_script(const std::string& arg, std::string& output) {
|
||||
std::stringstream ss;
|
||||
std::string script = TAI_MUX_EXEC_DEFAULT_SCRIPT;
|
||||
auto e = std::getenv(TAI_MUX_EXEC_SCRIPT.c_str());
|
||||
if ( e != nullptr ) {
|
||||
script = e;
|
||||
}
|
||||
ss << script;
|
||||
ss << " ";
|
||||
ss << arg;
|
||||
auto ret = exec(ss.str(), output);
|
||||
if ( ret != 0 ) {
|
||||
TAI_ERROR("failed to execute %s: ret: %d", script.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
rtrim(output);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ExecPlatformAdapter::ExecPlatformAdapter(uint64_t flags, const tai_service_method_table_t* services) : m_flags(flags) {
|
||||
|
||||
m_services.module_presence = nullptr;
|
||||
if ( services != nullptr ) {
|
||||
m_services.get_module_io_handler = services->get_module_io_handler;
|
||||
}
|
||||
|
||||
if ( services != nullptr && services->module_presence != nullptr ) {
|
||||
std::string output;
|
||||
auto ret = exec_script("list", output);
|
||||
if ( ret != 0 ) {
|
||||
throw Exception(TAI_STATUS_FAILURE);
|
||||
}
|
||||
TAI_DEBUG("result of list: %s", output.c_str());
|
||||
std::stringstream ss(output);
|
||||
std::string location;
|
||||
while(getline(ss, location)) {
|
||||
services->module_presence(true, const_cast<char*>(location.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExecPlatformAdapter::~ExecPlatformAdapter() {
|
||||
for ( auto& m : m_ma_map ) {
|
||||
m.second->tai_api_uninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
S_ModuleAdapter ExecPlatformAdapter::get_module_adapter(const std::string& location) {
|
||||
std::string lib;
|
||||
auto ret = exec_script(location, lib);
|
||||
if ( ret != 0 ) {
|
||||
TAI_ERROR("script failed: %d", ret);
|
||||
return nullptr;
|
||||
}
|
||||
auto dl = ModuleAdapter::dl_address(lib);
|
||||
S_ModuleAdapter ma;
|
||||
if ( dl == 0 ) {
|
||||
ma = std::make_shared<ModuleAdapter>(lib, m_flags, &m_services);
|
||||
dl = ModuleAdapter::dl_address(lib);
|
||||
m_lib_map[dl] = ma;
|
||||
} else {
|
||||
ma = m_lib_map[dl];
|
||||
}
|
||||
m_ma_map[location] = ma;
|
||||
return ma;
|
||||
}
|
||||
}
|
||||
48
tai_mux/exec_platform_adapter.hpp
Normal file
48
tai_mux/exec_platform_adapter.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef __EXEC_PLATFORM_ADAPTER_HPP__
|
||||
#define __EXEC_PLATFORM_ADAPTER_HPP__
|
||||
|
||||
#include <thread>
|
||||
#include <map>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "platform_adapter.hpp"
|
||||
#include "module_adapter.hpp"
|
||||
#include "tai.h"
|
||||
#include "json.hpp"
|
||||
|
||||
namespace tai::mux {
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
const std::string TAI_MUX_EXEC_SCRIPT = "TAI_MUX_EXEC_SCRIPT";
|
||||
const std::string TAI_MUX_EXEC_DEFAULT_SCRIPT = "/etc/tai/mux/exec.sh";
|
||||
|
||||
class ExecPlatformAdapter : public PlatformAdapter {
|
||||
public:
|
||||
ExecPlatformAdapter(uint64_t flags, const tai_service_method_table_t* services);
|
||||
~ExecPlatformAdapter();
|
||||
S_ModuleAdapter get_module_adapter(const std::string& location);
|
||||
const std::unordered_set<S_ModuleAdapter> list_module_adapters() {
|
||||
std::unordered_set<S_ModuleAdapter> set;
|
||||
for ( auto m : m_ma_map ) {
|
||||
set.emplace(m.second);
|
||||
}
|
||||
return set;
|
||||
};
|
||||
|
||||
virtual tai_mux_platform_adapter_type_t type() const {
|
||||
return TAI_MUX_PLATFORM_ADAPTER_TYPE_EXEC;
|
||||
}
|
||||
private:
|
||||
std::map<uint64_t, S_ModuleAdapter> m_lib_map;
|
||||
std::map<std::string, S_ModuleAdapter> m_ma_map;
|
||||
std::thread m_th;
|
||||
tai_service_method_table_t m_services;
|
||||
const uint64_t m_flags;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,7 @@ namespace tai::mux {
|
||||
ModuleAdapter::ModuleAdapter(const std::string& name, uint64_t flags, const tai_service_method_table_t* services) : m_name(name) {
|
||||
m_dl = dlopen(name.c_str(), RTLD_NOW | RTLD_DEEPBIND);
|
||||
if ( m_dl == nullptr ) {
|
||||
TAI_ERROR("dlerror: %s", dlerror());
|
||||
throw std::runtime_error(dlerror());
|
||||
}
|
||||
LOAD_TAI_API(tai_api_initialize)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "mux.hpp"
|
||||
#include <iostream>
|
||||
#include "taimetadata.h"
|
||||
#include "static_platform_adapter.hpp"
|
||||
#include "exec_platform_adapter.hpp"
|
||||
|
||||
namespace tai::mux {
|
||||
|
||||
@@ -35,11 +37,16 @@ namespace tai::mux {
|
||||
tai_mux_platform_adapter_type_t pa_type;
|
||||
if ( pa_name == "static" ) {
|
||||
pa_type = TAI_MUX_PLATFORM_ADAPTER_TYPE_STATIC;
|
||||
} else if ( pa_name == "exec" ) {
|
||||
pa_type = TAI_MUX_PLATFORM_ADAPTER_TYPE_EXEC;
|
||||
}
|
||||
switch ( pa_type ) {
|
||||
case TAI_MUX_PLATFORM_ADAPTER_TYPE_STATIC:
|
||||
m_pa = std::make_shared<StaticPlatformAdapter>(0, services);
|
||||
break;
|
||||
case TAI_MUX_PLATFORM_ADAPTER_TYPE_EXEC:
|
||||
m_pa = std::make_shared<ExecPlatformAdapter>(0, services);
|
||||
break;
|
||||
default:
|
||||
TAI_ERROR("unsupported platform_adapter: %s", pa_name.c_str());
|
||||
throw Exception(TAI_STATUS_NOT_SUPPORTED);
|
||||
@@ -162,6 +169,10 @@ namespace tai::mux {
|
||||
}
|
||||
|
||||
tai_status_t Platform::set_log(tai_api_t api, tai_log_level_t level, tai_log_fn log_fn) {
|
||||
auto ret = tai::Logger::get_instance().set_log(api, level, log_fn);
|
||||
if ( ret != TAI_STATUS_SUCCESS ) {
|
||||
return ret;
|
||||
}
|
||||
auto set = m_pa->list_module_adapters();
|
||||
for ( const auto& a : set ) {
|
||||
auto ret = a->tai_log_set(api, level, log_fn);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <string>
|
||||
#include "platform_adapter.hpp"
|
||||
#include "static_platform_adapter.hpp"
|
||||
#include "module_adapter.hpp"
|
||||
#include "tai.h"
|
||||
#include <mutex>
|
||||
|
||||
Reference in New Issue
Block a user