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 <errno.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include <sys/mman.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 #include "init_cmds.h"
27 #include "param_manager.h"
28 #include "trigger_checker.h"
29
AddCommand(JobNode * trigger,uint32_t cmdKeyIndex,const char * content)30 int AddCommand(JobNode *trigger, uint32_t cmdKeyIndex, const char *content)
31 {
32 PARAM_CHECK(trigger != NULL, return -1, "trigger is null");
33 uint32_t size = sizeof(CommandNode);
34 size += (content == NULL) ? 1 : (strlen(content) + 1);
35 size = PARAM_ALIGN(size);
36
37 CommandNode *node = (CommandNode *)calloc(1, size);
38 PARAM_CHECK(node != NULL, return -1, "Failed to alloc memory for command");
39 node->cmdKeyIndex = cmdKeyIndex;
40 node->next = NULL;
41 node->content[0] = '\0';
42 if (content != NULL && strlen(content) != 0) {
43 int ret = memcpy_s(node->content, size, content, strlen(content));
44 node->content[strlen(content)] = '\0';
45 PARAM_CHECK(ret == EOK, free(node);
46 return 0, "Failed to copy command");
47 }
48 // 插入队列
49 if (trigger->firstCmd == NULL) {
50 trigger->firstCmd = node;
51 trigger->lastCmd = node;
52 } else {
53 PARAM_CHECK(trigger->lastCmd != NULL, free(node);
54 return 0, "Invalid last cmd");
55 trigger->lastCmd->next = node;
56 trigger->lastCmd = node;
57 }
58 return 0;
59 }
60
GetNextCmdNode(const JobNode * trigger,const CommandNode * curr)61 CommandNode *GetNextCmdNode(const JobNode *trigger, const CommandNode *curr)
62 {
63 PARAM_CHECK(trigger != NULL, return NULL, "trigger is null");
64 if (curr == NULL) {
65 return trigger->firstCmd;
66 }
67 return curr->next;
68 }
69
CopyCondition(TriggerNode * node,const char * condition)70 static int CopyCondition(TriggerNode *node, const char *condition)
71 {
72 if (condition == NULL || strlen(condition) == 0) {
73 return 0;
74 }
75 uint32_t buffSize = 0;
76 char *cond = GetTriggerCache(&buffSize);
77 int ret = ConvertInfixToPrefix(condition, cond, buffSize);
78 PARAM_CHECK(ret == 0, return -1, "Failed to convert condition for trigger");
79 node->condition = strdup(cond);
80 PARAM_CHECK(node->condition != NULL, return -1, "Failed to dup conditition");
81 return 0;
82 }
83
AddTriggerNode_(TriggerHeader * triggerHead,uint32_t type,const char * condition,uint32_t dataSize)84 static TriggerNode *AddTriggerNode_(TriggerHeader *triggerHead,
85 uint32_t type, const char *condition, uint32_t dataSize)
86 {
87 TriggerNode *node = (TriggerNode *)calloc(1, dataSize);
88 PARAM_CHECK(node != NULL, return NULL, "Failed to alloc memory for trigger");
89 node->condition = NULL;
90 int ret = CopyCondition(node, condition);
91 PARAM_CHECK(ret == 0, free(node);
92 return NULL, "Failed to copy conditition");
93 node->type = type;
94 node->flags = 0;
95 ListInit(&node->node);
96 ListAddTail(&triggerHead->triggerList, &node->node);
97 triggerHead->triggerCount++;
98 return node;
99 }
100
AddJobNode_(TriggerNode * trigger,const TriggerExtInfo * extInfo)101 static int32_t AddJobNode_(TriggerNode *trigger, const TriggerExtInfo *extInfo)
102 {
103 JobNode *node = (JobNode *)trigger;
104 int ret = strcpy_s(node->name, strlen(extInfo->info.name) + 1, extInfo->info.name);
105 PARAM_CHECK(ret == EOK, return -1, "Failed to copy name for trigger");
106 node->firstCmd = NULL;
107 node->lastCmd = NULL;
108 ret = HashMapAdd(GetTriggerWorkSpace()->hashMap, &node->hashNode);
109 PARAM_CHECK(ret == 0, return -1, "Failed to add hash node");
110 return 0;
111 }
112
AddJobTrigger_(const TriggerWorkSpace * workSpace,const char * condition,const TriggerExtInfo * extInfo)113 static TriggerNode *AddJobTrigger_(const TriggerWorkSpace *workSpace,
114 const char *condition, const TriggerExtInfo *extInfo)
115 {
116 PARAM_CHECK(workSpace != NULL, return NULL, "workSpace is null");
117 PARAM_CHECK(extInfo != NULL && extInfo->addNode != NULL, return NULL, "extInfo is null");
118 PARAM_CHECK(extInfo->type <= TRIGGER_UNKNOW, return NULL, "Invalid type");
119 TriggerHeader *triggerHead = GetTriggerHeader(workSpace, extInfo->type);
120 PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", extInfo->type);
121 uint32_t nameLen = strlen(extInfo->info.name);
122 uint32_t triggerNodeLen = PARAM_ALIGN(nameLen + 1) + sizeof(JobNode);
123 TriggerNode *node = (TriggerNode *)AddTriggerNode_(triggerHead, extInfo->type, condition, triggerNodeLen);
124 PARAM_CHECK(node != NULL, return NULL, "Failed to alloc jobnode");
125 int ret = extInfo->addNode(node, extInfo);
126 PARAM_CHECK(ret == 0, FreeTrigger(workSpace, node);
127 return NULL, "Failed to add hash node");
128 if (extInfo->type == TRIGGER_BOOT) {
129 TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_ONCE);
130 TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_SUBTRIGGER);
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 ListRemove(&trigger->node);
156 triggerHead->triggerCount--;
157 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 ListRemove(&trigger->node);
206 if (trigger->type == TRIGGER_PARAM_WAIT) {
207 WaitNode *node = (WaitNode *)trigger;
208 ListRemove(&node->item);
209 } else if (trigger->type == TRIGGER_PARAM_WATCH) {
210 WatchNode *node = (WatchNode *)trigger;
211 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 = 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 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 const char *condition = head->getCondition(trigger);
393 if (head->checkCondition(calculator, condition, content, contentSize) == 1) {
394 calculator->triggerCheckDone(trigger, content, contentSize);
395 }
396 trigger = head->nextTrigger(head, trigger);
397 }
398 return 0;
399 }
400
CheckBootMatch_(const TriggerWorkSpace * workSpace,int type,LogicCalculator * calculator,const char * content,uint32_t contentSize)401 static int CheckBootMatch_(const TriggerWorkSpace *workSpace,
402 int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
403 {
404 PARAM_CHECK(workSpace != NULL, return -1, "Invaid space");
405 PARAM_CHECK((type == TRIGGER_BOOT) || (type == TRIGGER_PARAM_WATCH), return -1, "Invaid type");
406 return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
407 }
408
CheckParamMatch_(const TriggerWorkSpace * workSpace,int type,LogicCalculator * calculator,const char * content,uint32_t contentSize)409 static int CheckParamMatch_(const TriggerWorkSpace *workSpace,
410 int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
411 {
412 PARAM_CHECK(workSpace != NULL, return -1, "Invaid space");
413 PARAM_CHECK((type == TRIGGER_PARAM) || (type == TRIGGER_PARAM_WAIT), return -1, "Invaid type");
414
415 CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1);
416 int ret = GetValueFromContent(content, contentSize, 0, calculator->inputName, SUPPORT_DATA_BUFFER_MAX);
417 PARAM_CHECK(ret == 0, return -1, "Failed parse content name");
418 ret = GetValueFromContent(content, contentSize,
419 strlen(calculator->inputName) + 1, calculator->inputContent, SUPPORT_DATA_BUFFER_MAX);
420 PARAM_CHECK(ret == 0, return -1, "Failed parse content value");
421 return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
422 }
423
CheckUnknowMatch_(const TriggerWorkSpace * workSpace,int type,LogicCalculator * calculator,const char * content,uint32_t contentSize)424 static int CheckUnknowMatch_(const TriggerWorkSpace *workSpace,
425 int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
426 {
427 PARAM_CHECK(workSpace != NULL && content != NULL, return -1, "Failed arg for trigger");
428 PARAM_CHECK(type == TRIGGER_UNKNOW, return -1, "Invaid type");
429
430 CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1);
431 int ret = memcpy_s(calculator->triggerContent, sizeof(calculator->triggerContent), content, contentSize);
432 PARAM_CHECK(ret == EOK, return -1, "Failed to memcpy");
433 calculator->inputName = NULL;
434 calculator->inputContent = NULL;
435 return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
436 }
437
CheckAndMarkTrigger_(const TriggerWorkSpace * workSpace,int type,const char * name)438 int32_t CheckAndMarkTrigger_(const TriggerWorkSpace *workSpace, int type, const char *name)
439 {
440 PARAM_CHECK(workSpace != NULL && name != NULL, return 0, "Failed arg for trigger");
441 TriggerHeader *head = GetTriggerHeader(workSpace, type);
442 PARAM_CHECK(head != NULL, return 0, "Failed to get header %d", type);
443 int ret = 0;
444 TriggerNode *trigger = head->nextTrigger(head, NULL);
445 while (trigger != NULL) {
446 if (head->getCondition(trigger) == NULL) {
447 trigger = head->nextTrigger(head, trigger);
448 continue;
449 }
450 const char *tmp = strstr(head->getCondition(trigger), name);
451 if (tmp != NULL && strncmp(tmp + strlen(name), "=", 1) == 0) {
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 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("\t command name %s \n", GetCmdKey(cmd->cmdKeyIndex));
488 PARAM_DUMP("\t 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 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 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
DumpTrigger(const TriggerWorkSpace * workSpace)524 void DumpTrigger(const TriggerWorkSpace *workSpace)
525 {
526 PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace ");
527 PARAM_DUMP("Ready to dump all trigger memory \n");
528 PARAM_DUMP("workspace queue BOOT info:\n");
529 DumpTrigger_(workSpace, TRIGGER_BOOT);
530 PARAM_DUMP("workspace queue parameter info:\n");
531 DumpTrigger_(workSpace, TRIGGER_PARAM);
532 PARAM_DUMP("workspace queue other info:\n");
533 DumpTrigger_(workSpace, TRIGGER_UNKNOW);
534 PARAM_DUMP("workspace queue watch info:\n");
535 DumpTrigger_(workSpace, TRIGGER_PARAM_WATCH);
536 PARAM_DUMP("workspace queue wait info:\n");
537 DumpTrigger_(workSpace, TRIGGER_PARAM_WAIT);
538
539 PARAM_DUMP("workspace queue execute info:\n");
540 PARAM_DUMP("queue info count: %u start: %u end: %u\n",
541 workSpace->executeQueue.queueCount, workSpace->executeQueue.startIndex, workSpace->executeQueue.endIndex);
542 for (uint32_t index = workSpace->executeQueue.startIndex; index < workSpace->executeQueue.endIndex; index++) {
543 TriggerNode *trigger = workSpace->executeQueue.executeQueue[index % workSpace->executeQueue.queueCount];
544 if (trigger != 0) {
545 PARAM_DUMP("queue node trigger name: %s \n", GetTriggerName(trigger));
546 }
547 }
548 }
549
CompareData_(const struct tagTriggerNode_ * trigger,const void * data)550 static int32_t CompareData_(const struct tagTriggerNode_ *trigger, const void *data)
551 {
552 PARAM_CHECK(trigger != NULL && data != NULL, return -1, "Invalid trigger");
553 if (trigger->type == TRIGGER_PARAM_WAIT) {
554 WaitNode *node = (WaitNode *)trigger;
555 return node->waitId == *(uint32_t *)data;
556 } else if (trigger->type == TRIGGER_PARAM_WATCH) {
557 WatchNode *node = (WatchNode *)trigger;
558 return node->watchId == *(uint32_t *)data;
559 }
560 return -1;
561 }
562
TriggerHeadSetDefault(TriggerHeader * head)563 static void TriggerHeadSetDefault(TriggerHeader *head)
564 {
565 ListInit(&head->triggerList);
566 head->triggerCount = 0;
567 head->cmdNodeCount = 0;
568 head->addTrigger = AddJobTrigger_;
569 head->nextTrigger = GetNextTrigger_;
570 head->delTrigger = DelJobTrigger_;
571 head->executeTrigger = NULL;
572 head->checkAndMarkTrigger = CheckAndMarkTrigger_;
573 head->checkTriggerMatch = CheckBootMatch_;
574 head->checkCondition = CheckBootCondition_;
575 head->getCondition = GetBootCondition_;
576 head->getTriggerName = GetJobName_;
577 head->dumpTrigger = DumpJobTrigger_;
578 head->compareData = CompareData_;
579 }
580
JobNodeNodeCompare(const HashNode * node1,const HashNode * node2)581 static int JobNodeNodeCompare(const HashNode *node1, const HashNode *node2)
582 {
583 JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode);
584 JobNode *jobNode2 = HASHMAP_ENTRY(node2, JobNode, hashNode);
585 return strcmp(jobNode1->name, jobNode2->name);
586 }
587
JobNodeKeyCompare(const HashNode * node1,const void * key)588 static int JobNodeKeyCompare(const HashNode *node1, const void *key)
589 {
590 JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode);
591 return strcmp(jobNode1->name, (char *)key);
592 }
593
JobNodeGetNodeHasCode(const HashNode * node)594 static int JobNodeGetNodeHasCode(const HashNode *node)
595 {
596 JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode);
597 int code = 0;
598 for (size_t i = 0; i < strlen(jobNode->name); i++) {
599 code += jobNode->name[i] - 'A';
600 }
601 return code;
602 }
603
JobNodeGetKeyHasCode(const void * key)604 static int JobNodeGetKeyHasCode(const void *key)
605 {
606 int code = 0;
607 const char *buff = (char *)key;
608 for (size_t i = 0; i < strlen(buff); i++) {
609 code += buff[i] - 'A';
610 }
611 return code;
612 }
613
JobNodeFree(const HashNode * node)614 static void JobNodeFree(const HashNode *node)
615 {
616 JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode);
617 FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)jobNode);
618 }
619
InitTriggerHead(const TriggerWorkSpace * workSpace)620 void InitTriggerHead(const TriggerWorkSpace *workSpace)
621 {
622 HashInfo info = {
623 JobNodeNodeCompare,
624 JobNodeKeyCompare,
625 JobNodeGetNodeHasCode,
626 JobNodeGetKeyHasCode,
627 JobNodeFree,
628 64
629 };
630 PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace");
631 int ret = HashMapCreate((HashMapHandle *)&workSpace->hashMap, &info);
632 PARAM_CHECK(ret == 0, return, "Failed to create hash map");
633
634 TriggerHeader *head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_BOOT];
635 TriggerHeadSetDefault(head);
636 // param trigger
637 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM];
638 TriggerHeadSetDefault(head);
639 head->checkTriggerMatch = CheckParamMatch_;
640 head->checkCondition = CheckParamCondition_;
641 head->getCondition = GetTriggerCondition_;
642 // unknow trigger
643 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_UNKNOW];
644 TriggerHeadSetDefault(head);
645 head->checkTriggerMatch = CheckUnknowMatch_;
646 head->checkCondition = CheckUnknowCondition_;
647 head->getCondition = GetTriggerCondition_;
648 // wait trigger
649 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WAIT];
650 TriggerHeadSetDefault(head);
651 head->addTrigger = AddWatchTrigger_;
652 head->delTrigger = DelWatchTrigger_;
653 head->checkTriggerMatch = CheckParamMatch_;
654 head->checkCondition = CheckParamCondition_;
655 head->getCondition = GetTriggerCondition_;
656 head->dumpTrigger = DumpWaitTrigger_;
657 head->getTriggerName = GetWatchName_;
658 // watch trigger
659 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WATCH];
660 TriggerHeadSetDefault(head);
661 head->addTrigger = AddWatchTrigger_;
662 head->delTrigger = DelWatchTrigger_;
663 head->checkTriggerMatch = CheckBootMatch_;
664 head->checkCondition = CheckWatchCondition_;
665 head->getCondition = GetTriggerCondition_;
666 head->dumpTrigger = DumpWatchTrigger_;
667 head->getTriggerName = GetWatchName_;
668 }
669
DelWatchTrigger(int type,const void * data)670 void DelWatchTrigger(int type, const void *data)
671 {
672 PARAM_CHECK(data != NULL, return, "Invalid data");
673 TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type);
674 PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
675 PARAM_CHECK(head->compareData != NULL, return, "Invalid compareData");
676 TriggerNode *trigger = head->nextTrigger(head, NULL);
677 while (trigger != NULL) {
678 if (head->compareData(trigger, data) == 0) {
679 head->delTrigger(GetTriggerWorkSpace(), trigger);
680 return;
681 }
682 trigger = head->nextTrigger(head, trigger);
683 }
684 }
685
ClearWatchTrigger(ParamWatcher * watcher,int type)686 void ClearWatchTrigger(ParamWatcher *watcher, int type)
687 {
688 PARAM_CHECK(watcher != NULL, return, "Invalid watcher");
689 TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type);
690 PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
691 ListNode *node = watcher->triggerHead.next;
692 while (node != &watcher->triggerHead) {
693 TriggerNode *trigger = NULL;
694 if (type == TRIGGER_PARAM_WAIT) {
695 trigger = (TriggerNode *)ListEntry(node, WaitNode, item);
696 } else if (type == TRIGGER_PARAM_WATCH) {
697 trigger = (TriggerNode *)ListEntry(node, WatchNode, item);
698 }
699 if (trigger == NULL || type != trigger->type) {
700 PARAM_LOGE("ClearWatchTrigger %s error type %d", GetTriggerName(trigger), type);
701 return;
702 }
703 PARAM_LOGV("ClearWatchTrigger %p %s", trigger, GetTriggerName(trigger));
704 ListNode *next = node->next;
705 FreeTrigger(GetTriggerWorkSpace(), trigger);
706 node = next;
707 }
708 }
709
CheckWatchTriggerTimeout(void)710 int CheckWatchTriggerTimeout(void)
711 {
712 TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), TRIGGER_PARAM_WAIT);
713 PARAM_CHECK(head != NULL && head->nextTrigger != NULL, return 0, "Invalid header");
714 int hasNode = 0;
715 WaitNode *node = (WaitNode *)head->nextTrigger(head, NULL);
716 while (node != NULL) {
717 WaitNode *next = (WaitNode *)head->nextTrigger(head, (TriggerNode *)node);
718 if (node->timeout > 0) {
719 node->timeout--;
720 } else {
721 head->executeTrigger((TriggerNode*)node, NULL, 0);
722 FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)node);
723 }
724 hasNode = 1;
725 node = next;
726 }
727 return hasNode;
728 }
729
GetTriggerHeader(const TriggerWorkSpace * workSpace,int type)730 TriggerHeader *GetTriggerHeader(const TriggerWorkSpace *workSpace, int type)
731 {
732 if (workSpace == NULL || type >= TRIGGER_MAX) {
733 return NULL;
734 }
735 return (TriggerHeader *)&workSpace->triggerHead[type];
736 }
737
GetTriggerCache(uint32_t * size)738 char *GetTriggerCache(uint32_t *size)
739 {
740 TriggerWorkSpace *space = GetTriggerWorkSpace();
741 if (space == NULL) {
742 return NULL;
743 }
744 if (size != NULL) {
745 *size = sizeof(space->cache) / sizeof(space->cache[0]);
746 }
747 return space->cache;
748 }
749
GetTriggerName(const TriggerNode * trigger)750 const char *GetTriggerName(const TriggerNode *trigger)
751 {
752 PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
753 TriggerHeader *triggerHead = GetTriggerHeader(GetTriggerWorkSpace(), trigger->type);
754 if (triggerHead) {
755 return triggerHead->getTriggerName(trigger);
756 }
757 return "";
758 }