Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add the new integrated files version (use xbt data structures instead my own data...
[simgrid.git] / tools / tesh2 / src / writer.c
1 /*\r
2  * src/writer.c - type representing a stdin writer.\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 writer type.\r
12  *\r
13  */\r
14  \r
15 #include <writer.h>\r
16 #include <command.h>\r
17 \r
18 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
19 \r
20 static void*\r
21 writer_start_routine(void* p);\r
22 \r
23 writer_t\r
24 writer_new(command_t command)\r
25 {\r
26         writer_t writer;\r
27         /* TODO : check the parameter */\r
28         \r
29         writer = xbt_new0(s_writer_t, 1);\r
30 \r
31         writer->thread = NULL;\r
32         writer->command = command;\r
33         writer->written = xbt_os_sem_init(0);\r
34         writer->can_write = xbt_os_sem_init(0);\r
35         \r
36         writer->done = 0;\r
37 \r
38         return writer;\r
39 }\r
40 \r
41 int\r
42 writer_free(writer_t* ptr)\r
43 {\r
44         /* TODO : check the parameter */\r
45         \r
46         /*xbt_os_sem_destroy((*writer)->started);\r
47         xbt_os_sem_destroy((*writer)->can_write);*/\r
48         \r
49         free(*ptr);\r
50         *ptr = NULL;\r
51         \r
52         return 0;\r
53 }\r
54 \r
55 void\r
56 writer_write(writer_t writer)\r
57 {\r
58         writer->thread = xbt_os_thread_create("", writer_start_routine, writer);\r
59 }\r
60 \r
61 #ifdef WIN32\r
62 static void*\r
63 writer_start_routine(void* p)\r
64 {\r
65         writer_t writer = (writer_t)p;\r
66         command_t command = writer->command;\r
67         \r
68         char* input = (char*)(command->context->input->data);\r
69         \r
70         DWORD number_of_bytes_to_write = command->context->input->used;\r
71         DWORD number_of_bytes_written = 0;\r
72 \r
73         while(!command->failed && !command->interrupted && !command->successeded && ! writer->failed && ! writer->broken_pipe && number_of_bytes_to_write)\r
74         {\r
75                 if(!WriteFile(writer->command->stdin_fd, input, number_of_bytes_to_write, &number_of_bytes_written, NULL))\r
76                 {\r
77                         if(GetLastError() ==  ERROR_NO_DATA)\r
78                                 writer->broken_pipe = 1;\r
79                         else\r
80                         writer->failed = 1;\r
81                                 \r
82                 }\r
83                 else\r
84                 {\r
85                         input += number_of_bytes_written;\r
86                         number_of_bytes_to_write -= number_of_bytes_written;\r
87                 }\r
88         }\r
89         \r
90         command->context->input->data[0]='\0';\r
91         command->context->input->used=0;\r
92         \r
93         if(writer->failed  && !command->successeded && !command->failed && !command->interrupted)\r
94         {\r
95                 error_register("Write failure", errno, command->context->command_line, command->unit->fstream->name);\r
96                 command_handle_failure(command, csr_write_failure);\r
97         }\r
98         /*else if(writer->broken_pipe && !command->successeded && !command->failed && !command->interrupted)\r
99         {\r
100                 command_kill(command);\r
101                 command_handle_failure(command, csr_write_pipe_broken);\r
102         }*/\r
103         \r
104         CloseHandle(command->stdin_fd);\r
105         command->stdin_fd = INDEFINITE_FD;\r
106 \r
107         return NULL;\r
108 }\r
109 #else\r
110 static void* \r
111 writer_start_routine(void* p) \r
112 {\r
113         writer_t writer = (writer_t)p;\r
114         command_t command = writer->command;\r
115         int number_of_bytes_to_write = command->context->input->used;\r
116         char* input = (char*)(command->context->input->data);\r
117         int got;\r
118         int released = 0;\r
119         \r
120         while(!command->failed && !command->interrupted && !command->successeded && number_of_bytes_to_write > 0)\r
121         {\r
122                 got = number_of_bytes_to_write > PIPE_BUF ? PIPE_BUF : number_of_bytes_to_write;\r
123                 got = write(writer->command->stdin_fd, input, got );\r
124                 \r
125                 if(got < 0) \r
126                 {\r
127                         if(EINTR == errno)\r
128                                 continue;\r
129                                 \r
130                         else if(EAGAIN == errno)\r
131                         {/* the pipe is full */\r
132                                 if(!released)\r
133                                 {\r
134                                         xbt_os_sem_release(writer->written);\r
135                                         released = 1;\r
136                                         xbt_os_thread_yield();\r
137                                 }\r
138                                 \r
139                                 continue;\r
140                         }\r
141                         else if(EPIPE == errno) \r
142                         {\r
143                                 writer->broken_pipe = 1;\r
144                                 break;\r
145                         } \r
146                         else\r
147                         {\r
148                                 writer->failed = 1;\r
149                                 break;\r
150                         }\r
151                         \r
152                 }\r
153                 \r
154                 number_of_bytes_to_write -= got;\r
155                 input += got;\r
156                 \r
157                 if(got == 0)\r
158                         xbt_os_thread_yield();\r
159                 \r
160         }\r
161         \r
162         if(!released)\r
163                 xbt_os_sem_release(writer->written);\r
164         \r
165         \r
166         if(close(command->stdin_fd) < 0)\r
167         {\r
168                 /* TODO */\r
169         }\r
170         else\r
171                 command->stdin_fd = INDEFINITE_FD;\r
172         \r
173         command->context->input->data[0]='\0';\r
174         command->context->input->used=0;\r
175         \r
176         if(writer->failed && !command->successeded && !command->failed && !command->interrupted)\r
177         {\r
178                 command_kill(command);\r
179                 error_register("Write failure", errno, command->context->command_line, command->unit->fstream->name);\r
180                 command_handle_failure(command, csr_write_failure);\r
181         }\r
182         else if(writer->broken_pipe && !command->successeded && !command->failed && !command->interrupted)\r
183         {\r
184                 error_register("write() function failed", errno, command->context->command_line, command->unit->fstream->name);\r
185                 command_kill(command);\r
186                 command_handle_failure(command, csr_write_pipe_broken);\r
187         }\r
188         \r
189         writer->done = 1;\r
190         \r
191         return NULL;\r
192         \r
193 }\r
194 \r
195 #endif\r
196 void\r
197 writer_wait(writer_t writer)\r
198 {\r
199         xbt_os_thread_join(writer->thread, NULL);\r
200 \r
201 }\r