1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 #include "iotx_dm_internal.h"
5 
6 #if !defined(DM_MESSAGE_CACHE_DISABLED)
7 
8 dm_msg_cache_ctx_t g_dm_msg_cache_ctx;
9 
_dm_msg_cache_get_ctx(void)10 dm_msg_cache_ctx_t *_dm_msg_cache_get_ctx(void)
11 {
12     return &g_dm_msg_cache_ctx;
13 }
14 
_dm_msg_cache_mutex_lock(void)15 static void _dm_msg_cache_mutex_lock(void)
16 {
17     dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
18     if (ctx->mutex) {
19         HAL_MutexLock(ctx->mutex);
20     }
21 }
22 
_dm_msg_cache_mutex_unlock(void)23 static void _dm_msg_cache_mutex_unlock(void)
24 {
25     dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
26     if (ctx->mutex) {
27         HAL_MutexUnlock(ctx->mutex);
28     }
29 }
30 
dm_msg_cache_init(void)31 int dm_msg_cache_init(void)
32 {
33     dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
34 
35     memset(ctx, 0, sizeof(dm_msg_cache_ctx_t));
36 
37     /* Create Mutex */
38     ctx->mutex = HAL_MutexCreate();
39     if (ctx->mutex == NULL) {
40         return DM_MEMORY_NOT_ENOUGH;
41     }
42 
43     /* Init Message Cache List */
44     INIT_LIST_HEAD(&ctx->dmc_list);
45 
46     return SUCCESS_RETURN;
47 }
48 
dm_msg_cache_deinit(void)49 int dm_msg_cache_deinit(void)
50 {
51     dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
52     dm_msg_cache_node_t *node = NULL;
53     dm_msg_cache_node_t *next = NULL;
54 
55     _dm_msg_cache_mutex_lock();
56     list_for_each_entry_safe(node, next, &ctx->dmc_list, linked_list,
57                              dm_msg_cache_node_t)
58     {
59         list_del(&node->linked_list);
60         if (node->data) {
61             DM_free(node->data);
62         }
63         DM_free(node);
64         _dm_msg_cache_mutex_unlock();
65     }
66     _dm_msg_cache_mutex_unlock();
67 
68     if (ctx->mutex) {
69         HAL_MutexDestroy(ctx->mutex);
70     }
71 
72     return SUCCESS_RETURN;
73 }
74 
dm_msg_cache_insert(int msgid,int devid,iotx_dm_event_types_t type,char * data)75 int dm_msg_cache_insert(int msgid, int devid, iotx_dm_event_types_t type,
76                         char *data)
77 {
78     dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
79     dm_msg_cache_node_t *node = NULL;
80 
81     dm_log_debug("dmc list size: %d", ctx->dmc_list_size);
82     if (ctx->dmc_list_size >= CONFIG_MSGCACHE_QUEUE_MAXLEN) {
83         return FAIL_RETURN;
84     }
85 
86     node = DM_malloc(sizeof(dm_msg_cache_node_t));
87     if (node == NULL) {
88         return DM_MEMORY_NOT_ENOUGH;
89     }
90     memset(node, 0, sizeof(dm_msg_cache_node_t));
91 
92     node->msgid = msgid;
93     node->devid = devid;
94     node->response_type = type;
95     node->data = data;
96     node->ctime = HAL_UptimeMs();
97     INIT_LIST_HEAD(&node->linked_list);
98 
99     _dm_msg_cache_mutex_lock();
100     list_add_tail(&node->linked_list, &ctx->dmc_list);
101     ctx->dmc_list_size++;
102     _dm_msg_cache_mutex_unlock();
103 
104     return SUCCESS_RETURN;
105 }
106 
dm_msg_cache_search(_IN_ int msgid,_OU_ dm_msg_cache_node_t ** node)107 int dm_msg_cache_search(_IN_ int msgid, _OU_ dm_msg_cache_node_t **node)
108 {
109     dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
110     dm_msg_cache_node_t *search_node = NULL;
111 
112     if (msgid < 0 || node == NULL || *node != NULL) {
113         return DM_INVALID_PARAMETER;
114     }
115 
116     _dm_msg_cache_mutex_lock();
117     list_for_each_entry(search_node, &ctx->dmc_list, linked_list,
118                         dm_msg_cache_node_t)
119     {
120         if (search_node->msgid == msgid) {
121             *node = search_node;
122             _dm_msg_cache_mutex_unlock();
123             return SUCCESS_RETURN;
124         }
125     }
126 
127     _dm_msg_cache_mutex_unlock();
128     return FAIL_RETURN;
129 }
130 
dm_msg_cache_remove(int msgid)131 int dm_msg_cache_remove(int msgid)
132 {
133     dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
134     dm_msg_cache_node_t *node = NULL;
135     dm_msg_cache_node_t *next = NULL;
136 
137     _dm_msg_cache_mutex_lock();
138     list_for_each_entry_safe(node, next, &ctx->dmc_list, linked_list,
139                              dm_msg_cache_node_t)
140     {
141         if (node->msgid == msgid) {
142             list_del(&node->linked_list);
143             if (node->data) {
144                 DM_free(node->data);
145             }
146             ctx->dmc_list_size--;
147             DM_free(node);
148             dm_log_debug("Remove Message ID: %d", msgid);
149             _dm_msg_cache_mutex_unlock();
150             return SUCCESS_RETURN;
151         }
152     }
153 
154     _dm_msg_cache_mutex_unlock();
155     return FAIL_RETURN;
156 }
157 
dm_msg_cache_tick(void)158 void dm_msg_cache_tick(void)
159 {
160     dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
161     dm_msg_cache_node_t *node = NULL;
162     dm_msg_cache_node_t *next = NULL;
163     uint64_t current_time = HAL_UptimeMs();
164 
165     _dm_msg_cache_mutex_lock();
166     list_for_each_entry_safe(node, next, &ctx->dmc_list, linked_list,
167                              dm_msg_cache_node_t)
168     {
169         if (current_time < node->ctime) {
170             node->ctime = current_time;
171         }
172         if (current_time - node->ctime >= DM_MSG_CACHE_TIMEOUT_MS_DEFAULT) {
173             dm_log_debug("Message ID Timeout: %d", node->msgid);
174             /* Send Timeout Message To User */
175             dm_msg_send_msg_timeout_to_user(node->msgid, node->devid,
176                                             node->response_type);
177             list_del(&node->linked_list);
178             if (node->data) {
179                 DM_free(node->data);
180             }
181             DM_free(node);
182         }
183     }
184     _dm_msg_cache_mutex_unlock();
185 }
186 #endif
187