1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "trigger_manager.h"
17
18 #include <string.h>
19 #include <sys/types.h>
20
21 #include "init_cmds.h"
22 #include "param_manager.h"
23 #include "trigger_checker.h"
24 #include "securec.h"
25
26 static DUMP_PRINTF g_printf = printf;
27
AddCommand(JobNode * trigger,uint32_t cmdKeyIndex,const char * content,const ConfigContext * cfgContext)28 int AddCommand(JobNode *trigger, uint32_t cmdKeyIndex, const char *content, const ConfigContext *cfgContext)
29 {
30 PARAM_CHECK(trigger != NULL, return -1, "trigger is null");
31 uint32_t size = sizeof(CommandNode);
32 size += (content == NULL) ? 1 : (strlen(content) + 1);
33 size = PARAM_ALIGN(size);
34
35 CommandNode *node = (CommandNode *)calloc(1, size);
36 PARAM_CHECK(node != NULL, return -1, "Failed to alloc memory for command");
37 node->cmdKeyIndex = cmdKeyIndex;
38 node->next = NULL;
39 node->content[0] = '\0';
40 if (content != NULL && strlen(content) != 0) {
41 int ret = memcpy_s(node->content, size, content, strlen(content));
42 node->content[strlen(content)] = '\0';
43 PARAM_CHECK(ret == EOK, free(node);
44 return 0, "Failed to copy command");
45 }
46 node->cfgContext.type = INIT_CONTEXT_MAIN;
47 if (cfgContext != NULL) {
48 node->cfgContext.type = cfgContext->type;
49 }
50 if (trigger->firstCmd == NULL) {
51 trigger->firstCmd = node;
52 trigger->lastCmd = node;
53 } else {
54 PARAM_CHECK(trigger->lastCmd != NULL, free(node);
55 return 0, "Invalid last cmd");
56 trigger->lastCmd->next = node;
57 trigger->lastCmd = node;
58 }
59 return 0;
60 }
61
GetNextCmdNode(const JobNode * trigger,const CommandNode * curr)62 CommandNode *GetNextCmdNode(const JobNode *trigger, const CommandNode *curr)
63 {
64 PARAM_CHECK(trigger != NULL, return NULL, "trigger is null");
65 if (curr == NULL) {
66 return trigger->firstCmd;
67 }
68 return curr->next;
69 }
70
CopyCondition(TriggerNode * node,const char * condition)71 static int CopyCondition(TriggerNode *node, const char *condition)
72 {
73 if (condition == NULL || strlen(condition) == 0) {
74 return 0;
75 }
76 uint32_t buffSize = 0;
77 char *cond = GetTriggerCache(&buffSize);
78 int ret = ConvertInfixToPrefix(condition, cond, buffSize);
79 PARAM_CHECK(ret == 0, return -1, "Failed to convert condition for trigger");
80 node->condition = strdup(cond);
81 PARAM_CHECK(node->condition != NULL, return -1, "Failed to dup conditition");
82 return 0;
83 }
84
AddTriggerNode_(TriggerHeader * triggerHead,uint32_t type,const char * condition,uint32_t dataSize)85 static TriggerNode *AddTriggerNode_(TriggerHeader *triggerHead,
86 uint32_t type, const char *condition, uint32_t dataSize)
87 {
88 TriggerNode *node = (TriggerNode *)calloc(1, dataSize);
89 PARAM_CHECK(node != NULL, return NULL, "Failed to alloc memory for trigger");
90 node->condition = NULL;
91 int ret = CopyCondition(node, condition);
92 PARAM_CHECK(ret == 0, free(node);
93 return NULL, "Failed to copy conditition");
94 node->type = type;
95 node->flags = 0;
96 OH_ListInit(&node->node);
97 OH_ListAddTail(&triggerHead->triggerList, &node->node);
98 triggerHead->triggerCount++;
99 return node;
100 }
101
AddJobNode_(TriggerNode * trigger,const TriggerExtInfo * extInfo)102 static int32_t AddJobNode_(TriggerNode *trigger, const TriggerExtInfo *extInfo)
103 {
104 JobNode *node = (JobNode *)trigger;
105 int ret = strcpy_s(node->name, strlen(extInfo->info.name) + 1, extInfo->info.name);
106 PARAM_CHECK(ret == EOK, return -1, "Failed to copy name for trigger");
107 node->firstCmd = NULL;
108 node->lastCmd = NULL;
109 ret = OH_HashMapAdd(GetTriggerWorkSpace()->hashMap, &node->hashNode);
110 PARAM_CHECK(ret == 0, return -1, "Failed to add hash node");
111 return 0;
112 }
113
AddJobTrigger_(const TriggerWorkSpace * workSpace,const char * condition,const TriggerExtInfo * extInfo)114 static TriggerNode *AddJobTrigger_(const TriggerWorkSpace *workSpace,
115 const char *condition, const TriggerExtInfo *extInfo)
116 {
117 PARAM_CHECK(workSpace != NULL, return NULL, "workSpace is null");
118 PARAM_CHECK(extInfo != NULL && extInfo->addNode != NULL, return NULL, "extInfo is null");
119 PARAM_CHECK(extInfo->type <= TRIGGER_UNKNOW, return NULL, "Invalid type");
120 TriggerHeader *triggerHead = GetTriggerHeader(workSpace, extInfo->type);
121 PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", extInfo->type);
122 uint32_t nameLen = strlen(extInfo->info.name);
123 uint32_t triggerNodeLen = PARAM_ALIGN(nameLen + 1) + sizeof(JobNode);
124 TriggerNode *node = (TriggerNode *)AddTriggerNode_(triggerHead, extInfo->type, condition, triggerNodeLen);
125 PARAM_CHECK(node != NULL, return NULL, "Failed to alloc jobnode");
126 int ret = extInfo->addNode(node, extInfo);
127 PARAM_CHECK(ret == 0, FreeTrigger(workSpace, node);
128 return NULL, "Failed to add hash node");
129 if (extInfo->type == TRIGGER_BOOT) {
130 TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_ONCE);
131 if (strncmp("boot-service:", extInfo->info.name, strlen("boot-service:")) != 0) {
132 TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_SUBTRIGGER);
133 }
134 }
135 return node;
136 }
137
DelJobTrigger_(const TriggerWorkSpace * workSpace,TriggerNode * trigger)138 static void DelJobTrigger_(const TriggerWorkSpace *workSpace, TriggerNode *trigger)
139 {
140 PARAM_CHECK(workSpace != NULL, return, "Param is null");
141 PARAM_CHECK(trigger != NULL, return, "Trigger is null");
142 JobNode *jobNode = (JobNode *)trigger;
143 TriggerHeader *triggerHead = GetTriggerHeader(workSpace, trigger->type);
144 PARAM_CHECK(triggerHead != NULL, return, "Failed to get header %d", trigger->type);
145 CommandNode *cmd = jobNode->firstCmd;
146 while (cmd != NULL) {
147 CommandNode *next = cmd->next;
148 free(cmd);
149 triggerHead->cmdNodeCount--;
150 cmd = next;
151 }
152 if (jobNode->condition != NULL) {
153 free(jobNode->condition);
154 jobNode->condition = NULL;
155 }
156 jobNode->lastCmd = NULL;
157 jobNode->firstCmd = NULL;
158 OH_ListRemove(&trigger->node);
159 triggerHead->triggerCount--;
160 OH_HashMapRemove(workSpace->hashMap, jobNode->name);
161
162 if (!TRIGGER_IN_QUEUE(trigger)) {
163 free(jobNode);
164 return;
165 }
166 TriggerExecuteQueue *executeQueue = (TriggerExecuteQueue *)&workSpace->executeQueue;
167 for (uint32_t i = executeQueue->startIndex; i < executeQueue->endIndex; i++) {
168 if (executeQueue->executeQueue[i] == trigger) {
169 executeQueue->executeQueue[i] = NULL;
170 break;
171 }
172 }
173 free(jobNode);
174 }
175
AddWatchTrigger_(const TriggerWorkSpace * workSpace,const char * condition,const TriggerExtInfo * extInfo)176 static TriggerNode *AddWatchTrigger_(const TriggerWorkSpace *workSpace,
177 const char *condition, const TriggerExtInfo *extInfo)
178 {
179 PARAM_CHECK(workSpace != NULL, return NULL, "workSpace is null");
180 PARAM_CHECK(extInfo != NULL && extInfo->addNode != NULL, return NULL, "extInfo is null");
181 TriggerHeader *triggerHead = GetTriggerHeader(workSpace, extInfo->type);
182 PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", extInfo->type);
183 uint32_t size = 0;
184 if (extInfo->type == TRIGGER_PARAM_WATCH) {
185 size = sizeof(WatchNode);
186 } else if (extInfo->type == TRIGGER_PARAM_WAIT) {
187 size = sizeof(WaitNode);
188 } else {
189 PARAM_LOGE("Invalid trigger type %d", extInfo->type);
190 return NULL;
191 }
192 TriggerNode *node = AddTriggerNode_(triggerHead, extInfo->type, condition, size);
193 PARAM_CHECK(node != NULL, return NULL, "Failed to alloc memory for trigger");
194 int ret = extInfo->addNode(node, extInfo);
195 PARAM_CHECK(ret == 0, FreeTrigger(workSpace, node);
196 return NULL, "Failed to add node");
197 if (extInfo->type == TRIGGER_PARAM_WAIT) {
198 TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_ONCE);
199 }
200 return node;
201 }
202
DelWatchTrigger_(const TriggerWorkSpace * workSpace,TriggerNode * trigger)203 static void DelWatchTrigger_(const TriggerWorkSpace *workSpace, TriggerNode *trigger)
204 {
205 PARAM_CHECK(workSpace != NULL, return, "Param is null");
206 TriggerHeader *triggerHead = GetTriggerHeader(workSpace, trigger->type);
207 PARAM_CHECK(triggerHead != NULL, return, "Failed to get header %d", trigger->type);
208 OH_ListRemove(&trigger->node);
209 if (trigger->type == TRIGGER_PARAM_WAIT) {
210 WaitNode *node = (WaitNode *)trigger;
211 OH_ListRemove(&node->item);
212 } else if (trigger->type == TRIGGER_PARAM_WATCH) {
213 WatchNode *node = (WatchNode *)trigger;
214 OH_ListRemove(&node->item);
215 }
216 PARAM_LOGV("DelWatchTrigger_ %s count %d", GetTriggerName(trigger), triggerHead->triggerCount);
217 triggerHead->triggerCount--;
218 if (trigger->condition != NULL) {
219 free(trigger->condition);
220 trigger->condition = NULL;
221 }
222 free(trigger);
223 }
224
GetNextTrigger_(const TriggerHeader * triggerHead,const TriggerNode * curr)225 static TriggerNode *GetNextTrigger_(const TriggerHeader *triggerHead, const TriggerNode *curr)
226 {
227 PARAM_CHECK(triggerHead != NULL, return NULL, "Invalid triggerHead");
228 ListNode *node = NULL;
229 if (curr != NULL) {
230 node = curr->node.next;
231 } else {
232 node = triggerHead->triggerList.next;
233 }
234 if (node != &triggerHead->triggerList) {
235 return ListEntry(node, TriggerNode, node);
236 }
237 return NULL;
238 }
239
GetTriggerCondition_(const TriggerNode * trigger)240 static const char *GetTriggerCondition_(const TriggerNode *trigger)
241 {
242 return (trigger == NULL || trigger->condition == NULL) ? "" : trigger->condition;
243 }
244
GetBootCondition_(const TriggerNode * trigger)245 static const char *GetBootCondition_(const TriggerNode *trigger)
246 {
247 PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
248 PARAM_CHECK(trigger->type == TRIGGER_BOOT, return "", "Invalid type");
249 const JobNode *node = (const JobNode *)trigger;
250 return node->name;
251 }
252
GetJobName_(const TriggerNode * trigger)253 static const char *GetJobName_(const TriggerNode *trigger)
254 {
255 PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
256 PARAM_CHECK(trigger->type <= TRIGGER_UNKNOW, return "", "Invalid type");
257 const JobNode *node = (const JobNode *)trigger;
258 return node->name;
259 }
260
GetWatchName_(const TriggerNode * trigger)261 static const char *GetWatchName_(const TriggerNode *trigger)
262 {
263 PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
264 PARAM_CHECK(trigger->type < TRIGGER_MAX && trigger->type > TRIGGER_UNKNOW,
265 return "", "Invalid type");
266 return trigger->condition;
267 }
268
UpdateJobTrigger(const TriggerWorkSpace * workSpace,int type,const char * condition,const char * name)269 JobNode *UpdateJobTrigger(const TriggerWorkSpace *workSpace,
270 int type, const char *condition, const char *name)
271 {
272 PARAM_CHECK(workSpace != NULL && name != NULL, return NULL, "name is null");
273 PARAM_CHECK(type <= TRIGGER_UNKNOW, return NULL, "Invalid type");
274 TriggerHeader *triggerHead = GetTriggerHeader(workSpace, type);
275 PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", type);
276 JobNode *jobNode = GetTriggerByName(workSpace, name);
277 if (jobNode == NULL) {
278 TriggerExtInfo extInfo = {};
279 extInfo.info.name = (char *)name;
280 extInfo.type = type;
281 extInfo.addNode = AddJobNode_;
282 return (JobNode *)triggerHead->addTrigger(workSpace, condition, &extInfo);
283 } else if (jobNode->condition == NULL && condition != NULL) {
284 int ret = CopyCondition((TriggerNode *)jobNode, condition);
285 PARAM_CHECK(ret == 0, FreeTrigger(workSpace, (TriggerNode*)jobNode);
286 return NULL, "Failed to copy conditition");
287 }
288 return jobNode;
289 }
290
GetTriggerByName(const TriggerWorkSpace * workSpace,const char * triggerName)291 JobNode *GetTriggerByName(const TriggerWorkSpace *workSpace, const char *triggerName)
292 {
293 PARAM_CHECK(workSpace != NULL && triggerName != NULL, return NULL, "Invalid param");
294 HashNode *node = OH_HashMapGet(workSpace->hashMap, triggerName);
295 if (node == NULL) {
296 return NULL;
297 }
298 JobNode *trigger = HASHMAP_ENTRY(node, JobNode, hashNode);
299 return trigger;
300 }
301
FreeTrigger(const TriggerWorkSpace * workSpace,TriggerNode * trigger)302 void FreeTrigger(const TriggerWorkSpace *workSpace, TriggerNode *trigger)
303 {
304 PARAM_CHECK(workSpace != NULL && trigger != NULL, return, "Invalid param");
305 TriggerHeader *head = GetTriggerHeader(workSpace, trigger->type);
306 if (head != NULL) {
307 head->delTrigger(workSpace, trigger);
308 }
309 }
310
ClearTrigger(const TriggerWorkSpace * workSpace,int8_t type)311 void ClearTrigger(const TriggerWorkSpace *workSpace, int8_t type)
312 {
313 PARAM_CHECK(workSpace != NULL, return, "head is null");
314 TriggerHeader *head = GetTriggerHeader(workSpace, type);
315 PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
316 TriggerNode *trigger = head->nextTrigger(head, NULL);
317 while (trigger != NULL) {
318 TriggerNode *next = head->nextTrigger(head, trigger);
319 FreeTrigger(workSpace, trigger);
320 trigger = next;
321 }
322 OH_ListInit(&head->triggerList);
323 }
324
ExecuteQueuePush(TriggerWorkSpace * workSpace,const TriggerNode * trigger)325 int ExecuteQueuePush(TriggerWorkSpace *workSpace, const TriggerNode *trigger)
326 {
327 PARAM_CHECK(workSpace != NULL, return -1, "Invalid workSpace");
328 uint32_t index = workSpace->executeQueue.endIndex++ % workSpace->executeQueue.queueCount;
329 workSpace->executeQueue.executeQueue[index] = (TriggerNode *)trigger;
330 return 0;
331 }
332
ExecuteQueuePop(TriggerWorkSpace * workSpace)333 TriggerNode *ExecuteQueuePop(TriggerWorkSpace *workSpace)
334 {
335 PARAM_CHECK(workSpace != NULL, return NULL, "Invalid workSpace");
336 TriggerNode *trigger = NULL;
337 do {
338 if (workSpace->executeQueue.endIndex <= workSpace->executeQueue.startIndex) {
339 return NULL;
340 }
341 uint32_t currIndex = workSpace->executeQueue.startIndex % workSpace->executeQueue.queueCount;
342 trigger = workSpace->executeQueue.executeQueue[currIndex];
343 workSpace->executeQueue.executeQueue[currIndex] = NULL;
344 workSpace->executeQueue.startIndex++;
345 } while (trigger == NULL);
346 return trigger;
347 }
348
CheckBootCondition_(LogicCalculator * calculator,const char * condition,const char * content,uint32_t contentSize)349 static int CheckBootCondition_(LogicCalculator *calculator,
350 const char *condition, const char *content, uint32_t contentSize)
351 {
352 UNUSED(calculator);
353 if (strncmp(condition, content, contentSize) == 0) {
354 return 1;
355 }
356 return 0;
357 }
358
CheckWatchCondition_(LogicCalculator * calculator,const char * condition,const char * content,uint32_t contentSize)359 static int CheckWatchCondition_(LogicCalculator *calculator,
360 const char *condition, const char *content, uint32_t contentSize)
361 {
362 UNUSED(calculator);
363 UNUSED(contentSize);
364 if (strncmp(condition, content, strlen(condition)) == 0) {
365 return 1;
366 }
367 return 0;
368 }
369
CheckParamCondition_(LogicCalculator * calculator,const char * condition,const char * content,uint32_t contentSize)370 static int CheckParamCondition_(LogicCalculator *calculator,
371 const char *condition, const char *content, uint32_t contentSize)
372 {
373 UNUSED(content);
374 UNUSED(contentSize);
375 if (calculator->inputName != NULL) {
376 if (!CheckMatchSubCondition(condition, calculator->inputName, strlen(calculator->inputName))) {
377 return 0;
378 }
379 }
380 return ComputeCondition(calculator, condition);
381 }
382
CheckUnknowCondition_(LogicCalculator * calculator,const char * condition,const char * content,uint32_t contentSize)383 static int CheckUnknowCondition_(LogicCalculator *calculator,
384 const char *condition, const char *content, uint32_t contentSize)
385 {
386 if (condition != NULL && content != NULL && strcmp(content, condition) == 0) {
387 return 1;
388 }
389 return ComputeCondition(calculator, condition);
390 }
391
ExecTriggerMatch_(const TriggerWorkSpace * workSpace,int type,LogicCalculator * calculator,const char * content,uint32_t contentSize)392 static int ExecTriggerMatch_(const TriggerWorkSpace *workSpace,
393 int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
394 {
395 TriggerHeader *head = GetTriggerHeader(workSpace, type);
396 PARAM_CHECK(head != NULL, return 0, "Failed to get header %d", type);
397 TriggerNode *trigger = head->nextTrigger(head, NULL);
398 while (trigger != NULL) {
399 TriggerNode *next = head->nextTrigger(head, trigger);
400 const char *condition = head->getCondition(trigger);
401 if (head->checkCondition(calculator, condition, content, contentSize) == 1) {
402 calculator->triggerCheckDone(trigger, content, contentSize);
403 }
404 trigger = next;
405 }
406 return 0;
407 }
408
CheckBootMatch_(const TriggerWorkSpace * workSpace,int type,LogicCalculator * calculator,const char * content,uint32_t contentSize)409 static int CheckBootMatch_(const TriggerWorkSpace *workSpace,
410 int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
411 {
412 PARAM_CHECK(workSpace != NULL, return -1, "Invalid space");
413 PARAM_CHECK((type == TRIGGER_BOOT) || (type == TRIGGER_PARAM_WATCH), return -1, "Invalid type");
414 return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
415 }
416
CheckParamMatch_(const TriggerWorkSpace * workSpace,int type,LogicCalculator * calculator,const char * content,uint32_t contentSize)417 static int CheckParamMatch_(const TriggerWorkSpace *workSpace,
418 int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
419 {
420 PARAM_CHECK(workSpace != NULL, return -1, "Invalid space");
421 PARAM_CHECK((type == TRIGGER_PARAM) || (type == TRIGGER_PARAM_WAIT), return -1, "Invalid type");
422
423 CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1);
424 int ret = GetValueFromContent(content, contentSize, 0, calculator->inputName, SUPPORT_DATA_BUFFER_MAX);
425 PARAM_CHECK(ret == 0, return -1, "Failed parse content name");
426 ret = GetValueFromContent(content, contentSize,
427 strlen(calculator->inputName) + 1, calculator->inputContent, SUPPORT_DATA_BUFFER_MAX);
428 PARAM_CHECK(ret == 0, return -1, "Failed parse content value");
429 return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
430 }
431
CheckUnknowMatch_(const TriggerWorkSpace * workSpace,int type,LogicCalculator * calculator,const char * content,uint32_t contentSize)432 static int CheckUnknowMatch_(const TriggerWorkSpace *workSpace,
433 int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
434 {
435 PARAM_CHECK(workSpace != NULL && content != NULL, return -1, "Failed arg for trigger");
436 PARAM_CHECK(type == TRIGGER_UNKNOW, return -1, "Invalid type");
437
438 CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1);
439 int ret = memcpy_s(calculator->triggerContent, sizeof(calculator->triggerContent), content, contentSize);
440 PARAM_CHECK(ret == EOK, return -1, "Failed to memcpy");
441 calculator->inputName = NULL;
442 calculator->inputContent = NULL;
443 return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
444 }
445
CheckAndMarkTrigger_(const TriggerWorkSpace * workSpace,int type,const char * name)446 int32_t CheckAndMarkTrigger_(const TriggerWorkSpace *workSpace, int type, const char *name)
447 {
448 PARAM_CHECK(workSpace != NULL && name != NULL, return 0, "Failed arg for trigger");
449 TriggerHeader *head = GetTriggerHeader(workSpace, type);
450 PARAM_CHECK(head != NULL, return 0, "Failed to get header %d", type);
451 int ret = 0;
452 TriggerNode *trigger = head->nextTrigger(head, NULL);
453 while (trigger != NULL) {
454 if (head->getCondition(trigger) == NULL) {
455 trigger = head->nextTrigger(head, trigger);
456 continue;
457 }
458 if (CheckMatchSubCondition(head->getCondition(trigger), name, strlen(name)) == 1) {
459 TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_RELATED);
460 ret = 1;
461 }
462 trigger = head->nextTrigger(head, trigger);
463 }
464 return ret;
465 }
466
CheckTrigger(TriggerWorkSpace * workSpace,int type,const char * content,uint32_t contentSize,PARAM_CHECK_DONE triggerCheckDone)467 int CheckTrigger(TriggerWorkSpace *workSpace, int type,
468 const char *content, uint32_t contentSize, PARAM_CHECK_DONE triggerCheckDone)
469 {
470 PARAM_CHECK(workSpace != NULL && content != NULL && triggerCheckDone != NULL,
471 return -1, "Failed arg for trigger");
472 PARAM_LOGV("CheckTrigger_ type: %d content: %s ", type, content);
473 TriggerHeader *triggerHead = GetTriggerHeader(workSpace, type);
474 if (triggerHead != NULL) {
475 LogicCalculator calculator = {{0}};
476 calculator.triggerCheckDone = triggerCheckDone;
477 int ret = triggerHead->checkTriggerMatch(workSpace, type, &calculator, content, contentSize);
478 CalculatorFree(&calculator);
479 return ret;
480 }
481 return 0;
482 }
483
DumpJobTrigger_(const TriggerWorkSpace * workSpace,const TriggerNode * trigger)484 static void DumpJobTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger)
485 {
486 const JobNode *node = (const JobNode *)trigger;
487 PARAM_DUMP("trigger flags: 0x%08x \n", trigger->flags);
488 PARAM_DUMP("trigger name: %s \n", node->name);
489 PARAM_DUMP("trigger condition: %s \n", node->condition);
490 const int maxCmd = 1024;
491 int count = 0;
492 CommandNode *cmd = GetNextCmdNode(node, NULL);
493 while (cmd != NULL && count < maxCmd) {
494 PARAM_DUMP(" command name: %s (%s) \n", GetCmdKey(cmd->cmdKeyIndex),
495 (cmd->cfgContext.type == INIT_CONTEXT_CHIPSET) ? "chipset" : "system");
496 PARAM_DUMP(" command args : %s \n", cmd->content);
497 cmd = GetNextCmdNode(node, cmd);
498 count++;
499 }
500 }
501
DumpWatchTrigger_(const TriggerWorkSpace * workSpace,const TriggerNode * trigger)502 static void DumpWatchTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger)
503 {
504 const WatchNode *node = (const WatchNode *)trigger;
505 PARAM_DUMP("trigger flags: 0x%08x \n", trigger->flags);
506 PARAM_DUMP("trigger condition: %s \n", trigger->condition);
507 PARAM_DUMP("trigger watchId: %d \n", node->watchId);
508 }
509
DumpWaitTrigger_(const TriggerWorkSpace * workSpace,const TriggerNode * trigger)510 static void DumpWaitTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger)
511 {
512 const WaitNode *node = (const WaitNode *)trigger;
513 PARAM_DUMP("trigger flags: 0x%08x \n", trigger->flags);
514 PARAM_DUMP("trigger name: %s \n", GetTriggerName(trigger));
515 PARAM_DUMP("trigger condition: %s \n", trigger->condition);
516 PARAM_DUMP("trigger waitId: %d \n", node->waitId);
517 PARAM_DUMP("trigger timeout: %d \n", node->timeout);
518 }
519
DumpTrigger_(const TriggerWorkSpace * workSpace,int type)520 static void DumpTrigger_(const TriggerWorkSpace *workSpace, int type)
521 {
522 PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace ");
523 TriggerHeader *head = GetTriggerHeader(workSpace, type);
524 PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
525 TriggerNode *trigger = head->nextTrigger(head, NULL);
526 while (trigger != NULL) {
527 head->dumpTrigger(workSpace, trigger);
528 trigger = head->nextTrigger(head, trigger);
529 }
530 }
531
SystemDumpTriggers(int verbose,int (* dump)(const char * fmt,...))532 void SystemDumpTriggers(int verbose, int (*dump)(const char *fmt, ...))
533 {
534 if (dump != NULL) {
535 g_printf = dump;
536 } else {
537 g_printf = printf;
538 }
539 TriggerWorkSpace *workSpace = GetTriggerWorkSpace();
540 PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace ");
541 PARAM_DUMP("workspace queue BOOT info:\n");
542 DumpTrigger_(workSpace, TRIGGER_BOOT);
543 PARAM_DUMP("workspace queue parameter info:\n");
544 DumpTrigger_(workSpace, TRIGGER_PARAM);
545 PARAM_DUMP("workspace queue other info:\n");
546 DumpTrigger_(workSpace, TRIGGER_UNKNOW);
547 PARAM_DUMP("workspace queue watch info:\n");
548 DumpTrigger_(workSpace, TRIGGER_PARAM_WATCH);
549 PARAM_DUMP("workspace queue wait info:\n");
550 DumpTrigger_(workSpace, TRIGGER_PARAM_WAIT);
551
552 PARAM_DUMP("workspace queue execute info:\n");
553 PARAM_DUMP("queue info count: %u start: %u end: %u\n",
554 workSpace->executeQueue.queueCount, workSpace->executeQueue.startIndex, workSpace->executeQueue.endIndex);
555 for (uint32_t index = workSpace->executeQueue.startIndex; index < workSpace->executeQueue.endIndex; index++) {
556 TriggerNode *trigger = workSpace->executeQueue.executeQueue[index % workSpace->executeQueue.queueCount];
557 if (trigger != 0) {
558 PARAM_DUMP(" queue node trigger name: %s \n", GetTriggerName(trigger));
559 }
560 }
561 }
562
CompareData_(const struct tagTriggerNode_ * trigger,const void * data)563 static int32_t CompareData_(const struct tagTriggerNode_ *trigger, const void *data)
564 {
565 PARAM_CHECK(trigger != NULL && data != NULL, return -1, "Invalid trigger");
566 if (trigger->type == TRIGGER_PARAM_WAIT) {
567 WaitNode *node = (WaitNode *)trigger;
568 return node->waitId - *(uint32_t *)data;
569 } else if (trigger->type == TRIGGER_PARAM_WATCH) {
570 WatchNode *node = (WatchNode *)trigger;
571 return node->watchId - *(uint32_t *)data;
572 }
573 return -1;
574 }
575
TriggerHeadSetDefault(TriggerHeader * head)576 static void TriggerHeadSetDefault(TriggerHeader *head)
577 {
578 OH_ListInit(&head->triggerList);
579 head->triggerCount = 0;
580 head->cmdNodeCount = 0;
581 head->addTrigger = AddJobTrigger_;
582 head->nextTrigger = GetNextTrigger_;
583 head->delTrigger = DelJobTrigger_;
584 head->executeTrigger = NULL;
585 head->checkAndMarkTrigger = CheckAndMarkTrigger_;
586 head->checkTriggerMatch = CheckBootMatch_;
587 head->checkCondition = CheckBootCondition_;
588 head->getCondition = GetBootCondition_;
589 head->getTriggerName = GetJobName_;
590 head->dumpTrigger = DumpJobTrigger_;
591 head->compareData = CompareData_;
592 }
593
JobNodeNodeCompare(const HashNode * node1,const HashNode * node2)594 static int JobNodeNodeCompare(const HashNode *node1, const HashNode *node2)
595 {
596 JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode);
597 JobNode *jobNode2 = HASHMAP_ENTRY(node2, JobNode, hashNode);
598 return strcmp(jobNode1->name, jobNode2->name);
599 }
600
JobNodeKeyCompare(const HashNode * node1,const void * key)601 static int JobNodeKeyCompare(const HashNode *node1, const void *key)
602 {
603 JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode);
604 return strcmp(jobNode1->name, (char *)key);
605 }
606
JobNodeGetNodeHasCode(const HashNode * node)607 static int JobNodeGetNodeHasCode(const HashNode *node)
608 {
609 JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode);
610 int code = 0;
611 size_t nameLen = strlen(jobNode->name);
612 for (size_t i = 0; i < nameLen; i++) {
613 code += jobNode->name[i] - 'A';
614 }
615 return code;
616 }
617
JobNodeGetKeyHasCode(const void * key)618 static int JobNodeGetKeyHasCode(const void *key)
619 {
620 int code = 0;
621 const char *buff = (char *)key;
622 size_t buffLen = strlen(buff);
623 for (size_t i = 0; i < buffLen; i++) {
624 code += buff[i] - 'A';
625 }
626 return code;
627 }
628
JobNodeFree(const HashNode * node,void * context)629 static void JobNodeFree(const HashNode *node, void *context)
630 {
631 JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode);
632 FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)jobNode);
633 }
634
InitTriggerHead(const TriggerWorkSpace * workSpace)635 void InitTriggerHead(const TriggerWorkSpace *workSpace)
636 {
637 HashInfo info = {
638 JobNodeNodeCompare,
639 JobNodeKeyCompare,
640 JobNodeGetNodeHasCode,
641 JobNodeGetKeyHasCode,
642 JobNodeFree,
643 64
644 };
645 PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace");
646 int ret = OH_HashMapCreate((HashMapHandle *)&workSpace->hashMap, &info);
647 PARAM_CHECK(ret == 0, return, "Failed to create hash map");
648
649 TriggerHeader *head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_BOOT];
650 TriggerHeadSetDefault(head);
651 // param trigger
652 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM];
653 TriggerHeadSetDefault(head);
654 head->checkTriggerMatch = CheckParamMatch_;
655 head->checkCondition = CheckParamCondition_;
656 head->getCondition = GetTriggerCondition_;
657 // unknown trigger
658 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_UNKNOW];
659 TriggerHeadSetDefault(head);
660 head->checkTriggerMatch = CheckUnknowMatch_;
661 head->checkCondition = CheckUnknowCondition_;
662 head->getCondition = GetTriggerCondition_;
663 // wait trigger
664 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WAIT];
665 TriggerHeadSetDefault(head);
666 head->addTrigger = AddWatchTrigger_;
667 head->delTrigger = DelWatchTrigger_;
668 head->checkTriggerMatch = CheckParamMatch_;
669 head->checkCondition = CheckParamCondition_;
670 head->getCondition = GetTriggerCondition_;
671 head->dumpTrigger = DumpWaitTrigger_;
672 head->getTriggerName = GetWatchName_;
673 // watch trigger
674 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WATCH];
675 TriggerHeadSetDefault(head);
676 head->addTrigger = AddWatchTrigger_;
677 head->delTrigger = DelWatchTrigger_;
678 head->checkTriggerMatch = CheckBootMatch_;
679 head->checkCondition = CheckWatchCondition_;
680 head->getCondition = GetTriggerCondition_;
681 head->dumpTrigger = DumpWatchTrigger_;
682 head->getTriggerName = GetWatchName_;
683 }
684
DelWatchTrigger(int type,const void * data)685 void DelWatchTrigger(int type, const void *data)
686 {
687 PARAM_CHECK(data != NULL, return, "Invalid data");
688 TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type);
689 PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
690 PARAM_CHECK(head->compareData != NULL, return, "Invalid compareData");
691 TriggerNode *trigger = head->nextTrigger(head, NULL);
692 while (trigger != NULL) {
693 if (head->compareData(trigger, data) == 0) {
694 head->delTrigger(GetTriggerWorkSpace(), trigger);
695 return;
696 }
697 trigger = head->nextTrigger(head, trigger);
698 }
699 }
700
ClearWatchTrigger(ParamWatcher * watcher,int type)701 void ClearWatchTrigger(ParamWatcher *watcher, int type)
702 {
703 PARAM_CHECK(watcher != NULL, return, "Invalid watcher");
704 TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type);
705 PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
706 ListNode *node = watcher->triggerHead.next;
707 while (node != &watcher->triggerHead) {
708 TriggerNode *trigger = NULL;
709 if (type == TRIGGER_PARAM_WAIT) {
710 trigger = (TriggerNode *)ListEntry(node, WaitNode, item);
711 } else if (type == TRIGGER_PARAM_WATCH) {
712 trigger = (TriggerNode *)ListEntry(node, WatchNode, item);
713 }
714 if (trigger == NULL || type != trigger->type) {
715 PARAM_LOGE("ClearWatchTrigger %s error type %d", GetTriggerName(trigger), type);
716 return;
717 }
718 PARAM_LOGV("ClearWatchTrigger %s", GetTriggerName(trigger));
719 ListNode *next = node->next;
720 FreeTrigger(GetTriggerWorkSpace(), trigger);
721 node = next;
722 }
723 }
724
CheckWatchTriggerTimeout(void)725 int CheckWatchTriggerTimeout(void)
726 {
727 TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), TRIGGER_PARAM_WAIT);
728 PARAM_CHECK(head != NULL && head->nextTrigger != NULL, return 0, "Invalid header");
729 int hasNode = 0;
730 WaitNode *node = (WaitNode *)head->nextTrigger(head, NULL);
731 while (node != NULL) {
732 WaitNode *next = (WaitNode *)head->nextTrigger(head, (TriggerNode *)node);
733 if (node->timeout > 0) {
734 node->timeout--;
735 } else {
736 head->executeTrigger((TriggerNode*)node, NULL, 0);
737 FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)node);
738 }
739 hasNode = 1;
740 node = next;
741 }
742 return hasNode;
743 }
744
GetTriggerHeader(const TriggerWorkSpace * workSpace,int type)745 TriggerHeader *GetTriggerHeader(const TriggerWorkSpace *workSpace, int type)
746 {
747 if (workSpace == NULL || type >= TRIGGER_MAX) {
748 return NULL;
749 }
750 return (TriggerHeader *)&workSpace->triggerHead[type];
751 }
752
GetTriggerCache(uint32_t * size)753 char *GetTriggerCache(uint32_t *size)
754 {
755 TriggerWorkSpace *space = GetTriggerWorkSpace();
756 if (space == NULL) {
757 return NULL;
758 }
759 if (size != NULL) {
760 *size = sizeof(space->cache) / sizeof(space->cache[0]);
761 }
762 return space->cache;
763 }
764
GetTriggerName(const TriggerNode * trigger)765 const char *GetTriggerName(const TriggerNode *trigger)
766 {
767 PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
768 TriggerHeader *triggerHead = GetTriggerHeader(GetTriggerWorkSpace(), trigger->type);
769 if (triggerHead) {
770 return triggerHead->getTriggerName(trigger);
771 }
772 return "";
773 }
774