diff options
| author | Qiuwen Lu <[email protected]> | 2016-12-01 10:22:32 +0800 |
|---|---|---|
| committer | Qiuwen Lu <[email protected]> | 2016-12-01 10:22:32 +0800 |
| commit | a19fa9f23845e4a8ceb40aad480bab917d054f3e (patch) | |
| tree | fddf9743fa401e8ab3ea3a60998898b24537ebd2 | |
| parent | e63d5b8533310a3e3baca7985fe6fb3372caecec (diff) | |
通过JSON输出运行状态监测、统计信息
| -rw-r--r-- | core/include/mr_buffer.h | 6 | ||||
| -rw-r--r-- | core/src/buffer.c | 52 | ||||
| -rw-r--r-- | core/src/stat.c | 34 | ||||
| -rw-r--r-- | service/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | service/include/sc_common.h | 2 | ||||
| -rw-r--r-- | service/src/cJSON.c | 2233 | ||||
| -rw-r--r-- | service/src/cJSON.h | 165 | ||||
| -rw-r--r-- | service/src/config.c | 54 | ||||
| -rw-r--r-- | service/src/core.c | 48 | ||||
| -rw-r--r-- | service/src/monit.c | 107 | ||||
| -rw-r--r-- | service/src/register.c | 43 |
11 files changed, 2672 insertions, 74 deletions
diff --git a/core/include/mr_buffer.h b/core/include/mr_buffer.h index 67a5db5..c15b5da 100644 --- a/core/include/mr_buffer.h +++ b/core/include/mr_buffer.h @@ -28,8 +28,12 @@ int mr_buffer_user_pool_produce(struct mr_core_instance* instance, unsigned int int mr_buffer_pool_produce(struct mr_core_instance* instance, unsigned int socket_id, unsigned int data_size, unsigned int pool_size, unsigned int cache_size); -int mr_buffer_ctrlzone_register(struct mr_core_instance* instance, uint8_t id, uint8_t size); +int mr_buffer_ctrlzone_register(struct mr_core_instance* instance, const char* cz_sym, + uint8_t id, uint8_t size); + +int mr_buffer_ctrlzone_lookup(struct mr_core_instance* instance, const char* cz_sym, + uint8_t * id, uint8_t * size); #ifdef __cplusplus } diff --git a/core/src/buffer.c b/core/src/buffer.c index b197528..e0b0793 100644 --- a/core/src/buffer.c +++ b/core/src/buffer.c @@ -27,11 +27,19 @@ struct mrb_zone_idx_t struct mrb_priv_zone_t { - struct rte_mempool * next; + struct rte_mbuf * next; uint8_t cz_num; struct mrb_zone_idx_t idx[0]; }__rte_packed; +struct mrb_zone_info_t +{ + char symbol[MR_SYMBOL_MAX]; + unsigned int cz_id; + unsigned int size; + unsigned int in_use; +}; + struct whole_mrb_pool_t { struct mrb_pool_t external; //"external" must be the first member of this struct @@ -40,6 +48,7 @@ struct whole_mrb_pool_t unsigned int total_ctrl_zone_size; uint8_t ctrlzone_num; + struct mrb_zone_info_t ctrlzone_info[MRB_MAX_CTRLZONE_NUM]; struct mrb_zone_idx_t ctrlzone[MRB_MAX_CTRLZONE_NUM]; }; @@ -185,28 +194,61 @@ int mr_buffer_pool_produce(struct mr_core_instance* instance, unsigned int socke return i; } -int mr_buffer_ctrlzone_register(struct mr_core_instance* instance, uint8_t id, uint8_t size) +int mr_buffer_ctrlzone_register(struct mr_core_instance* instance, const char* cz_sym, + uint8_t id, uint8_t size) { struct whole_mrb_pool_t *_handle = (struct whole_mrb_pool_t *)instance->mrb_pool_handle; if (_handle->ctrlzone_num >= MRB_MAX_CTRLZONE_NUM) { - return -1; + return -EOVERFLOW; } if (_handle->ctrlzone[id].size != 0) { - return -1; + return -EEXIST; + } + + if(_handle->ctrlzone_info[id].in_use) + { + return -EEXIST; } + snprintf(_handle->ctrlzone_info[id].symbol, sizeof(_handle->ctrlzone_info[id].symbol), "%s", cz_sym); + _handle->ctrlzone_info[id].size = size; + _handle->ctrlzone_info[id].cz_id = id; + _handle->ctrlzone_info[id].in_use = 1; + _handle->ctrlzone[id].size = size; _handle->ctrlzone[id].offset = _handle->total_ctrl_zone_size; _handle->total_ctrl_zone_size += (size + sizeof(struct mrb_zone_idx_t)); _handle->ctrlzone_num++; - return 0; } +int mr_buffer_ctrlzone_lookup(struct mr_core_instance* instance, const char* cz_sym, + uint8_t * id, uint8_t * size) +{ + struct whole_mrb_pool_t *_handle = (struct whole_mrb_pool_t *)instance->mrb_pool_handle; + for(int i = 0; i < _handle->ctrlzone_num; i++) + { + struct mrb_zone_idx_t * cz = &_handle->ctrlzone[i]; + struct mrb_zone_info_t * czinfo = &_handle->ctrlzone_info[i]; + if (strcmp(czinfo->symbol, cz_sym) != 0) continue; + + assert(cz->size != 0); + assert(czinfo->in_use > 0); + assert(czinfo->size > 0); + assert(czinfo->cz_id == i); + + *id = czinfo->cz_id; + *size = czinfo->size; + return 0; + } + + return -1; +} + void * marsio_buff_ctrlzone(marsio_buff_t *mr_buff, uint8_t id) { assert(id < mrbuf_cz_num(mr_buff)); diff --git a/core/src/stat.c b/core/src/stat.c index 72e3d60..f81361d 100644 --- a/core/src/stat.c +++ b/core/src/stat.c @@ -11,27 +11,6 @@ #include <mr_stat.h> #include <mr_core.h> #include <mr_runtime.h> -#include "MESA_prof_load.h" - -#ifndef MR_STAT_OPT_DEFAULT_DEV_STAT_ENABLE -#define MR_STAT_OPT_DEFAULT_DEV_STAT_ENABLE 1 -#endif - -#ifndef MR_STAT_OPT_DEFAULT_VNODE_STAT_ENABLE -#define MR_STAT_OPT_DEFAULT_VNODE_STAT_ENABLE 1 -#endif - -#ifndef MR_STAT_OPT_DEFAULT_PERF_STAT_ENABLE -#define MR_STAT_OPT_DEFAULT_PERF_STAT_ENABLE 1 -#endif - -#ifndef MR_STAT_OPT_DEFAULT_APP_STAT_ENABLE -#define MR_STAT_OPT_DEFAULT_APP_STAT_ENABLE 1 -#endif - -#ifndef MR_STAT_OPT_DEFAULT_EVENT_STAT_ENABLE -#define MR_STAT_OPT_DEFAULT_EVENT_STAT_ENABLE 1 -#endif struct stat_ctx { @@ -92,19 +71,6 @@ int stat_init(struct mr_core_instance * core_instance) int stat_config(struct mr_core_instance * core_instance) { - struct mr_global_config * g_cfg = core_instance->g_cfg; - struct stat_ctx * module_ctx = mr_core_default_instance_get()->stat_ctx; - - MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "device_stat_enable", - &module_ctx->device_stat_enable, MR_STAT_OPT_DEFAULT_DEV_STAT_ENABLE); - MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "vnode_stat_enable", - &module_ctx->vnode_stat_enable, MR_STAT_OPT_DEFAULT_VNODE_STAT_ENABLE); - MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "perf_stat_enable", - &module_ctx->perf_stat_enable, MR_STAT_OPT_DEFAULT_PERF_STAT_ENABLE); - MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "app_stat_enable", - &module_ctx->app_stat_enable, MR_STAT_OPT_DEFAULT_APP_STAT_ENABLE); - MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "event_stat_enable", - &module_ctx->event_stat_enable, MR_STAT_OPT_DEFAULT_EVENT_STAT_ENABLE); return 0; } diff --git a/service/CMakeLists.txt b/service/CMakeLists.txt index 8747c73..b71dd11 100644 --- a/service/CMakeLists.txt +++ b/service/CMakeLists.txt @@ -7,7 +7,7 @@ include_directories(${DPDK_INCLUDE_DIR}) include_directories(include)
add_definitions(${DPDK_C_PREDEFINED})
-add_executable(zcpd src/core.c src/config.c src/register.c src/rxtx.c src/ldbc.c)
+add_executable(zcpd src/cJSON.c src/core.c src/config.c src/register.c src/rxtx.c src/ldbc.c src/monit.c)
target_link_libraries(zcpd ${DPDK_LIBRARY} MESA_prof_load_static)
target_link_libraries(zcpd rt pthread dl core stack)
target_include_directories(zcpd INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include/")
diff --git a/service/include/sc_common.h b/service/include/sc_common.h index d69108b..84963c7 100644 --- a/service/include/sc_common.h +++ b/service/include/sc_common.h @@ -96,6 +96,8 @@ struct sc_instance char local_cfgfile[MR_STRING_MAX]; /* ������־�ļ�λ�� */ char local_logfile[MR_STRING_MAX]; + /* ״̬����ļ� */ + char local_monitfile[MR_STRING_MAX]; /* CPU���룬�����������CPU������ */ cpu_mask_t cpu_mask; /* ���õ��豸�б� */ diff --git a/service/src/cJSON.c b/service/src/cJSON.c new file mode 100644 index 0000000..766e558 --- /dev/null +++ b/service/src/cJSON.c @@ -0,0 +1,2233 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <stdlib.h> +#include <float.h> +#include <limits.h> +#include <ctype.h> +#include "cJSON.h" + +/* Determine the number of bits that an integer has using the preprocessor */ +#if INT_MAX == 32767 + /* 16 bits */ + #define INTEGER_SIZE 0x0010 +#elif INT_MAX == 2147483647 + /* 32 bits */ + #define INTEGER_SIZE 0x0100 +#elif INT_MAX == 9223372036854775807 + /* 64 bits */ + #define INTEGER_SIZE 0x1000 +#else + #error "Failed to determine the size of an integer" +#endif + +/* define our own boolean type */ +typedef int cjbool; +#define true ((cjbool)1) +#define false ((cjbool)0) + +static const char *global_ep = NULL; + +const char *cJSON_GetErrorPtr(void) +{ + return global_ep; +} + +/* case insensitive strcmp */ +static int cJSON_strcasecmp(const char *s1, const char *s2) +{ + if (!s1) + { + return (s1 == s2) ? 0 : 1; /* both NULL? */ + } + if (!s2) + { + return 1; + } + for(; tolower(*(const unsigned char *)s1) == tolower(*(const unsigned char *)s2); ++s1, ++s2) + { + if (*s1 == '\0') + { + return 0; + } + } + + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; + +static char* cJSON_strdup(const char* str) +{ + size_t len = 0; + char *copy = NULL; + + len = strlen(str) + 1; + if (!(copy = (char*)cJSON_malloc(len))) + { + return NULL; + } + memcpy(copy, str, len); + + return copy; +} + +void cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) + { + /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc; + cJSON_free = (hooks->free_fn) ? hooks->free_fn : free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(void) +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +void cJSON_Delete(cJSON *c) +{ + cJSON *next = NULL; + while (c) + { + next = c->next; + if (!(c->type & cJSON_IsReference) && c->child) + { + cJSON_Delete(c->child); + } + if (!(c->type & cJSON_IsReference) && c->valuestring) + { + cJSON_free(c->valuestring); + } + if (!(c->type & cJSON_StringIsConst) && c->string) + { + cJSON_free(c->string); + } + cJSON_free(c); + c = next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item, const char *num) +{ + double n = 0; + double sign = 1; + double scale = 0; + int subscale = 0; + int signsubscale = 1; + + /* Has sign? */ + if (*num == '-') + { + sign = -1; + num++; + } + /* is zero */ + if (*num == '0') + { + num++; + } + /* Number? */ + if ((*num >= '1') && (*num <= '9')) + { + do + { + n = (n * 10.0) + (*num++ - '0'); + } + while ((*num >= '0') && (*num<='9')); + } + /* Fractional part? */ + if ((*num == '.') && (num[1] >= '0') && (num[1] <= '9')) + { + num++; + do + { + n = (n *10.0) + (*num++ - '0'); + scale--; + } while ((*num >= '0') && (*num <= '9')); + } + /* Exponent? */ + if ((*num == 'e') || (*num == 'E')) + { + num++; + /* With sign? */ + if (*num == '+') + { + num++; + } + else if (*num == '-') + { + signsubscale = -1; + num++; + } + /* Number? */ + while ((*num>='0') && (*num<='9')) + { + subscale = (subscale * 10) + (*num++ - '0'); + } + } + + /* number = +/- number.fraction * 10^+/- exponent */ + n = sign * n * pow(10.0, (scale + subscale * signsubscale)); + + item->valuedouble = n; + item->valueint = (int)n; + item->type = cJSON_Number; + + return num; +} + +/* calculate the next largest power of 2 */ +static int pow2gt (int x) +{ + --x; + + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; +#if INTEGER_SIZE & 0x1110 /* at least 16 bit */ + x |= x >> 8; +#endif +#if INTEGER_SIZE & 0x1100 /* at least 32 bit */ + x |= x >> 16; +#endif +#if INT_SIZE & 0x1000 /* 64 bit */ + x |= x >> 32; +#endif + + return x + 1; +} + +typedef struct +{ + char *buffer; + int length; + int offset; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static char* ensure(printbuffer *p, int needed) +{ + char *newbuffer = NULL; + int newsize = 0; + if (!p || !p->buffer) + { + return NULL; + } + needed += p->offset; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + newsize = pow2gt(needed); + newbuffer = (char*)cJSON_malloc(newsize); + if (!newbuffer) + { + cJSON_free(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + if (newbuffer) + { + memcpy(newbuffer, p->buffer, p->length); + } + cJSON_free(p->buffer); + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer */ +static int update(const printbuffer *p) +{ + char *str = NULL; + if (!p || !p->buffer) + { + return 0; + } + str = p->buffer + p->offset; + + return p->offset + strlen(str); +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(const cJSON *item, printbuffer *p) +{ + char *str = NULL; + double d = item->valuedouble; + /* special case for 0. */ + if (d == 0) + { + if (p) + { + str = ensure(p, 2); + } + else + { + str = (char*)cJSON_malloc(2); + } + if (str) + { + strcpy(str,"0"); + } + } + /* value is an int */ + else if ((fabs(((double)item->valueint) - d) <= DBL_EPSILON) && (d <= INT_MAX) && (d >= INT_MIN)) + { + if (p) + { + str = ensure(p, 21); + } + else + { + /* 2^64+1 can be represented in 21 chars. */ + str = (char*)cJSON_malloc(21); + } + if (str) + { + sprintf(str, "%d", item->valueint); + } + } + /* value is a floating point number */ + else + { + if (p) + { + /* This is a nice tradeoff. */ + str = ensure(p, 64); + } + else + { + /* This is a nice tradeoff. */ + str=(char*)cJSON_malloc(64); + } + if (str) + { + /* This checks for NaN and Infinity */ + if ((d * 0) != 0) + { + sprintf(str, "null"); + } + else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60)) + { + sprintf(str, "%.0f", d); + } + else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9)) + { + sprintf(str, "%e", d); + } + else + { + sprintf(str, "%f", d); + } + } + } + return str; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const char *str) +{ + unsigned h = 0; + /* first digit */ + if ((*str >= '0') && (*str <= '9')) + { + h += (*str) - '0'; + } + else if ((*str >= 'A') && (*str <= 'F')) + { + h += 10 + (*str) - 'A'; + } + else if ((*str >= 'a') && (*str <= 'f')) + { + h += 10 + (*str) - 'a'; + } + else /* invalid */ + { + return 0; + } + + + /* second digit */ + h = h << 4; + str++; + if ((*str >= '0') && (*str <= '9')) + { + h += (*str) - '0'; + } + else if ((*str >= 'A') && (*str <= 'F')) + { + h += 10 + (*str) - 'A'; + } + else if ((*str >= 'a') && (*str <= 'f')) + { + h += 10 + (*str) - 'a'; + } + else /* invalid */ + { + return 0; + } + + /* third digit */ + h = h << 4; + str++; + if ((*str >= '0') && (*str <= '9')) + { + h += (*str) - '0'; + } + else if ((*str >= 'A') && (*str <= 'F')) + { + h += 10 + (*str) - 'A'; + } + else if ((*str >= 'a') && (*str <= 'f')) + { + h += 10 + (*str) - 'a'; + } + else /* invalid */ + { + return 0; + } + + /* fourth digit */ + h = h << 4; + str++; + if ((*str >= '0') && (*str <= '9')) + { + h += (*str) - '0'; + } + else if ((*str >= 'A') && (*str <= 'F')) + { + h += 10 + (*str) - 'A'; + } + else if ((*str >= 'a') && (*str <= 'f')) + { + h += 10 + (*str) - 'a'; + } + else /* invalid */ + { + return 0; + } + + return h; +} + +/* first bytes of UTF8 encoding for a given length in bytes */ +static const unsigned char firstByteMark[7] = +{ + 0x00, /* should never happen */ + 0x00, /* 0xxxxxxx */ + 0xC0, /* 110xxxxx */ + 0xE0, /* 1110xxxx */ + 0xF0, /* 11110xxx */ + 0xF8, + 0xFC +}; + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const char *parse_string(cJSON *item, const char *str, const char **ep) +{ + const char *ptr = str + 1; + const char *end_ptr =str + 1; + char *ptr2 = NULL; + char *out = NULL; + int len = 0; + unsigned uc = 0; + unsigned uc2 = 0; + + /* not a string! */ + if (*str != '\"') + { + *ep = str; + return NULL; + } + + while ((*end_ptr != '\"') && *end_ptr && ++len) + { + if (*end_ptr++ == '\\') + { + if (*end_ptr == '\0') + { + /* prevent buffer overflow when last input character is a backslash */ + return NULL; + } + /* Skip escaped quotes. */ + end_ptr++; + } + } + + /* This is at most how long we need for the string, roughly. */ + out = (char*)cJSON_malloc(len + 1); + if (!out) + { + return NULL; + } + item->valuestring = out; /* assign here so out will be deleted during cJSON_Delete() later */ + item->type = cJSON_String; + + ptr = str + 1; + ptr2 = out; + /* loop through the string literal */ + while (ptr < end_ptr) + { + if (*ptr != '\\') + { + *ptr2++ = *ptr++; + } + /* escape sequence */ + else + { + ptr++; + switch (*ptr) + { + case 'b': + *ptr2++ = '\b'; + break; + case 'f': + *ptr2++ = '\f'; + break; + case 'n': + *ptr2++ = '\n'; + break; + case 'r': + *ptr2++ = '\r'; + break; + case 't': + *ptr2++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *ptr2++ = *ptr; + break; + case 'u': + /* transcode utf16 to utf8. See RFC2781 and RFC3629. */ + uc = parse_hex4(ptr + 1); /* get the unicode char. */ + ptr += 4; + if (ptr >= end_ptr) + { + /* invalid */ + *ep = str; + return NULL; + } + /* check for invalid. */ + if (((uc >= 0xDC00) && (uc <= 0xDFFF)) || (uc == 0)) + { + *ep = str; + return NULL; + } + + /* UTF16 surrogate pairs. */ + if ((uc >= 0xD800) && (uc<=0xDBFF)) + { + if ((ptr + 6) > end_ptr) + { + /* invalid */ + *ep = str; + return NULL; + } + if ((ptr[1] != '\\') || (ptr[2] != 'u')) + { + /* missing second-half of surrogate. */ + *ep = str; + return NULL; + } + uc2 = parse_hex4(ptr + 3); + ptr += 6; /* \uXXXX */ + if ((uc2 < 0xDC00) || (uc2 > 0xDFFF)) + { + /* invalid second-half of surrogate. */ + *ep = str; + return NULL; + } + /* calculate unicode codepoint from the surrogate pair */ + uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF)); + } + + /* encode as UTF8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + len = 4; + if (uc < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + len = 1; + } + else if (uc < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + len = 2; + } + else if (uc < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + len = 3; + } + ptr2 += len; + + switch (len) { + case 4: + /* 10xxxxxx */ + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + case 3: + /* 10xxxxxx */ + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + case 2: + /* 10xxxxxx */ + *--ptr2 = ((uc | 0x80) & 0xBF); + uc >>= 6; + case 1: + /* depending on the length in bytes this determines the + * encoding ofthe first UTF8 byte */ + *--ptr2 = (uc | firstByteMark[len]); + } + ptr2 += len; + break; + default: + *ep = str; + return NULL; + } + ptr++; + } + } + *ptr2 = '\0'; + if (*ptr == '\"') + { + ptr++; + } + + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str, printbuffer *p) +{ + const char *ptr = NULL; + char *ptr2 = NULL; + char *out = NULL; + int len = 0; + cjbool flag = false; + unsigned char token = '\0'; + + /* empty string */ + if (!str) + { + if (p) + { + out = ensure(p, 3); + } + else + { + out = (char*)cJSON_malloc(3); + } + if (!out) + { + return NULL; + } + strcpy(out, "\"\""); + + return out; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (ptr = str; *ptr; ptr++) + { + flag |= (((*ptr > 0) && (*ptr < 32)) /* unprintable characters */ + || (*ptr == '\"') /* double quote */ + || (*ptr == '\\')) /* backslash */ + ? 1 + : 0; + } + /* no characters have to be escaped */ + if (!flag) + { + len = ptr - str; + if (p) + { + out = ensure(p, len + 3); + } + else + { + out = (char*)cJSON_malloc(len + 3); + } + if (!out) + { + return NULL; + } + + ptr2 = out; + *ptr2++ = '\"'; + strcpy(ptr2, str); + ptr2[len] = '\"'; + ptr2[len + 1] = '\0'; + + return out; + } + + ptr = str; + /* calculate additional space that is needed for escaping */ + while ((token = *ptr) && ++len) + { + if (strchr("\"\\\b\f\n\r\t", token)) + { + len++; /* +1 for the backslash */ + } + else if (token < 32) + { + len += 5; /* +5 for \uXXXX */ + } + ptr++; + } + + if (p) + { + out = ensure(p, len + 3); + } + else + { + out = (char*)cJSON_malloc(len + 3); + } + if (!out) + { + return NULL; + } + + ptr2 = out; + ptr = str; + *ptr2++ = '\"'; + /* copy the string */ + while (*ptr) + { + if (((unsigned char)*ptr > 31) && (*ptr != '\"') && (*ptr != '\\')) + { + /* normal character, copy */ + *ptr2++ = *ptr++; + } + else + { + /* character needs to be escaped */ + *ptr2++ = '\\'; + switch (token = *ptr++) + { + case '\\': + *ptr2++ = '\\'; + break; + case '\"': + *ptr2++ = '\"'; + break; + case '\b': + *ptr2++ = 'b'; + break; + case '\f': + *ptr2++ = 'f'; + break; + case '\n': + *ptr2++ = 'n'; + break; + case '\r': + *ptr2++ = 'r'; + break; + case '\t': + *ptr2++ = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf(ptr2, "u%04x", token); + ptr2 += 5; + break; + } + } + } + *ptr2++ = '\"'; + *ptr2++ = '\0'; + + return out; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static char *print_string(const cJSON *item, printbuffer *p) +{ + return print_string_ptr(item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item, const char *value, const char **ep); +static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *p); +static const char *parse_array(cJSON *item, const char *value, const char **ep); +static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *p); +static const char *parse_object(cJSON *item, const char *value, const char **ep); +static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *p); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) +{ + while (in && *in && ((unsigned char)*in<=32)) + { + in++; + } + + return in; +} + +/* Parse an object - create a new root, and populate. */ +cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cjbool require_null_terminated) +{ + const char *end = NULL; + /* use global error pointer if no specific one was given */ + const char **ep = return_parse_end ? return_parse_end : &global_ep; + cJSON *c = cJSON_New_Item(); + *ep = NULL; + if (!c) /* memory fail */ + { + return NULL; + } + + end = parse_value(c, skip(value), ep); + if (!end) + { + /* parse failure. ep is set. */ + cJSON_Delete(c); + return NULL; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + end = skip(end); + if (*end) + { + cJSON_Delete(c); + *ep = end; + return NULL; + } + } + if (return_parse_end) + { + *return_parse_end = end; + } + + return c; +} + +/* Default options for cJSON_Parse */ +cJSON *cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +/* Render a cJSON item/entity/structure to text. */ +char *cJSON_Print(const cJSON *item) +{ + return print_value(item, 0, 1, 0); +} + +char *cJSON_PrintUnformatted(const cJSON *item) +{ + return print_value(item, 0, 0, 0); +} + +char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt) +{ + printbuffer p; + p.buffer = (char*)cJSON_malloc(prebuffer); + if (!p.buffer) + { + return NULL; + } + p.length = prebuffer; + p.offset = 0; + + return print_value(item, 0, fmt, &p); +} + + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item, const char *value, const char **ep) +{ + if (!value) + { + /* Fail on null. */ + return NULL; + } + + /* parse the different types of values */ + if (!strncmp(value, "null", 4)) + { + item->type = cJSON_NULL; + return value + 4; + } + if (!strncmp(value, "false", 5)) + { + item->type = cJSON_False; + return value + 5; + } + if (!strncmp(value, "true", 4)) + { + item->type = cJSON_True; + item->valueint = 1; + return value + 4; + } + if (*value == '\"') + { + return parse_string(item, value, ep); + } + if ((*value == '-') || ((*value >= '0') && (*value <= '9'))) + { + return parse_number(item, value); + } + if (*value == '[') + { + return parse_array(item, value, ep); + } + if (*value == '{') + { + return parse_object(item, value, ep); + } + + /* failure. */ + *ep = value; + return NULL; +} + +/* Render a value to text. */ +static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *p) +{ + char *out = NULL; + + if (!item) + { + return NULL; + } + if (p) + { + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + out = ensure(p, 5); + if (out) + { + strcpy(out, "null"); + } + break; + case cJSON_False: + out = ensure(p, 6); + if (out) + { + strcpy(out, "false"); + } + break; + case cJSON_True: + out = ensure(p, 5); + if (out) + { + strcpy(out, "true"); + } + break; + case cJSON_Number: + out = print_number(item, p); + break; + case cJSON_String: + out = print_string(item, p); + break; + case cJSON_Array: + out = print_array(item, depth, fmt, p); + break; + case cJSON_Object: + out = print_object(item, depth, fmt, p); + break; + } + } + else + { + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + out = cJSON_strdup("null"); + break; + case cJSON_False: + out = cJSON_strdup("false"); + break; + case cJSON_True: + out = cJSON_strdup("true"); + break; + case cJSON_Number: + out = print_number(item, 0); + break; + case cJSON_String: + out = print_string(item, 0); + break; + case cJSON_Array: + out = print_array(item, depth, fmt, 0); + break; + case cJSON_Object: + out = print_object(item, depth, fmt, 0); + break; + } + } + + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value,const char **ep) +{ + cJSON *child = NULL; + if (*value != '[') + { + /* not an array! */ + *ep = value; + return NULL; + } + + item->type = cJSON_Array; + value = skip(value + 1); + if (*value == ']') + { + /* empty array. */ + return value + 1; + } + + item->child = child = cJSON_New_Item(); + if (!item->child) + { + /* memory fail */ + return NULL; + } + /* skip any spacing, get the value. */ + value = skip(parse_value(child, skip(value), ep)); + if (!value) + { + return NULL; + } + + /* loop through the comma separated array elements */ + while (*value == ',') + { + cJSON *new_item = NULL; + if (!(new_item = cJSON_New_Item())) + { + /* memory fail */ + return NULL; + } + /* add new item to end of the linked list */ + child->next = new_item; + new_item->prev = child; + child = new_item; + + /* go to the next comma */ + value = skip(parse_value(child, skip(value + 1), ep)); + if (!value) + { + /* memory fail */ + return NULL; + } + } + + if (*value == ']') + { + /* end of array */ + return value + 1; + } + + /* malformed. */ + *ep = value; + + return NULL; +} + +/* Render an array to text */ +static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *p) +{ + char **entries; + char *out = NULL; + char *ptr = NULL; + char *ret = NULL; + int len = 5; + cJSON *child = item->child; + int numentries = 0; + int i = 0; + cjbool fail = false; + size_t tmplen = 0; + + /* How many entries in the array? */ + while (child) + { + numentries++; + child = child->next; + } + + /* Explicitly handle numentries == 0 */ + if (!numentries) + { + if (p) + { + out = ensure(p, 3); + } + else + { + out = (char*)cJSON_malloc(3); + } + if (out) + { + strcpy(out,"[]"); + } + + return out; + } + + if (p) + { + /* Compose the output array. */ + /* opening square bracket */ + i = p->offset; + ptr = ensure(p, 1); + if (!ptr) + { + return NULL; + } + *ptr = '['; + p->offset++; + + child = item->child; + while (child && !fail) + { + print_value(child, depth + 1, fmt, p); + p->offset = update(p); + if (child->next) + { + len = fmt ? 2 : 1; + ptr = ensure(p, len + 1); + if (!ptr) + { + return NULL; + } + *ptr++ = ','; + if(fmt) + { + *ptr++ = ' '; + } + *ptr = '\0'; + p->offset += len; + } + child = child->next; + } + ptr = ensure(p, 2); + if (!ptr) + { + return NULL; + } + *ptr++ = ']'; + *ptr = '\0'; + out = (p->buffer) + i; + } + else + { + /* Allocate an array to hold the pointers to all printed values */ + entries = (char**)cJSON_malloc(numentries * sizeof(char*)); + if (!entries) + { + return NULL; + } + memset(entries, '\0', numentries * sizeof(char*)); + + /* Retrieve all the results: */ + child = item->child; + while (child && !fail) + { + ret = print_value(child, depth + 1, fmt, 0); + entries[i++] = ret; + if (ret) + { + len += strlen(ret) + 2 + (fmt ? 1 : 0); + } + else + { + fail = true; + } + child = child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) + { + out = (char*)cJSON_malloc(len); + } + /* If that fails, we fail. */ + if (!out) + { + fail = true; + } + + /* Handle failure. */ + if (fail) + { + /* free all the entries in the array */ + for (i = 0; i < numentries; i++) + { + if (entries[i]) + { + cJSON_free(entries[i]); + } + } + cJSON_free(entries); + return NULL; + } + + /* Compose the output array. */ + *out='['; + ptr = out + 1; + *ptr = '\0'; + for (i = 0; i < numentries; i++) + { + tmplen = strlen(entries[i]); + memcpy(ptr, entries[i], tmplen); + ptr += tmplen; + if (i != (numentries - 1)) + { + *ptr++ = ','; + if(fmt) + { + *ptr++ = ' '; + } + *ptr = '\0'; + } + cJSON_free(entries[i]); + } + cJSON_free(entries); + *ptr++ = ']'; + *ptr++ = '\0'; + } + + return out; +} + +/* Build an object from the text. */ +static const char *parse_object(cJSON *item, const char *value, const char **ep) +{ + cJSON *child = NULL; + if (*value != '{') + { + /* not an object! */ + *ep = value; + return NULL; + } + + item->type = cJSON_Object; + value = skip(value + 1); + if (*value == '}') + { + /* empty object. */ + return value + 1; + } + + child = cJSON_New_Item(); + item->child = child; + if (!item->child) + { + return NULL; + } + /* parse first key */ + value = skip(parse_string(child, skip(value), ep)); + if (!value) + { + return NULL; + } + /* use string as key, not value */ + child->string = child->valuestring; + child->valuestring = NULL; + + if (*value != ':') + { + /* invalid object. */ + *ep = value; + return NULL; + } + /* skip any spacing, get the value. */ + value = skip(parse_value(child, skip(value + 1), ep)); + if (!value) + { + return NULL; + } + + while (*value == ',') + { + cJSON *new_item = NULL; + if (!(new_item = cJSON_New_Item())) + { + /* memory fail */ + return NULL; + } + /* add to linked list */ + child->next = new_item; + new_item->prev = child; + + child = new_item; + value = skip(parse_string(child, skip(value + 1), ep)); + if (!value) + { + return NULL; + } + + /* use string as key, not value */ + child->string = child->valuestring; + child->valuestring = NULL; + + if (*value != ':') + { + /* invalid object. */ + *ep = value; + return NULL; + } + /* skip any spacing, get the value. */ + value = skip(parse_value(child, skip(value + 1), ep)); + if (!value) + { + return NULL; + } + } + /* end of object */ + if (*value == '}') + { + return value + 1; + } + + /* malformed */ + *ep = value; + return NULL; +} + +/* Render an object to text. */ +static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *p) +{ + char **entries = NULL; + char **names = NULL; + char *out = NULL; + char *ptr = NULL; + char *ret = NULL; + char *str = NULL; + int len = 7; + int i = 0; + int j = 0; + cJSON *child = item->child; + int numentries = 0; + cjbool fail = false; + size_t tmplen = 0; + + /* Count the number of entries. */ + while (child) + { + numentries++; + child = child->next; + } + + /* Explicitly handle empty object case */ + if (!numentries) + { + if (p) + { + out = ensure(p, fmt ? depth + 4 : 3); + } + else + { + out = (char*)cJSON_malloc(fmt ? depth + 4 : 3); + } + if (!out) + { + return NULL; + } + ptr = out; + *ptr++ = '{'; + if (fmt) { + *ptr++ = '\n'; + for (i = 0; i < depth; i++) + { + *ptr++ = '\t'; + } + } + *ptr++ = '}'; + *ptr++ = '\0'; + + return out; + } + + if (p) + { + /* Compose the output: */ + i = p->offset; + len = fmt ? 2 : 1; /* fmt: {\n */ + ptr = ensure(p, len + 1); + if (!ptr) + { + return NULL; + } + + *ptr++ = '{'; + if (fmt) + { + *ptr++ = '\n'; + } + *ptr = '\0'; + p->offset += len; + + child = item->child; + depth++; + while (child) + { + if (fmt) + { + ptr = ensure(p, depth); + if (!ptr) + { + return NULL; + } + for (j = 0; j < depth; j++) + { + *ptr++ = '\t'; + } + p->offset += depth; + } + + /* print key */ + print_string_ptr(child->string, p); + p->offset = update(p); + + len = fmt ? 2 : 1; + ptr = ensure(p, len); + if (!ptr) + { + return NULL; + } + *ptr++ = ':'; + if (fmt) + { + *ptr++ = '\t'; + } + p->offset+=len; + + /* print value */ + print_value(child, depth, fmt, p); + p->offset = update(p); + + /* print comma if not last */ + len = (fmt ? 1 : 0) + (child->next ? 1 : 0); + ptr = ensure(p, len + 1); + if (!ptr) + { + return NULL; + } + if (child->next) + { + *ptr++ = ','; + } + + if (fmt) + { + *ptr++ = '\n'; + } + *ptr = '\0'; + p->offset += len; + + child = child->next; + } + + ptr = ensure(p, fmt ? (depth + 1) : 2); + if (!ptr) + { + return NULL; + } + if (fmt) + { + for (i = 0; i < (depth - 1); i++) + { + *ptr++ = '\t'; + } + } + *ptr++ = '}'; + *ptr = '\0'; + out = (p->buffer) + i; + } + else + { + /* Allocate space for the names and the objects */ + entries = (char**)cJSON_malloc(numentries * sizeof(char*)); + if (!entries) + { + return NULL; + } + names = (char**)cJSON_malloc(numentries * sizeof(char*)); + if (!names) + { + cJSON_free(entries); + return NULL; + } + memset(entries, '\0', sizeof(char*) * numentries); + memset(names, '\0', sizeof(char*) * numentries); + + /* Collect all the results into our arrays: */ + child = item->child; + depth++; + if (fmt) + { + len += depth; + } + while (child && !fail) + { + names[i] = str = print_string_ptr(child->string, 0); /* print key */ + entries[i++] = ret = print_value(child, depth, fmt, 0); + if (str && ret) + { + len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0); + } + else + { + fail = true; + } + child = child->next; + } + + /* Try to allocate the output string */ + if (!fail) + { + out = (char*)cJSON_malloc(len); + } + if (!out) + { + fail = true; + } + + /* Handle failure */ + if (fail) + { + /* free all the printed keys and values */ + for (i = 0; i < numentries; i++) + { + if (names[i]) + { + cJSON_free(names[i]); + } + if (entries[i]) + { + cJSON_free(entries[i]); + } + } + cJSON_free(names); + cJSON_free(entries); + return NULL; + } + + /* Compose the output: */ + *out = '{'; + ptr = out + 1; + if (fmt) + { + *ptr++ = '\n'; + } + *ptr = '\0'; + for (i = 0; i < numentries; i++) + { + if (fmt) + { + for (j = 0; j < depth; j++) + { + *ptr++='\t'; + } + } + tmplen = strlen(names[i]); + memcpy(ptr, names[i], tmplen); + ptr += tmplen; + *ptr++ = ':'; + if (fmt) + { + *ptr++ = '\t'; + } + strcpy(ptr, entries[i]); + ptr += strlen(entries[i]); + if (i != (numentries - 1)) + { + *ptr++ = ','; + } + if (fmt) + { + *ptr++ = '\n'; + } + *ptr = '\0'; + cJSON_free(names[i]); + cJSON_free(entries[i]); + } + + cJSON_free(names); + cJSON_free(entries); + if (fmt) + { + for (i = 0; i < (depth - 1); i++) + { + *ptr++ = '\t'; + } + } + *ptr++ = '}'; + *ptr++ = '\0'; + } + + return out; +} + +/* Get Array size/item / object item. */ +int cJSON_GetArraySize(const cJSON *array) +{ + cJSON *c = array->child; + int i = 0; + while(c) + { + i++; + c = c->next; + } + return i; +} + +cJSON *cJSON_GetArrayItem(const cJSON *array, int item) +{ + cJSON *c = array ? array->child : NULL; + while (c && item > 0) + { + item--; + c = c->next; + } + + return c; +} + +cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string) +{ + cJSON *c = object ? object->child : NULL; + while (c && cJSON_strcasecmp(c->string, string)) + { + c = c->next; + } + return c; +} + +cjbool cJSON_HasObjectItem(const cJSON *object,const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item) +{ + cJSON *ref = cJSON_New_Item(); + if (!ref) + { + return NULL; + } + memcpy(ref, item, sizeof(cJSON)); + ref->string = NULL; + ref->type |= cJSON_IsReference; + ref->next = ref->prev = NULL; + return ref; +} + +/* Add item to array/object. */ +void cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + cJSON *c = array->child; + if (!item) + { + return; + } + if (!c) + { + /* list is empty, start new one */ + array->child = item; + } + else + { + /* append to the end */ + while (c->next) + { + c = c->next; + } + suffix_object(c, item); + } +} + +void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + if (!item) + { + return; + } + + /* free old key and set new one */ + if (item->string) + { + cJSON_free(item->string); + } + item->string = cJSON_strdup(string); + + cJSON_AddItemToArray(object,item); +} + +/* Add an item to an object with constant string as key */ +void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + if (!item) + { + return; + } + if (!(item->type & cJSON_StringIsConst) && item->string) + { + cJSON_free(item->string); + } + item->string = (char*)string; + item->type |= cJSON_StringIsConst; + cJSON_AddItemToArray(object, item); +} + +void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + cJSON_AddItemToArray(array, create_reference(item)); +} + +void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + cJSON_AddItemToObject(object, string, create_reference(item)); +} + +cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) +{ + cJSON *c = array->child; + while (c && (which > 0)) + { + c = c->next; + which--; + } + if (!c) + { + /* item doesn't exist */ + return NULL; + } + if (c->prev) + { + /* not the first element */ + c->prev->next = c->next; + } + if (c->next) + { + c->next->prev = c->prev; + } + if (c==array->child) + { + array->child = c->next; + } + /* make sure the detached item doesn't point anywhere anymore */ + c->prev = c->next = NULL; + + return c; +} + +void cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + int i = 0; + cJSON *c = object->child; + while (c && cJSON_strcasecmp(c->string,string)) + { + i++; + c = c->next; + } + if (c) + { + return cJSON_DetachItemFromArray(object, i); + } + + return NULL; +} + +void cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +/* Replace array/object items with new ones. */ +void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *c = array->child; + while (c && (which > 0)) + { + c = c->next; + which--; + } + if (!c) + { + cJSON_AddItemToArray(array, newitem); + return; + } + newitem->next = c; + newitem->prev = c->prev; + c->prev = newitem; + if (c == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } +} + +void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *c = array->child; + while (c && (which > 0)) + { + c = c->next; + which--; + } + if (!c) + { + return; + } + newitem->next = c->next; + newitem->prev = c->prev; + if (newitem->next) + { + newitem->next->prev = newitem; + } + if (c == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } + c->next = c->prev = NULL; + cJSON_Delete(c); +} + +void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + int i = 0; + cJSON *c = object->child; + while(c && cJSON_strcasecmp(c->string, string)) + { + i++; + c = c->next; + } + if(c) + { + /* free the old string if not const */ + if (!(newitem->type & cJSON_StringIsConst) && newitem->string) + { + cJSON_free(newitem->string); + } + + newitem->string = cJSON_strdup(string); + cJSON_ReplaceItemInArray(object, i, newitem); + } +} + +/* Create basic types: */ +cJSON *cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +cJSON *cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(); + if(item) + { + item->type = cJSON_True; + } + + return item; +} + +cJSON *cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(); + if(item) + { + item->type = cJSON_False; + } + + return item; +} + +cJSON *cJSON_CreateBool(cjbool b) +{ + cJSON *item = cJSON_New_Item(); + if(item) + { + item->type = b ? cJSON_True : cJSON_False; + } + + return item; +} + +cJSON *cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(); + if(item) + { + item->type = cJSON_Number; + item->valuedouble = num; + item->valueint = (int)num; + } + + return item; +} + +cJSON *cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(); + if(item) + { + item->type = cJSON_String; + item->valuestring = cJSON_strdup(string); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +cJSON *cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +cJSON *cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +cJSON *cJSON_CreateIntArray(const int *numbers, int count) +{ + int i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = cJSON_CreateArray(); + for(i = 0; a && (i < count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if (!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +cJSON *cJSON_CreateFloatArray(const float *numbers, int count) +{ + int i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = cJSON_CreateArray(); + for(i = 0; a && (i < count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +cJSON *cJSON_CreateDoubleArray(const double *numbers, int count) +{ + int i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = cJSON_CreateArray(); + for(i = 0;a && (i < count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +cJSON *cJSON_CreateStringArray(const char **strings, int count) +{ + int i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = cJSON_CreateArray(); + for (i = 0; a && (i < count); i++) + { + n = cJSON_CreateString(strings[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p,n); + } + p = n; + } + + return a; +} + +/* Duplication */ +cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse) +{ + cJSON *newitem = NULL; + cJSON *cptr = NULL; + cJSON *nptr = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + return NULL; + } + /* Create new item */ + newitem = cJSON_New_Item(); + if (!newitem) + { + return NULL; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) + { + newitem->valuestring = cJSON_strdup(item->valuestring); + if (!newitem->valuestring) + { + cJSON_Delete(newitem); + return NULL; + } + } + if (item->string) + { + newitem->string = cJSON_strdup(item->string); + if (!newitem->string) + { + cJSON_Delete(newitem); + return NULL; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + cptr = item->child; + while (cptr) + { + newchild = cJSON_Duplicate(cptr, 1); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + cJSON_Delete(newitem); + return NULL; + } + if (nptr) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + nptr->next = newchild; + newchild->prev = nptr; + nptr = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; nptr = newchild; + } + cptr = cptr->next; + } + + return newitem; +} + +void cJSON_Minify(char *json) +{ + char *into = json; + while (*json) + { + if (*json == ' ') + { + json++; + } + else if (*json == '\t') + { + /* Whitespace characters. */ + json++; + } + else if (*json == '\r') + { + json++; + } + else if (*json=='\n') + { + json++; + } + else if ((*json == '/') && (json[1] == '/')) + { + /* double-slash comments, to end of line. */ + while (*json && (*json != '\n')) + { + json++; + } + } + else if ((*json == '/') && (json[1] == '*')) + { + /* multiline comments. */ + while (*json && !((*json == '*') && (json[1] == '/'))) + { + json++; + } + json += 2; + } + else if (*json == '\"') + { + /* string literals, which are \" sensitive. */ + *into++ = *json++; + while (*json && (*json != '\"')) + { + if (*json == '\\') + { + *into++=*json++; + } + *into++ = *json++; + } + *into++ = *json++; + } + else + { + /* All other characters. */ + *into++ = *json++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} diff --git a/service/src/cJSON.h b/service/src/cJSON.h new file mode 100644 index 0000000..dbbb739 --- /dev/null +++ b/service/src/cJSON.h @@ -0,0 +1,165 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stddef.h> + +/* cJSON Types: */ +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String */ + char *valuestring; + /* The item's number, if type==cJSON_Number */ + int valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +extern char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, int fmt); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(const cJSON *array, int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string); +extern int cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(void); +extern cJSON *cJSON_CreateTrue(void); +extern cJSON *cJSON_CreateFalse(void); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(void); +extern cJSON *cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(const int *numbers, int count); +extern cJSON *cJSON_CreateFloatArray(const float *numbers, int count); +extern cJSON *cJSON_CreateDoubleArray(const double *numbers, int count); +extern cJSON *cJSON_CreateStringArray(const char **strings, int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +extern void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which); +extern void cJSON_DeleteItemFromArray(cJSON *array, int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string); + +/* Update array items. */ +extern void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +extern cJSON *cJSON_Duplicate(const cJSON *item, int recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ + +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */ +extern cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated); + +extern void cJSON_Minify(char *json); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val)) +#define cJSON_SetNumberValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val)) + +/* Macro for iterating over an array */ +#define cJSON_ArrayForEach(pos, head) for(pos = (head)->child; pos != NULL; pos = pos->next) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/service/src/config.c b/service/src/config.c index b404f04..2324f46 100644 --- a/service/src/config.c +++ b/service/src/config.c @@ -13,6 +13,7 @@ #include <mr_mask.h> #include <mr_runtime.h> #include <arpa/inet.h> +#include "mr_buffer.h" #ifndef MR_SERVICE_DEFAULT_SZ_BUFFER #define MR_SERVICE_DEFAULT_SZ_BUFFER 32 @@ -91,6 +92,55 @@ static int __parser_str_core(char * str_core, int sz_buffer, return 0; } + +void __ctrlzone_list_join(struct sc_instance * instance, const char * ctrlzone, + unsigned int ctrlzone_id, unsigned int sz_ctrlzone) +{ + struct sc_ctrlzone * sc_ctrlzone = rte_zmalloc(NULL, sizeof(sc_ctrlzone), 0); + MR_CHECK(sc_ctrlzone != NULL, "Cannot alloc memory for sc_ctrlzone"); + + snprintf(sc_ctrlzone->symbol, sizeof(sc_ctrlzone->symbol), "%s", ctrlzone); + sc_ctrlzone->id = ctrlzone_id; + sc_ctrlzone->size = sz_ctrlzone; + + TAILQ_INSERT_TAIL(&instance->ctrlzone_list, sc_ctrlzone, next); + return; +} + +int sc_config_ctrlzone(const char * cfg, struct sc_instance * instance) +{ + char str_ctrlzone_key[MR_SYMBOL_MAX]; + char str_ctrlzone_info[MR_STRING_MAX]; + char str_ctrlzone_name[MR_STRING_MAX]; + int sz_ctrlzone = 0; + int ret = 0; + + for(int ctrlzone_id = 0; ctrlzone_id < MRB_MAX_CTRLZONE_NUM; ctrlzone_id++) + { + snprintf(str_ctrlzone_key, sizeof(str_ctrlzone_key), "ctrlzone%d", ctrlzone_id); + ret = MESA_load_profile_string_nodef(cfg, "ctrlzone", str_ctrlzone_key, + str_ctrlzone_info, sizeof(str_ctrlzone_info)); + if (ret < 0) continue; + + char * tokens[MR_TOKENS_MAX]; + ret = rte_strsplit(str_ctrlzone_info, sizeof(str_ctrlzone_info), tokens, + MR_TOKENS_MAX, ','); + + if (ret != 2) + return __errlog_invaild_format("LoadCtrlZone", "ctrlzone", str_ctrlzone_key); + + snprintf(str_ctrlzone_name, sizeof(str_ctrlzone_name), "%s", tokens[0]); + sz_ctrlzone = __parser_uint(tokens[1]); + + if(sz_ctrlzone < 0) + return __errlog_invaild_format("LoadCtrlZone", "ctrlzone", str_ctrlzone_key); + + __ctrlzone_list_join(instance, str_ctrlzone_name, ctrlzone_id, sz_ctrlzone); + } + + return 0; +} + int sc_config_thread_info(const char * cfg, struct sc_instance * instance) { char str_thread_info[MR_STRING_MAX]; @@ -338,6 +388,8 @@ void sc_stage_config(struct sc_instance * instance) "Please check configure file %s, Failed. ", cfgfile); MR_CHECK(sc_config_stack_info(cfgfile, instance) >= 0, "Please check configure file %s, Failed. ", cfgfile); - + MR_CHECK(sc_config_ctrlzone(cfgfile, instance) >= 0, + "Please check configure file %s, Failed. ", cfgfile); + return; }
\ No newline at end of file diff --git a/service/src/core.c b/service/src/core.c index 5f62cea..f477ec2 100644 --- a/service/src/core.c +++ b/service/src/core.c @@ -31,16 +31,20 @@ const char service_git_version[] = ""; #define MR_SERVICE_MAX_EAL_ARGC 512 #endif +#ifndef MR_SERVICE_DEFAULT_MONIT_FILE +#define MR_SERVICE_DEFAULT_MONIT_FILE "/tmp/.mrzcpd.moint" +#endif + #ifndef MR_SERVICE_DEFAULT_GLOB_CFG -#define MR_SERVICE_GLOB_CFG "/etc/mrglobal.conf" +#define MR_SERVICE_DEFAULT_GLOB_CFG "/etc/mrglobal.conf" #endif #ifndef MR_SERVICE_DEFAULT_PROCSYM -#define MR_SERVICE_DEFAULT_PROCSYM "serv" +#define MR_SERVICE_DEFAULT_PROCSYM "serv" #endif #ifndef MR_LOGREADER_DEFAULT_PROCSYM -#define MR_LOGREADER_DEFAULT_PROCSYM "logreader" +#define MR_LOGREADER_DEFAULT_PROCSYM "logreader" #endif extern void * sc_runtime_thread(void * args); @@ -150,6 +154,14 @@ struct sc_instance * sc_instance_new() return instance; } +void sc_instance_init_monitfile(struct sc_instance * instance) +{ + snprintf(instance->local_monitfile, sizeof(instance->local_monitfile), "%s", + MR_SERVICE_DEFAULT_MONIT_FILE); + return; +} + + void sc_instance_init_log(struct sc_instance * instance) { // 如果没有设置,使用默认的日志流(到屏幕上) @@ -177,7 +189,7 @@ void sc_instance_init_cfg(struct sc_instance * instance) default_cfgfile: snprintf(instance->local_cfgfile, sizeof(instance->local_logfile), "%s", - MR_SERVICE_GLOB_CFG); + MR_SERVICE_DEFAULT_GLOB_CFG); MR_LOG(INFO, SERVICE, "Global Configure File: %s\n", instance->local_cfgfile); } @@ -190,11 +202,19 @@ void sc_instance_init_progsym(struct sc_instance * instance) return; } +void sc_instance_init_ctrlzone_list(struct sc_instance * instance) +{ + TAILQ_INIT(&instance->ctrlzone_list); + return; +} + void sc_instance_init(struct sc_instance * instance) { sc_instance_init_log(instance); sc_instance_init_cfg(instance); + sc_instance_init_monitfile(instance); sc_instance_init_progsym(instance); + sc_instance_init_ctrlzone_list(instance); } void sc_instance_ctx_init(struct sc_instance * instance) @@ -209,11 +229,29 @@ void sc_stage_init(struct sc_instance * instance) return; } +extern int sc_monit_loop(struct sc_instance * sc_instance); + +void * sc_loop_thread(void * args) +{ + struct sc_instance * instance = (struct sc_instance *)args; + pthread_detach(pthread_self()); + + while(1) + { + sc_monit_loop(instance); + sleep(1); + } +} + + void sc_launch_thread(struct sc_instance * instance) { int nr_thread = mask_popcnt(instance->cpu_mask); MR_CHECK(nr_thread >= 0, "Invailed CPU Mask"); - + + pthread_t pid_loop; + pthread_create(&pid_loop, NULL, sc_loop_thread, instance); + pthread_t * pids = (pthread_t *)malloc(sizeof(pthread_t) * nr_thread); MR_CHECK(pids != NULL, "Cannot alloc memory for pthread_t structures"); diff --git a/service/src/monit.c b/service/src/monit.c new file mode 100644 index 0000000..14489c3 --- /dev/null +++ b/service/src/monit.c @@ -0,0 +1,107 @@ +/* \brief ״̬����������
+ *
+ * \author Lu Qiuwen<[email protected]>
+ * \date 2016-11-30
+ */
+
+#include <sc_common.h>
+#include <mr_device.h>
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "cJSON.h"
+
+// ��������ͳ�Ƽ���
+static cJSON * __create_device_stats(struct mr_dev * dev)
+{
+ struct cJSON * j_device_stats = cJSON_CreateObject();
+ struct rte_eth_stats _eth_stat;
+ rte_eth_stats_get(dev->port_id, &_eth_stat);
+
+ cJSON_AddNumberToObject(j_device_stats, "ipackets", _eth_stat.ipackets);
+ cJSON_AddNumberToObject(j_device_stats, "opackets", _eth_stat.opackets);
+ cJSON_AddNumberToObject(j_device_stats, "ibytes", _eth_stat.ibytes);
+ cJSON_AddNumberToObject(j_device_stats, "obytes", _eth_stat.obytes);
+ cJSON_AddNumberToObject(j_device_stats, "imissed", _eth_stat.imissed);
+ cJSON_AddNumberToObject(j_device_stats, "ierrors", _eth_stat.ierrors);
+ cJSON_AddNumberToObject(j_device_stats, "oerrors", _eth_stat.oerrors);
+ cJSON_AddNumberToObject(j_device_stats, "rxnombuf", _eth_stat.rx_nombuf);
+ return j_device_stats;
+}
+
+// ����������·��Ϣ���
+static cJSON * __create_device_link(struct mr_dev * dev)
+{
+ struct cJSON * j_device_link = cJSON_CreateObject();
+ struct rte_eth_link _eth_link;
+
+ rte_eth_link_get_nowait(dev->port_id, &_eth_link);
+ cJSON_AddNumberToObject(j_device_link, "LinkSpeed", _eth_link.link_speed);
+ cJSON_AddBoolToObject(j_device_link, "LinkDuplex", _eth_link.link_duplex);
+ cJSON_AddBoolToObject(j_device_link, "LinkAutoNeg", _eth_link.link_autoneg);
+ cJSON_AddBoolToObject(j_device_link, "LinkStatus", _eth_link.link_status);
+ return j_device_link;
+}
+
+// ��������������Ϣ���
+static cJSON * __create_device_info(struct mr_dev * dev)
+{
+ struct cJSON * j_device_info = cJSON_CreateObject();
+
+ char str_ether_addr[MR_STRING_MAX];
+ ether_format_addr(str_ether_addr, sizeof(str_ether_addr), &dev->ether_addr);
+
+ struct rte_pci_addr * pci_addr = &dev->info.pci_addr;
+ char str_pci_addr[MR_STRING_MAX];
+ snprintf(str_pci_addr, sizeof(str_pci_addr), PCI_PRI_FMT, pci_addr->bus,
+ pci_addr->devid, pci_addr->domain, pci_addr->function);
+
+ cJSON_AddStringToObject(j_device_info, "EtherAddr", str_ether_addr);
+ cJSON_AddStringToObject(j_device_info, "PCIAddr", str_pci_addr);
+ cJSON_AddNumberToObject(j_device_info, "PortID", dev->port_id);
+ cJSON_AddNumberToObject(j_device_info, "RxQueueCount", dev->nr_rxq);
+ cJSON_AddNumberToObject(j_device_info, "TxQueueCount", dev->nr_txq);
+ cJSON_AddNumberToObject(j_device_info, "MTU", dev->mtu);
+
+ return j_device_info;
+}
+
+// ���������豸���
+static cJSON * monit_device_info(struct sc_instance * sc_instance)
+{
+ struct cJSON * j_device_array = cJSON_CreateArray();
+
+ int nr_devices = 0;
+ struct mr_dev * mr_dev_info[MR_DEVICE_MAX];
+ nr_devices = mr_device_list(sc_instance->core_instance, mr_dev_info, MR_DEVICE_MAX, 0);
+
+ for(int i = 0; i < nr_devices; i++)
+ {
+ struct cJSON * j_device = cJSON_CreateObject();
+ cJSON_AddStringToObject(j_device, "symbol", mr_dev_info[i]->symbol);
+ cJSON_AddItemToObject(j_device, "information", __create_device_info(mr_dev_info[i]));
+ cJSON_AddItemToObject(j_device, "link", __create_device_link(mr_dev_info[i]));
+ cJSON_AddItemToObject(j_device, "stats", __create_device_stats(mr_dev_info[i]));
+ cJSON_AddItemToArray(j_device_array, j_device);
+ }
+
+ return j_device_array;
+}
+
+static cJSON * monit_root(struct sc_instance * sc_instance)
+{
+ struct cJSON * j_root = cJSON_CreateObject();
+ cJSON_AddItemToObject(j_root, "device", monit_device_info(sc_instance));
+ return j_root;
+}
+
+int sc_monit_loop(struct sc_instance * sc_instance)
+{
+ FILE * fp_monit = fopen(sc_instance->local_monitfile, "w");
+ cJSON * j_root = monit_root(sc_instance);
+ char * str_json_print = cJSON_Print(j_root);
+ fprintf(fp_monit, "%s", str_json_print);
+ free(j_root);
+ fclose(fp_monit);
+ return 0;
+}
\ No newline at end of file diff --git a/service/src/register.c b/service/src/register.c index a0c158d..57b66d4 100644 --- a/service/src/register.c +++ b/service/src/register.c @@ -44,36 +44,23 @@ static int sc_core_instance_register(struct sc_instance * instance) static int sc_core_ctrlzone_register(struct sc_instance * instance) { - for(int i = 0; i < MRB_MAX_CTRLZONE_NUM; i++) + struct sc_ctrlzone * ctrlzone_iter; + TAILQ_FOREACH(ctrlzone_iter, &instance->ctrlzone_list, next) { - char str_ctrlzone_info[MR_STRING_MAX]; - char str_ctrlzone_key[MR_SYMBOL_MAX]; - snprintf(str_ctrlzone_key, sizeof(str_ctrlzone_key), "ctrlzone%d", i); - - if (MESA_load_profile_string_nodef(instance->local_logfile, "ctrlzone", - str_ctrlzone_key, str_ctrlzone_info, sizeof(str_ctrlzone_info)) < 0) continue; - - + int ret = mr_buffer_ctrlzone_register(instance->core_instance, + ctrlzone_iter->symbol, ctrlzone_iter->id, ctrlzone_iter->size); + + if(ret < 0) + { + MR_LOG(ERR, SERVICE, "Register ctrlzone %s(size=%d, id=%d) failed. ", + ctrlzone_iter->symbol, ctrlzone_iter->size, ctrlzone_iter->id); + return -1; + } + + MR_LOG(INFO, SERVICE, "Register ctrlzone %s(size=%d, id=%d) successfully. \n", + ctrlzone_iter->symbol, ctrlzone_iter->size, ctrlzone_iter->id); } - - - - - - - - - - - - - - - - - - return 0; } @@ -269,6 +256,8 @@ void sc_stage_register(struct sc_instance * instance) { MR_CHECK(sc_core_instance_register(instance) >= 0, "Cannot register core instance, Failed. Please recheck runtime log. "); + MR_CHECK(sc_core_ctrlzone_register(instance) >= 0, + "Cannot register control zone, Failed. Please recheck runtime log."); MR_CHECK(sc_stack_instance_register(instance) >= 0, "Cannot register stack instance, Failed. Please recheck runtime log. "); MR_CHECK(sc_app_register(instance) >= 0, |
