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 26static DUMP_PRINTF g_printf = printf; 27 28int 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 62CommandNode *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 71static 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 85static 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 102static 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 114static 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 138static 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 176static 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 203static void DelWatchTrigger_(const TriggerWorkSpace *workSpace, TriggerNode *trigger) 204{ 205 PARAM_CHECK(workSpace != NULL && trigger != 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 225static 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 240static const char *GetTriggerCondition_(const TriggerNode *trigger) 241{ 242 return (trigger == NULL || trigger->condition == NULL) ? "" : trigger->condition; 243} 244 245static 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 253static 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 261static 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 269JobNode *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 291JobNode *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 302void 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 311void 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 325int 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 333TriggerNode *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 349static 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 359static 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 370static 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 383static 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 392static 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 409static 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 417static 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 432static 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 446int32_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 467int 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 484static 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 502static void DumpWatchTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger) 503{ 504 PARAM_CHECK(trigger != NULL, return, "Empty trigger"); 505 const WatchNode *node = (const WatchNode *)trigger; 506 PARAM_DUMP("trigger flags: 0x%08x \n", trigger->flags); 507 PARAM_DUMP("trigger condition: %s \n", trigger->condition); 508 PARAM_DUMP("trigger watchId: %d \n", node->watchId); 509} 510 511static void DumpWaitTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger) 512{ 513 PARAM_CHECK(trigger != NULL, return, "Empty trigger"); 514 const WaitNode *node = (const WaitNode *)trigger; 515 PARAM_DUMP("trigger flags: 0x%08x \n", trigger->flags); 516 PARAM_DUMP("trigger name: %s \n", GetTriggerName(trigger)); 517 PARAM_DUMP("trigger condition: %s \n", trigger->condition); 518 PARAM_DUMP("trigger waitId: %d \n", node->waitId); 519 PARAM_DUMP("trigger timeout: %d \n", node->timeout); 520} 521 522static void DumpTrigger_(const TriggerWorkSpace *workSpace, int type) 523{ 524 PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace "); 525 TriggerHeader *head = GetTriggerHeader(workSpace, type); 526 PARAM_CHECK(head != NULL, return, "Failed to get header %d", type); 527 TriggerNode *trigger = head->nextTrigger(head, NULL); 528 while (trigger != NULL) { 529 head->dumpTrigger(workSpace, trigger); 530 trigger = head->nextTrigger(head, trigger); 531 } 532} 533 534void SystemDumpTriggers(int verbose, int (*dump)(const char *fmt, ...)) 535{ 536 if (dump != NULL) { 537 g_printf = dump; 538 } else { 539 g_printf = printf; 540 } 541 TriggerWorkSpace *workSpace = GetTriggerWorkSpace(); 542 PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace "); 543 PARAM_DUMP("workspace queue BOOT info:\n"); 544 DumpTrigger_(workSpace, TRIGGER_BOOT); 545 PARAM_DUMP("workspace queue parameter info:\n"); 546 DumpTrigger_(workSpace, TRIGGER_PARAM); 547 PARAM_DUMP("workspace queue other info:\n"); 548 DumpTrigger_(workSpace, TRIGGER_UNKNOW); 549 PARAM_DUMP("workspace queue watch info:\n"); 550 DumpTrigger_(workSpace, TRIGGER_PARAM_WATCH); 551 PARAM_DUMP("workspace queue wait info:\n"); 552 DumpTrigger_(workSpace, TRIGGER_PARAM_WAIT); 553 554 PARAM_DUMP("workspace queue execute info:\n"); 555 PARAM_DUMP("queue info count: %u start: %u end: %u\n", 556 workSpace->executeQueue.queueCount, workSpace->executeQueue.startIndex, workSpace->executeQueue.endIndex); 557 for (uint32_t index = workSpace->executeQueue.startIndex; index < workSpace->executeQueue.endIndex; index++) { 558 TriggerNode *trigger = workSpace->executeQueue.executeQueue[index % workSpace->executeQueue.queueCount]; 559 if (trigger != 0) { 560 PARAM_DUMP(" queue node trigger name: %s \n", GetTriggerName(trigger)); 561 } 562 } 563} 564 565static int32_t CompareData_(const struct tagTriggerNode_ *trigger, const void *data) 566{ 567 PARAM_CHECK(trigger != NULL && data != NULL, return -1, "Invalid trigger"); 568 if (trigger->type == TRIGGER_PARAM_WAIT) { 569 WaitNode *node = (WaitNode *)trigger; 570 return node->waitId - *(uint32_t *)data; 571 } else if (trigger->type == TRIGGER_PARAM_WATCH) { 572 WatchNode *node = (WatchNode *)trigger; 573 return node->watchId - *(uint32_t *)data; 574 } 575 return -1; 576} 577 578static void TriggerHeadSetDefault(TriggerHeader *head) 579{ 580 OH_ListInit(&head->triggerList); 581 head->triggerCount = 0; 582 head->cmdNodeCount = 0; 583 head->addTrigger = AddJobTrigger_; 584 head->nextTrigger = GetNextTrigger_; 585 head->delTrigger = DelJobTrigger_; 586 head->executeTrigger = NULL; 587 head->checkAndMarkTrigger = CheckAndMarkTrigger_; 588 head->checkTriggerMatch = CheckBootMatch_; 589 head->checkCondition = CheckBootCondition_; 590 head->getCondition = GetBootCondition_; 591 head->getTriggerName = GetJobName_; 592 head->dumpTrigger = DumpJobTrigger_; 593 head->compareData = CompareData_; 594} 595 596static int JobNodeNodeCompare(const HashNode *node1, const HashNode *node2) 597{ 598 JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode); 599 JobNode *jobNode2 = HASHMAP_ENTRY(node2, JobNode, hashNode); 600 return strcmp(jobNode1->name, jobNode2->name); 601} 602 603static int JobNodeKeyCompare(const HashNode *node1, const void *key) 604{ 605 JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode); 606 return strcmp(jobNode1->name, (char *)key); 607} 608 609static int JobNodeGetNodeHasCode(const HashNode *node) 610{ 611 JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode); 612 int code = 0; 613 size_t nameLen = strlen(jobNode->name); 614 for (size_t i = 0; i < nameLen; i++) { 615 code += jobNode->name[i] - 'A'; 616 } 617 return code; 618} 619 620static int JobNodeGetKeyHasCode(const void *key) 621{ 622 int code = 0; 623 const char *buff = (char *)key; 624 size_t buffLen = strlen(buff); 625 for (size_t i = 0; i < buffLen; i++) { 626 code += buff[i] - 'A'; 627 } 628 return code; 629} 630 631static void JobNodeFree(const HashNode *node, void *context) 632{ 633 JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode); 634 FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)jobNode); 635} 636 637void InitTriggerHead(const TriggerWorkSpace *workSpace) 638{ 639 HashInfo info = { 640 JobNodeNodeCompare, 641 JobNodeKeyCompare, 642 JobNodeGetNodeHasCode, 643 JobNodeGetKeyHasCode, 644 JobNodeFree, 645 64 646 }; 647 PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace"); 648 int ret = OH_HashMapCreate((HashMapHandle *)&workSpace->hashMap, &info); 649 PARAM_CHECK(ret == 0, return, "Failed to create hash map"); 650 651 TriggerHeader *head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_BOOT]; 652 TriggerHeadSetDefault(head); 653 // param trigger 654 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM]; 655 TriggerHeadSetDefault(head); 656 head->checkTriggerMatch = CheckParamMatch_; 657 head->checkCondition = CheckParamCondition_; 658 head->getCondition = GetTriggerCondition_; 659 // unknown trigger 660 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_UNKNOW]; 661 TriggerHeadSetDefault(head); 662 head->checkTriggerMatch = CheckUnknowMatch_; 663 head->checkCondition = CheckUnknowCondition_; 664 head->getCondition = GetTriggerCondition_; 665 // wait trigger 666 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WAIT]; 667 TriggerHeadSetDefault(head); 668 head->addTrigger = AddWatchTrigger_; 669 head->delTrigger = DelWatchTrigger_; 670 head->checkTriggerMatch = CheckParamMatch_; 671 head->checkCondition = CheckParamCondition_; 672 head->getCondition = GetTriggerCondition_; 673 head->dumpTrigger = DumpWaitTrigger_; 674 head->getTriggerName = GetWatchName_; 675 // watch trigger 676 head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WATCH]; 677 TriggerHeadSetDefault(head); 678 head->addTrigger = AddWatchTrigger_; 679 head->delTrigger = DelWatchTrigger_; 680 head->checkTriggerMatch = CheckBootMatch_; 681 head->checkCondition = CheckWatchCondition_; 682 head->getCondition = GetTriggerCondition_; 683 head->dumpTrigger = DumpWatchTrigger_; 684 head->getTriggerName = GetWatchName_; 685} 686 687void DelWatchTrigger(int type, const void *data) 688{ 689 PARAM_CHECK(data != NULL, return, "Invalid data"); 690 TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type); 691 PARAM_CHECK(head != NULL, return, "Failed to get header %d", type); 692 PARAM_CHECK(head->compareData != NULL, return, "Invalid compareData"); 693 TriggerNode *trigger = head->nextTrigger(head, NULL); 694 while (trigger != NULL) { 695 if (head->compareData(trigger, data) == 0) { 696 head->delTrigger(GetTriggerWorkSpace(), trigger); 697 return; 698 } 699 trigger = head->nextTrigger(head, trigger); 700 } 701} 702 703void ClearWatchTrigger(ParamWatcher *watcher, int type) 704{ 705 PARAM_CHECK(watcher != NULL, return, "Invalid watcher"); 706 TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type); 707 PARAM_CHECK(head != NULL, return, "Failed to get header %d", type); 708 ListNode *node = watcher->triggerHead.next; 709 while (node != &watcher->triggerHead) { 710 TriggerNode *trigger = NULL; 711 if (type == TRIGGER_PARAM_WAIT) { 712 trigger = (TriggerNode *)ListEntry(node, WaitNode, item); 713 } else if (type == TRIGGER_PARAM_WATCH) { 714 trigger = (TriggerNode *)ListEntry(node, WatchNode, item); 715 } 716 if (trigger == NULL || type != trigger->type) { 717 PARAM_LOGE("ClearWatchTrigger %s error type %d", GetTriggerName(trigger), type); 718 return; 719 } 720 PARAM_LOGV("ClearWatchTrigger %s", GetTriggerName(trigger)); 721 ListNode *next = node->next; 722 FreeTrigger(GetTriggerWorkSpace(), trigger); 723 node = next; 724 } 725} 726 727int CheckWatchTriggerTimeout(void) 728{ 729 TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), TRIGGER_PARAM_WAIT); 730 PARAM_CHECK(head != NULL && head->nextTrigger != NULL, return 0, "Invalid header"); 731 int hasNode = 0; 732 WaitNode *node = (WaitNode *)head->nextTrigger(head, NULL); 733 while (node != NULL) { 734 WaitNode *next = (WaitNode *)head->nextTrigger(head, (TriggerNode *)node); 735 if (node->timeout > 0) { 736 node->timeout--; 737 } else { 738 head->executeTrigger((TriggerNode*)node, NULL, 0); 739 FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)node); 740 } 741 hasNode = 1; 742 node = next; 743 } 744 return hasNode; 745} 746 747TriggerHeader *GetTriggerHeader(const TriggerWorkSpace *workSpace, int type) 748{ 749 if (workSpace == NULL || type >= TRIGGER_MAX) { 750 return NULL; 751 } 752 return (TriggerHeader *)&workSpace->triggerHead[type]; 753} 754 755char *GetTriggerCache(uint32_t *size) 756{ 757 TriggerWorkSpace *space = GetTriggerWorkSpace(); 758 if (space == NULL) { 759 return NULL; 760 } 761 if (size != NULL) { 762 *size = sizeof(space->cache) / sizeof(space->cache[0]); 763 } 764 return space->cache; 765} 766 767const char *GetTriggerName(const TriggerNode *trigger) 768{ 769 PARAM_CHECK(trigger != NULL, return "", "Invalid trigger"); 770 TriggerHeader *triggerHead = GetTriggerHeader(GetTriggerWorkSpace(), trigger->type); 771 if (triggerHead) { 772 return triggerHead->getTriggerName(trigger); 773 } 774 return ""; 775} 776