• 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,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