Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
tesh version 2
[simgrid.git] / tools / tesh2 / src / runner.c
1 #include <runner.h>
2 #include <units.h>
3 #include <error.h>
4
5 #include <errno.h>      /* for error code       */
6 #include <stdlib.h>     /* for calloc()         */
7 #include <stdio.h>      
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 = ELEADTIME;
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 = ELEADTIME;
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(int want_check_syntax, int timeout, fstreams_t fstreams)
97 {
98         
99         if(runner)
100         {
101                 ERROR0("Runner is already initialized");
102                 return EEXIST;
103         }
104                 
105                 
106         runner = xbt_new0(s_runner_t, 1);
107         
108         if(!(runner->units = units_new(runner, fstreams)))
109         {
110                 ERROR0("Runner initialization failed");
111                 
112                 free(runner);
113                 runner = NULL;
114                 return errno;
115         }
116
117         runner->timeout = timeout;
118         runner->timeouted = 0;
119         runner->interrupted = 0;
120         runner->number_of_ended_units = 0;
121         runner->number_of_runned_units = 0;
122         runner->waiting = 0;
123         
124         if(want_check_syntax)
125         {
126                 if((errno = check_syntax()))
127                         return errno;           
128         }
129                 
130         return 0;
131                 
132 }
133
134 void
135 runner_destroy(void)
136 {
137         units_free((void**)(&(runner->units)));
138
139         #ifdef WIN32
140         CloseHandle(timer_handle);
141         #endif
142
143         if(runner->thread)
144                 xbt_os_thread_join(runner->thread, NULL);
145
146         free(runner);
147
148         runner = NULL;
149 }
150
151 void
152 runner_run(void)
153 {
154         xbt_os_mutex_t mutex;
155
156         mutex = xbt_os_mutex_init();
157         
158         units_run_all(runner->units, mutex);
159         
160         if(!interrupted)
161                 runner_wait();
162         
163         /* if the runner is timeouted or receive a interruption request
164          * , interrupt all the active units.
165          */
166         if(runner->timeouted || interrupted)
167                 runner_interrupt();
168         
169         units_join_all(runner->units);
170
171         xbt_os_mutex_destroy(mutex);
172
173 }
174
175 static void
176 runner_wait(void)
177 {
178         if(runner->timeout > 0)
179                 runner->thread = xbt_os_thread_create("", runner_start_routine, NULL);
180         /* signal that the runner is waiting */
181         runner->waiting = 1;
182         
183         /* wait for the end of all the units */
184         xbt_os_sem_acquire(units_sem);
185         
186         runner->waiting = 0;
187 }
188
189
190
191 /*
192  * interrupt all the active units.
193  * this function is called when the lead time of the execution is reached
194  * or when a failed unit requests an interruption of the execution.
195  */
196 void
197 runner_interrupt(void)
198 {
199         units_interrupt_all(runner->units);
200 }
201
202 void
203 runner_display_status(void)
204 {
205         if(!want_dry_run)
206         {
207                 
208                 /*unit_t unit;*/
209         
210                 printf("Runner\n");
211                 printf("Status informations :\n");
212         
213                 printf("    number of units     %d\n",units_get_size(runner->units));
214                 printf("    exit code           %d (%s)\n",exit_code, exit_code ? error_to_string(exit_code) : "success");
215                 
216                 units_verbose(runner->units);
217         }
218         else
219         {
220                 if(exit_code)
221                         ERROR0("Syntax error detected");
222                 else if(exit_code == 0)
223                         INFO0("Syntax 0K");
224         }
225 }
226
227 static int
228 check_syntax(void)
229 {
230         if(!want_dry_run)
231         {
232                 want_dry_run = 1;
233                 
234                 runner_run();
235         
236                 want_dry_run = 0;
237                 
238                 if(0 == exit_code)
239                 {
240                         if(!want_silent)
241                                 INFO0("syntax checked (OK)");
242                         
243                         units_reset_all(runner->units);
244                 
245                 }
246                 
247         }
248         else
249         {
250                 WARN0("mismatch in the syntax : --just-check-syntax and --check-syntax options at same time");
251         }
252
253         return exit_code;
254 }