57274be2086a17d35192dd98bd68c54716de2507
[awesomized/libmemcached] / lib / memcached_connect.c
1 #include "common.h"
2
3 #include <fcntl.h>
4 #include <sys/types.h>
5 #include <sys/socket.h>
6 #include <netinet/tcp.h>
7 #include <netdb.h>
8
9 memcached_return memcached_real_connect(memcached_st *ptr, unsigned int server_key)
10 {
11 struct sockaddr_in localAddr, servAddr;
12 struct hostent *h;
13
14 if (ptr->hosts[server_key].fd == -1)
15 {
16 /* Old connection junk still is in the structure */
17 assert(ptr->hosts[server_key].stack_responses == 0);
18
19 if ((h= gethostbyname(ptr->hosts[server_key].hostname)) == NULL)
20 {
21 ptr->my_errno= h_errno;
22 return MEMCACHED_HOST_LOCKUP_FAILURE;
23 }
24
25 servAddr.sin_family= h->h_addrtype;
26 memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
27 servAddr.sin_port = htons(ptr->hosts[server_key].port);
28
29 /* Create the socket */
30 if ((ptr->hosts[server_key].fd= socket(AF_INET, SOCK_STREAM, 0)) < 0)
31 {
32 ptr->my_errno= errno;
33 return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE;
34 }
35
36
37 /* bind any port number */
38 localAddr.sin_family = AF_INET;
39 localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
40 localAddr.sin_port = htons(0);
41
42 /* For the moment, not getting a nonblocking mode will note be fatal */
43 if (ptr->flags & MEM_NO_BLOCK)
44 {
45 int flags;
46
47 flags= fcntl(ptr->hosts[server_key].fd, F_GETFL, 0);
48 if (flags != -1)
49 (void)fcntl(ptr->hosts[server_key].fd, F_SETFL, flags | O_NONBLOCK);
50 }
51
52 if (ptr->flags & MEM_TCP_NODELAY)
53 {
54 int flag= 1;
55
56 setsockopt(ptr->hosts[server_key].fd, IPPROTO_TCP, TCP_NODELAY,
57 &flag, (socklen_t)sizeof(int));
58 }
59
60 /* connect to server */
61 test_connect:
62 if (connect(ptr->hosts[server_key].fd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
63 {
64 switch (errno) {
65 /* We are spinning waiting on connect */
66 case EALREADY:
67 case EINPROGRESS:
68 case EINTR:
69 goto test_connect;
70 case EISCONN: /* We were spinning waiting on connect */
71 break;
72 default:
73 ptr->my_errno= errno;
74 return MEMCACHED_ERRNO;
75 }
76 ptr->connected++;
77 }
78 assert(ptr->hosts[server_key].stack_responses == 0);
79 }
80
81 return MEMCACHED_SUCCESS;
82 }
83
84
85 memcached_return memcached_connect(memcached_st *ptr, unsigned int server_key)
86 {
87 memcached_return rc;
88 LIBMEMCACHED_MEMCACHED_CONNECT_START();
89
90 if (ptr->connected == ptr->number_of_hosts)
91 return MEMCACHED_SUCCESS;
92
93 if (!ptr->hosts)
94 return MEMCACHED_NO_SERVERS;
95
96 /* We need to clean up the multi startup piece */
97 if (server_key)
98 rc= memcached_real_connect(ptr, server_key);
99 else
100 {
101 unsigned int x;
102
103 for (x= 0; x < ptr->number_of_hosts; x++)
104 rc= memcached_real_connect(ptr, x);
105 }
106 LIBMEMCACHED_MEMCACHED_CONNECT_END();
107
108 return rc;
109 }