2 * Copyright (C) 2005-2011 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief A client for an lpp solving server.
23 * @author Sebastian Hack
33 #include <sys/socket.h>
34 #include <sys/types.h>
35 #include <sys/resource.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
45 #define INADDR_NONE (in_addr_t)(-1)
65 static int winsock_init(void)
67 WORD wVersionRequested;
71 wVersionRequested = MAKEWORD( 2, 2 );
73 err = WSAStartup( wVersionRequested, &wsaData );
75 /* Tell the user that we could not find a usable */
80 /* Confirm that the WinSock DLL supports 2.2.*/
81 /* Note that if the DLL supports versions greater */
82 /* than 2.2 in addition to 2.2, it will still return */
83 /* 2.2 in wVersion since that is the version we */
86 if ( LOBYTE( wsaData.wVersion ) != 2 ||
87 HIBYTE( wsaData.wVersion ) != 2 ) {
88 /* Tell the user that we could not find a usable */
97 static int connect_tcp(const char *host, uint16_t port)
100 struct protoent *ppe;
101 struct sockaddr_in sin;
108 memset(&sin, 0, sizeof(sin));
109 sin.sin_family = AF_INET;
110 sin.sin_port = htons(port);
112 if ((phe = gethostbyname(host)))
113 memcpy(&sin.sin_addr, phe->h_addr_list[0], phe->h_length);
114 else if((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
115 lpp_print_err("cannot get host entry for %s", host);
119 ppe = getprotobyname("tcp");
120 ERRNO_CHECK_RETURN(s = socket(PF_INET, SOCK_STREAM, ppe->p_proto), <, 0, -1);
121 ERRNO_CHECK_RETURN(connect(s, (struct sockaddr *) &sin, sizeof(sin)), <, 0, -1);
126 char **lpp_get_solvers(const char *host)
132 ERR_CHECK_RETURN(fd = connect_tcp(host, LPP_PORT), <, 0,
133 ("could not connect to %s", host), NULL);
135 comm = lpp_comm_new(fd, LPP_BUFSIZE);
137 lpp_writel(comm, LPP_CMD_SOLVERS);
140 res = XMALLOCN(char*, n+1);
145 for(i = 0; i < n; ++i)
146 res[i] = lpp_reads(comm);
149 lpp_writel(comm, LPP_CMD_BYE);
156 void lpp_set_dbg(const char *host, int mask)
161 ERR_CHECK_RETURN_VOID(fd = connect_tcp(host, LPP_PORT), <, 0, ("could not connect to %s", host));
163 comm = lpp_comm_new(fd, LPP_BUFSIZE);
165 lpp_writel(comm, LPP_CMD_SET_DEBUG);
166 lpp_writel(comm, mask);
168 lpp_writel(comm, LPP_CMD_BYE);
174 void lpp_solve_net(lpp_t *lpp, const char *host, const char *solver)
179 ir_timer_t *t_send, *t_recv;
181 ERR_CHECK_RETURN_VOID(fd = connect_tcp(host, LPP_PORT), <, 0,
182 ("could not connect to %s", host));
184 comm = lpp_comm_new(fd, LPP_BUFSIZE);
187 lpp_writel(comm, LPP_CMD_SOLVER);
188 lpp_writes(comm, solver);
192 ERR_CHECK_RETURN_VOID(lpp_ack(fd, sizeof(buf), buf), == 0,
193 ("could not set solver: %s", solver));
196 t_send = ir_timer_new();
197 t_recv = ir_timer_new();
199 ir_timer_start(t_send);
200 lpp_writel(comm, LPP_CMD_PROBLEM);
201 lpp_serialize(comm, lpp, 1);
202 lpp_serialize_values(comm, lpp, lpp_value_start);
204 ir_timer_stop(t_send);
205 lpp->send_time = ir_timer_elapsed_usec(t_send);
209 int cmd = lpp_readl(comm);
211 case LPP_CMD_SOLUTION:
212 ir_timer_push(t_recv);
213 lpp_deserialize_stats(comm, lpp);
214 lpp_deserialize_values(comm, lpp, lpp_value_solution);
215 ir_timer_stop(t_recv);
216 lpp->recv_time = ir_timer_elapsed_usec(t_recv);
220 lpp_readbuf(comm, buf, sizeof(buf));
221 buf[sizeof(buf) - 1] = '\0';
223 if(lpp->log != NULL) {
224 fputs(buf, lpp->log);
226 if(buf[n - 1] != '\n')
227 putc('\n', lpp->log);
232 fprintf(stderr, "solver process died unexpectedly\n");
235 fprintf(stderr, "invalid command: %s(%d)\n", lpp_get_cmd_name(cmd), cmd);
240 lpp_writel(comm, LPP_CMD_BYE);