Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
b1ed324f76a4e758059489321395e2436bec961f
[simgrid.git] / tools / tesh2 / src / runner..0.c
1 #include <runner.h>
2 #include <unit.h>
3
4 #include <errno.h>      /* for error code       */
5 #include <stdlib.h>     /* for calloc()         */
6 #include <stdio.h>      
7
8
9 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
10
11 /* the unique tesh runner */
12 static runner_t
13 runner = NULL;
14
15 /* wait for the tesh runner terminaison */
16 static void
17 runner_wait(void);
18
19 static void*
20 runner_start_routine(void* p);
21
22
23 /* check the syntax of the tesh files if 
24  * the want_check_syntax is specified. Returns
25  * 0 if the syntax is clean.
26  */
27 static int
28 check_syntax(void);
29
30 #ifdef WIN32
31
32 static HANDLE 
33 timer_handle = NULL;
34
35 static void*
36 runner_start_routine(void* p)
37 {
38         
39     LARGE_INTEGER li;
40
41     li.QuadPart=- runner->timeout * 10000000;   /* 10000000 = 10 000 000 * 100 nanoseconds = 1 second */
42
43     /* create the waitable timer */
44     timer_handle = CreateWaitableTimer(NULL, TRUE, NULL);
45
46     /* set a timer to wait for timeout seconds */
47     SetWaitableTimer(timer_handle, &li, 0, NULL, NULL, 0);
48     
49     /* wait for the timer */
50     WaitForSingleObject(timer_handle, INFINITE);
51         
52         if(runner->waiting)
53         {
54                 exit_code = E_GLOBAL_TIMEOUT;
55                 runner->timeouted = 1;
56                 xbt_os_sem_release(units_sem);
57         }
58
59         return NULL;
60 }
61
62 #else
63 static void*
64 runner_start_routine(void* p)
65 {
66         struct timespec ts;
67
68         ts.tv_sec = runner->timeout;
69         ts.tv_nsec = 0L;
70
71         do
72         {
73                 nanosleep(&ts, &ts);
74         }while(EINTR == errno);
75         
76         if(errno)
77         {
78                 /* TODO process the error */
79         }
80         else
81         {
82                 if(runner->waiting)
83                 {
84                         exit_code = E_GLOBAL_TIMEOUT;
85                         runner->timeouted = 1;
86                         xbt_os_sem_release(units_sem);
87                 }
88         }
89         
90         return NULL;
91 }
92 #endif
93
94
95 int
96 runner_init(
97                                         int want_check_syntax, 
98                                         int timeout,
99                                         int number_of_files, 
100                                         strings_t files, 
101                                         FILE** streams)
102 {
103         int i, rv;
104         int j = 0;
105         
106
107         runner = xbt_new0(s_runner_t, 1);
108         
109         runner->units = xbt_new0(unit_t, number_of_files);
110
111         if(!(runner->units))
112         {
113                 /* TODO : display the error */
114                 free(runner);
115                 runner = NULL;
116         }
117         
118         
119         runner->number_of_units = number_of_files;
120
121         runner->timeout = timeout;
122         runner->timeouted = 0;
123         runner->interrupted = 0;
124         runner->number_of_ended_units = 0;
125         runner->number_of_runned_units = 0;
126         runner->waiting = 0;
127         
128         for(i = 0; i < files->number; i++)
129         {
130                 if(streams[i])
131                         (runner->units)[j++] = unit_new(runner, NULL, files->items[i], streams[i]);
132         }
133         
134         
135         if(want_check_syntax)
136         {
137                 if((rv = check_syntax()))
138                         return rv;              
139         }
140                 
141         return 0;
142                 
143 }
144
145 void
146 runner_destroy(void)
147 {
148         int i, size;
149
150         size = runner->number_of_units;
151
152         for(i = 0; i < size; i++)
153         {
154                 unit_free(&(runner->units[i]));
155         }
156
157         free(runner->units);
158
159         #ifdef WIN32
160         CloseHandle(timer_handle);
161         #endif
162
163         if(runner->thread)
164                 xbt_os_thread_join(runner->thread, NULL);
165
166         free(runner);
167
168         runner = NULL;
169 }
170
171 void
172 runner_run(void)
173 {
174         int i;
175         xbt_os_mutex_t mutex;
176         xbt_os_thread_t thread;
177
178         mutex = xbt_os_mutex_init();
179         
180         for(i = 0; i < runner->number_of_units; i++)
181         {
182                 if(!unit_run(runner->units[i], mutex))
183                 {
184                         ERROR1("Can't run the unit %s",runner->units[i]->file_name);
185                         interrupted = 1;
186                         break;
187                 }
188         }
189         
190         if(!interrupted)
191                 runner_wait();
192         
193         /* if the runner is timeouted or receive a interruption request
194          * , interrupt all the active units.
195          */
196
197         if(runner->timeouted || interrupted)
198                 runner_interrupt();
199         
200         
201         /*printf("the runner try to join all the units\n");*/
202         
203         for(i = 0; i < runner->number_of_units; i++)
204         {
205                 thread = runner->units[i]->thread;
206                 
207                 if(thread)
208                         xbt_os_thread_join(thread, NULL);
209         }
210         
211         /*printf("the runner has joined all the units\n");*/
212
213         xbt_os_mutex_destroy(mutex);
214
215 }
216
217 static void
218 runner_wait(void)
219 {
220         if(runner->timeout > 0)
221                 runner->thread = xbt_os_thread_create("", runner_start_routine, NULL);
222
223         /* signal that the runner is waiting */
224         runner->waiting = 1;
225
226         /*printf("the runner try to acquire the units sem\n");*/
227         /* wait for the end of all the units */
228         xbt_os_sem_acquire(units_sem);
229         /*printf("the runner has acquired the units sem\n");*/
230         
231         runner->waiting = 0;
232 }
233
234 /*
235  * interrupt all the active units.
236  * this function is called when the lead time of the execution is reached
237  * or when a failed unit requests an interruption of the execution.
238  */
239 void
240 runner_interrupt(void)
241 {
242         int i;
243         int size;
244         
245         size = runner->number_of_units;
246
247         for(i = 0; i < size; i++)
248                 if(!(runner->units[i]->successeded) && !(runner->units[i]->interrupted))
249                         unit_interrupt(runner->units[i]);
250 }
251
252 void
253 runner_display_status(void)
254 {
255         if(!want_dry_run)
256         {
257                 int i, size;
258                 
259                 size = runner->number_of_units;
260         
261                 printf("Runner\n");
262                 printf("Status informations :\n");
263         
264                 printf("    number of units     %d\n",size);
265                 
266                 if(exit_code)
267                         printf("    exit code           %d (failure)\n",exit_code);
268                 else
269                         printf("    exit code           %d (success)\n",exit_code);
270                 
271                 
272                         for(i = 0; i < size; i++)
273                                 unit_display_status(runner->units[i]); 
274         }
275         else
276         {
277                 if(exit_code == E_SYNTAX)
278                         ERROR0("Syntax error detected");
279                 else if(exit_code == 0)
280                         INFO0("Syntax 0K");
281         }
282 }
283
284 static int
285 check_syntax(void)
286 {
287         if(!want_dry_run)
288         {
289                 want_dry_run = 1;
290                 
291                 runner_run();
292         
293                 want_dry_run = 0;
294                 
295                 if(0 == exit_code)
296                 {
297                         int i;
298                         unit_t unit;
299                         
300                         if(!want_silent)
301                                 INFO0("syntax checked (OK)");
302                         
303                         for(i = 0; i < runner->number_of_units; i++)
304                         {
305                                 unit = runner->units[i];
306                                 
307                                 fseek(unit->stream,0L, SEEK_SET);
308                                 unit->parsed = 0;
309                                 unit->number_of_commands = 0;
310                         }
311                 
312                 }
313                 
314         }
315         else
316         {
317                 WARN0("mismatch in the syntax : --just-check-syntax and --check-syntax options at same time");
318         }
319
320         return exit_code;
321 }