]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_requests.c
0ac95f35194d04a2d5ae59cc33ead50f175ec4ad
[frescor/fna.git] / src_frescan / frescan_requests.c
1 /*!
2  * @file frescan_requests.c
3  *
4  * @brief FRESCAN requests
5  *
6  * This module contains an operation to create the queue, an operation to
7  * enqueue a message (with a request), and an operation to
8  * dequeue a message.
9  *
10  * @version 0.01
11  *
12  * @date 1-Apr-2008
13  *
14  * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
15  *
16  */
17
18 #include <misc/freelist.h>
19 #include <misc/linux_list.h>
20 #include "frescan.h"
21 #include "frescan_requests.h"
22 #include "frescan_config.h"
23 #include "frescan_debug.h"
24 #include "fosa_mutexes_and_condvars.h"
25
26 static bool is_initialized = false;
27
28 /**
29  * the_requests_pool
30  *
31  * We will use a freelist to allocate and free the requests.
32  *
33  **/
34
35 struct request_t {
36         frescan_req_type_t  type;
37         frescan_robj_id_t   reply;
38         frescan_contract_t  *contract;
39         frescan_ss_t        ss;
40         frescan_node_t      src;
41         void                *return_info;
42         struct list_head    request_list;
43         int pool_pos;
44 };
45
46 static fosa_mutex_t requests_mutex;
47 static fosa_cond_t  requests_cond;
48
49 static struct request_t the_requests_pool[FRESCAN_MX_REQUESTS];
50 static freelist_t freelist;
51 static struct request_t the_requests_list;
52
53 /**
54  * frescan_requests_init()
55  *
56  * Init the freelist, requests list, cond var and mutex.
57  *
58  **/
59
60 int frescan_requests_init(int max_ceiling)
61 {
62         int err;
63
64         err = fosa_mutex_init(&requests_mutex, max_ceiling);
65         if (err != 0) return err;
66
67         err = fosa_cond_init(&requests_cond);
68         if (err != 0) return err;
69
70         err = freelist_init(&freelist, FRESCAN_MX_REQUESTS);
71         if (err != 0) return err;
72
73         INIT_LIST_HEAD(&the_requests_list.request_list);
74
75         is_initialized = true;
76         return 0;
77 }
78
79 /**
80  * frescan_request_alloc()
81  *
82  * Allocate a request with the mutex locked
83  *
84  **/
85
86 int frescan_request_alloc(frescan_request_id_t *id)
87 {
88         int err, pos;
89
90         if (is_initialized == false) return -1;
91
92         err = fosa_mutex_lock(&requests_mutex);
93         if (err != 0) return err;
94
95                 pos = freelist_alloc(&freelist);
96                 if (pos < 0) goto locked_error;
97
98         err = fosa_mutex_unlock(&requests_mutex);
99         if (err != 0) return err;
100
101         *id = (unsigned int)pos;
102         the_requests_pool[*id].pool_pos = pos;
103
104         return 0;
105
106 locked_error:
107         fosa_mutex_unlock(&requests_mutex);
108         return pos;
109 }
110
111 /**
112  * frescan_request_free()
113  *
114  * free the request from the pool
115  *
116  **/
117
118 int frescan_request_free(frescan_request_id_t id)
119 {
120         int err;
121
122         if (is_initialized == false) return -1;
123
124         err = fosa_mutex_lock(&requests_mutex);
125         if (err != 0) return err;
126
127                 err = freelist_free(&freelist, id);
128                 if (err != 0) goto locked_error;
129
130         err = fosa_mutex_unlock(&requests_mutex);
131         if (err != 0) return err;
132
133         return 0;
134
135 locked_error:
136         fosa_mutex_unlock(&requests_mutex);
137         return err;
138 }
139
140 /**
141  * frescan_request_set_type()
142  *
143  **/
144
145 int frescan_request_set_type(frescan_request_id_t id, frescan_req_type_t type)
146 {
147         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "id:%d, type:%d\n", id, type);
148         the_requests_pool[id].type = type;
149         return 0;
150 }
151
152 /**
153  * frescan_request_set_reply()
154  *
155  **/
156
157 int frescan_request_set_reply(frescan_request_id_t id, frescan_robj_id_t reply)
158 {
159         the_requests_pool[id].reply = reply;
160         return 0;
161 }
162
163 /**
164  * frescan_request_set_contract()
165  *
166  **/
167
168 int frescan_request_set_contract(frescan_request_id_t id,
169                                  const frescan_contract_t *contract)
170 {
171         the_requests_pool[id].contract = (frescan_contract_t *)contract;
172         return 0;
173 }
174
175 /**
176  * frescan_request_set_ss()
177  *
178  **/
179
180 int frescan_request_set_ss(frescan_request_id_t id,
181                            frescan_ss_t         ss)
182 {
183         the_requests_pool[id].ss = ss;
184         return 0;
185 }
186
187 /**
188  * frescan_request_set_src()
189  *
190  **/
191
192 int frescan_request_set_src(frescan_request_id_t id, frescan_node_t src)
193 {
194         the_requests_pool[id].src = src;
195         return 0;
196 }
197
198 /**
199  * frescan_request_set_return_info()
200  *
201  **/
202
203 int frescan_request_set_return_info(frescan_request_id_t id,
204                                     void *return_info)
205 {
206         the_requests_pool[id].return_info = return_info;
207         return 0;
208 }
209
210 /**
211  * frescan_request_get_type()
212  *
213  **/
214
215 int frescan_request_get_type(frescan_request_id_t id, frescan_req_type_t *type)
216 {
217         *type = the_requests_pool[id].type;
218         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "id:%d, type:%d\n", id, *type);
219         return 0;
220 }
221
222 /**
223  * frescan_request_get_reply()
224  *
225  **/
226
227 int frescan_request_get_reply(frescan_request_id_t id, frescan_robj_id_t *reply)
228 {
229         *reply = the_requests_pool[id].reply;
230         return 0;
231 }
232
233 /**
234  * frescan_request_get_contract()
235  *
236  **/
237
238 int frescan_request_get_contract(frescan_request_id_t id,
239                                  frescan_contract_t **contract)
240 {
241         *contract = the_requests_pool[id].contract;
242         return 0;
243 }
244
245 /**
246  * frescan_request_get_src()
247  *
248  **/
249
250 int frescan_request_get_src(frescan_request_id_t id, frescan_node_t *src)
251 {
252         *src = the_requests_pool[id].src;
253         return 0;
254 }
255
256 /**
257  * frescan_request_get_return_info()
258  *
259  **/
260
261 int frescan_request_get_return_info(frescan_request_id_t id,
262                                     void **return_info)
263 {
264         *return_info = the_requests_pool[id].return_info;
265         return 0;
266 }
267
268 /**
269  * frescan_requestqueue_enqueue()
270  *
271  **/
272
273 int frescan_requestqueue_enqueue(frescan_request_id_t id)
274 {
275         int err;
276
277         err = fosa_mutex_lock(&requests_mutex);
278         if (err != 0) return err;
279
280         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
281               "is list empty A? %d\n",
282               list_empty(&the_requests_list.request_list));
283
284         list_add_tail(&the_requests_pool[id].request_list,
285                       &the_requests_list.request_list);
286
287         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
288               "is list empty B? %d\n",
289               list_empty(&the_requests_list.request_list));
290
291         err = fosa_cond_signal(&requests_cond);
292         if (err != 0) goto locked_error;
293
294         err = fosa_mutex_unlock(&requests_mutex);
295         if (err != 0) return err;
296
297         return 0;
298
299 locked_error:
300         fosa_mutex_unlock(&requests_mutex);
301         return err;
302 }
303
304 /**
305  * frescan_requestqueue_dequeue()
306  *
307  **/
308
309 int frescan_requestqueue_dequeue(frescan_request_id_t *id)
310 {
311         int err;
312         struct list_head *pos;
313         struct request_t *request = NULL;
314
315         err = fosa_mutex_lock(&requests_mutex);
316         if (err != 0) return err;
317
318         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "entering\n");
319
320         while (list_empty(&the_requests_list.request_list)) {
321                 err = fosa_cond_wait(&requests_cond, &requests_mutex);
322                 if (err != 0) goto locked_error;
323                 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "received signal\n");
324         }
325
326         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "dequeueing a request\n");
327
328         list_for_each(pos, &the_requests_list.request_list) {
329                 request = list_entry(pos, struct request_t, request_list);
330                 break;
331         }
332
333         list_del(&request->request_list);
334
335         *id = request->pool_pos;
336
337         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
338               "is list empty now? %d\n",
339               list_empty(&the_requests_list.request_list));
340
341         err = fosa_mutex_unlock(&requests_mutex);
342         if (err != 0) return err;
343
344         return 0;
345
346 locked_error:
347         fosa_mutex_unlock(&requests_mutex);
348         return err;
349 }