Use the same type to compare values
[platform/framework/web/download-provider.git] / provider / download-provider-queue.c
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18
19 #include <download-provider-queue.h>
20 #include <download-provider-log.h>
21 #include <download-provider-pthread.h>
22 #include <download-provider-client.h>
23 #include <download-provider-client-manager.h>
24
25 /* queue
26  * 1. push : at the tail of linked list
27  * 2. pop  : at the head of linked list
28  * 3. priority push : at the head of linked list
29  * 4. in pop, check client of slot, search request by download_id
30  */
31
32 //dp_queue_fmt *g_dp_queue = NULL; // head of linked list
33 static pthread_mutex_t g_dp_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
34
35 // normal . push at the tail of queue.
36 int dp_queue_push(dp_queue_fmt **queue, void *slot, void *request)
37 {
38         if (queue == NULL) {
39                 TRACE_ERROR("check memory address of queue");
40                 return -1;
41         }
42         dp_client_slots_fmt *baseslot = slot;
43         dp_request_fmt *new_request = request;
44         if (slot == NULL || request == NULL || new_request->id <= 0) {
45                 TRACE_ERROR("check client and request memory address");
46                 return -1;
47         } else if (new_request->id <= 0) {
48                 TRACE_ERROR("check slot or download id:%d", new_request->id);
49                 return -1;
50         } else if (new_request->state != DP_STATE_QUEUED) {
51                 TRACE_ERROR("check id:%d state:%s", new_request->id, dp_print_state(new_request->state));
52                 return -1;
53         }
54
55         CLIENT_MUTEX_LOCK(&g_dp_queue_mutex);
56         // search the tail of queue
57         int i = 0;
58         dp_queue_fmt *tailp = *queue;
59         dp_queue_fmt *prevp = NULL;
60         TRACE_DEBUG("queue req slot:%p request:%p id:%d", slot, request, (request == NULL ? 0 : new_request->id));
61         for (; tailp != NULL; i++) {
62                 dp_request_fmt *qrequestp = tailp->request;
63                 if (tailp->slot == NULL || tailp->request == NULL ||
64                                 qrequestp->state != DP_STATE_QUEUED) {
65                         TRACE_DEBUG("queue error %d slot:%p request:%p id:%d", i, tailp->slot, tailp->request, (tailp->request == NULL ? 0 : ((dp_request_fmt *)tailp->request)->id));
66                 } else if (tailp->slot == slot && tailp->request == request && qrequestp->id == new_request->id) {
67                         TRACE_INFO("queue duplicte %d slot:%p request:%p id:%d", i, slot, request, new_request->id);
68                         CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex);
69                         return 0;
70                 } else {
71                         TRACE_INFO("queue info %d slot:%p request:%p id:%d %s", i, tailp->slot, tailp->request, ((dp_request_fmt *)tailp->request)->id, ((dp_client_slots_fmt *)tailp->slot)->pkgname);
72                 }
73                 prevp = tailp;
74                 tailp = tailp->next;
75         }
76         dp_queue_fmt *new_queue = (dp_queue_fmt *)malloc(sizeof(dp_queue_fmt));
77         if (new_queue != NULL) {
78                 new_queue->slot = slot;
79                 new_queue->request = request;
80                 new_queue->next = NULL;
81                 if (prevp == NULL)
82                         *queue = new_queue;
83                 else
84                         prevp->next = new_queue;
85         } else {
86                 CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex);
87                 return -1;
88         }
89         TRACE_DEBUG("queue push %d info:%s id:%d", i, baseslot->pkgname, new_request->id);
90         CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex);
91         return 0;
92 }
93
94 int dp_queue_pop(dp_queue_fmt **queue, void **slot, void **request)
95 {
96         if (queue == NULL) {
97                 TRACE_ERROR("check memory address of queue");
98                 return -1;
99         }
100         if (slot == NULL || request == NULL) {
101                 TRACE_ERROR("check client and request memory address");
102                 return -1;
103         }
104
105         int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_queue_mutex);
106         if (lock != 0) {
107                 TRACE_DEBUG("skip queue is used by other thread");
108                 return 0;
109         }
110         if (*queue == NULL) {
111                 //TRACE_DEBUG("queue empty");
112                 CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex);
113                 return -1;
114         }
115         // get a head of queue
116         int ret = -1;
117         dp_queue_fmt *popp;
118         do {
119                  popp = *queue;
120                 *queue = popp->next;
121                 dp_client_slots_fmt *slotp = popp->slot;
122                 dp_request_fmt *requestp = popp->request;
123                 if (slotp == NULL || requestp == NULL ||
124                                 requestp->state != DP_STATE_QUEUED) {
125                         TRACE_DEBUG("queue error slot:%p request:%p id:%d", popp->slot, popp->request, (requestp == NULL ? 0 : requestp->id));
126                         free(popp);
127                 } else {
128                         TRACE_INFO("queue pop slot:%p request:%p id:%d %s", popp->slot, popp->request, requestp->id, slotp->pkgname);
129                         *slot = popp->slot;
130                         *request = popp->request;
131                         ret = 0;
132                         free(popp);
133                         break;
134                 }
135         } while (*queue != NULL); // if meet the tail of queue
136         CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex);
137         return ret;
138 }
139
140 void dp_queue_clear(dp_queue_fmt **queue, void *request)
141 {
142         if (queue == NULL) {
143                 TRACE_ERROR("check memory address of queue");
144                 return ;
145         }
146         if (request == NULL) {
147                 TRACE_ERROR("check client and request memory address");
148                 return ;
149         }
150         CLIENT_MUTEX_LOCK(&g_dp_queue_mutex);
151         int i = 0;
152         dp_queue_fmt *tailp = *queue;
153         dp_queue_fmt *prevp = NULL;
154         TRACE_DEBUG("queue clear req request:%p id:%d", request, (request == NULL ? 0 : ((dp_request_fmt *)request)->id));
155         for (; tailp != NULL; i++) {
156                 dp_request_fmt *requestp = tailp->request;
157                 TRACE_DEBUG("queue info %d request:%p id:%d", i, requestp, (requestp == NULL ? 0 : requestp->id));
158                 if (requestp == request) {
159                         // clear.
160                         if (prevp == NULL)
161                                 *queue = tailp->next;
162                         else
163                                 prevp->next = tailp->next;
164                         TRACE_DEBUG("queue clear this %d request:%p id:%d", i, requestp, (requestp == NULL ? 0 : requestp->id));
165                         free(tailp);
166                         break;
167                 }
168                 prevp = tailp;
169                 tailp = tailp->next;
170         }
171         CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex);
172 }
173
174 void dp_queue_clear_all(dp_queue_fmt **queue)
175 {
176         if (queue == NULL) {
177                 TRACE_ERROR("check memory address of queue");
178                 return ;
179         }
180         CLIENT_MUTEX_LOCK(&g_dp_queue_mutex);
181         if (queue == NULL || *queue == NULL) {
182                 TRACE_DEBUG("queue empty");
183                 CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex);
184                 return ;
185         }
186         // get a head of queue
187         do {
188                 dp_queue_fmt *popp = *queue;
189                 *queue = popp->next;
190                 TRACE_DEBUG("queue clear slot:%p request:%p id:%d", popp->slot, popp->request, (popp->request == NULL ? 0 : ((dp_request_fmt *)popp->request)->id));
191                 free(popp);
192         } while (*queue != NULL); // if meet the tail of queue
193         CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex);
194 }