Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
convert svn logs into ChangeLog (up to r7858 for now)
[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 #include <unit.h>\r
18     \rXBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
19 \r\rstatic void *\r writer_start_routine(void *p);
20 \r\rwriter_t \r writer_new(command_t command) \r
21 {
22   \rwriter_t writer;
23   \r
24       /* TODO : check the parameter */ \r
25       \rwriter = xbt_new0(s_writer_t, 1);
26   \r\rwriter->thread = NULL;
27   \rwriter->command = command;
28   \rwriter->written = xbt_os_sem_init(0);
29   \rwriter->can_write = xbt_os_sem_init(0);
30   \r\rwriter->done = 0;
31   \r\rreturn writer;
32 \r}
33
34 \r\rint \r writer_free(writer_t * ptr) \r
35 {
36   \r\rif ((*ptr)->written)
37     \rxbt_os_sem_destroy((*ptr)->written);
38   \r\rif ((*ptr)->can_write)
39     \rxbt_os_sem_destroy((*ptr)->can_write);
40   \r\rfree(*ptr);
41   \r\r*ptr = NULL;
42   \r\rreturn 0;
43 \r}
44
45 \r\rvoid \r writer_write(writer_t writer) \r
46 {
47   \rwriter->thread = xbt_os_thread_create("", writer_start_routine, writer);
48 \r\r\r
49
50 #ifdef _XBT_WIN32\r
51 static void *\r writer_start_routine(void *p) \r
52 {
53   \rwriter_t writer = (writer_t) p;
54   \rcommand_t command = writer->command;
55   \r\rchar *input = (char *) (command->context->input->data);
56   \r\rDWORD number_of_bytes_to_write = command->context->input->used;
57   \rDWORD number_of_bytes_written = 0;
58   \r\rxbt_os_sem_release(writer->written);
59   \r\rwhile (!command->failed && !command->interrupted
60            && !command->successeded && !writer->failed
61            && !writer->broken_pipe && number_of_bytes_to_write)
62     \r {
63     \rif (!WriteFile
64          (writer->command->stdin_fd, input, number_of_bytes_to_write,
65           &number_of_bytes_written, NULL))
66       \r {
67       \rif (GetLastError() == ERROR_NO_DATA)
68         \rwriter->broken_pipe = 1;
69       \r
70       else
71         \rwriter->failed = 1;
72       \r\r}
73     \r
74     else
75       \r {
76       \rinput += number_of_bytes_written;
77       \rnumber_of_bytes_to_write -= number_of_bytes_written;
78       \r}
79     \r}
80   \r\rcommand->context->input->data[0] = '\0';
81   \rcommand->context->input->used = 0;
82   \r\rif (writer->failed && !command->successeded && !command->failed
83         && !command->interrupted)
84     \r {
85     \rERROR2("[%s] Error while writing input to child `%s'",
86             command->context->pos, command->context->command_line);
87     \runit_set_error(command->unit, (int) GetLastError(), 0,
88                     command->context->pos);
89     \rcommand_handle_failure(command, csr_write_failure);
90     \r}
91   \r
92       /*else if(writer->broken_pipe && !command->successeded && !command->failed && !command->interrupted)\r
93          {\r
94          \r
95          ERROR2("[%s] Pipe broken while writing input to child `%s'", command->context->pos, command->context->command_line);\r
96          unit_set_error(command->unit, (int)GetLastError(), 0);\r
97          command_kill(command);\r
98          command_handle_failure(command, csr_write_pipe_broken);\r
99          } */ \r
100       \rCloseHandle(command->stdin_fd);
101   \rcommand->stdin_fd = INDEFINITE_FD;
102   \r\rreturn NULL;
103 \r}
104
105 \r
106 #else   /* \r */
107 static void *\r writer_start_routine(void *p) \r
108 {
109   \rwriter_t writer = (writer_t) p;
110   \rcommand_t command = writer->command;
111   \rint number_of_bytes_to_write = command->context->input->used;
112   \rchar *input = (char *) (command->context->input->data);
113   \rint got;
114   \rint released = 0;
115   \r\rwhile (!command->failed && !command->interrupted
116            && !command->successeded && number_of_bytes_to_write > 0)
117     \r {
118     \rgot =
119         number_of_bytes_to_write >
120         PIPE_BUF ? PIPE_BUF : number_of_bytes_to_write;
121     \rgot = write(writer->command->stdin_fd, input, got);
122     \r\rif (got < 0)
123       \r {
124       \rif (EINTR == errno)
125         \rcontinue;
126       \r\r
127       else if (EAGAIN == errno)
128         \r {                     /* the pipe is full */
129         \rif (!released)
130           \r {
131           \rxbt_os_sem_release(writer->written);
132           \rreleased = 1;
133           \rxbt_os_thread_yield();
134           \r}
135         \r\rcontinue;
136         \r}
137       \r
138       else if (EPIPE == errno)
139         \r {
140         \rwriter->broken_pipe = 1;
141         \rbreak;
142         \r}
143       \r
144       else
145         \r {
146         \rwriter->failed = 1;
147         \rbreak;
148         \r}
149       \r\r}
150     \r\rnumber_of_bytes_to_write -= got;
151     \rinput += got;
152     \r\rif (got == 0)
153       \rxbt_os_thread_yield();
154     \r\r}
155   \r\rif (!released)
156     \rxbt_os_sem_release(writer->written);
157   \r\r\rif (close(command->stdin_fd) < 0)
158     \r {
159     \r
160         /* TODO */ \r
161     }
162   \r
163   else
164     \rcommand->stdin_fd = INDEFINITE_FD;
165   \r\rcommand->context->input->data[0] = '\0';
166   \rcommand->context->input->used = 0;
167   \r\rif (writer->failed && !command->successeded && !command->failed
168         && !command->interrupted)
169     \r {
170     \rcommand_kill(command);
171     \rERROR2("[%s] Error while writing input to child `%s'",
172             command->context->pos, command->context->command_line);
173     \r\runit_set_error(command->unit, errno, 0, command->context->pos);
174     \rcommand_handle_failure(command, csr_write_failure);
175     \r}
176   \r
177   else if (writer->broken_pipe && !command->successeded && !command->failed
178            && !command->interrupted)
179     \r {
180     \rERROR2("[%s] Pipe broken while writing input to child `%s'",
181             command->context->pos, command->context->command_line);
182     \r\runit_set_error(command->unit, errno, 0, command->context->pos);
183     \rcommand_kill(command);
184     \rcommand_handle_failure(command, csr_write_pipe_broken);
185     \r}
186   \r\rwriter->done = 1;
187   \r\rreturn NULL;
188 \r\r}
189
190 \r\r
191 #endif  /* \r */
192 void \r writer_wait(writer_t writer) \r
193 {
194   \rxbt_os_thread_join(writer->thread, NULL);
195 \r\r\r