trigger_manager.c 29.1 KB
Newer Older
Z
zhong_ning 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "trigger_manager.h"

#include <errno.h>
#include <fcntl.h>
S
sun_fan 已提交
20
#include <string.h>
Z
zhong_ning 已提交
21 22 23 24 25 26
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "init_cmds.h"
S
sun_fan 已提交
27
#include "param_manager.h"
Z
zhong_ning 已提交
28
#include "trigger_checker.h"
M
Mupceet 已提交
29
#include "securec.h"
Z
zhong_ning 已提交
30

X
xionglei6 已提交
31
int AddCommand(JobNode *trigger, uint32_t cmdKeyIndex, const char *content)
Z
zhong_ning 已提交
32
{
X
xionglei6 已提交
33
    PARAM_CHECK(trigger != NULL, return -1, "trigger is null");
S
sun_fan 已提交
34
    uint32_t size = sizeof(CommandNode);
4
411148299@qq.com 已提交
35
    size += (content == NULL) ? 1 : (strlen(content) + 1);
S
sun_fan 已提交
36 37
    size = PARAM_ALIGN(size);

4
411148299@qq.com 已提交
38
    CommandNode *node = (CommandNode *)calloc(1, size);
S
sun_fan 已提交
39 40 41 42 43 44 45
    PARAM_CHECK(node != NULL, return -1, "Failed to alloc memory for command");
    node->cmdKeyIndex = cmdKeyIndex;
    node->next = NULL;
    node->content[0] = '\0';
    if (content != NULL && strlen(content) != 0) {
        int ret = memcpy_s(node->content, size, content, strlen(content));
        node->content[strlen(content)] = '\0';
4
411148299@qq.com 已提交
46
        PARAM_CHECK(ret == EOK, free(node);
47
            return 0, "Failed to copy command");
Z
zhong_ning 已提交
48
    }
S
sun_fan 已提交
49 50 51 52 53
    // 插入队列
    if (trigger->firstCmd == NULL) {
        trigger->firstCmd = node;
        trigger->lastCmd = node;
    } else {
S
sun_fan 已提交
54 55
        PARAM_CHECK(trigger->lastCmd != NULL, free(node);
            return 0, "Invalid last cmd");
S
sun_fan 已提交
56 57
        trigger->lastCmd->next = node;
        trigger->lastCmd = node;
Z
zhong_ning 已提交
58 59 60 61
    }
    return 0;
}

X
xionglei6 已提交
62
CommandNode *GetNextCmdNode(const JobNode *trigger, const CommandNode *curr)
Z
zhong_ning 已提交
63
{
4
411148299@qq.com 已提交
64
    PARAM_CHECK(trigger != NULL, return NULL, "trigger is null");
S
sun_fan 已提交
65 66
    if (curr == NULL) {
        return trigger->firstCmd;
Z
zhong_ning 已提交
67
    }
S
sun_fan 已提交
68
    return curr->next;
Z
zhong_ning 已提交
69 70
}

X
xionglei6 已提交
71
static int CopyCondition(TriggerNode *node, const char *condition)
Z
zhong_ning 已提交
72
{
X
xionglei6 已提交
73 74
    if (condition == NULL || strlen(condition) == 0) {
        return 0;
Z
zhong_ning 已提交
75
    }
X
xionglei6 已提交
76 77 78 79 80 81 82 83
    uint32_t buffSize = 0;
    char *cond = GetTriggerCache(&buffSize);
    int ret = ConvertInfixToPrefix(condition, cond, buffSize);
    PARAM_CHECK(ret == 0, return -1, "Failed to convert condition for trigger");
    node->condition = strdup(cond);
    PARAM_CHECK(node->condition != NULL, return -1, "Failed to dup conditition");
    return 0;
}
Z
zhong_ning 已提交
84

X
xionglei6 已提交
85 86 87 88
static TriggerNode *AddTriggerNode_(TriggerHeader *triggerHead,
    uint32_t type, const char *condition, uint32_t dataSize)
{
    TriggerNode *node = (TriggerNode *)calloc(1, dataSize);
S
sun_fan 已提交
89 90
    PARAM_CHECK(node != NULL, return NULL, "Failed to alloc memory for trigger");
    node->condition = NULL;
X
xionglei6 已提交
91 92 93 94
    int ret = CopyCondition(node, condition);
    PARAM_CHECK(ret == 0, free(node);
            return NULL, "Failed to copy conditition");
    node->type = type;
S
sun_fan 已提交
95 96 97 98 99
    node->flags = 0;
    ListInit(&node->node);
    ListAddTail(&triggerHead->triggerList, &node->node);
    triggerHead->triggerCount++;
    return node;
Z
zhong_ning 已提交
100 101
}

X
xionglei6 已提交
102
static int32_t AddJobNode_(TriggerNode *trigger, const TriggerExtInfo *extInfo)
Z
zhong_ning 已提交
103
{
X
xionglei6 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
    JobNode *node = (JobNode *)trigger;
    int ret = strcpy_s(node->name, strlen(extInfo->info.name) + 1, extInfo->info.name);
    PARAM_CHECK(ret == EOK, return -1, "Failed to copy name for trigger");
    node->firstCmd = NULL;
    node->lastCmd = NULL;
    ret = HashMapAdd(GetTriggerWorkSpace()->hashMap, &node->hashNode);
    PARAM_CHECK(ret == 0, return -1, "Failed to add hash node");
    return 0;
}

static TriggerNode *AddJobTrigger_(const TriggerWorkSpace *workSpace,
    const char *condition, const TriggerExtInfo *extInfo)
{
    PARAM_CHECK(workSpace != NULL, return NULL, "workSpace is null");
    PARAM_CHECK(extInfo != NULL && extInfo->addNode != NULL, return NULL, "extInfo is null");
    PARAM_CHECK(extInfo->type <= TRIGGER_UNKNOW, return NULL, "Invalid type");
    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, extInfo->type);
    PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", extInfo->type);
    uint32_t nameLen = strlen(extInfo->info.name);
    uint32_t triggerNodeLen = PARAM_ALIGN(nameLen + 1) + sizeof(JobNode);
    TriggerNode *node = (TriggerNode *)AddTriggerNode_(triggerHead, extInfo->type, condition, triggerNodeLen);
    PARAM_CHECK(node != NULL, return NULL, "Failed to alloc jobnode");
    int ret = extInfo->addNode(node, extInfo);
    PARAM_CHECK(ret == 0, FreeTrigger(workSpace, node);
        return NULL, "Failed to add hash node");
    if (extInfo->type == TRIGGER_BOOT) {
        TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_ONCE);
        TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_SUBTRIGGER);
Z
zhong_ning 已提交
132
    }
X
xionglei6 已提交
133
    return node;
Z
zhong_ning 已提交
134 135
}

X
xionglei6 已提交
136
static void DelJobTrigger_(const TriggerWorkSpace *workSpace, TriggerNode *trigger)
Z
zhong_ning 已提交
137
{
X
xionglei6 已提交
138 139 140 141 142 143
    PARAM_CHECK(workSpace != NULL, return, "Param is null");
    PARAM_CHECK(trigger != NULL, return, "Trigger is null");
    JobNode *jobNode = (JobNode *)trigger;
    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, trigger->type);
    PARAM_CHECK(triggerHead != NULL, return, "Failed to get header %d", trigger->type);
    CommandNode *cmd = jobNode->firstCmd;
S
sun_fan 已提交
144 145 146
    while (cmd != NULL) {
        CommandNode *next = cmd->next;
        free(cmd);
X
xionglei6 已提交
147
        triggerHead->cmdNodeCount--;
S
sun_fan 已提交
148
        cmd = next;
Z
zhong_ning 已提交
149
    }
X
xionglei6 已提交
150 151 152
    if (jobNode->condition != NULL) {
        free(jobNode->condition);
        jobNode->condition = NULL;
X
xionglei6 已提交
153
    }
X
xionglei6 已提交
154 155 156 157 158
    jobNode->lastCmd = NULL;
    jobNode->firstCmd = NULL;
    ListRemove(&trigger->node);
    triggerHead->triggerCount--;
    HashMapRemove(workSpace->hashMap, jobNode->name);
S
sun_fan 已提交
159 160

    if (!TRIGGER_IN_QUEUE(trigger)) {
X
xionglei6 已提交
161
        free(jobNode);
S
sun_fan 已提交
162
        return;
Z
zhong_ning 已提交
163
    }
X
xionglei6 已提交
164
    TriggerExecuteQueue *executeQueue = (TriggerExecuteQueue *)&workSpace->executeQueue;
S
sun_fan 已提交
165 166 167 168
    for (uint32_t i = executeQueue->startIndex; i < executeQueue->endIndex; i++) {
        if (executeQueue->executeQueue[i] == trigger) {
            executeQueue->executeQueue[i] = NULL;
            break;
Z
zhong_ning 已提交
169 170
        }
    }
X
xionglei6 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
    free(jobNode);
}

static TriggerNode *AddWatchTrigger_(const TriggerWorkSpace *workSpace,
    const char *condition, const TriggerExtInfo *extInfo)
{
    PARAM_CHECK(workSpace != NULL, return NULL, "workSpace is null");
    PARAM_CHECK(extInfo != NULL && extInfo->addNode != NULL, return NULL, "extInfo is null");
    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, extInfo->type);
    PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", extInfo->type);
    uint32_t size = 0;
    if (extInfo->type == TRIGGER_PARAM_WATCH) {
        size = sizeof(WatchNode);
    } else if (extInfo->type == TRIGGER_PARAM_WAIT) {
        size = sizeof(WaitNode);
    } else {
        PARAM_LOGE("Invalid trigger type %d", extInfo->type);
        return NULL;
    }
    TriggerNode *node = AddTriggerNode_(triggerHead, extInfo->type, condition, size);
    PARAM_CHECK(node != NULL, return NULL, "Failed to alloc memory for trigger");
    int ret = extInfo->addNode(node, extInfo);
    PARAM_CHECK(ret == 0, FreeTrigger(workSpace, node);
        return NULL, "Failed to add node");
    if (extInfo->type == TRIGGER_PARAM_WAIT) {
        TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_ONCE);
    }
    return node;
}

static void DelWatchTrigger_(const TriggerWorkSpace *workSpace, TriggerNode *trigger)
{
    PARAM_CHECK(workSpace != NULL, return, "Param is null");
    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, trigger->type);
    PARAM_CHECK(triggerHead != NULL, return, "Failed to get header %d", trigger->type);
    ListRemove(&trigger->node);
    if (trigger->type == TRIGGER_PARAM_WAIT) {
        WaitNode *node = (WaitNode *)trigger;
        ListRemove(&node->item);
    } else if (trigger->type == TRIGGER_PARAM_WATCH) {
        WatchNode *node = (WatchNode *)trigger;
        ListRemove(&node->item);
    }
    PARAM_LOGV("DelWatchTrigger_ %s count %d", GetTriggerName(trigger), triggerHead->triggerCount);
    triggerHead->triggerCount--;
S
sun_fan 已提交
216
    free(trigger);
Z
zhong_ning 已提交
217 218
}

X
xionglei6 已提交
219
static TriggerNode *GetNextTrigger_(const TriggerHeader *triggerHead, const TriggerNode *curr)
Z
zhong_ning 已提交
220
{
4
411148299@qq.com 已提交
221
    PARAM_CHECK(triggerHead != NULL, return NULL, "Invalid triggerHead");
S
sun_fan 已提交
222 223 224 225 226
    ListNode *node = NULL;
    if (curr != NULL) {
        node = curr->node.next;
    } else {
        node = triggerHead->triggerList.next;
Z
zhong_ning 已提交
227
    }
S
sun_fan 已提交
228 229
    if (node != &triggerHead->triggerList) {
        return ListEntry(node, TriggerNode, node);
Z
zhong_ning 已提交
230
    }
S
sun_fan 已提交
231
    return NULL;
Z
zhong_ning 已提交
232 233
}

X
xionglei6 已提交
234
static const char *GetTriggerCondition_(const TriggerNode *trigger)
Z
zhong_ning 已提交
235
{
4
411148299@qq.com 已提交
236
    return (trigger == NULL || trigger->condition == NULL) ? "" : trigger->condition;
Z
zhong_ning 已提交
237 238
}

X
xionglei6 已提交
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
static const char *GetBootCondition_(const TriggerNode *trigger)
{
    PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
    PARAM_CHECK(trigger->type == TRIGGER_BOOT, return "", "Invalid type");
    const JobNode *node = (const JobNode *)trigger;
    return node->name;
}

static const char *GetJobName_(const TriggerNode *trigger)
{
    PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
    PARAM_CHECK(trigger->type <= TRIGGER_UNKNOW, return "", "Invalid type");
    const JobNode *node = (const JobNode *)trigger;
    return node->name;
}

static const char *GetWatchName_(const TriggerNode *trigger)
{
    PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
    PARAM_CHECK(trigger->type < TRIGGER_MAX && trigger->type > TRIGGER_UNKNOW,
        return "", "Invalid type");
    return trigger->condition;
}

JobNode *UpdateJobTrigger(const TriggerWorkSpace *workSpace,
    int type, const char *condition, const char *name)
{
    PARAM_CHECK(workSpace != NULL && name != NULL, return NULL, "name is null");
    PARAM_CHECK(type <= TRIGGER_UNKNOW, return NULL, "Invalid type");
    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, type);
    PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", type);
    JobNode *jobNode = GetTriggerByName(workSpace, name);
    if (jobNode == NULL) {
        TriggerExtInfo extInfo = {};
        extInfo.info.name = (char *)name;
        extInfo.type = type;
        extInfo.addNode = AddJobNode_;
        return (JobNode *)triggerHead->addTrigger(workSpace, condition, &extInfo);
    } else if (jobNode->condition == NULL && condition != NULL) {
        int ret = CopyCondition((TriggerNode *)jobNode, condition);
        PARAM_CHECK(ret == 0, FreeTrigger(workSpace, (TriggerNode*)jobNode);
            return NULL, "Failed to copy conditition");
    }
    return jobNode;
}

JobNode *GetTriggerByName(const TriggerWorkSpace *workSpace, const char *triggerName)
Z
zhong_ning 已提交
286
{
S
sun_fan 已提交
287
    PARAM_CHECK(workSpace != NULL && triggerName != NULL, return NULL, "Invalid param");
X
xionglei6 已提交
288 289 290
    HashNode *node = HashMapGet(workSpace->hashMap, triggerName);
    if (node == NULL) {
        return NULL;
Z
zhong_ning 已提交
291
    }
X
xionglei6 已提交
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
    JobNode *trigger = HASHMAP_ENTRY(node, JobNode, hashNode);
    return trigger;
}

void FreeTrigger(const TriggerWorkSpace *workSpace, TriggerNode *trigger)
{
    PARAM_CHECK(workSpace != NULL && trigger != NULL, return, "Invalid param");
    TriggerHeader *head = GetTriggerHeader(workSpace, trigger->type);
    if (head != NULL) {
        head->delTrigger(workSpace, trigger);
    }
}

void ClearTrigger(const TriggerWorkSpace *workSpace, int8_t type)
{
    PARAM_CHECK(workSpace != NULL, return, "head is null");
    TriggerHeader *head = GetTriggerHeader(workSpace, type);
    PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
    TriggerNode *trigger = head->nextTrigger(head, NULL);
    while (trigger != NULL) {
        TriggerNode *next = head->nextTrigger(head, trigger);
        FreeTrigger(workSpace, trigger);
        trigger = next;
    }
    ListInit(&head->triggerList);
Z
zhong_ning 已提交
317 318
}

4
411148299@qq.com 已提交
319
int ExecuteQueuePush(TriggerWorkSpace *workSpace, const TriggerNode *trigger)
Z
zhong_ning 已提交
320
{
4
411148299@qq.com 已提交
321
    PARAM_CHECK(workSpace != NULL, return -1, "Invalid workSpace");
S
sun_fan 已提交
322
    uint32_t index = workSpace->executeQueue.endIndex++ % workSpace->executeQueue.queueCount;
4
411148299@qq.com 已提交
323
    workSpace->executeQueue.executeQueue[index] = (TriggerNode *)trigger;
Z
zhong_ning 已提交
324 325 326 327 328
    return 0;
}

TriggerNode *ExecuteQueuePop(TriggerWorkSpace *workSpace)
{
4
411148299@qq.com 已提交
329
    PARAM_CHECK(workSpace != NULL, return NULL, "Invalid workSpace");
S
sun_fan 已提交
330 331 332 333 334 335 336 337 338 339 340
    TriggerNode *trigger = NULL;
    do {
        if (workSpace->executeQueue.endIndex <= workSpace->executeQueue.startIndex) {
            return NULL;
        }
        uint32_t currIndex = workSpace->executeQueue.startIndex % workSpace->executeQueue.queueCount;
        trigger = workSpace->executeQueue.executeQueue[currIndex];
        workSpace->executeQueue.executeQueue[currIndex] = NULL;
        workSpace->executeQueue.startIndex++;
    } while (trigger == NULL);
    return trigger;
Z
zhong_ning 已提交
341 342
}

X
xionglei6 已提交
343 344
static int CheckBootCondition_(LogicCalculator *calculator,
    const char *condition, const char *content, uint32_t contentSize)
Z
zhong_ning 已提交
345
{
4
411148299@qq.com 已提交
346
    UNUSED(calculator);
X
xionglei6 已提交
347
    if (strncmp(condition, content, contentSize) == 0) {
Z
zhong_ning 已提交
348 349 350 351 352
        return 1;
    }
    return 0;
}

X
xionglei6 已提交
353 354
static int CheckWatchCondition_(LogicCalculator *calculator,
    const char *condition, const char *content, uint32_t contentSize)
Z
zhong_ning 已提交
355
{
4
411148299@qq.com 已提交
356 357
    UNUSED(calculator);
    UNUSED(contentSize);
X
xionglei6 已提交
358
    if (strncmp(condition, content, strlen(condition)) == 0) {
S
sun_fan 已提交
359 360 361 362 363
        return 1;
    }
    return 0;
}

X
xionglei6 已提交
364 365
static int CheckParamCondition_(LogicCalculator *calculator,
    const char *condition, const char *content, uint32_t contentSize)
S
sun_fan 已提交
366 367 368
{
    UNUSED(content);
    UNUSED(contentSize);
X
xionglei6 已提交
369
    if (calculator->inputName != NULL) {
S
sun_fan 已提交
370
        if (!CheckMatchSubCondition(condition, calculator->inputName, strlen(calculator->inputName))) {
Z
zhong_ning 已提交
371 372 373
            return 0;
        }
    }
S
sun_fan 已提交
374 375 376
    return ComputeCondition(calculator, condition);
}

X
xionglei6 已提交
377 378
static int CheckUnknowCondition_(LogicCalculator *calculator,
    const char *condition, const char *content, uint32_t contentSize)
S
sun_fan 已提交
379
{
380 381 382
    if (condition != NULL && content != NULL && strcmp(content, condition) == 0) {
        return 1;
    }
S
sun_fan 已提交
383 384 385
    return ComputeCondition(calculator, condition);
}

X
xionglei6 已提交
386 387
static int ExecTriggerMatch_(const TriggerWorkSpace *workSpace,
    int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
S
sun_fan 已提交
388
{
X
xionglei6 已提交
389 390 391 392
    TriggerHeader *head = GetTriggerHeader(workSpace, type);
    PARAM_CHECK(head != NULL, return 0, "Failed to get header %d", type);
    TriggerNode *trigger = head->nextTrigger(head, NULL);
    while (trigger != NULL) {
X
xionglei6 已提交
393
        TriggerNode *next = head->nextTrigger(head, trigger);
X
xionglei6 已提交
394 395 396
        const char *condition = head->getCondition(trigger);
        if (head->checkCondition(calculator, condition, content, contentSize) == 1) {
            calculator->triggerCheckDone(trigger, content, contentSize);
S
sun_fan 已提交
397
        }
X
xionglei6 已提交
398
        trigger = next;
S
sun_fan 已提交
399 400
    }
    return 0;
Z
zhong_ning 已提交
401 402
}

X
xionglei6 已提交
403 404
static int CheckBootMatch_(const TriggerWorkSpace *workSpace,
    int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
Z
zhong_ning 已提交
405
{
W
Wen liumin 已提交
406 407
    PARAM_CHECK(workSpace != NULL, return -1, "Invalid space");
    PARAM_CHECK((type == TRIGGER_BOOT) || (type == TRIGGER_PARAM_WATCH), return -1, "Invalid type");
X
xionglei6 已提交
408
    return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
Z
zhong_ning 已提交
409 410
}

X
xionglei6 已提交
411 412
static int CheckParamMatch_(const TriggerWorkSpace *workSpace,
    int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
Z
zhong_ning 已提交
413
{
W
Wen liumin 已提交
414 415
    PARAM_CHECK(workSpace != NULL, return -1, "Invalid space");
    PARAM_CHECK((type == TRIGGER_PARAM) || (type == TRIGGER_PARAM_WAIT), return -1, "Invalid type");
X
xionglei6 已提交
416 417

    CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1);
X
xionglei6 已提交
418
    int ret = GetValueFromContent(content, contentSize, 0, calculator->inputName, SUPPORT_DATA_BUFFER_MAX);
X
xionglei6 已提交
419 420 421 422 423
    PARAM_CHECK(ret == 0, return -1, "Failed parse content name");
    ret = GetValueFromContent(content, contentSize,
        strlen(calculator->inputName) + 1, calculator->inputContent, SUPPORT_DATA_BUFFER_MAX);
    PARAM_CHECK(ret == 0, return -1, "Failed parse content value");
    return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
Z
zhong_ning 已提交
424 425
}

X
xionglei6 已提交
426 427
static int CheckUnknowMatch_(const TriggerWorkSpace *workSpace,
    int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
Z
zhong_ning 已提交
428
{
X
xionglei6 已提交
429
    PARAM_CHECK(workSpace != NULL && content != NULL, return -1, "Failed arg for trigger");
W
Wen liumin 已提交
430
    PARAM_CHECK(type == TRIGGER_UNKNOW, return -1, "Invalid type");
X
xionglei6 已提交
431 432 433 434 435 436 437

    CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1);
    int ret = memcpy_s(calculator->triggerContent, sizeof(calculator->triggerContent), content, contentSize);
    PARAM_CHECK(ret == EOK, return -1, "Failed to memcpy");
    calculator->inputName = NULL;
    calculator->inputContent = NULL;
    return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
Z
zhong_ning 已提交
438 439
}

X
xionglei6 已提交
440
int32_t CheckAndMarkTrigger_(const TriggerWorkSpace *workSpace, int type, const char *name)
Z
zhong_ning 已提交
441
{
X
xionglei6 已提交
442 443 444
    PARAM_CHECK(workSpace != NULL && name != NULL, return 0, "Failed arg for trigger");
    TriggerHeader *head = GetTriggerHeader(workSpace, type);
    PARAM_CHECK(head != NULL, return 0, "Failed to get header %d", type);
S
sun_fan 已提交
445
    int ret = 0;
X
xionglei6 已提交
446
    TriggerNode *trigger = head->nextTrigger(head, NULL);
S
sun_fan 已提交
447
    while (trigger != NULL) {
X
xionglei6 已提交
448 449
        if (head->getCondition(trigger) == NULL) {
            trigger = head->nextTrigger(head, trigger);
4
411148299@qq.com 已提交
450 451
            continue;
        }
X
xionglei6 已提交
452
        const char *tmp = strstr(head->getCondition(trigger), name);
S
sun_fan 已提交
453 454 455 456
        if (tmp != NULL && strncmp(tmp + strlen(name), "=", 1) == 0) {
            TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_RELATED);
            ret = 1;
        }
X
xionglei6 已提交
457
        trigger = head->nextTrigger(head, trigger);
S
sun_fan 已提交
458 459 460
    }
    return ret;
}
Z
zhong_ning 已提交
461

X
xionglei6 已提交
462 463
int CheckTrigger(TriggerWorkSpace *workSpace, int type,
    const char *content, uint32_t contentSize, PARAM_CHECK_DONE triggerCheckDone)
S
sun_fan 已提交
464
{
X
xionglei6 已提交
465 466 467 468 469
    PARAM_CHECK(workSpace != NULL && content != NULL && triggerCheckDone != NULL,
        return -1, "Failed arg for trigger");
    PARAM_LOGV("CheckTrigger_ type: %d content: %s ", type, content);
    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, type);
    if (triggerHead != NULL) {
Y
yichengzhao 已提交
470
        LogicCalculator calculator = {{0}};
X
xionglei6 已提交
471 472 473 474
        calculator.triggerCheckDone = triggerCheckDone;
        int ret = triggerHead->checkTriggerMatch(workSpace, type, &calculator, content, contentSize);
        CalculatorFree(&calculator);
        return ret;
S
sun_fan 已提交
475
    }
X
xionglei6 已提交
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
    return 0;
}

static void DumpJobTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger)
{
    const JobNode *node = (const JobNode *)trigger;
    PARAM_DUMP("trigger 0x%08x \n", trigger->flags);
    PARAM_DUMP("trigger name %s \n", node->name);
    PARAM_DUMP("trigger condition %s \n", node->condition);
    const int maxCmd = 1024;
    int count = 0;
    CommandNode *cmd = GetNextCmdNode(node, NULL);
    while (cmd != NULL && count < maxCmd) {
        PARAM_DUMP("\t command name %s \n", GetCmdKey(cmd->cmdKeyIndex));
        PARAM_DUMP("\t command args %s \n", cmd->content);
        cmd = GetNextCmdNode(node, cmd);
        count++;
S
sun_fan 已提交
493
    }
Z
zhong_ning 已提交
494 495
}

X
xionglei6 已提交
496
static void DumpWatchTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger)
Z
zhong_ning 已提交
497
{
X
xionglei6 已提交
498 499 500 501 502
    const WatchNode *node = (const WatchNode *)trigger;
    PARAM_DUMP("trigger 0x%08x \n", trigger->flags);
    PARAM_DUMP("trigger condition %s \n", trigger->condition);
    PARAM_DUMP("trigger watchId %d \n", node->watchId);
}
S
sun_fan 已提交
503

X
xionglei6 已提交
504 505 506 507 508 509 510 511
static void DumpWaitTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger)
{
    const WaitNode *node = (const WaitNode *)trigger;
    PARAM_DUMP("trigger 0x%08x \n", trigger->flags);
    PARAM_DUMP("trigger name %s \n", GetTriggerName(trigger));
    PARAM_DUMP("trigger condition %s \n", trigger->condition);
    PARAM_DUMP("trigger waitId %d \n", node->waitId);
    PARAM_DUMP("trigger timeout %d \n", node->timeout);
S
sun_fan 已提交
512
}
Z
zhong_ning 已提交
513

X
xionglei6 已提交
514
static void DumpTrigger_(const TriggerWorkSpace *workSpace, int type)
S
sun_fan 已提交
515
{
X
xionglei6 已提交
516 517 518 519
    PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace ");
    TriggerHeader *head = GetTriggerHeader(workSpace, type);
    PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
    TriggerNode *trigger = head->nextTrigger(head, NULL);
S
sun_fan 已提交
520
    while (trigger != NULL) {
X
xionglei6 已提交
521 522 523 524 525
        head->dumpTrigger(workSpace, trigger);
        trigger = head->nextTrigger(head, trigger);
    }
}

M
Mupceet 已提交
526
void SystemDumpTriggers(int verbose)
X
xionglei6 已提交
527
{
M
Mupceet 已提交
528
    TriggerWorkSpace *workSpace = GetTriggerWorkSpace();
X
xionglei6 已提交
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
    PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace ");
    PARAM_DUMP("Ready to dump all trigger memory \n");
    PARAM_DUMP("workspace queue BOOT info:\n");
    DumpTrigger_(workSpace, TRIGGER_BOOT);
    PARAM_DUMP("workspace queue parameter info:\n");
    DumpTrigger_(workSpace, TRIGGER_PARAM);
    PARAM_DUMP("workspace queue other info:\n");
    DumpTrigger_(workSpace, TRIGGER_UNKNOW);
    PARAM_DUMP("workspace queue watch info:\n");
    DumpTrigger_(workSpace, TRIGGER_PARAM_WATCH);
    PARAM_DUMP("workspace queue wait info:\n");
    DumpTrigger_(workSpace, TRIGGER_PARAM_WAIT);

    PARAM_DUMP("workspace queue execute info:\n");
    PARAM_DUMP("queue info count: %u start: %u end: %u\n",
        workSpace->executeQueue.queueCount, workSpace->executeQueue.startIndex, workSpace->executeQueue.endIndex);
    for (uint32_t index = workSpace->executeQueue.startIndex; index < workSpace->executeQueue.endIndex; index++) {
        TriggerNode *trigger = workSpace->executeQueue.executeQueue[index % workSpace->executeQueue.queueCount];
        if (trigger != 0) {
            PARAM_DUMP("queue node trigger name: %s \n", GetTriggerName(trigger));
S
sun_fan 已提交
549 550 551
        }
    }
}
Z
zhong_ning 已提交
552

X
xionglei6 已提交
553
static int32_t CompareData_(const struct tagTriggerNode_ *trigger, const void *data)
S
sun_fan 已提交
554
{
X
xionglei6 已提交
555 556 557 558 559 560 561
    PARAM_CHECK(trigger != NULL && data != NULL, return -1, "Invalid trigger");
    if (trigger->type == TRIGGER_PARAM_WAIT) {
        WaitNode *node = (WaitNode *)trigger;
        return node->waitId == *(uint32_t *)data;
    } else if (trigger->type == TRIGGER_PARAM_WATCH) {
        WatchNode *node = (WatchNode *)trigger;
        return node->watchId == *(uint32_t *)data;
S
sun_fan 已提交
562
    }
X
xionglei6 已提交
563
    return -1;
Z
zhong_ning 已提交
564 565
}

X
xionglei6 已提交
566
static void TriggerHeadSetDefault(TriggerHeader *head)
Z
zhong_ning 已提交
567
{
X
xionglei6 已提交
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
    ListInit(&head->triggerList);
    head->triggerCount = 0;
    head->cmdNodeCount = 0;
    head->addTrigger = AddJobTrigger_;
    head->nextTrigger = GetNextTrigger_;
    head->delTrigger = DelJobTrigger_;
    head->executeTrigger = NULL;
    head->checkAndMarkTrigger = CheckAndMarkTrigger_;
    head->checkTriggerMatch = CheckBootMatch_;
    head->checkCondition = CheckBootCondition_;
    head->getCondition = GetBootCondition_;
    head->getTriggerName = GetJobName_;
    head->dumpTrigger = DumpJobTrigger_;
    head->compareData = CompareData_;
}

static int JobNodeNodeCompare(const HashNode *node1, const HashNode *node2)
{
    JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode);
    JobNode *jobNode2 = HASHMAP_ENTRY(node2, JobNode, hashNode);
    return strcmp(jobNode1->name, jobNode2->name);
}

static int JobNodeKeyCompare(const HashNode *node1, const void *key)
{
    JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode);
    return strcmp(jobNode1->name, (char *)key);
}

static int JobNodeGetNodeHasCode(const HashNode *node)
{
    JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode);
    int code = 0;
X
xionglei6 已提交
601 602
    size_t nameLen = strlen(jobNode->name);
    for (size_t i = 0; i < nameLen; i++) {
X
xionglei6 已提交
603 604 605 606 607 608 609 610 611
        code += jobNode->name[i] - 'A';
    }
    return code;
}

static int JobNodeGetKeyHasCode(const void *key)
{
    int code = 0;
    const char *buff = (char *)key;
X
xionglei6 已提交
612 613
    size_t buffLen = strlen(buff);
    for (size_t i = 0; i < buffLen; i++) {
X
xionglei6 已提交
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
        code += buff[i] - 'A';
    }
    return code;
}

static void JobNodeFree(const HashNode *node)
{
    JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode);
    FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)jobNode);
}

void InitTriggerHead(const TriggerWorkSpace *workSpace)
{
    HashInfo info = {
        JobNodeNodeCompare,
        JobNodeKeyCompare,
        JobNodeGetNodeHasCode,
        JobNodeGetKeyHasCode,
        JobNodeFree,
        64
    };
    PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace");
    int ret = HashMapCreate((HashMapHandle *)&workSpace->hashMap, &info);
    PARAM_CHECK(ret == 0, return, "Failed to create hash map");

    TriggerHeader *head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_BOOT];
    TriggerHeadSetDefault(head);
    // param trigger
    head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM];
    TriggerHeadSetDefault(head);
    head->checkTriggerMatch = CheckParamMatch_;
    head->checkCondition = CheckParamCondition_;
    head->getCondition = GetTriggerCondition_;
    // unknow trigger
    head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_UNKNOW];
    TriggerHeadSetDefault(head);
    head->checkTriggerMatch = CheckUnknowMatch_;
    head->checkCondition = CheckUnknowCondition_;
    head->getCondition = GetTriggerCondition_;
    // wait trigger
    head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WAIT];
    TriggerHeadSetDefault(head);
    head->addTrigger = AddWatchTrigger_;
    head->delTrigger = DelWatchTrigger_;
    head->checkTriggerMatch = CheckParamMatch_;
    head->checkCondition = CheckParamCondition_;
    head->getCondition = GetTriggerCondition_;
    head->dumpTrigger = DumpWaitTrigger_;
    head->getTriggerName = GetWatchName_;
    // watch trigger
    head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WATCH];
    TriggerHeadSetDefault(head);
    head->addTrigger = AddWatchTrigger_;
    head->delTrigger = DelWatchTrigger_;
    head->checkTriggerMatch = CheckBootMatch_;
    head->checkCondition = CheckWatchCondition_;
    head->getCondition = GetTriggerCondition_;
    head->dumpTrigger = DumpWatchTrigger_;
    head->getTriggerName = GetWatchName_;
}

void DelWatchTrigger(int type, const void *data)
{
    PARAM_CHECK(data != NULL, return, "Invalid data");
    TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type);
    PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
    PARAM_CHECK(head->compareData != NULL, return, "Invalid compareData");
    TriggerNode *trigger = head->nextTrigger(head, NULL);
S
sun_fan 已提交
682
    while (trigger != NULL) {
X
xionglei6 已提交
683 684 685
        if (head->compareData(trigger, data) == 0) {
            head->delTrigger(GetTriggerWorkSpace(), trigger);
            return;
4
411148299@qq.com 已提交
686
        }
X
xionglei6 已提交
687 688 689
        trigger = head->nextTrigger(head, trigger);
    }
}
S
sun_fan 已提交
690

X
xionglei6 已提交
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
void ClearWatchTrigger(ParamWatcher *watcher, int type)
{
    PARAM_CHECK(watcher != NULL, return, "Invalid watcher");
    TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type);
    PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
    ListNode *node = watcher->triggerHead.next;
    while (node != &watcher->triggerHead) {
        TriggerNode *trigger = NULL;
        if (type == TRIGGER_PARAM_WAIT) {
            trigger = (TriggerNode *)ListEntry(node, WaitNode, item);
        } else if (type == TRIGGER_PARAM_WATCH) {
            trigger = (TriggerNode *)ListEntry(node, WatchNode, item);
        }
        if (trigger == NULL || type != trigger->type) {
            PARAM_LOGE("ClearWatchTrigger %s error type %d", GetTriggerName(trigger), type);
            return;
S
sun_fan 已提交
707
        }
X
xionglei6 已提交
708 709 710 711
        PARAM_LOGV("ClearWatchTrigger %p %s", trigger, GetTriggerName(trigger));
        ListNode *next = node->next;
        FreeTrigger(GetTriggerWorkSpace(), trigger);
        node = next;
S
sun_fan 已提交
712 713 714
    }
}

X
xionglei6 已提交
715
int CheckWatchTriggerTimeout(void)
S
sun_fan 已提交
716
{
X
xionglei6 已提交
717 718 719 720 721 722 723 724 725 726 727
    TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), TRIGGER_PARAM_WAIT);
    PARAM_CHECK(head != NULL && head->nextTrigger != NULL, return 0, "Invalid header");
    int hasNode = 0;
    WaitNode *node = (WaitNode *)head->nextTrigger(head, NULL);
    while (node != NULL) {
        WaitNode *next = (WaitNode *)head->nextTrigger(head, (TriggerNode *)node);
        if (node->timeout > 0) {
            node->timeout--;
        } else {
            head->executeTrigger((TriggerNode*)node, NULL, 0);
            FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)node);
Z
zhong_ning 已提交
728
        }
X
xionglei6 已提交
729 730 731 732 733 734 735 736
        hasNode = 1;
        node = next;
    }
    return hasNode;
}

TriggerHeader *GetTriggerHeader(const TriggerWorkSpace *workSpace, int type)
{
X
xionglei6 已提交
737
    if (workSpace == NULL || type >= TRIGGER_MAX) {
X
xionglei6 已提交
738 739 740 741 742 743 744 745 746 747 748 749 750
        return NULL;
    }
    return (TriggerHeader *)&workSpace->triggerHead[type];
}

char *GetTriggerCache(uint32_t *size)
{
    TriggerWorkSpace *space = GetTriggerWorkSpace();
    if (space == NULL) {
        return NULL;
    }
    if (size != NULL) {
        *size = sizeof(space->cache) / sizeof(space->cache[0]);
Z
zhong_ning 已提交
751
    }
X
xionglei6 已提交
752
    return space->cache;
753
}
X
xionglei6 已提交
754 755 756 757 758 759 760 761 762

const char *GetTriggerName(const TriggerNode *trigger)
{
    PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
    TriggerHeader *triggerHead = GetTriggerHeader(GetTriggerWorkSpace(), trigger->type);
    if (triggerHead) {
        return triggerHead->getTriggerName(trigger);
    }
    return "";
W
Wen liumin 已提交
763
}