/** * @brief Callback called by the event loop watcher when health check timer expires. */ static void sr_pd_health_check_timer_cb(struct ev_loop *loop, ev_timer *w, int revents) { sr_pd_ctx_t *ctx = NULL; bool init_retry_needed = false; int rc = SR_ERR_OK; CHECK_NULL_ARG_VOID2(w, w->data); ctx = (sr_pd_ctx_t*)w->data; CHECK_NULL_ARG_VOID(ctx); for (size_t i = 0; i < ctx->plugins_cnt; i++) { if (ctx->plugins[i].initialized && (NULL != ctx->plugins[i].health_check_cb)) { rc = ctx->plugins[i].health_check_cb(ctx->session, ctx->plugins[i].private_ctx); if (SR_ERR_OK != rc) { SR_LOG_ERR("Health check of the plugin '%s' returned an error: %s", ctx->plugins[i].filename, sr_strerror(rc)); sr_pd_cleanup_plugin(ctx, &(ctx->plugins[i])); init_retry_needed = true; } } } if (init_retry_needed) { SR_LOG_DBG("Scheduling plugin init retry after %d seconds.", SR_PLUGIN_INIT_RETRY_TIMEOUT); ev_timer_start(ctx->event_loop, &ctx->init_retry_timer); } }
/** * @brief Callback called by the event loop watcher when init retry timer expires. */ static void sr_pd_init_retry_timer_cb(struct ev_loop *loop, ev_timer *w, int revents) { sr_pd_ctx_t *ctx = NULL; bool init_retry_needed = false; int rc = SR_ERR_OK; CHECK_NULL_ARG_VOID2(w, w->data); ctx = (sr_pd_ctx_t*)w->data; CHECK_NULL_ARG_VOID(ctx); for (size_t i = 0; i < ctx->plugins_cnt; i++) { if (! ctx->plugins[i].initialized) { rc = sr_pd_init_plugin(ctx->session, &(ctx->plugins[i])); if (SR_ERR_OK != rc) { init_retry_needed = true; } } } if (!init_retry_needed) { ev_timer_stop(ctx->event_loop, &ctx->init_retry_timer); } else { SR_LOG_DBG("Scheduling plugin init retry after %d seconds.", SR_PLUGIN_INIT_RETRY_TIMEOUT); } }
/* * Tests logging into callback function. */ static void logger_callback_test(void **state) { sr_log_set_cb(log_callback); SR_LOG_DBG("Testing logging callback %d, %d, %d, %s", 5, 4, 3, "..."); SR_LOG_INF("Testing logging callback %d, %d, %d, %s", 2, 1, 0, "GO!"); }
int cl_socket_connect(sr_conn_ctx_t *conn_ctx, const char *socket_path) { struct sockaddr_un addr; struct timeval tv = { 0, }; int fd = -1, rc = -1; CHECK_NULL_ARG2(socket_path, socket_path); SR_LOG_DBG("Connecting to socket=%s", socket_path); /* prepare a socket */ fd = socket(AF_UNIX, SOCK_STREAM, 0); if (-1 == fd) { SR_LOG_ERR("Unable to create a new socket: %s", sr_strerror_safe(errno)); return SR_ERR_INTERNAL; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1); /* connect to server */ rc = connect(fd, (struct sockaddr*)&addr, sizeof(addr)); if (-1 == rc) { SR_LOG_DBG("Unable to connect to socket=%s: %s", socket_path, sr_strerror_safe(errno)); close(fd); return SR_ERR_DISCONNECT; } /* set timeout for receive operation */ if (SR_REQUEST_TIMEOUT > 0) { tv.tv_sec = SR_REQUEST_TIMEOUT; tv.tv_usec = 0; rc = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); if (-1 == rc) { SR_LOG_ERR("Unable to set timeout for socket operations on socket=%s: %s", socket_path, sr_strerror_safe(errno)); close(fd); return SR_ERR_DISCONNECT; } } conn_ctx->fd = fd; return SR_ERR_OK; }
/** * @brief Callback called by the event loop watcher when a signal is caught. */ static void sr_pd_signal_cb(struct ev_loop *loop, struct ev_signal *w, int revents) { CHECK_NULL_ARG_VOID2(loop, w); SR_LOG_DBG("Signal %d caught, breaking the event loop.", w->signum); ev_break(loop, EVBREAK_ALL); }
void sr_log_stderr(sr_log_level_t log_level) { #if SR_LOGGING_ENABLED sr_ll_stderr = log_level; SR_LOG_DBG("Setting log level for stderr logs to %d.", log_level); #endif }
/** * @brief Loads a plugin form provided filename. */ static int sr_pd_load_plugin(sr_session_ctx_t *session, const char *plugin_filename, sr_pd_plugin_ctx_t *plugin_ctx) { int rc = SR_ERR_OK; CHECK_NULL_ARG3(session, plugin_filename, plugin_ctx); plugin_ctx->filename = strdup(plugin_filename); CHECK_NULL_NOMEM_GOTO(plugin_ctx->filename, rc, cleanup); /* open the dynamic library with plugin */ plugin_ctx->dl_handle = dlopen(plugin_filename, RTLD_LAZY); if (NULL == plugin_ctx->dl_handle) { SR_LOG_WRN("Unable to load the plugin: %s.", dlerror()); rc = SR_ERR_INIT_FAILED; goto cleanup; } /* get init function pointer */ *(void **) (&plugin_ctx->init_cb) = dlsym(plugin_ctx->dl_handle, SR_PLUGIN_INIT_FN_NAME); if (NULL == plugin_ctx->init_cb) { SR_LOG_WRN("Unable to find '%s' function: %s.", SR_PLUGIN_INIT_FN_NAME, dlerror()); rc = SR_ERR_INIT_FAILED; goto cleanup; } /* get cleanup function pointer */ *(void **) (&plugin_ctx->cleanup_cb) = dlsym(plugin_ctx->dl_handle, SR_PLUGIN_CLEANUP_FN_NAME); if (NULL == plugin_ctx->cleanup_cb) { SR_LOG_WRN("Unable to find '%s' function: %s.", SR_PLUGIN_CLEANUP_FN_NAME, dlerror()); rc = SR_ERR_INIT_FAILED; goto cleanup; } /* get health check function pointer */ *(void **) (&plugin_ctx->health_check_cb) = dlsym(plugin_ctx->dl_handle, SR_PLUGIN_HEALTH_CHECK_FN_NAME); if (NULL != plugin_ctx->health_check_cb) { SR_LOG_DBG("'%s' function found, health checks will be applied.", SR_PLUGIN_HEALTH_CHECK_FN_NAME); } return SR_ERR_OK; cleanup: if (NULL != plugin_ctx->dl_handle) { dlclose(plugin_ctx->dl_handle); } free(plugin_ctx->filename); return rc; }
void sr_log_syslog(sr_log_level_t log_level) { #if SR_LOGGING_ENABLED sr_ll_syslog = log_level; SR_LOG_DBG("Setting log level for syslog logs to %d.", log_level); if ((SR_LL_NONE != log_level) && !sr_syslog_enabled) { /* if syslog connection hasn't been initiated yet, initiate it now */ if (NULL == sr_syslog_identifier) { /* if we don't have any syslog identifier set, sr_logger_init hasn't been called yet */ sr_logger_init(NULL); } /* open the connection to syslog */ openlog((char*)sr_syslog_identifier, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON); sr_syslog_enabled = true; SR_LOG_DBG_MSG("Opening the connection to system logger (syslog)."); } #endif }
/** * @brief Logging callback called from libyang for each log entry. */ static void srcfg_ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path) { switch (level) { case LY_LLERR: if (ly_diminish_errors) SR_LOG_WRN("libyang: %s", msg); else SR_LOG_ERR("libyang: %s", msg); break; case LY_LLWRN: SR_LOG_WRN("libyang: %s", msg); break; case LY_LLVRB: SR_LOG_INF("libyang: %s", msg); break; case LY_LLDBG: SR_LOG_DBG("libyang: %s", msg); break; default: break; } }
int cl_request_process(sr_session_ctx_t *session, Sr__Msg *msg_req, Sr__Msg **msg_resp, sr_mem_ctx_t *sr_mem_resp, const Sr__Operation expected_response_op) { int rc = SR_ERR_OK; struct timeval tv = { 0, }; CHECK_NULL_ARG4(session, session->conn_ctx, msg_req, msg_resp); SR_LOG_DBG("Sending %s request.", sr_gpb_operation_name(expected_response_op)); pthread_mutex_lock(&session->conn_ctx->lock); /* some operation may take more time, raise the timeout */ if (SR__OPERATION__COMMIT == expected_response_op || SR__OPERATION__COPY_CONFIG == expected_response_op || SR__OPERATION__RPC == expected_response_op || SR__OPERATION__ACTION == expected_response_op) { tv.tv_sec = SR_LONG_REQUEST_TIMEOUT; tv.tv_usec = 0; rc = setsockopt(session->conn_ctx->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); if (-1 == rc) { SR_LOG_WRN("Unable to set timeout for socket operations: %s", sr_strerror_safe(errno)); } } /* send the request */ rc = cl_message_send(session->conn_ctx, msg_req); if (SR_ERR_OK != rc) { SR_LOG_ERR("Unable to send the message with request (session id=%"PRIu32", operation=%s).", session->id, sr_gpb_operation_name(msg_req->request->operation)); pthread_mutex_unlock(&session->conn_ctx->lock); return rc; } SR_LOG_DBG("%s request sent, waiting for response.", sr_gpb_operation_name(expected_response_op)); /* receive the response */ rc = cl_message_recv(session->conn_ctx, msg_resp, sr_mem_resp); if (SR_ERR_OK != rc) { SR_LOG_ERR("Unable to receive the message with response (session id=%"PRIu32", operation=%s).", session->id, sr_gpb_operation_name(msg_req->request->operation)); pthread_mutex_unlock(&session->conn_ctx->lock); return rc; } /* change socket timeout to the standard value */ if (SR__OPERATION__COMMIT == expected_response_op || SR__OPERATION__COPY_CONFIG == expected_response_op || SR__OPERATION__RPC == expected_response_op || SR__OPERATION__ACTION == expected_response_op) { tv.tv_sec = SR_REQUEST_TIMEOUT; rc = setsockopt(session->conn_ctx->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); if (-1 == rc) { SR_LOG_WRN("Unable to set timeout for socket operations: %s", sr_strerror_safe(errno)); } } pthread_mutex_unlock(&session->conn_ctx->lock); SR_LOG_DBG("%s response received, processing.", sr_gpb_operation_name(expected_response_op)); /* validate the response */ rc = sr_gpb_msg_validate(*msg_resp, SR__MSG__MSG_TYPE__RESPONSE, expected_response_op); if (SR_ERR_OK != rc) { SR_LOG_ERR("Malformed message with response received (session id=%"PRIu32", operation=%s).", session->id, sr_gpb_operation_name(msg_req->request->operation)); return rc; } /* check for errors */ if (SR_ERR_OK != (*msg_resp)->response->result) { if (NULL != (*msg_resp)->response->error) { /* set detailed error information into session */ rc = cl_session_set_error(session, (*msg_resp)->response->error->message, (*msg_resp)->response->error->xpath); } /* log the error (except expected ones) */ if (SR_ERR_NOT_FOUND != (*msg_resp)->response->result && SR_ERR_VALIDATION_FAILED != (*msg_resp)->response->result && SR_ERR_UNAUTHORIZED != (*msg_resp)->response->result && SR_ERR_OPERATION_FAILED != (*msg_resp)->response->result) { SR_LOG_ERR("Error by processing of the %s request (session id=%"PRIu32"): %s.", sr_gpb_operation_name(msg_req->request->operation), session->id, (NULL != (*msg_resp)->response->error && NULL != (*msg_resp)->response->error->message) ? (*msg_resp)->response->error->message : sr_strerror((*msg_resp)->response->result)); } return (*msg_resp)->response->result; } return rc; }
int cl_version_verify(sr_conn_ctx_t *connection) { int rc = SR_ERR_OK; Sr__Msg *msg_req = NULL, *msg_resp = NULL; sr_mem_ctx_t *sr_mem = NULL; /* prepare version-verification request */ rc = sr_mem_new(0, &sr_mem); CHECK_RC_MSG_GOTO(rc, cleanup, "Failed to create a new Sysrepo memory context."); rc = sr_gpb_req_alloc(sr_mem, SR__OPERATION__VERSION_VERIFY, /* undefined session id */ 0, &msg_req); CHECK_RC_MSG_GOTO(rc, cleanup, "Cannot allocate GPB message."); /* set argument */ sr_mem_edit_string(sr_mem, &msg_req->request->version_verify_req->soname, SR_COMPAT_VERSION); CHECK_NULL_NOMEM_GOTO(msg_req->request->version_verify_req->soname, rc, cleanup); /* send the request */ SR_LOG_DBG("Sending %s request.", sr_gpb_operation_name(SR__OPERATION__VERSION_VERIFY)); pthread_mutex_lock(&connection->lock); rc = cl_message_send(connection, msg_req); if (SR_ERR_OK != rc) { SR_LOG_ERR("Unable to send the message with request (operation=%s).", sr_gpb_operation_name(msg_req->request->operation)); pthread_mutex_unlock(&connection->lock); goto cleanup; } SR_LOG_DBG("%s request sent, waiting for response.", sr_gpb_operation_name(SR__OPERATION__VERSION_VERIFY)); /* receive the response */ rc = cl_message_recv(connection, &msg_resp, NULL); if (SR_ERR_OK != rc) { SR_LOG_ERR("Unable to receive the message with response (operation=%s).", sr_gpb_operation_name(msg_req->request->operation)); pthread_mutex_unlock(&connection->lock); goto cleanup; } pthread_mutex_unlock(&connection->lock); SR_LOG_DBG("%s response received, processing.", sr_gpb_operation_name(SR__OPERATION__VERSION_VERIFY)); /* validate the response */ rc = sr_gpb_msg_validate(msg_resp, SR__MSG__MSG_TYPE__RESPONSE, SR__OPERATION__VERSION_VERIFY); if (SR_ERR_OK != rc) { SR_LOG_ERR("Malformed message with response received (operation=%s).", sr_gpb_operation_name(msg_req->request->operation)); goto cleanup; } /* process the result */ if (SR_ERR_OK != msg_resp->response->result) { SR_LOG_ERR("Sysrepod's \"%s\" version is not compatible with version \""SR_COMPAT_VERSION"\" in use.", msg_resp->response->version_verify_resp->soname); rc = msg_resp->response->result; goto cleanup; } cleanup: if (NULL != msg_req) { sr_msg_free(msg_req); } else { sr_mem_free(sr_mem); } if (NULL != msg_resp) { sr_msg_free(msg_resp); } return rc; }
/** * @brief Import content of the specified datastore for the given module from a file * referenced by the descriptor 'fd_in' */ static int srcfg_import_datastore(struct ly_ctx *ly_ctx, int fd_in, const char *module_name, srcfg_datastore_t datastore, LYD_FORMAT format, bool permanent) { int rc = SR_ERR_INTERNAL; unsigned i = 0; struct lyd_node *new_data_tree = NULL; struct lyd_node *current_data_tree = NULL; struct lyd_difflist *diff = NULL; char *first_xpath = NULL, *second_xpath = NULL; char *input_data = NULL; int ret = 0; struct stat info; CHECK_NULL_ARG2(ly_ctx, module_name); /* parse input data */ ret = fstat(fd_in, &info); CHECK_NOT_MINUS1_LOG_GOTO(ret, rc, SR_ERR_INTERNAL, cleanup, "Unable to obtain input file info: %s.", sr_strerror_safe(errno)); ly_errno = LY_SUCCESS; if (S_ISREG(info.st_mode)) { /* load (using mmap) and parse the input data in one step */ new_data_tree = lyd_parse_fd(ly_ctx, fd_in, format, LYD_OPT_STRICT | LYD_OPT_CONFIG); } else { /* most likely STDIN */ /* load input data into the memory first */ ret = srcfg_read_file_content(fd_in, &input_data); CHECK_RC_MSG_GOTO(ret, cleanup, "Unable to read the input data."); /* parse the input data stored inside memory buffer */ new_data_tree = lyd_parse_mem(ly_ctx, input_data, format, LYD_OPT_STRICT | LYD_OPT_CONFIG); } if (NULL == new_data_tree && LY_SUCCESS != ly_errno) { SR_LOG_ERR("Unable to parse the input data: %s", ly_errmsg()); goto cleanup; } /* validate input data */ if (NULL != new_data_tree) { ret = lyd_validate(&new_data_tree, LYD_OPT_STRICT | LYD_OPT_CONFIG | LYD_WD_IMPL_TAG); CHECK_ZERO_LOG_GOTO(ret, rc, SR_ERR_INTERNAL, cleanup, "Input data are not valid: %s", ly_errmsg()); } /* remove default nodes */ lyd_wd_cleanup(&new_data_tree, 0); /* get data tree of currently stored configuration */ rc = srcfg_get_module_data(ly_ctx, module_name, ¤t_data_tree); if (SR_ERR_OK != rc) { goto cleanup; } /* get the list of changes made by the user */ diff = lyd_diff(current_data_tree, new_data_tree, 0); if (NULL == diff) { SR_LOG_ERR("Unable to get the list of changes: %s", ly_errmsg()); goto cleanup; } /* iterate over the list of differences and for each issue corresponding Sysrepo command(s) */ while (diff->type && LYD_DIFF_END != diff->type[i]) { if (NULL != diff->first[i]) { first_xpath = lyd_path(diff->first[i]); if (NULL == first_xpath) { SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg()); goto cleanup; } } if (NULL != diff->second[i]) { second_xpath = lyd_path(diff->second[i]); if (NULL == second_xpath) { free(first_xpath); first_xpath = NULL; SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg()); goto cleanup; } } switch (diff->type[i]) { case LYD_DIFF_DELETED: SR_LOG_DBG("<LYD_DIFF_DELETED> node: %s", first_xpath); rc = srcfg_convert_lydiff_deleted(first_xpath); break; case LYD_DIFF_CHANGED: SR_LOG_DBG("<LYD_DIFF_CHANGED> orig: %s, new: %s", first_xpath, second_xpath); rc = srcfg_convert_lydiff_changed(first_xpath, diff->second[i]); break; case LYD_DIFF_MOVEDAFTER1: SR_LOG_DBG("<LYD_DIFF_MOVEDAFTER1> moved: %s, after: %s", first_xpath, second_xpath); rc = srcfg_convert_lydiff_movedafter(first_xpath, second_xpath); break; case LYD_DIFF_CREATED: SR_LOG_DBG("<LYD_DIFF_CREATED> parent: %s, new node: %s", first_xpath, second_xpath); rc = srcfg_convert_lydiff_created(diff->second[i]); break; case LYD_DIFF_MOVEDAFTER2: SR_LOG_DBG("<LYD_DIFF_MOVEDAFTER2> after: %s, this new node was inserted: %s", first_xpath, second_xpath); rc = srcfg_convert_lydiff_movedafter(second_xpath, first_xpath); break; default: assert(0 && "not reachable"); } free(first_xpath); free(second_xpath); first_xpath = second_xpath = NULL; if (SR_ERR_OK != rc) { goto cleanup; } ++i; } if (0 == i) { SR_LOG_DBG_MSG("No changes were made."); } else { /* commit the changes */ rc = sr_commit(srcfg_session); if (SR_ERR_OK != rc) { SR_LOG_ERR("Error returned from sr_commit: %s.", sr_strerror(rc)); goto cleanup; } if (SRCFG_STORE_RUNNING == datastore && permanent) { /* copy running datastore data into the startup datastore */ rc = sr_copy_config(srcfg_session, module_name, SR_DS_RUNNING, SR_DS_STARTUP); if (SR_ERR_OK != rc) { SR_LOG_ERR("Error returned from sr_copy_config: %s.", sr_strerror(rc)); goto cleanup; } } } rc = SR_ERR_OK; cleanup: if (NULL != diff) { lyd_free_diff(diff); } if (NULL != current_data_tree) { lyd_free_withsiblings(current_data_tree); } if (NULL != new_data_tree) { lyd_free_withsiblings(new_data_tree); } if (input_data) { free(input_data); } return rc; }
/** * @brief Initializes libyang ctx with all schemas installed for specified module in sysrepo. */ static int srcfg_ly_init(struct ly_ctx **ly_ctx, const char *module_name) { DIR *dp = NULL; struct dirent *ep = NULL; char *delim = NULL; char schema_filename[PATH_MAX] = { 0, }; const struct lys_module *module = NULL; CHECK_NULL_ARG2(ly_ctx, module_name); *ly_ctx = ly_ctx_new(srcfg_schema_search_dir); if (NULL == *ly_ctx) { SR_LOG_ERR("Unable to initialize libyang context: %s", ly_errmsg()); return SR_ERR_INTERNAL; } ly_set_log_clb(srcfg_ly_log_cb, 1); /* iterate over all files in the directory with schemas */ dp = opendir(srcfg_schema_search_dir); if (NULL == dp) { SR_LOG_ERR("Failed to open the schema directory: %s.", sr_strerror_safe(errno)); return SR_ERR_INTERNAL; } while (NULL != (ep = readdir(dp))) { /* test file extension */ LYS_INFORMAT fmt = LYS_IN_UNKNOWN; if (sr_str_ends_with(ep->d_name, SR_SCHEMA_YIN_FILE_EXT)) { fmt = LYS_IN_YIN; } else if (sr_str_ends_with(ep->d_name, SR_SCHEMA_YANG_FILE_EXT)) { fmt = LYS_IN_YANG; } if (fmt != LYS_IN_UNKNOWN) { /* strip extension and revision */ strcpy(schema_filename, ep->d_name); delim = strrchr(schema_filename, '.'); assert(delim); *delim = '\0'; delim = strrchr(schema_filename, '@'); if (delim) { *delim = '\0'; } /* TODO install all revisions and dependencies of the specified module, but not more */ #if 0 /* XXX install all schemas until we can resolve all dependencies */ if (strcmp(schema_filename, module_name) == 0) { #endif /* construct full file path */ snprintf(schema_filename, PATH_MAX, "%s%s", srcfg_schema_search_dir, ep->d_name); /* load the schema into the context */ SR_LOG_DBG("Loading module schema: '%s'.", schema_filename); module = lys_parse_path(*ly_ctx, schema_filename, fmt); if (NULL == module) { continue; } for (uint8_t i = 0; i < module->features_size; i++) { lys_features_enable(module, module->features[i].name); } #if 0 } #endif } } closedir(dp); return SR_ERR_OK; }
int cl_request_process(sr_session_ctx_t *session, Sr__Msg *msg_req, Sr__Msg **msg_resp, sr_mem_ctx_t *sr_mem_resp, const Sr__Operation expected_response_op) { int rc = SR_ERR_OK; CHECK_NULL_ARG4(session, session->conn_ctx, msg_req, msg_resp); SR_LOG_DBG("Sending %s request.", sr_gpb_operation_name(expected_response_op)); pthread_mutex_lock(&session->conn_ctx->lock); /* send the request */ rc = cl_message_send(session->conn_ctx, msg_req); if (SR_ERR_OK != rc) { SR_LOG_ERR("Unable to send the message with request (session id=%"PRIu32", operation=%s).", session->id, sr_gpb_operation_name(msg_req->request->operation)); pthread_mutex_unlock(&session->conn_ctx->lock); return rc; } SR_LOG_DBG("%s request sent, waiting for response.", sr_gpb_operation_name(expected_response_op)); /* receive the response */ rc = cl_message_recv(session->conn_ctx, msg_resp, sr_mem_resp); if (SR_ERR_OK != rc) { SR_LOG_ERR("Unable to receive the message with response (session id=%"PRIu32", operation=%s).", session->id, sr_gpb_operation_name(msg_req->request->operation)); pthread_mutex_unlock(&session->conn_ctx->lock); return rc; } pthread_mutex_unlock(&session->conn_ctx->lock); SR_LOG_DBG("%s response received, processing.", sr_gpb_operation_name(expected_response_op)); /* validate the response */ rc = sr_gpb_msg_validate(*msg_resp, SR__MSG__MSG_TYPE__RESPONSE, expected_response_op); if (SR_ERR_OK != rc) { SR_LOG_ERR("Malformed message with response received (session id=%"PRIu32", operation=%s).", session->id, sr_gpb_operation_name(msg_req->request->operation)); return rc; } /* check for errors */ if (SR_ERR_OK != (*msg_resp)->response->result) { if (NULL != (*msg_resp)->response->error) { /* set detailed error information into session */ rc = cl_session_set_error(session, (*msg_resp)->response->error->message, (*msg_resp)->response->error->xpath); } /* log the error (except expected ones) */ if (SR_ERR_NOT_FOUND != (*msg_resp)->response->result && SR_ERR_VALIDATION_FAILED != (*msg_resp)->response->result && SR_ERR_UNAUTHORIZED != (*msg_resp)->response->result && SR_ERR_OPERATION_FAILED != (*msg_resp)->response->result) { SR_LOG_ERR("Error by processing of the %s request (session id=%"PRIu32"): %s.", sr_gpb_operation_name(msg_req->request->operation), session->id, (NULL != (*msg_resp)->response->error && NULL != (*msg_resp)->response->error->message) ? (*msg_resp)->response->error->message : sr_strerror((*msg_resp)->response->result)); } return (*msg_resp)->response->result; } return rc; }
/** * @brief Loads all plugins in plugins directory. */ static int sr_pd_load_plugins(sr_pd_ctx_t *ctx) { DIR *dir; struct dirent entry, *result; char *env_str = NULL; char plugins_dir[PATH_MAX - 256] = { 0, }; char plugin_filename[PATH_MAX + 1] = { 0, }; sr_pd_plugin_ctx_t *tmp = NULL; bool init_retry_needed = false; int ret = 0; int rc = SR_ERR_OK; CHECK_NULL_ARG(ctx); /* get plugins dir from environment variable, or use default one */ env_str = getenv("SR_PLUGINS_DIR"); if (NULL != env_str) { strncat(plugins_dir, env_str, PATH_MAX - 257); } else { strncat(plugins_dir, SR_PLUGINS_DIR, PATH_MAX - 257); } SR_LOG_DBG("Loading plugins from '%s'.", plugins_dir); dir = opendir(plugins_dir); if (NULL == dir) { SR_LOG_ERR("Error by opening plugin directory: %s.", sr_strerror_safe(errno)); return SR_ERR_INVAL_ARG; } do { ret = readdir_r(dir, &entry, &result); if (0 != ret) { SR_LOG_ERR("Error by reading plugin directory: %s.", sr_strerror_safe(errno)); break; } if ((NULL != result) && (DT_DIR != entry.d_type) && (0 != strcmp(entry.d_name, ".")) && (0 != strcmp(entry.d_name, ".."))) { SR_LOG_DBG("Loading plugin from file '%s'.", entry.d_name); snprintf(plugin_filename, PATH_MAX, "%s/%s", plugins_dir, entry.d_name); /* realloc plugins array */ tmp = realloc(ctx->plugins, sizeof(*ctx->plugins) * (ctx->plugins_cnt + 1)); if (NULL == tmp) { SR_LOG_ERR_MSG("Unable to realloc plugins array, skipping the rest of plugins."); break; } ctx->plugins = tmp; /* load the plugin */ rc = sr_pd_load_plugin(ctx->session, plugin_filename, &(ctx->plugins[ctx->plugins_cnt])); if (SR_ERR_OK != rc) { SR_LOG_WRN("Ignoring the file '%s'.", plugin_filename); continue; } /* initialize the plugin */ rc = sr_pd_init_plugin(ctx->session, &(ctx->plugins[ctx->plugins_cnt])); if (SR_ERR_OK != rc) { init_retry_needed = true; } ctx->plugins_cnt += 1; } } while (NULL != result); closedir(dir); if (init_retry_needed) { SR_LOG_DBG("Scheduling plugin init retry after %d seconds.", SR_PLUGIN_INIT_RETRY_TIMEOUT); ev_timer_start(ctx->event_loop, &ctx->init_retry_timer); } return SR_ERR_OK; }