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