1 /*
2 * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3 */
4
5 #include "ulog_session_file.h"
6 #include <string.h>
7 #include <fcntl.h>
8 #include "aos/kernel.h"
9 #include "cJSON.h"
10 #include "errno.h"
11 #include "ulog_api.h"
12
13 #define ULOG_CFG_PARA_KEY_SIZE 12
14
15 typedef struct {
16 ulog_cfg_type_t type;
17 char* desription;
18 char* cfg_key[ulog_cfg_para_cnt];
19 } ulog_cfg_key_list_t;
20
21 typedef struct {
22 char ulog_cfg_val[ULOG_CFG_PARA_VAL_SIZE];
23 } ulog_cfg_t;
24
25 typedef struct _ulog_cfg_node_t {
26 ulog_cfg_type_t type;
27 unsigned short file_idx;
28 ulog_cfg_t *cfg[ulog_cfg_para_cnt];
29 struct _ulog_cfg_node_t *next;
30 } ulog_cfg_node_t;
31
32 static aos_mutex_t mutex_entry_cfg_mm;
33
34 static ulog_cfg_node_t *ulog_cfg_header = NULL;
35
36 ulog_cfg_key_list_t cfg_key_list[ulog_cfg_type_cnt] = {
37 {ulog_cfg_type_working, "working_idx", {NULL, NULL}},
38 {ulog_cfg_type_list, "file_idx", {"start", "end"}}
39 };
40
41 static void parser_cfg_file(const char* cfg);
42
get_ulog_cfg_key(const ulog_cfg_type_t type)43 static ulog_cfg_key_list_t *get_ulog_cfg_key(const ulog_cfg_type_t type)
44 {
45 ulog_cfg_key_list_t *rc = NULL;
46 uint8_t i = 0;
47 for (; i < ulog_cfg_type_cnt; i++) {
48 if (type == cfg_key_list[i].type) {
49 rc = &cfg_key_list[i];
50 break;
51 }
52 }
53 return rc;
54 }
55
cfg_init_mutex(void)56 void cfg_init_mutex(void)
57 {
58 aos_mutex_new(&mutex_entry_cfg_mm);
59 }
60
cfg_get_mutex(void)61 bool cfg_get_mutex(void)
62 {
63 return 0 == aos_mutex_lock(&mutex_entry_cfg_mm, AOS_WAIT_FOREVER);
64 }
65
cfg_release_mutex(void)66 void cfg_release_mutex(void)
67 {
68 aos_mutex_unlock(&mutex_entry_cfg_mm);
69 }
70
aos_get_ulog_list(char * buf,const unsigned short len)71 int aos_get_ulog_list(char* buf, const unsigned short len)
72 {
73 int rc = -EINVAL;
74 if(NULL!=buf && (len>=strlen(LOG_LIST_PREFIX)+strlen(LOG_LIST_SUFFIX)+1) ) {
75 rc = -EIO;
76 if(aos_mutex_is_valid(&mutex_entry_cfg_mm)) {
77 if(cfg_get_mutex()) {
78 rc = 0;
79 ulog_cfg_node_t *p = ulog_cfg_header;
80 if(NULL!=p) {
81 char time_buf[24];
82 snprintf(buf, len-strlen(LOG_LIST_SUFFIX)-1, LOG_LIST_PREFIX, ulog_format_time(time_buf, sizeof(time_buf)));
83 unsigned short off = strlen(buf);
84
85 while (p != NULL && rc == 0) {
86 if (p->type == ulog_cfg_type_list) {
87 const int empty_room = len-strlen(LOG_LIST_SUFFIX)-1-off;
88 int result = 0;
89 if(empty_room>(result=snprintf(&buf[off], empty_room, LOG_LIST_NODE,p->file_idx,
90 p->cfg[0]==NULL?"":p->cfg[0]->ulog_cfg_val,p->cfg[1]==NULL?"":p->cfg[1]->ulog_cfg_val))) {
91 off += result;
92 } else {
93 rc = -ENOMEM;
94 }
95 }
96 p = p->next;
97 }
98 if(rc==0) {
99 if(buf[off-1]==',') {
100 off--;
101 }
102 snprintf(&buf[off], len-strlen(LOG_LIST_SUFFIX)-1-off, LOG_LIST_SUFFIX);
103 }
104 } else {
105 rc = -EIO;
106 }
107 cfg_release_mutex();
108 }
109 }
110 }
111 return rc;
112 }
113
update_mm_cfg(const ulog_cfg_type_t type,const unsigned short idx,const ulog_cfg_para_t para_type,char val[ULOG_CFG_PARA_VAL_SIZE])114 int update_mm_cfg(const ulog_cfg_type_t type, const unsigned short idx, const ulog_cfg_para_t para_type, char val[ULOG_CFG_PARA_VAL_SIZE])
115 {
116 int rc = -1;
117 if(cfg_get_mutex()) {
118 if (NULL == ulog_cfg_header) {
119 ulog_cfg_header = (ulog_cfg_node_t *)aos_malloc(sizeof(ulog_cfg_node_t));
120 if (NULL != ulog_cfg_header) {
121 ulog_cfg_header->next = NULL;
122 ulog_cfg_header->type = type;
123 ulog_cfg_header->file_idx = idx;
124 uint8_t i = 0;
125 for(; i<ulog_cfg_para_cnt; i++) {
126 if(NULL!=get_ulog_cfg_key(type)->cfg_key[i]) {
127 ulog_cfg_header->cfg[i] = (ulog_cfg_t *)aos_malloc(sizeof(ulog_cfg_t));
128 memset(ulog_cfg_header->cfg[para_type], 0, sizeof(ulog_cfg_t));
129 }
130 }
131 if (ulog_cfg_para_none != para_type) {
132 strncpy(ulog_cfg_header->cfg[para_type]->ulog_cfg_val, val, ULOG_CFG_PARA_VAL_SIZE - 1);
133 }
134 rc = 0;
135 } else {
136 SESSION_FS_INFO("alloc memory fail for type %d idx %d\n", type, idx);
137 }
138 } else {
139 ulog_cfg_node_t *p = ulog_cfg_header;
140 while (p != NULL && rc != 0) {
141 if (p->type == type && (ulog_cfg_para_none == para_type || p->file_idx == idx)) { /* found it alredy in list, just update */
142 if (ulog_cfg_para_none == para_type) {
143 /* no cfg, just update file list, apply to type working */
144 p->file_idx = idx;
145 rc = 0;
146 break;
147 } else {
148 uint8_t i = 0;
149 for(; i<ulog_cfg_para_cnt; i++) {
150 if(NULL!=get_ulog_cfg_key(type)->cfg_key[i] && NULL==p->cfg[i]) {
151 p->cfg[i] = (ulog_cfg_t *)aos_malloc(sizeof(ulog_cfg_t));
152 memset(p->cfg[i], 0, sizeof(ulog_cfg_t));
153 }
154 }
155 strncpy(p->cfg[para_type]->ulog_cfg_val, val, ULOG_CFG_PARA_VAL_SIZE - 1);
156 rc = 0;
157 }
158 break;
159 }
160 if (p->next == NULL) { /* last node */
161 p->next = (ulog_cfg_node_t*)aos_malloc(sizeof(ulog_cfg_node_t));
162 if (NULL != p->next) {
163 p->next->next = NULL;
164 p->next->type = type;
165 p->next->file_idx = idx;
166
167 uint8_t i = 0;
168 for(; i<ulog_cfg_para_cnt; i++) {
169 if(NULL!=get_ulog_cfg_key(type)->cfg_key[i]) {
170 p->next->cfg[i] = (ulog_cfg_t *)aos_malloc(sizeof(ulog_cfg_t));
171 memset(p->next->cfg[i], 0, sizeof(ulog_cfg_t));
172 }
173 }
174 if (ulog_cfg_para_none != para_type) {
175 strncpy(p->next->cfg[para_type]->ulog_cfg_val, val, ULOG_CFG_PARA_VAL_SIZE - 1);
176 }
177 rc = 0;
178 } else {
179 SESSION_FS_INFO("alloc memory fail for type %d idx %d\n", type, idx);
180 }
181 break;
182 } else {
183 p = p->next;
184 }
185 }
186 }
187 cfg_release_mutex();
188 }
189 return rc;
190 }
191
192 /**
193 *
194 * Sync cfg from cfg file to memory
195 *
196 * return 0 if this step pass, else indicates this step fail
197 *
198 */
load_cfg_2_mm(void)199 int load_cfg_2_mm(void)
200 {
201 int rc = -1;
202 char one_cfg_item[ULOG_CFG_LINE_MAX_SIZE];
203 int off = 0;
204 int read_len = 0;
205
206 int fd = open_log_file(ULOG_FILE_CFG_IDX, O_RDONLY, 0);
207 if (fd < 0) {
208 SESSION_FS_DEBUG("%s %d open log cfg file fail\r\n", __FILE__, __LINE__);
209 return rc;
210 }
211
212 do {
213 read_len = get_log_line(fd, one_cfg_item, sizeof(one_cfg_item));
214 parser_cfg_file(one_cfg_item);
215 }while (read_len > 0);
216
217 aos_close(fd);
218
219 ulog_cfg_node_t *p = ulog_cfg_header;
220 while (p != NULL) {
221 SESSION_FS_DEBUG("check cfg item in mm type %d idx %d\n", p->type, p->file_idx);
222 uint8_t i = 0;
223 for(; i<ulog_cfg_para_cnt; i++) {
224 if(p->cfg[i]!=NULL) {
225 SESSION_FS_DEBUG("check cfg item in mm cfg value %s @ %d\n", p->cfg[i]->ulog_cfg_val, i);
226 }
227 }
228 p = p->next;
229
230 }
231 return rc;
232 }
233
234 /**
235 *
236 * Sync cfg from memory to file
237 *
238 * return 0 if this step pass, else indicates this step fail
239 *
240 */
cfg_mm_2_file(const int fd)241 int cfg_mm_2_file(const int fd)
242 {
243 int rc = -EINVAL;
244 if (fd >= 0 && NULL != ulog_cfg_header) {
245 ulog_cfg_node_t *p = ulog_cfg_header;
246 while (NULL != p) {
247 switch (p->type) {
248 case ulog_cfg_type_working: {
249 cJSON *ulog_cfg_obj = cJSON_CreateObject();
250 if (NULL != ulog_cfg_obj) {
251
252 cJSON_AddItemToObject(ulog_cfg_obj, get_ulog_cfg_key(p->type)->desription, cJSON_CreateNumber(p->file_idx));
253 char *cfg_line = cJSON_PrintUnformatted(ulog_cfg_obj);
254 cJSON_Delete(ulog_cfg_obj);
255 if (NULL != cfg_line) {
256 write_log_line(fd, cfg_line, true);
257 SESSION_FS_INFO("sync cfg to file %s\n", cfg_line);
258 cJSON_free(cfg_line);
259 cfg_line = NULL;
260 rc = 0;
261 } else {
262 rc = -EIO;
263 }
264 } else {
265 rc = -ENOMEM;
266 SESSION_FS_INFO("[%s#%d]create cjson obj fail\n", __FILE__, __LINE__);
267 }
268
269 }
270 break;
271
272 case ulog_cfg_type_list: {
273 cJSON *ulog_cfg_obj = cJSON_CreateObject();
274 if (NULL != ulog_cfg_obj) {
275 uint8_t i = 0;
276 cJSON_AddItemToObject(ulog_cfg_obj, get_ulog_cfg_key(p->type)->desription, cJSON_CreateNumber(p->file_idx));
277 for (; i < ulog_cfg_para_cnt; i++) {
278 if (p->cfg[i] != NULL) {
279 cJSON_AddItemToObject(ulog_cfg_obj, get_ulog_cfg_key(p->type)->cfg_key[i], cJSON_CreateString(p->cfg[i]->ulog_cfg_val));
280 }
281 }
282
283 char *cfg_line = cJSON_PrintUnformatted(ulog_cfg_obj);
284 cJSON_Delete(ulog_cfg_obj);
285 if (NULL != cfg_line) {
286 write_log_line(fd, cfg_line, true);
287 SESSION_FS_INFO("sync cfg to file %s\n", cfg_line);
288 cJSON_free(cfg_line);
289 cfg_line = NULL;
290 rc = 0;
291 } else {
292 rc = -EIO;
293 }
294 } else {
295 rc = -ENOMEM;
296 SESSION_FS_INFO("[%s#%d]create cjson obj fail\n", __FILE__, __LINE__);
297 }
298
299 }
300 break;
301
302 default:
303 break;
304 }
305 p = p->next;
306 }
307
308 } else {
309 SESSION_FS_INFO("sync fail as mm illegal\n");
310 }
311 return rc;
312 }
313
parser_cfg_file(const char * cfg)314 static void parser_cfg_file(const char* cfg)
315 {
316 uint8_t i = 0;
317 uint8_t j = 0;
318 cJSON *root = NULL;
319 cJSON *config_para = NULL;
320 cJSON *config_node = NULL;
321
322 if (NULL == cfg) {
323 return ;
324 }
325
326 root = cJSON_Parse(cfg);
327 if (NULL == root) {
328 return ;
329 }
330
331 SESSION_FS_DEBUG("parser_cfg_file input %s %d \n", cfg, __LINE__);
332 for (; i < ulog_cfg_type_cnt; i++) {
333 SESSION_FS_DEBUG("key list description %s @ %d\n", cfg_key_list[i].desription, i);
334 config_node = cJSON_GetObjectItem(root, cfg_key_list[i].desription);
335 if (NULL == config_node) {
336 continue;
337 }
338
339 if (cJSON_IsNumber(config_node)) {
340 if (ulog_cfg_type_working == cfg_key_list[i].type) {
341 update_mm_cfg(cfg_key_list[i].type, (ulog_idx_type)config_node->valueint, ulog_cfg_para_none, NULL);
342 }
343
344 for (; j < ulog_cfg_para_cnt; j++) {
345 if (cfg_key_list[i].cfg_key[j] != NULL) {
346 SESSION_FS_DEBUG("key list description %s cfg key %s @ %d %d\n", cfg_key_list[i].desription,
347 cfg_key_list[i].cfg_key[j], i, j);
348 config_para = cJSON_GetObjectItem(root, cfg_key_list[i].cfg_key[j]);
349 if (NULL != config_para && cJSON_IsString(config_para)) {
350 update_mm_cfg(cfg_key_list[i].type,
351 (ulog_idx_type)config_node->valueint,
352 j,
353 config_para->valuestring);
354 }
355 }
356 }
357 }
358 break;
359 }
360
361 cJSON_Delete(root);
362 root = NULL;
363
364 }
365
get_working_from_cfg_mm()366 ulog_idx_type get_working_from_cfg_mm()
367 {
368 ulog_idx_type rc = ULOG_FILE_IDX_INVALID;
369 ulog_cfg_node_t *p = ulog_cfg_header;
370 while (p != NULL) {
371 if (p->type == ulog_cfg_type_working) { /* found it alredy in list, just update */
372 rc = p->file_idx;
373 break;
374 } else {
375 p = p->next;
376 }
377 }
378 return rc;
379 }
380
381