Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
some new files used to check Tesh
[simgrid.git] / tools / tesh2 / src / reader.c
1 /*\r
2  * src/reader.c - type representing a stdout reader.\r
3  *\r
4  * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved. \r
5  *\r
6  * This program is free software; you can redistribute it and/or modify it \r
7  * under the terms of the license (GNU LGPL) which comes with this package.\r
8  *\r
9  * Purpose:\r
10  *              This file contains all the definitions of the functions related with\r
11  *              the tesh reader type.\r
12  *\r
13  */\r
14 \r
15 #include <unit.h>\r
16 #include <reader.h>\r
17 #include <command.h>\r
18 \r
19 \r
20 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
21 \r
22 \r
23 static void*\r
24 reader_start_routine(void* p);\r
25 \r
26 reader_t\r
27 reader_new(command_t command)\r
28 {\r
29         reader_t reader;\r
30         \r
31         /* TODO : check the parameter */\r
32         \r
33         reader = xbt_new0(s_reader_t, 1);\r
34         \r
35         reader->thread = NULL;\r
36         reader->command = command;\r
37         reader->broken_pipe = 0;\r
38         reader->failed = 0;\r
39         reader->done = 0;\r
40         \r
41         reader->started = xbt_os_sem_init(0);\r
42         \r
43         return reader;\r
44 }\r
45 \r
46 int\r
47 reader_free(reader_t* ptr)\r
48 {\r
49         if((*ptr)->started)\r
50                 xbt_os_sem_destroy((*ptr)->started);\r
51         \r
52         free(*ptr);\r
53         \r
54         *ptr = NULL;\r
55         \r
56         return 0;\r
57 }\r
58 \r
59 void\r
60 reader_read(reader_t reader)\r
61 {\r
62         reader->thread = xbt_os_thread_create("", reader_start_routine, reader);\r
63 }\r
64 \r
65 #ifdef WIN32\r
66 static void*\r
67 reader_start_routine(void* p)\r
68 {\r
69         reader_t reader = (reader_t)p;\r
70         command_t command = reader->command;\r
71         \r
72         xbt_strbuff_t output = command->output;\r
73         HANDLE stdout_fd = command->stdout_fd;\r
74         \r
75         DWORD number_of_bytes_to_read = 1024; /*command->context->output->used;*/\r
76         DWORD number_of_bytes_readed = 0;\r
77         \r
78         char* buffer = (char*)calloc(number_of_bytes_to_read + 1,sizeof(char));\r
79         char* clean = (char*)calloc(number_of_bytes_to_read + 1,sizeof(char));\r
80         size_t i, j;\r
81 \r
82         while(!command->failed && !command->interrupted && !command->successeded && !reader->failed && !reader->broken_pipe)\r
83         {\r
84                 if(!ReadFile(stdout_fd, buffer, number_of_bytes_to_read, &number_of_bytes_readed, NULL) || (0 == number_of_bytes_readed))\r
85                 {\r
86                         if(GetLastError() == ERROR_BROKEN_PIPE)\r
87                                 reader->broken_pipe = 1;\r
88                         else\r
89                         reader->failed = 1;\r
90                                 \r
91                 }\r
92                 else\r
93                 {\r
94                         if(number_of_bytes_readed > 0) \r
95                         {\r
96                                 for(i= 0, j= 0; i < number_of_bytes_readed; i++)\r
97                                         if((int)(buffer[i]) != 13)\r
98                                                 clean[j++] = buffer[i];\r
99 \r
100                                 xbt_strbuff_append(output,clean);\r
101 \r
102                                 memset(buffer, 0, 1024);\r
103                                 memset(clean, 0, 1024);\r
104                         } \r
105                         else \r
106                         {\r
107                                 xbt_os_thread_yield();\r
108                         }\r
109                 }\r
110         }\r
111 \r
112         free(clean);\r
113         free(buffer);\r
114 \r
115         xbt_strbuff_chomp(command->output);\r
116         xbt_strbuff_trim(command->output);\r
117 \r
118         reader->done = 1;\r
119         \r
120         if(command->failed)\r
121         {\r
122                 if(command->reason == csr_write_failure)\r
123                 {\r
124                         if(command->output->used)\r
125                                 INFO2("[%s] Output on write failure:\n%s",command->context->pos, command->output->data);\r
126                         else\r
127                                 INFO1("[%s] No output before write failure",command->context->pos);\r
128                 }\r
129                 else if(command->reason == csr_write_pipe_broken)\r
130                 {\r
131                         if(command->output->used)\r
132                                 INFO2("[%s] Output on broken pipe:\n%s",command->context->pos, command->output->data);\r
133                         else\r
134                                 INFO1("[%s] No output before broken pipe",command->context->pos);\r
135                 }\r
136         }\r
137         else if(command->interrupted)\r
138         {\r
139                 if(command->output->used)\r
140                         INFO2("[%s] Output on interruption:\n%s",command->context->pos, command->output->data);\r
141                 else\r
142                         INFO1("[%s] No output before interruption",command->context->pos);\r
143         }\r
144         else if(reader->failed && !command->failed && !command->interrupted && !command->successeded)\r
145         {\r
146                 ERROR2("[%s] Error while reading output of child `%s'", command->context->pos, command->context->command_line);\r
147                 \r
148                 if(command->output->used)\r
149                         INFO2("[%s] Output on read failure:\n%s",command->context->pos, command->output->data);\r
150                 else\r
151                         INFO1("[%s] No output before read failure",command->context->pos);\r
152                 \r
153                 unit_set_error(command->unit, errno, 0);\r
154                 command_kill(command);\r
155                 command_handle_failure(command, csr_read_failure);\r
156         }\r
157 \r
158         \r
159         \r
160         return NULL;\r
161 }\r
162 \r
163 #else\r
164 static void*\r
165 reader_start_routine(void* p) \r
166 {\r
167         reader_t reader = (reader_t)p;\r
168         command_t command = reader->command;\r
169         xbt_strbuff_t output = command->output;\r
170         int stdout_fd = command->stdout_fd;\r
171         int number_of_bytes_readed;\r
172         int number_of_bytes_to_read = (1024 > SSIZE_MAX) ? SSIZE_MAX : 1024;\r
173 \r
174         int total = 0;\r
175                 \r
176         char* buffer = (char*)calloc(number_of_bytes_to_read,sizeof(char));\r
177         xbt_os_sem_release(reader->started);\r
178         \r
179         do \r
180         {\r
181                 number_of_bytes_readed = read(stdout_fd, buffer, number_of_bytes_to_read);\r
182                 \r
183                 if(number_of_bytes_readed < 0 && errno != EINTR && errno != EAGAIN) \r
184                 {\r
185                         reader->failed = 1;\r
186                 }\r
187                 \r
188                 if(number_of_bytes_readed > 0) \r
189                 {\r
190                         buffer[number_of_bytes_readed]='\0';\r
191                         xbt_strbuff_append(output,buffer);\r
192                         total += total;\r
193                 } \r
194                 else \r
195                 {\r
196                         xbt_os_thread_yield();\r
197                 }\r
198         \r
199         }while(!command->failed && !command->interrupted && !command->successeded && !reader->failed && (number_of_bytes_readed != 0 /* end of file <-> normal exit */));\r
200         \r
201         free(buffer);\r
202         \r
203         if(close(command->stdout_fd) < 0)\r
204         {\r
205                 /* TODO */\r
206         }\r
207         else\r
208                 command->stdout_fd = INDEFINITE_FD;\r
209         \r
210         xbt_strbuff_chomp(command->output);\r
211         xbt_strbuff_trim(command->output);\r
212 \r
213         reader->done = 1;\r
214 \r
215         if(command->failed)\r
216         {\r
217                 if(command->reason == csr_write_failure)\r
218                 {\r
219                         if(command->output->used)\r
220                                 INFO2("[%s] Output on write failure:\n%s",command->context->pos, command->output->data);\r
221                         else\r
222                                 INFO1("[%s] No output before write failur",command->context->pos);\r
223                 }\r
224                 else if(command->reason == csr_write_pipe_broken)\r
225                 {\r
226                         if(command->output->used)\r
227                                 INFO2("[%s] Output on broken pipe:\n%s",command->context->pos, command->output->data);\r
228                         else\r
229                                 INFO1("[%s] No output before broken pipe",command->context->pos);\r
230                 }\r
231         }\r
232         else if(command->interrupted)\r
233         {\r
234                 if(command->output->used)\r
235                         INFO2("[%s] Output on interruption:\n%s",command->context->pos, command->output->data);\r
236                 else\r
237                         INFO1("[%s] No output before interruption",command->context->pos);\r
238         }\r
239         else if(reader->failed && !command->failed && !command->interrupted && !command->successeded)\r
240         {\r
241                 ERROR2("[%s] Error while reading output of child `%s'", command->context->pos, command->context->command_line);\r
242                 \r
243                 if(command->output->used)\r
244                         INFO2("[%s] Output on read failure:\n%s",command->context->pos, command->output->data);\r
245                 else\r
246                         INFO1("[%s] No output before read failure",command->context->pos);\r
247                 \r
248                 unit_set_error(command->unit, errno, 0);\r
249                 command_kill(command);\r
250                 command_handle_failure(command, csr_read_failure);\r
251         }\r
252         \r
253         \r
254         return NULL;\r
255\r
256 #endif\r
257 \r
258 void\r
259 reader_wait(reader_t reader)\r
260 {\r
261         xbt_os_thread_join(reader->thread, NULL);\r
262 }\r