]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_servers_replenishments.c
added the functions to renegotiate and cancel a contract. TODO: there is a bug when...
[frescor/fna.git] / src_frescan / frescan_servers_replenishments.c
1 /*!
2  * @file frescan_servers_replenishments.c
3  *
4  * @brief the replenishment data and thread for the servers
5  *
6  * @version 0.01
7  *
8  * @date 12-Mar-2008
9  *
10  * @author
11  *      Daniel Sangorrin
12  *
13  * @comments
14  *
15  * This module contains the thread that waits for server's replenishment
16  * timer signals and perform the necessary replenishments.
17  *
18  * @license
19  *
20  * See MaRTE OS license
21  *
22  */
23
24 #include <time.h>            // clock_gettime
25
26 #include <misc/freelist.h>   // freelist_t
27 #include <misc/linux_list.h> // list_add_tail
28 #include <misc/timespec_operations.h>
29
30 #include "frescan_servers_replenishments.h"
31 #include "frescan_config.h"  // FRESCAN_MX_REPL_OPS
32 #include "frescan_debug.h"   // ERROR
33 #include "frescan_data.h"    // frescan_repl_op_t
34 #include "fosa_threads_and_signals.h" // fosa_thread_attr_init...
35
36 /**
37  * the_repl_op_pool - pool of replenishment operations
38  *
39  * We have a pool of replenishment operation structures and an associated
40  * freelist where we can get/put replenishment operations in O(1) time
41  *
42  * @the_repl_op_pool: array with the replenishment operations allocated
43  * @the_repl_op_pool_freelist: freelist for the_repl_op_pool
44  * @frescan_repl_op_init: initializes the freelist
45  * @frescan_repl_op_alloc: get a free replenishment operation structure
46  * @frescan_repl_op_free: free a replenishment operation structure
47  *
48  */
49
50 static frescan_repl_op_t the_repl_op_pool[FRESCAN_MX_REPL_OPS];
51 static freelist_t the_repl_op_pool_freelist;
52
53 static int frescan_repl_op_init()
54 {
55         return freelist_init(&the_repl_op_pool_freelist, FRESCAN_MX_REPL_OPS);
56 }
57
58 frescan_repl_op_t *frescan_repl_op_alloc()
59 {
60         int pos;
61
62         pos = freelist_alloc(&the_repl_op_pool_freelist);
63         if (pos == -1) {
64                 ERROR("could not allocate repl op\n");
65                 return NULL;
66         }
67         the_repl_op_pool[pos].pool_pos = pos; // to know how to free it
68         return &the_repl_op_pool[pos];
69 }
70
71 int frescan_repl_op_free(frescan_repl_op_t *repl_op)
72 {
73         return freelist_free(&the_repl_op_pool_freelist, repl_op->pool_pos);
74 }
75
76 /**
77  * frescan_repl_thread - the thread that executes the replenishments
78  */
79
80 static void *frescan_repl_thread(void *arg)
81 {
82         int ret;
83         sigset_t set;
84         siginfo_t siginfo;
85         frescan_ss_t id;
86         frescan_network_t net;
87         frescan_server_data_t *server;
88         struct itimerspec timerdata;
89
90         net = (frescan_network_t)(uint32_t)arg;
91         timerdata.it_interval.tv_sec  = 0;
92         timerdata.it_interval.tv_nsec = 0;
93
94         sigemptyset(&set);
95         sigaddset(&set, FRESCAN_REPL_SIGNAL_NUM);
96
97         while (1) {
98                 ret = sigwaitinfo(&set, &siginfo);
99                 if (ret == -1) {
100                         ERROR("sigwaitinfo failed\n");
101                         return NULL;
102                 }
103
104                 if (siginfo.si_signo != FRESCAN_REPL_SIGNAL_NUM) continue;
105
106                 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
107                       "net:%u signal:%d code:%d value(server_id):%d\n",
108                       net,
109                       siginfo.si_signo,            // FRESCAN_REPL_SIGNAL_NUM
110                       siginfo.si_code,             // SI_TIMER
111                       siginfo.si_value.sival_int); // the server id
112
113                 id = siginfo.si_value.sival_int;
114                 server = &the_servers_pool[net][id];
115
116                 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
117                       "id:%u current_prio:%u\n", id, server->current_priority);
118
119                 server->current_priority = server->params.prio;
120
121                 if (!list_empty(&server->packet_list.fifo_list)) {
122                         clock_gettime (CLOCK_MONOTONIC, &server->act_time);
123                 }
124         }
125
126         return NULL;
127 }
128
129 /**
130  * frescan_replenishments_init - init the replenishment structures and thread
131  *
132  * @net: the network instance
133  *
134  * Initialize the repl_op pool, set the mask for the timer signals and create
135  * the thread that will await for those signals and replenish the appropiate
136  * sporadic server.
137  */
138
139 int frescan_replenishments_init(frescan_network_t net)
140 {
141         int ret;
142         fosa_signal_t signal_set[1];
143         fosa_thread_attr_t attr;
144
145         ret = frescan_repl_op_init();
146         if (ret != 0) {
147                 ERROR("could not init repl_op pool\n");
148                 return ret;
149         }
150
151         signal_set[0] = FRESCAN_REPL_SIGNAL_NUM;
152
153         ret = fosa_set_accepted_signals(signal_set, 1);
154         if (ret != 0) {
155                 ERROR("could not set the repl signal\n");
156                 return ret;
157         }
158
159         // create the replenishment thread
160
161         ret = fosa_thread_attr_init(&attr);
162         if (ret != 0) {
163                 ERROR("could not init thread attributes\n");
164                 return ret;
165         }
166
167         ret = fosa_thread_attr_set_prio(&attr, FRESCAN_REPL_THREAD_PRIO);
168         if (ret != 0) {
169                 ERROR("could not set repl thread prio %d\n",
170                       FRESCAN_REPL_THREAD_PRIO);
171                 return ret;
172         }
173
174         ret = fosa_thread_create(&the_networks[net].repl_thread_id,
175                                  &attr,
176                                  frescan_repl_thread,
177                                  (void *)(uint32_t)net);
178         if (ret != 0) {
179                 ERROR("could not create the replenishment thread\n");
180                 return ret;
181         }
182
183         ret = fosa_thread_attr_destroy(&attr);
184         if (ret != 0) {
185                 ERROR("could not destroy thread attributes\n");
186                 return ret;
187         }
188
189         return 0;
190 }
191
192 /**
193  * frescan_replenishment_program - set a replenishment operation
194  *
195  * @net: the network instance
196  * @ss: the server
197  */
198
199 int frescan_replenishment_program(frescan_network_t net,
200                                   frescan_ss_t ss,
201                                   const struct timespec *timestamp)
202 {
203         int ret;
204         frescan_repl_op_t *repl = NULL;
205         struct itimerspec timerdata;
206         frescan_server_data_t *server;
207         struct list_head *pos;
208         struct timespec now;
209
210         server = &the_servers_pool[net][ss];
211
212         // extract the head
213         list_for_each(pos, &server->replenishments.repl_list) {
214                 repl = list_entry(pos, frescan_repl_op_t, repl_list);
215                 break;
216         }
217         list_del(&repl->repl_list);
218
219         // move to tail with new repl value
220         repl->when = *timestamp;
221         incr_timespec (&repl->when, &server->params.values.period);
222         repl->amount = 1;
223
224         list_add_tail(&repl->repl_list,
225                        &server->replenishments.repl_list);
226
227         // check the new head
228         list_for_each(pos, &server->replenishments.repl_list) {
229                 repl = list_entry(pos, frescan_repl_op_t, repl_list);
230                 break;
231         }
232
233         clock_gettime (CLOCK_MONOTONIC, &now);
234
235         if (smaller_timespec(&now, &repl->when)) {
236                 server->current_priority = FRESCAN_BACKGROUND_PRIO;
237
238                 timerdata.it_interval.tv_sec  = 0;
239                 timerdata.it_interval.tv_nsec = 0;
240                 timerdata.it_value = repl->when;
241
242                 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
243                       "set timer to %d sec, %d nsec\n",
244                       repl->when.tv_sec, repl->when.tv_nsec);
245
246                 ret = timer_settime(server->repl_timer,
247                                     TIMER_ABSTIME, &timerdata, NULL);
248                 if (ret != 0) {
249                         ERROR("could not set the replenishment timer\n");
250                         return ret;
251                 }
252         }
253
254         return 0;
255 }