cmogstored.git  about / heads / tags
alternative mogstored implementation for MogileFS
blob c5d9d593525f4b58d3e38cb49cc967ba810f5c90 1737 bytes (raw)
$ git show HEAD:bind_listen.c	# shows this blob on the CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
 
/*
 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
 */
#include "cmogstored.h"

/*
 * TODO
 * - configurable socket buffer sizes (where to put config?)
 * - configurable listen() backlog (where to put config?)
 *
 * TCP_DEFER_ACCEPT is probably not worth using on Linux
 * ref:
 *   https://bugs.launchpad.net/ubuntu/+source/apache2/+bug/134274
 *   https://labs.apnic.net/blabs/?p=57
 */

static int set_tcp_opts(int fd, bool inherited)
{
	int val;
	socklen_t len = sizeof(int);
	int rc;

	if (!inherited) {
		val = 1;
		rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, len);
		if (rc < 0) return rc;
	}

	val = 1;
	rc = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, len);
	if (rc < 0) return rc;

	val = 1;
	rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, len);
	if (rc < 0) return rc;

	return rc;
}

int mog_bind_listen(struct addrinfo *r)
{
	/* see if we inherited the socket, first */
	int fd = mog_inherit_get(r->ai_addr, r->ai_addrlen);
	const int backlog = 1024;

	if (fd >= 0 &&
	    set_tcp_opts(fd, true) == 0 &&
	    listen(fd, backlog) == 0)
		return fd;

	for (; r; r = r->ai_next) {
		fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
		if (fd < 0)
			continue;

		/*
		 * We'll need to unset FD_CLOEXEC in the child for upgrades
		 * Leave FD_CLOEXEC set because we fork+exec iostat(1)
		 * frequently.  We can't guarantee SOCK_CLOEXEC works
		 * everywhere yet (in 2012).
		 */
		if (mog_set_cloexec(fd, true) == 0 &&
		    set_tcp_opts(fd, false) == 0 &&
		    bind(fd, r->ai_addr, r->ai_addrlen) == 0 &&
		    listen(fd, backlog) == 0)
			break;

		PRESERVE_ERRNO( mog_close(fd) );
		fd = -1;
	}

	return fd;
}

git clone https://yhbt.net/cmogstored.git