• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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