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