Skip to content
Snippets Groups Projects
Commit 44891e07 authored by dmitriy.gerasimov's avatar dmitriy.gerasimov
Browse files

Merge branch 'features-2954' into 'master'

Features 2954

See merge request cellframe/libdap-chain-plugins-python!1
parents 745214b3 081aa383
No related branches found
No related tags found
1 merge request!1Features 2954
build/
cmake_minimum_required(VERSION 2.8)
project(dap_chain_plugins_python C)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_COLOR_MAKEFILE ON)
set(CMAKE_C_STANDARD 11)
add_definitions("-fpic")
add_definitions("-DDAP_LOG_MT")
if(UNIX)
add_definitions("-DDAP_OS_UNIX")
endif()
file(GLOB CHAIN_PLUGINS_PYTHON_SRCS src/*.c)
file(GLOB CHAIN_PLUGINS_PYTHON_HEADERS include/*.h)
set(Python_ADDITIONAL_VERSIONS 3.7 3.6 3.5 3.4)
find_package (PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIR} include/)
add_library(${PROJECT_NAME} STATIC ${CHAIN_PLUGINS_PYTHON_SRCS} ${CHAIN_PLUGINS_PYTHON_HEADERS})
target_link_libraries(${PROJECT_NAME})
target_link_libraries(${PROJECT_NAME} dap_core )
target_include_directories(${PROJECT_NAME} PUBLIC include/ )
#ifndef _DAP_CHAIN_PLUGINS_
#define _DAP_CHAIN_PLUGINS_
#include <Python.h>
#include "dap_config.h"
#include "dap_common.h"
#include "dap_file_utils.h"
#include "dap_chain_plugins_manifest.h"
#include "dap_chain_plugins_list.h"
#ifdef __cplusplus
extern "C"{
#endif
#undef LOG_TAG
#define LOG_TAG "dap_chain_plugins"
static PyObject *sys_path;
const char *plugins_root_path;
int dap_chain_plugins_init();
void dap_chain_plugins_deinit();
void dap_chain_plugins_loading();
void dap_chain_plugins_load_plugin(const char *dir_path, const char *name);
#ifdef __cplusplus
}
#endif
#endif //_DAP_CHAIN_PLUGINS_
#ifndef _DAP_CHAIN_PLUGINS_LIST_
#define _DAP_CHAIN_PLUGINS_LIST_
#include "Python.h"
#include "stdbool.h"
//#include "dap_list.h"
#include "dap_common.h"
#include "dap_strfuncs.h"
#include "utlist.h"
#include "dap_chain_plugins_manifest.h"
#ifdef __cplusplus
extern "C" {
#endif
#undef LOG_TAG
#define LOG_TAG "dap_chain_plugins_list"
typedef struct dap_chain_list_plugin_module{
char *name;
PyObject *obj_module;
bool isFuncOnChainsUpdated;
bool isFuncOnGdbUpdated;
bool isFuncOnNetStatusChanged;
struct dap_chain_list_plugin_module *next;
}dap_chain_plugin_list_module_t;
static dap_chain_plugin_list_module_t* m_dap_chain_plugins_module_list;
void dap_chain_plugins_list_init();
dap_chain_plugin_list_module_t* dap_chain_plugins_list_get();
bool dap_chain_plugins_list_check_load_plugins(dap_chain_plugins_list_char_t *list);
void dap_chain_plugins_list_add(PyObject *module, const char *name);
#ifdef __cplusplus
extern "C" {
#endif
#endif // _DAP_CHAIN_PLUGINS_LIST_
#ifndef _DAP_CHAIN_PLUGINS_MANIFEST_
#define _DAP_CHAIN_PLUGINS_MANIFEST_
#include "dap_common.h"
#include "dap_strfuncs.h"
#include "stdio.h"
#include "json-c/json_object.h"
#include "json-c/json_tokener.h"
#include "utlist.h"
#ifdef __cplusplus
extern "C"{
#endif
#undef LOG_TAG
#define LOG_TAG "dap_chain_plugins_manifest"
typedef struct dap_chain_plugins_list_char{
char *value;
struct dap_chain_plugins_list_char *next;
}dap_chain_plugins_list_char_t;
typedef struct dap_list_manifest{
char *name;
char *version;
char *author;
char *description;
dap_chain_plugins_list_char_t *dependencys;
struct dap_list_manifest *next;
}dap_chain_plugins_list_manifest_t;
dap_chain_plugins_list_manifest_t* manifests;
dap_chain_plugins_list_manifest_t *dap_chain_plugins_manifest_new(const char *name, const char *version, const dap_chain_plugins_list_char_t *dep, const char *author,
const char *description);
void dap_chain_plugins_manifest_list_create();
dap_chain_plugins_list_manifest_t* dap_chain_plugins_manifests_get_list();
dap_chain_plugins_list_manifest_t* dap_chain_plugins_add_manifest_from_file(const char *file_path);
bool dap_chain_plugins_manifest_list_add_from_file(const char *path_file);
#ifdef __cplusplus
}
#endif
#endif
#include "dap_chain_plugins.h"
int dap_chain_plugins_init(dap_config_t *config){
if(dap_config_get_item_bool_default(config, "plugins", "py_load", false)){
plugins_root_path = dap_config_get_item_str_default(config, "plugins", "py_path",
"/opt/cellframe-node/var/plugins/");
log_it(L_INFO, "Start initialize python plugins. Path plugins %s", plugins_root_path);
if (!dap_dir_test(plugins_root_path)){
log_it(L_ERROR, "The directory %s was not found.", plugins_root_path);
return -1;
}
Py_Initialize();
PyObject *sys_module = PyImport_ImportModule("sys");
sys_path = PyObject_GetAttrString(sys_module, "path");
//Get list files
dap_list_name_directories_t *list_plugins_name = dap_get_subs(plugins_root_path);
dap_list_name_directories_t *element;
//Loading manifest and start module
log_it(L_NOTICE, "Registration manifests");
dap_chain_plugins_manifest_list_create();
dap_chain_plugins_list_init();
char *name_file = NULL;
LL_FOREACH(list_plugins_name, element){
log_it(L_NOTICE, "Registration %s manifest", element->name_directory);
name_file = dap_strjoin("",plugins_root_path, element->name_directory, "/manifest.json", NULL);
if (!dap_chain_plugins_manifest_list_add_from_file(name_file)){
log_it(L_ERROR, "Registration %s manifest fail", element->name_directory);
}
DAP_FREE(name_file);
}
dap_chain_plugins_loading();
}else{
log_it(L_NOTICE, "Permission to initialize python plugins has not been obtained.");
return -2;
}
return 0;
}
void dap_chain_plugins_deinit(){
Py_Finalize();
}
void dap_chain_plugins_loading(){
log_it(L_NOTICE, "Loading plugins");
dap_chain_plugins_list_manifest_t *l_manifests = dap_chain_plugins_manifests_get_list();
dap_chain_plugins_list_manifest_t *man = NULL;
dap_chain_plugins_list_manifest_t *treshold = NULL;
dap_chain_plugins_list_manifest_t *tmp = NULL;
LL_FOREACH_SAFE(l_manifests, man, tmp){
if (man->name == NULL){
log_it(L_ERROR, "Can loading plugin, file not found");
break;
}
log_it(L_NOTICE, "Check dependencys for plugin %s", man->name);
if (man->dependencys != NULL){
log_it(L_NOTICE, "Plugin have dependencys");
if (!dap_chain_plugins_list_check_load_plugins(man->dependencys)){
log_it(L_NOTICE, "Plugin %s add treshold", man->name);
LL_APPEND(treshold, man);
}else{
dap_chain_plugins_load_plugin(dap_strjoin("", plugins_root_path, man->name, "/", NULL), man->name);
}
}else{
dap_chain_plugins_load_plugin(dap_strjoin("", plugins_root_path, man->name, "/", NULL), man->name);
}
}
int c_processed = 0;
int step_processed = 0;
int len;
LL_COUNT(treshold, man, len);
do{
LL_FOREACH_SAFE(treshold, man, tmp){
if (dap_chain_plugins_list_check_load_plugins(man->dependencys)){
log_it(L_NOTICE, "For plugin %s loading all dependecys", man->name);
dap_chain_plugins_load_plugin(dap_strjoin("", plugins_root_path, man->name, "/", NULL), man->name);
LL_DELETE(treshold, man);
c_processed++;
step_processed = 0;
}
}
step_processed++;
}while(c_processed < len && step_processed <= 2);
//Check loading all treshold
LL_COUNT(treshold, man, len);
if (len > 0){
log_it(L_WARNING, "I can't loading some plugins from list treshold");
LL_FOREACH(treshold, man){
log_it(L_ERROR, "The plugin %s does not load with a dependency resolution error.", man->name);
}
}
}
void dap_chain_plugins_load_plugin(const char *dir_path, const char *name){
log_it(L_NOTICE, "Loading %s plugin directory %s", name, dir_path);
PyErr_Clear();
PyObject *obj_dir_path = PyUnicode_FromString(dir_path);
PyList_Append(sys_path, obj_dir_path);
Py_XDECREF(obj_dir_path);
PyObject *module = PyImport_ImportModule(name);
PyObject *func_init = PyObject_GetAttrString(module, "init");
PyObject *func_deinit = PyObject_GetAttrString(module, "deinit");
PyObject *res_int = NULL;
PyErr_Clear();
if (func_init != NULL && PyCallable_Check(func_init)){
res_int = PyEval_CallObject(func_init, NULL);
if (res_int && PyLong_Check(res_int)){
if (_PyLong_AsInt(res_int) == 0){
dap_chain_plugins_list_add(module, name);
} else {
log_it(L_ERROR, "Code error %i at initialization %s plugin", _PyLong_AsInt(res_int), name);
}
} else {
log_it(L_ERROR, "Function initialization %s plugin don't reterned integer value", name);
}
Py_XDECREF(res_int);
}else {
log_it(L_ERROR, "For plugins %s don't found function init", name);
}
if (func_deinit == NULL || !PyCallable_Check(func_deinit)){
log_it(L_WARNING, "For plugins %s don't found function deinit", name);
}
}
#include "dap_chain_plugins_list.h"
void dap_chain_plugins_list_init(){
m_dap_chain_plugins_module_list = NULL;
}
void dap_chain_plugins_list_add(PyObject *module, const char *name){
dap_chain_plugin_list_module_t *elemnet = (dap_chain_plugin_list_module_t*)DAP_NEW(dap_chain_plugin_list_module_t);
elemnet->name = dap_strdup(name);
elemnet->obj_module = module;
elemnet->isFuncOnGdbUpdated = true;
elemnet->isFuncOnChainsUpdated = true;
elemnet->isFuncOnNetStatusChanged = true;
//Checking function
PyObject *F_FuncOnGdbUpdated = PyObject_GetAttrString(elemnet->obj_module, "onGdbUpdated");
PyObject *F_FuncOnChainsUpdated = PyObject_GetAttrString(elemnet->obj_module, "onChainsUpdated");
PyObject *F_FuncOnNetStatusChanged = PyObject_GetAttrString(elemnet->obj_module, "onNetStatusChanged");
if (F_FuncOnGdbUpdated == NULL || !PyCallable_Check(F_FuncOnGdbUpdated)){
log_it(L_WARNING, "Plugin %s don't callable function onGdbUpdated", elemnet->name);
elemnet->isFuncOnGdbUpdated = false;
}
if (F_FuncOnChainsUpdated == NULL || !PyCallable_Check(F_FuncOnChainsUpdated)){
log_it(L_WARNING, "Plugin %s don't callable function onChainsUpdated", elemnet->name);
elemnet->isFuncOnChainsUpdated = false;
}
if (F_FuncOnNetStatusChanged == NULL || !PyCallable_Check(F_FuncOnNetStatusChanged)){
log_it(L_WARNING, "Plugin %s don't callable function onNetStatusChanged", elemnet->name);
elemnet->isFuncOnNetStatusChanged = false;
}
LL_APPEND(m_dap_chain_plugins_module_list, elemnet);
}
dap_chain_plugin_list_module_t* dap_chain_plugins_list_get(){
return m_dap_chain_plugins_module_list;
}
int dap_chain_plugins_list_cmp(dap_chain_plugin_list_module_t *e1, dap_chain_plugin_list_module_t *e2){
return strcmp(e1->name, e2->name);
}
bool dap_chain_plugins_list_check_load_plugins(dap_chain_plugins_list_char_t *list){
dap_chain_plugins_list_char_t *value_from_list = NULL;
dap_chain_plugin_list_module_t *element_from_list_module;
dap_chain_plugin_list_module_t *element_lnk = (dap_chain_plugin_list_module_t*)DAP_NEW(
dap_chain_plugin_list_module_t);
int lenght;
LL_COUNT(m_dap_chain_plugins_module_list, element_from_list_module, lenght);
if (lenght == 0)
return false;
LL_FOREACH(list, value_from_list){
element_lnk->name = value_from_list->value;
LL_SEARCH(m_dap_chain_plugins_module_list, element_from_list_module, element_lnk, dap_chain_plugins_list_cmp);
if (!element_from_list_module)
return false;
}
return true;
}
#include "dap_chain_plugins_manifest.h"
dap_chain_plugins_list_manifest_t *dap_chain_plugins_manifest_new(const char *name, const char *version, const dap_chain_plugins_list_char_t *dep, const char *author,
const char *description){
dap_chain_plugins_list_manifest_t *man = (dap_chain_plugins_list_manifest_t*)DAP_NEW(dap_chain_plugins_list_manifest_t);
man->name = dap_strdup(name);
man->author = dap_strdup(author);
man->version = dap_strdup(version);
man->description = dap_strdup(description);
man->dependencys = NULL;
//copy informantion from dep to man->dependencys
int len_dep;
dap_chain_plugins_list_char_t *char_t;
LL_COUNT((dap_chain_plugins_list_char_t*)dep, char_t, len_dep);
LL_FOREACH((dap_chain_plugins_list_char_t*)dep, char_t){
LL_APPEND(man->dependencys, char_t);
}
man->dependencys = (dap_chain_plugins_list_char_t*)dep;
return man;
}
static dap_chain_plugins_list_char_t* JSON_array_to_dap_list_char(json_object *j_obj){
dap_chain_plugins_list_char_t *list = NULL;
dap_chain_plugins_list_char_t *element = NULL;
for (int i = 0; i < json_object_array_length(j_obj); i++){
element = (dap_chain_plugins_list_char_t*)DAP_NEW(dap_chain_plugins_list_char_t);
element->value = dap_strdup(json_object_get_string(json_object_array_get_idx(j_obj, i)));
LL_APPEND(list, element);
}
return list;
}
void dap_chain_plugins_manifest_list_create(){
manifests = NULL;
}
dap_chain_plugins_list_manifest_t* dap_chain_plugins_add_manifest_from_file(const char *file_path){
//READ File in char
log_it(L_INFO, "Parse json file");
FILE *file = fopen(file_path, "rt");
if (file == NULL){
log_it(L_ERROR, "Error open manifest files along the way %s", file_path);
return NULL;
}
fseek(file, 0, SEEK_END);
size_t size_file = (size_t)ftell(file);
char *json = DAP_NEW_SIZE(char, size_file);
rewind(file);
fread(json, sizeof(char), size_file, file);
fclose(file);
//Parse JSON
json_object *j_obj = json_tokener_parse(json);
json_object *j_name = json_object_object_get(j_obj, "name");
json_object *j_version = json_object_object_get(j_obj, "version");
json_object *j_dependencys = json_object_object_get(j_obj, "dependencys");
json_object *j_author = json_object_object_get(j_obj, "author");
json_object *j_description = json_object_object_get(j_obj, "description");
const char *name, *version, *author, *description;
name = json_object_get_string(j_name);
version = json_object_get_string(j_version);
author = json_object_get_string(j_author);
description = json_object_get_string(j_description);
dap_chain_plugins_list_char_t *dep = JSON_array_to_dap_list_char(j_dependencys);
DAP_FREE(json);
dap_chain_plugins_list_char_t *tmp = NULL;
dap_chain_plugins_list_manifest_t *manifest = dap_chain_plugins_manifest_new(name, version, dep, author, description);
return manifest;
}
void dap_chain_plugins_manifest_list_add_manifest(dap_chain_plugins_list_manifest_t *man){
LL_APPEND(manifests, man);
}
dap_chain_plugins_list_manifest_t* dap_chain_plugins_manifests_get_list(){
return manifests;
}
bool dap_chain_plugins_manifest_list_add_from_file(const char *file_path){
dap_chain_plugins_list_manifest_t *manifest = dap_chain_plugins_add_manifest_from_file(file_path);
if (manifest == NULL)
return false;
dap_chain_plugins_manifest_list_add_manifest(manifest);
return true;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment