Add -c to ar to remove a diagnostic, when the archive is created.
[libfirm] / ir / lpp / lpp_net.c
1 /*
2  * Copyright (C) 2005-2011 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   A client for an lpp solving server.
23  * @author  Sebastian Hack
24  */
25 #include "config.h"
26
27 #ifdef _WIN32
28 #include <winsock.h>
29 #include <io.h>
30
31 #else
32 #include <sys/time.h>
33 #include <sys/socket.h>
34 #include <sys/types.h>
35 #include <sys/resource.h>
36 #include <sys/wait.h>
37
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #include <netdb.h>
41 #include <unistd.h>
42
43 /* solaris fix */
44 #ifndef INADDR_NONE
45 #define INADDR_NONE (in_addr_t)(-1)
46 #endif
47
48 #endif
49
50
51 #include <signal.h>
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <stdio.h>
55 #include <string.h>
56
57 #include "timing.h"
58
59 #include "lpp_net.h"
60 #include "lpp_t.h"
61 #include "lpp_comm.h"
62
63 #ifdef _WIN32
64 static int winsock_init(void)
65 {
66         WORD wVersionRequested;
67         WSADATA wsaData;
68         int err;
69
70         wVersionRequested = MAKEWORD( 2, 2 );
71
72         err = WSAStartup( wVersionRequested, &wsaData );
73         if ( err != 0 ) {
74                 /* Tell the user that we could not find a usable */
75                 /* WinSock DLL.                                  */
76                 return 0;
77         }
78
79         /* Confirm that the WinSock DLL supports 2.2.*/
80         /* Note that if the DLL supports versions greater    */
81         /* than 2.2 in addition to 2.2, it will still return */
82         /* 2.2 in wVersion since that is the version we      */
83         /* requested.                                        */
84
85         if ( LOBYTE( wsaData.wVersion ) != 2 ||
86                         HIBYTE( wsaData.wVersion ) != 2 ) {
87                 /* Tell the user that we could not find a usable */
88                 /* WinSock DLL.                                  */
89                 WSACleanup( );
90                 return 0;
91         }
92         return 1;
93 }
94 #endif
95
96 static int connect_tcp(const char *host, uint16_t port)
97 {
98         struct hostent     *phe;
99         struct protoent    *ppe;
100         struct sockaddr_in sin;
101         int s;
102
103 #ifdef _WIN32
104         winsock_init();
105 #endif
106
107         memset(&sin, 0, sizeof(sin));
108         sin.sin_family = AF_INET;
109         sin.sin_port   = htons(port);
110
111         if ((phe = gethostbyname(host)))
112                 memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
113         else if((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
114                 lpp_print_err("cannot get host entry for %s", host);
115                 return -1;
116         }
117
118         ppe = getprotobyname("tcp");
119         ERRNO_CHECK_RETURN(s = socket(PF_INET, SOCK_STREAM, ppe->p_proto), <, 0, -1);
120         ERRNO_CHECK_RETURN(connect(s, (struct sockaddr *) &sin, sizeof(sin)), <, 0, -1);
121
122         return s;
123 }
124
125 char **lpp_get_solvers(const char *host)
126 {
127         int fd, n;
128         char **res = NULL;
129         lpp_comm_t *comm;
130
131         ERR_CHECK_RETURN(fd = connect_tcp(host, LPP_PORT), <, 0,
132                         ("could not connect to %s", host), NULL);
133
134         comm = lpp_comm_new(fd, LPP_BUFSIZE);
135
136         lpp_writel(comm, LPP_CMD_SOLVERS);
137         lpp_flush(comm);
138         n = lpp_readl(comm);
139         res = malloc((n + 1) * sizeof(res[0]));
140         res[n] = NULL;
141
142         if(n > 0) {
143                 int i;
144                 for(i = 0; i < n; ++i)
145                         res[i] = lpp_reads(comm);
146         }
147
148         lpp_writel(comm, LPP_CMD_BYE);
149         lpp_flush(comm);
150         lpp_comm_free(comm);
151         close(fd);
152         return res;
153 }
154
155 void lpp_set_dbg(const char *host, int mask)
156 {
157         int fd;
158         lpp_comm_t *comm;
159
160         ERR_CHECK_RETURN_VOID(fd = connect_tcp(host, LPP_PORT), <, 0, ("could not connect to %s", host));
161
162         comm = lpp_comm_new(fd, LPP_BUFSIZE);
163
164         lpp_writel(comm, LPP_CMD_SET_DEBUG);
165         lpp_writel(comm, mask);
166         lpp_flush(comm);
167         lpp_writel(comm, LPP_CMD_BYE);
168         lpp_flush(comm);
169         lpp_comm_free(comm);
170         close(fd);
171 }
172
173 void lpp_solve_net(lpp_t *lpp, const char *host, const char *solver)
174 {
175         char buf[1024];
176         int n, fd, ready;
177         lpp_comm_t *comm;
178         ir_timer_t *t_send, *t_recv;
179
180         ERR_CHECK_RETURN_VOID(fd = connect_tcp(host, LPP_PORT), <, 0,
181                 ("could not connect to %s", host));
182
183         comm = lpp_comm_new(fd, LPP_BUFSIZE);
184
185         /* Set the solver */
186         lpp_writel(comm, LPP_CMD_SOLVER);
187         lpp_writes(comm, solver);
188         lpp_flush(comm);
189
190 #if 0
191         ERR_CHECK_RETURN_VOID(lpp_ack(fd, sizeof(buf), buf), == 0,
192                 ("could not set solver: %s", solver));
193 #endif
194
195         t_send = ir_timer_new();
196         t_recv = ir_timer_new();
197
198         ir_timer_push(t_send);
199         lpp_writel(comm, LPP_CMD_PROBLEM);
200         lpp_serialize(comm, lpp, 1);
201         lpp_serialize_values(comm, lpp, lpp_value_start);
202         lpp_flush(comm);
203         ir_timer_pop();
204         lpp->send_time = ir_timer_elapsed_usec(t_send);
205
206         ready = 0;
207         while (! ready) {
208                 int cmd = lpp_readl(comm);
209                 switch(cmd) {
210                         case LPP_CMD_SOLUTION:
211                                 ir_timer_push(t_recv);
212                                 lpp_deserialize_stats(comm, lpp);
213                                 lpp_deserialize_values(comm, lpp, lpp_value_solution);
214                                 ir_timer_pop();
215                                 lpp->recv_time = ir_timer_elapsed_usec(t_recv);
216                                 ready = 1;
217                                 break;
218                         case LPP_CMD_INFO:
219                                 lpp_readbuf(comm, buf, sizeof(buf));
220                                 buf[sizeof(buf) - 1] = '\0';
221
222                                 if(lpp->log != NULL) {
223                                         fputs(buf, lpp->log);
224                                         n = strlen(buf);
225                                         if(buf[n - 1] != '\n')
226                                                 putc('\n', lpp->log);
227                                         fflush(lpp->log);
228                                 }
229                                 break;
230                         case LPP_CMD_BAD:
231                                 fprintf(stderr, "solver process died unexpectedly\n");
232                                 goto end;
233                         default:
234                                 fprintf(stderr, "invalid command: %s(%d)\n", lpp_get_cmd_name(cmd), cmd);
235                                 return;
236                 }
237         }
238
239         lpp_writel(comm, LPP_CMD_BYE);
240         lpp_flush(comm);
241
242 end:
243         lpp_comm_free(comm);
244 #ifdef _WIN32
245         closesocket(fd);
246 #else
247         close(fd);
248 #endif
249 }