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