#include #include #include #include #include #include #include "rpc.h" #include "rpc_conn.h" #include "configm.h" config_service_t g_config_service[] = CONFIG_SERVICE_ARRAY; config_init_t g_config_init[] = CONFIG_INIT_ARRAY; int cm_format_data(ret_code ret_code, cJSON *item_obj, char *output) { int str_len = 0; char *ret_char = NULL; config_result_t tem_buff = {0}; config_result_t *config_ret = &tem_buff; snprintf(config_ret->resultCode, RET_CODE_LEN - 1, "%d", ret_code); config_ret->message = (char *)rpc_code_format(ret_code); s2j_create_json_obj(json_obj); if(json_obj == NULL) { return 0; } s2j_json_set_basic_element(json_obj, config_ret, string, resultCode); s2j_json_set_basic_element(json_obj, config_ret, string, message); cJSON_AddItemToObject(json_obj, "data", item_obj); ret_char = cJSON_PrintUnformatted(json_obj); str_len = strlen(ret_char); strncpy(output, ret_char, CM_BUFF_SIZE - 1); rpc_free(ret_char); cJSON_Delete(json_obj); return (str_len + 1); } void cm_return(rpc_conn *conn, ret_code err_code, char* err_message) { char *ret_char = NULL; char *null_str = ""; config_result_t tem_buff = {0}; config_result_t *config_ret = &tem_buff; rpc_log_dbg("error %d:%s\n", err_code, err_message); snprintf(config_ret->resultCode, RET_CODE_LEN - 1, "%d", err_code); config_ret->message = (char *)rpc_code_format(err_code); if(err_code == RET_SYSERR) { config_ret->data = strerror(errno); } else { config_ret->data = null_str; } s2j_create_json_obj(json_obj); if(json_obj == NULL) { return; } s2j_json_set_basic_element(json_obj, config_ret, string, resultCode); s2j_json_set_basic_element(json_obj, config_ret, string, message); s2j_json_set_basic_element(json_obj, config_ret, string, data); ret_char = cJSON_PrintUnformatted(json_obj); rpc_return(conn, ret_char, strlen(ret_char)+1); rpc_free(ret_char); cJSON_Delete(json_obj); return; } config_service_t *cm_config_service_get(uint64 config_id) { int len = sizeof(g_config_service) / sizeof(config_service_t); int config_idx; for(config_idx = 0; config_idx < len; config_idx++) { if(config_id == g_config_service[config_idx].config_id) { return &(g_config_service[config_idx]); } } return NULL; } ret_code cm_config_rec_pre(char **input, int *input_len, char **output, int *output_len) { /*if((access(CONFIG_RECOVERY_DONE, F_OK))!=-1) { return RET_ERR; } */ *input = rpc_new(char, CM_BUFF_SIZE); *output = rpc_new(char, CM_BUFF_SIZE); *input_len = CM_BUFF_SIZE; *output_len = CM_BUFF_SIZE; if(*input == NULL || *output == NULL) { return RET_NOMEM; } memset(*input, 0, CM_BUFF_SIZE); memset(*output, 0, CM_BUFF_SIZE); rpc_log_info("==>config revocery start\n"); return RET_OK; } ret_code cm_config_rec_done(char *input, char *output) { int fd; memset(input, 0, CM_BUFF_SIZE); memset(output, 0, CM_BUFF_SIZE); free(input); free(output); fd = open(CONFIG_RECOVERY_DONE, O_CREAT, 0777); if(fd <= 0) { rpc_log_error("create recovery file error"); } else { close(fd); } rpc_log_info("==>config revocery done!\n"); return RET_OK; } ret_code cm_config_get_allconfig(uint source, config_service_t *config_svr, char *input, int *intput_len) { ret_code ret = RET_OK; memset(input, 0, CM_BUFF_SIZE); ret = config_svr->getall_callback(source, input, intput_len); ASSERT_RET(ret); return ret; } ret_code cm_config_config_rec(uint source, config_service_t *config_svr, char *input, int input_len, char *output, int *output_len) { int config_type = CM_CONFIG_SET; ret_code ret = RET_OK; ret = config_svr->chk_callback(source, &config_type, input, &input_len, output, output_len); if(ret == RET_OK) { config_svr->proc_callback(source, config_type, input, input_len, output, output_len); } return ret; } void cm_config_module_init() { int len = sizeof(g_config_init) / sizeof(config_init_t); config_init_t *config_svr; int config_idx; for(config_idx = 0; config_idx < len; config_idx++) { config_svr = &(g_config_init[config_idx]); rpc_log_info("MODULE %d init\n", config_svr->config_mudlue); if(config_svr->init_callback) { config_svr->init_callback(); } } } /* 配置恢复 */ void cm_config_recovery() { int len = sizeof(g_config_service) / sizeof(config_service_t); config_service_t *config_svr; int input_len = 0; int output_len = 0; char *input = NULL; char *output = NULL; ret_code ret = RET_OK; int config_idx; int recover_idx = 1,recover_phase; ret = cm_config_rec_pre(&input, &input_len, &output, &output_len); ASSERT_RET_VOID(ret); while(recover_idx <= 2) { if(recover_idx == 1) { recover_phase = CONFIG_FROM_RECOVER1; } else if(recover_idx == 2) { recover_phase = CONFIG_FROM_RECOVER2; } else { break; } for(config_idx = 0; config_idx < len; config_idx++) { config_svr = &(g_config_service[config_idx]); if(config_svr->recovery != TRUE) { continue; } if(config_svr->chk_callback == NULL || config_svr->proc_callback == NULL) { continue; } cm_config_get_allconfig(recover_phase, config_svr, input, &input_len); cm_config_config_rec(recover_phase, config_svr, input, input_len, output, &output_len); } recover_idx++; } cm_config_rec_done(input, output); return; } ret_code cm_config_proc_pre(char **input, char **output, int *buff_len) { static char *cm_set_buff = NULL; static char *cm_get_buff = NULL; if(cm_set_buff == NULL) { cm_set_buff = rpc_new(char, CM_BUFF_SIZE); } if(cm_get_buff == NULL) { cm_get_buff = rpc_new(char, CM_BUFF_SIZE); } if(cm_get_buff == NULL || cm_set_buff == NULL) { return RET_NOMEM; } memset(cm_set_buff, 0, CM_BUFF_SIZE); memset(cm_get_buff, 0, CM_BUFF_SIZE); *input = cm_set_buff; *output = cm_get_buff; *buff_len = CM_BUFF_SIZE; return RET_OK; } /* 配置处理入口函数,所有的配置,均在此函数中处理 */ void cm_config_process(rpc_conn *conn, pointer input, int input_len, void* data) { config_service_t *config_svr; config_msg_t *config_msg; char *cm_get_buff = NULL; char *cm_set_buff = NULL; ret_code ret = RET_OK; int config_len = 0; int buff_len = CM_BUFF_SIZE; if(conn == NULL || input == NULL) { cm_return(conn, RET_NULLP, "NULL pointer"); return; } /*parse message*/ if(input_len < sizeof(config_msg_t)) { cm_return(conn, RET_NOMEM, "not enough memery"); return; } config_msg = (config_msg_t *)input; config_len = input_len - sizeof(config_msg_t); rpc_log_info("recv config from %d, config type is %d config id is 0x%llx ,len is %d\r\n", config_msg->source, config_msg->config_type, config_msg->config_id, config_len); config_svr = cm_config_service_get(config_msg->config_id); if(config_svr == NULL) { cm_return(conn, RET_NOCMID, "can not find config id"); return; } /*source check*/ if(!(config_svr->config_src & config_msg->source)) { cm_return(conn, RET_SRCERR, "source check error!\r\n"); return; } if(cm_config_proc_pre(&cm_set_buff, &cm_get_buff, &buff_len) != RET_OK) { cm_return(conn, RET_NOMEM, "not enough memory"); return; } memcpy(cm_set_buff, config_msg->config_buff, config_len); /*config check*/ if(config_svr->chk_callback) { ret = config_svr->chk_callback(config_msg->source, &(config_msg->config_type), cm_set_buff, &config_len, cm_get_buff, &buff_len); if(ret != RET_OK) { cm_return(conn, ret, cm_get_buff); return; } } /*config exec*/ switch(config_msg->config_type) { case CM_CONFIG_GET: if(config_svr->get_callback) { ret = config_svr->get_callback(config_msg->source, cm_set_buff, config_len, cm_get_buff, &buff_len); } break; case CM_CONFIG_GET_ALL: if(config_svr->getall_callback) { ret = config_svr->getall_callback(config_msg->source, cm_get_buff, &buff_len); } break; case CM_CONFIG_ADD: case CM_CONFIG_DEL: case CM_CONFIG_SET: if(config_svr->proc_callback) { ret = config_svr->proc_callback(config_msg->source, config_msg->config_type, cm_set_buff, config_len, cm_get_buff, &buff_len); } break; default: ret = RET_INPUTERR; break; } if(buff_len > CM_BUFF_SIZE) { ret = RET_NOMEM; } if(ret != RET_OK) { cm_return(conn, ret, cm_get_buff); return; } rpc_return(conn, cm_get_buff, buff_len); return; } int main(int argc, char **argv) { rpc_server *server; signal(SIGPIPE,SIG_IGN); if (server= rpc_server_create_ex("ConfigManger#0")) { rpc_log_info("start server\n"); } else { rpc_log_error("start server error\n"); return EXIT_FAILURE; } /* 模块初始化 */ cm_config_module_init(); /* 配置恢复 */ cm_config_recovery(); /* 注册配置处理函数 */ rpc_server_regservice(server, "ConfigManger#0", "cm_config_process", cm_config_process); for(;;) { rpc_sleep(1000); } return EXIT_SUCCESS; }