<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -59,6 +59,7 @@ AC_CHECK_HEADER(pthread.h, [], [echo &quot;pthread.h not found&quot;; exit1])
 
 # Checks for library functions.
 AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE([HAVE_GETHOSTBYNAME_R], [], [have gethostbyname_r() or not])])
+AC_CHECK_FUNC(epoll_create, [AC_DEFINE([HAVE_EPOLL], [], [have epoll functions or not])])
 
 AC_MSG_CHECKING(for gnu specific strerror_r)
 AC_TRY_COMPILE([</diff>
      <filename>configure.ac</filename>
    </modified>
    <modified>
      <diff>@@ -134,6 +134,7 @@ int flared::startup(int argc, char **argv) {
 	log_notice(&quot;  reconstruction_inteval: %d&quot;, ini_option_object().get_reconstruction_interval());
 	log_notice(&quot;  server_name:            %s&quot;, ini_option_object().get_server_name().c_str());
 	log_notice(&quot;  server_port:            %d&quot;, ini_option_object().get_server_port());
+	log_notice(&quot;  server_socket:          %s&quot;, ini_option_object().get_server_socket().c_str());
 	log_notice(&quot;  stack_size:             %d&quot;, ini_option_object().get_stack_size());
 	log_notice(&quot;  storage_ap:             %u&quot;, ini_option_object().get_storage_ap());
 	log_notice(&quot;  storage_bucket_size:    %llu&quot;, ini_option_object().get_storage_bucket_size());
@@ -161,9 +162,15 @@ int flared::startup(int argc, char **argv) {
 	// application objects
 	connection::read_timeout = ini_option_object().get_net_read_timeout() * 1000;		// -&gt; msec
 	this-&gt;_server = _new_ server();
-	if (this-&gt;_server-&gt;listen(ini_option_object().get_server_port(), ini_option_object().get_back_log()) &lt; 0) {
+	this-&gt;_server-&gt;set_back_log(ini_option_object().get_back_log());
+	if (this-&gt;_server-&gt;listen(ini_option_object().get_server_port()) &lt; 0) {
 		return -1;
 	}
+	if (ini_option_object().get_server_socket().empty() == false) {
+		if (this-&gt;_server-&gt;listen(ini_option_object().get_server_socket()) &lt; 0) {
+			return -1;
+		}
+	}
 
 	this-&gt;_thread_pool = _new_ thread_pool(ini_option_object().get_thread_pool_size(), ini_option_object().get_stack_size());
 </diff>
      <filename>src/flared/flared.cc</filename>
    </modified>
    <modified>
      <diff>@@ -42,6 +42,7 @@ ini_option::ini_option():
 		_reconstruction_interval(default_reconstruction_interval),
 		_server_name(&quot;&quot;),
 		_server_port(default_server_port),
+		_server_socket(&quot;&quot;),
 		_stack_size(default_stack_size),
 		_storage_ap(default_storage_ap),
 		_storage_bucket_size(default_storage_bucket_size),
@@ -215,6 +216,10 @@ int ini_option::load() {
 			this-&gt;_server_port = opt_var_map[&quot;server-port&quot;].as&lt;int&gt;();
 		}
 
+		if (opt_var_map.count(&quot;server-socket&quot;)) {
+			this-&gt;_server_socket = opt_var_map[&quot;server-socket&quot;].as&lt;string&gt;();
+		}
+
 		if (opt_var_map.count(&quot;stack-size&quot;)) {
 			this-&gt;_stack_size = opt_var_map[&quot;stack-size&quot;].as&lt;int&gt;();
 		}
@@ -388,6 +393,7 @@ int ini_option::_setup_config_option(program_options::options_description&amp; optio
 		(&quot;reconstruction-interval&quot;,	program_options::value&lt;int&gt;(),			&quot;master/slave dump interval in usec (dynamic)&quot;)
 		(&quot;server-name&quot;,							program_options::value&lt;string&gt;(),		&quot;my server name&quot;)
 		(&quot;server-port&quot;,							program_options::value&lt;int&gt;(),			&quot;my server port&quot;)
+		(&quot;server-socket&quot;,						program_options::value&lt;string&gt;(),		&quot;my server unix domain socket (optional)&quot;)
 		(&quot;stack-size&quot;,							program_options::value&lt;int&gt;(),			&quot;thread stack size (kb)&quot;)
 		(&quot;storage-ap&quot;,							program_options::value&lt;uint32_t&gt;(),	&quot;storage size of record alignment by power of 2 (tch)&quot;)
 		(&quot;storage-bucket-size&quot;,			program_options::value&lt;uint64_t&gt;(),	&quot;number of elements of the bucket array (tch)&quot;)</diff>
      <filename>src/flared/ini_option.cc</filename>
    </modified>
    <modified>
      <diff>@@ -45,6 +45,7 @@ private:
 	int					_reconstruction_interval;
 	string			_server_name;
 	int					_server_port;
+	string			_server_socket;
 	int					_stack_size;
 	uint32_t		_storage_ap;
 	uint64_t		_storage_bucket_size;
@@ -102,6 +103,7 @@ public:
 	int get_reconstruction_interval() { return this-&gt;_reconstruction_interval; };
 	string get_server_name() { return this-&gt;_server_name; };
 	int get_server_port() { return this-&gt;_server_port; };
+	string get_server_socket() { return this-&gt;_server_socket; };
 	int get_stack_size() { return this-&gt;_stack_size; };
 	uint32_t get_storage_ap() { return this-&gt;_storage_ap; };
 	uint64_t get_storage_bucket_size() { return this-&gt;_storage_bucket_size; };</diff>
      <filename>src/flared/ini_option.h</filename>
    </modified>
    <modified>
      <diff>@@ -115,6 +115,7 @@ int flarei::startup(int argc, char **argv) {
 	log_notice(&quot;  net_read_timeout:     %d&quot;, ini_option_object().get_net_read_timeout());
 	log_notice(&quot;  server_name:          %s&quot;, ini_option_object().get_server_name().c_str());
 	log_notice(&quot;  server_port:          %d&quot;, ini_option_object().get_server_port());
+	log_notice(&quot;  server_socket:        %s&quot;, ini_option_object().get_server_socket().c_str());
 	log_notice(&quot;  stack_size:           %d&quot;, ini_option_object().get_stack_size());
 	log_notice(&quot;  thread_pool_size:     %d&quot;, ini_option_object().get_thread_pool_size());
 
@@ -139,6 +140,11 @@ int flarei::startup(int argc, char **argv) {
 	if (this-&gt;_server-&gt;listen(ini_option_object().get_server_port()) &lt; 0) {
 		return -1;
 	}
+	if (ini_option_object().get_server_socket().empty() == false) {
+		if (this-&gt;_server-&gt;listen(ini_option_object().get_server_socket()) &lt; 0) {
+			return -1;
+		}
+	}
 
 	this-&gt;_thread_pool = _new_ thread_pool(ini_option_object().get_thread_pool_size(), ini_option_object().get_stack_size());
 </diff>
      <filename>src/flarei/flarei.cc</filename>
    </modified>
    <modified>
      <diff>@@ -32,6 +32,7 @@ ini_option::ini_option():
 		_net_read_timeout(default_net_read_timeout),
 		_server_name(&quot;&quot;),
 		_server_port(default_server_port),
+		_server_socket(&quot;&quot;),
 		_stack_size(default_stack_size),
 		_thread_pool_size(default_thread_pool_size) {
 }
@@ -157,6 +158,10 @@ int ini_option::load() {
 			this-&gt;_server_port = opt_var_map[&quot;server-port&quot;].as&lt;int&gt;();
 		}
 
+		if (opt_var_map.count(&quot;server-socket&quot;)) {
+			this-&gt;_server_socket = opt_var_map[&quot;server-socket&quot;].as&lt;string&gt;();
+		}
+
 		if (opt_var_map.count(&quot;stack-size&quot;)) {
 			this-&gt;_stack_size = opt_var_map[&quot;stack-size&quot;].as&lt;int&gt;();
 		}
@@ -291,6 +296,7 @@ int ini_option::_setup_config_option(program_options::options_description&amp; optio
 		(&quot;monitor-read-timeout&quot;,	program_options::value&lt;int&gt;(),			&quot;node server monitoring read timeout (millisec) (dynamic)&quot;)
 		(&quot;server-name&quot;,						program_options::value&lt;string&gt;(),		&quot;my server name&quot;)
 		(&quot;server-port&quot;,						program_options::value&lt;int&gt;(),			&quot;my server port&quot;)
+		(&quot;server-socket&quot;,					program_options::value&lt;string&gt;(),		&quot;my server unix domain socket (optional)&quot;)
 		(&quot;stack-size&quot;,						program_options::value&lt;int&gt;(),			&quot;thread stack size (kb)&quot;)
 		(&quot;thread-pool-size&quot;,			program_options::value&lt;int&gt;(),			&quot;thread pool size (dynamic)&quot;);
 </diff>
      <filename>src/flarei/ini_option.cc</filename>
    </modified>
    <modified>
      <diff>@@ -34,6 +34,7 @@ private:
 	int					_net_read_timeout;
 	string			_server_name;
 	int					_server_port;
+	string			_server_socket;
 	int					_stack_size;
 	int					_thread_pool_size;
 	
@@ -66,6 +67,7 @@ public:
 	int get_net_read_timeout() { return this-&gt;_net_read_timeout; };
 	string get_server_name() { return this-&gt;_server_name; };
 	int get_server_port() { return this-&gt;_server_port; };
+	string get_server_socket() { return this-&gt;_server_socket; };
 	int get_stack_size() { return this-&gt;_stack_size; };
 	int get_thread_pool_size() { return this-&gt;_thread_pool_size; };
 </diff>
      <filename>src/flarei/ini_option.h</filename>
    </modified>
    <modified>
      <diff>@@ -20,8 +20,10 @@ int connection::read_timeout = 10*60*1000;
  *	ctor for connection
  */
 connection::connection():
+		_addr_family(AF_INET),
 		_host(&quot;&quot;),
 		_port(-1),
+		_path(&quot;&quot;),
 		_read_timeout(read_timeout),
 		_read_buf(NULL),
 		_read_buf_p(NULL),
@@ -36,9 +38,30 @@ connection::connection():
  */
 connection::connection(int sock, struct sockaddr_in addr):
 		net(sock),
-		_addr(addr),
+		_addr_family(AF_INET),
+		_addr_inet(addr),
 		_host(&quot;&quot;),
 		_port(-1),
+		_path(&quot;&quot;),
+		_read_timeout(read_timeout),
+		_read_buf(NULL),
+		_read_buf_p(NULL),
+		_read_buf_len(0),
+		_write_buf(NULL),
+		_write_buf_len(0),
+		_write_buf_chunk_size(0) {
+}
+
+/**
+ *	ctor for connection
+ */
+connection::connection(int sock, struct sockaddr_un addr):
+		net(sock),
+		_addr_family(AF_UNIX),
+		_addr_unix(addr),
+		_host(&quot;&quot;),
+		_port(-1),
+		_path(&quot;&quot;),
 		_read_timeout(read_timeout),
 		_read_buf(NULL),
 		_read_buf_p(NULL),
@@ -66,7 +89,7 @@ connection::~connection() {
 
 // {{{ public methods
 /**
- *	open connection
+ *	open tcp connection
  */
 int connection::open(string host, int port) {
 	this-&gt;_errno = 0;
@@ -79,9 +102,10 @@ int connection::open(string host, int port) {
 		return -1;
 	}
 
-	memset(&amp;this-&gt;_addr, 0, sizeof(this-&gt;_addr));
-	this-&gt;_addr.sin_family = AF_INET;
-	this-&gt;_addr.sin_port = htons(port);
+	this-&gt;_addr_family = AF_INET;
+	memset(&amp;this-&gt;_addr_inet, 0, sizeof(this-&gt;_addr_inet));
+	this-&gt;_addr_inet.sin_family = AF_INET;
+	this-&gt;_addr_inet.sin_port = htons(port);
 
 	struct hostent he;
 	int he_errno;
@@ -90,11 +114,11 @@ int connection::open(string host, int port) {
 		this-&gt;close();
 		return -1;
 	}
-	memcpy(&amp;this-&gt;_addr.sin_addr, he.h_addr, he.h_length);
+	memcpy(&amp;this-&gt;_addr_inet.sin_addr, he.h_addr, he.h_length);
 
 	int i;
 	for (i = 0; i &lt; connection::connect_retry_limit; i++) {
-		if (connect(this-&gt;_sock, (struct sockaddr*)&amp;this-&gt;_addr, sizeof(this-&gt;_addr)) &lt; 0) {
+		if (connect(this-&gt;_sock, (struct sockaddr*)&amp;this-&gt;_addr_inet, sizeof(this-&gt;_addr_inet)) &lt; 0) {
 			log_warning(&quot;connect() failed: %s (%d) -&gt; wait for %d usec&quot;, util::strerror(errno), errno, connection::connect_retry_wait);
 			usleep(connection::connect_retry_wait);
 			continue;
@@ -536,10 +560,12 @@ int connection::writeline(const char* p) {
 string connection::get_host() {
 	if (this-&gt;_host.empty() == false) {
 		return this-&gt;_host;
+	} else if (this-&gt;_addr_family == AF_UNIX) {
+		return &quot;&quot;;
 	}
 
 	char buf[BUFSIZ];
-	util::inet_ntoa(this-&gt;_addr.sin_addr, buf);
+	util::inet_ntoa(this-&gt;_addr_inet.sin_addr, buf);
 
 	string s = buf;
 	return s;
@@ -548,9 +574,21 @@ string connection::get_host() {
 int connection::get_port() {
 	if (this-&gt;_port &gt;= 0) {
 		return this-&gt;_port;
+	} else if (this-&gt;_addr_family == AF_UNIX) {
+		return 0;
+	}
+
+	return ntohs(this-&gt;_addr_inet.sin_port);
+}
+
+string connection::get_path() {
+	if (this-&gt;_path.empty() == false) {
+		return this-&gt;_path;
+	} else if (this-&gt;_addr_family != AF_UNIX) {
+		return &quot;&quot;;
 	}
 
-	return ntohs(this-&gt;_addr.sin_port);
+	return this-&gt;_addr_unix.sun_path;
 }
 // }}}
 </diff>
      <filename>src/lib/connection.cc</filename>
    </modified>
    <modified>
      <diff>@@ -9,6 +9,7 @@
 #define __NET_CONNECTION_H__
 
 #include &lt;poll.h&gt;
+#include &lt;sys/un.h&gt;
 
 #include &quot;net.h&quot;
 
@@ -23,9 +24,12 @@ typedef shared_ptr&lt;connection&gt; shared_connection;
  */
 class connection : public net {
 protected:
-	struct sockaddr_in	_addr;
+	sa_family_t					_addr_family;
+	struct sockaddr_in	_addr_inet;
+	struct sockaddr_un	_addr_unix;
 	string							_host;
 	int									_port;
+	string							_path;
 	int									_read_timeout;
 	char*								_read_buf;
 	char*								_read_buf_p;
@@ -45,6 +49,7 @@ public:
 
 	connection();
 	connection(int sock, struct sockaddr_in addr);
+	connection(int sock, struct sockaddr_un addr);
 	virtual ~connection();
 
 	int open(string host, int port);
@@ -59,6 +64,7 @@ public:
 	bool is_error() { return this-&gt;_errno != 0 ? true : false; };
 	string get_host();
 	int get_port();
+	string get_path();
 	int get_read_timeout() { return this-&gt;_read_timeout; };
 	int set_read_timeout(int timeout) { this-&gt;_read_timeout = timeout; return 0; };
 </diff>
      <filename>src/lib/connection.h</filename>
    </modified>
    <modified>
      <diff>@@ -17,13 +17,20 @@ namespace flare {
  *	ctor for server
  */
 server::server():
-		_port(0) {
+		_listen_socket_index(0),
+#ifdef HAVE_EPOLL
+		_epoll_socket(0),
+#endif
+		_back_log(SOMAXCONN) {
 }
 
 /**
  *	dtor for server
  */
 server::~server() {
+	if (this-&gt;close() &lt; 0) {
+		// ...
+	}
 }
 // }}}
 
@@ -32,53 +39,161 @@ server::~server() {
 
 // {{{ public methods
 /**
+ *	close listening socket(s)
+ */
+int server::close() {
+	int r = 0;
+
+	struct sockaddr addr;
+	struct sockaddr_un* addr_unix = NULL;
+
+#ifdef HAVE_EPOLL
+	if (this-&gt;_epoll_socket &gt; 0) {
+		if (::close(this-&gt;_epoll_socket) &lt; 0) {
+			log_err(&quot;close() failed: %s (%d) (sock=epoll)&quot;, util::strerror(errno), errno);
+		}
+	}
+#endif
+
+	for (int i = 0; i &lt; this-&gt;_listen_socket_index; i++) {
+		int sock = this-&gt;_listen_socket[i];
+
+		if (sock &gt;= 0) {
+			// this will be cost but i do not care about it in this situation
+			socklen_t addr_len = sizeof(addr);
+			if (getsockname(sock, &amp;addr, &amp;addr_len) &lt; 0) {
+				log_notice(&quot;getsockname() failed: %s (%d) -&gt; assuming sa_family = AF_INET&quot;, util::strerror(errno), errno);
+				addr.sa_family = AF_INET;
+			}
+
+			if (::close(sock) &lt; 0) {
+				r = -1;
+				log_err(&quot;close() failed: %s (%d) (index=%d)&quot;, util::strerror(errno), errno, i);
+			} else {
+				log_debug(&quot;socket closed (sock=%d, index=%d)&quot;, sock, i);
+			}
+
+			if (addr.sa_family == AF_UNIX) {
+				addr_unix = reinterpret_cast&lt;struct sockaddr_un*&gt;(&amp;addr);
+				if (unlink(addr_unix-&gt;sun_path) &lt; 0) {
+					log_err(&quot;unlink() failed: %s (%d) (index=%d)&quot;, util::strerror(errno), errno, i);
+				} else {
+					log_debug(&quot;unix domain socket removed (path=%s)&quot;, addr_unix-&gt;sun_path);
+				}
+			}
+
+			this-&gt;_listen_socket[i] = -1;
+		} else {
+			log_info(&quot;close() called but socket seems to be already closed (sock=%d, index=%d)&quot;, sock, i);
+		}
+	}
+	this-&gt;_listen_socket_index = 0;
+
+	return r;
+}
+
+/**
  *	setup server socket
  */
-int server::listen(int port, int backlog) {
-	this-&gt;_port = port;
+int server::listen(int port) {
+	if (this-&gt;_listen_socket_index &gt;= this-&gt;max_listen_socket) {
+		log_err(&quot;listen socket limit exceeded (max_listen_socket=%d)&quot;, this-&gt;max_listen_socket);
+		return -1;
+	}
 
 	// creating a socket
-	this-&gt;_sock = socket(PF_INET, SOCK_STREAM, 0);
-	if (this-&gt;_sock &lt; 0) {
+	int sock = socket(PF_INET, SOCK_STREAM, 0);
+	if (sock &lt; 0) {
 		log_err(&quot;socket() failed: %s (%d)&quot;, util::strerror(errno), errno);
 		return -1;
 	}
 
 	// socket option/attr
-	int tmp = 1;
-	if (setsockopt(this-&gt;_sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast&lt;char *&gt;(&amp;tmp), sizeof(tmp)) &lt; 0) {
-		log_err(&quot;setsockopt() for SO_REUSEADDR failed: %s (%d)&quot;, util::strerror(errno), errno);
+	if (this-&gt;_set_listen_socket_option(sock) &lt; 0) {
 		return -1;
 	}
-	if (setsockopt(this-&gt;_sock, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast&lt;char *&gt;(&amp;tmp), sizeof(tmp)) &lt; 0) {
-		log_err(&quot;setsockopt() SO_KEEPALIVE failed: %s (%d)&quot;, util::strerror(errno), errno);
+
+	// bind -&gt; listen
+	struct sockaddr_in addr;
+	memset(&amp;addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = INADDR_ANY;
+	addr.sin_port = htons(port);
+	if (bind(sock, (struct sockaddr *)&amp;addr, sizeof(addr)) &lt; 0) {
+		log_err(&quot;bind() failed: %s (%d)&quot;, util::strerror(errno), errno);
 		return -1;
 	}
-	if (setsockopt(this-&gt;_sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast&lt;char*&gt;(&amp;tmp), sizeof(tmp)) &lt; 0) {
-		log_err(&quot;setsockopt() TCP_NODELAY failed: %s (%d)&quot;, util::strerror(errno), errno);
+	if (::listen(sock, this-&gt;_back_log) &lt; 0) {
+		log_err(&quot;listen() failed: %s (%d)&quot;, util::strerror(errno), errno);
 		return -1;
 	}
-	int flag = fcntl(this-&gt;_sock, F_GETFL, 0);
-	if (fcntl(this-&gt;_sock, F_SETFL, flag | O_NONBLOCK) &lt; 0) {
-		log_err(&quot;fcntl() failed: %s (%d)&quot;, util::strerror(errno), errno);
+
+	this-&gt;_listen_socket[this-&gt;_listen_socket_index] = sock;
+	this-&gt;_listen_socket_index++;
+
+	log_info(&quot;server socket (type=inet) is ready to accept (port: %d)&quot;, port);
+
+#ifdef HAVE_EPOLL
+	if (this-&gt;_add_epoll_socket(sock) &lt; 0) {
+		return -1;
+	}
+#endif
+
+	return 0;
+}
+
+/**
+ *	setup server socket
+ */
+int server::listen(string uds) {
+	if (this-&gt;_listen_socket_index &gt;= this-&gt;max_listen_socket) {
+		log_err(&quot;listen socket limit exceeded (max_listen_socket=%d)&quot;, this-&gt;max_listen_socket);
+		return -1;
+	}
+
+	// creating a socket
+	int sock = socket(PF_UNIX, SOCK_STREAM, 0);
+	if (sock &lt; 0) {
+		log_err(&quot;socket() failed: %s (%d)&quot;, util::strerror(errno), errno);
+		return -1;
+	}
+
+	// socket option/attr
+	if (this-&gt;_set_listen_socket_option(sock, PF_UNIX) &lt; 0) {
 		return -1;
 	}
 
 	// bind -&gt; listen
-	struct sockaddr_in addr;
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = INADDR_ANY;
-	addr.sin_port = htons(this-&gt;_port);
-	if (bind(this-&gt;_sock, (struct sockaddr *)&amp;addr, sizeof(addr)) &lt; 0) {
+	struct sockaddr_un addr;
+	memset(&amp;addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	strncpy(addr.sun_path, uds.c_str(), sizeof(addr.sun_path)-1);
+	if (bind(sock, (struct sockaddr *)&amp;addr, sizeof(addr)) &lt; 0) {
 		log_err(&quot;bind() failed: %s (%d)&quot;, util::strerror(errno), errno);
 		return -1;
 	}
-	if (::listen(this-&gt;_sock, backlog) &lt; 0) {
+	if (::listen(sock, this-&gt;_back_log) &lt; 0) {
 		log_err(&quot;listen() failed: %s (%d)&quot;, util::strerror(errno), errno);
 		return -1;
 	}
 
-	log_info(&quot;server socket is ready to accept (port: %d)&quot;, this-&gt;_port);
+	if (chmod(addr.sun_path, 0777) &lt; 0) {
+		log_err(&quot;chmod() failed: %s (%d) (path=%s)&quot;, util::strerror(errno), errno, addr.sun_path);
+		return -1;
+	} else {
+		log_debug(&quot;setting permission of unix domain socket as world writable (path=%s)&quot;, addr.sun_path);
+	}
+
+	this-&gt;_listen_socket[this-&gt;_listen_socket_index] = sock;
+	this-&gt;_listen_socket_index++;
+
+	log_info(&quot;server socket (type=unix) is ready to accept (path: %s)&quot;, uds.c_str());
+
+#ifdef HAVE_EPOLL
+	if (this-&gt;_add_epoll_socket(sock) &lt; 0) {
+		return -1;
+	}
+#endif
 
 	return 0;
 }
@@ -89,70 +204,171 @@ int server::listen(int port, int backlog) {
 vector&lt;shared_connection&gt; server::wait() {
 	vector&lt;shared_connection&gt; connection_list;
 
+#ifdef HAVE_EPOLL
+	const char* poll_type = &quot;epoll_wait&quot;;		// just for logging
+	struct epoll_event ev_list[this-&gt;max_listen_socket];
+	int n = epoll_wait(this-&gt;_epoll_socket, ev_list, this-&gt;max_listen_socket, -1);
+#else
+	const char* poll_type = &quot;select&quot;;		// just for logging
 	fd_set fds;
 	FD_ZERO(&amp;fds);
-	FD_SET(this-&gt;_sock, &amp;fds);
+	for (int i = 0; i &lt; this-&gt;_listen_socket_index; i++) {
+		FD_SET(this-&gt;_listen_socket[i], &amp;fds);
+	}
 	int n = select(FD_SETSIZE, &amp;fds, 0, 0, 0);
+#endif
 	if (n &lt;= 0) {
 		if (errno != EINTR) {
-			log_err(&quot;select() failed: %s (%d)&quot;, util::strerror(errno), errno);
+			log_err(&quot;%s() failed: %s (%d)&quot;, poll_type, util::strerror(errno), errno);
 		} else {
-			log_notice(&quot;select() failed: %s (%d)&quot;, util::strerror(errno), errno);
+			log_notice(&quot;%s() failed: %s (%d)&quot;, poll_type, util::strerror(errno), errno);
 		}
 		return connection_list;
 	}
 
 	// accpet anyway
-	struct sockaddr_in addr_remote;
-	socklen_t addr_remote_len;
-	int sock, j;
-	for (j = 0; j &lt; server::accept_retry_limit; j++) {
-		addr_remote_len = sizeof(addr_remote);
-		sock = accept(this-&gt;_sock, (struct sockaddr *)&amp;addr_remote, &amp;addr_remote_len);
-		if (sock &gt;= 0) {
-			break;
-		}
-		if (errno == EAGAIN || errno == EINTR) {
-			log_info(&quot;eagain or eintr -&gt; retrying accept() (%d times left)&quot;, server::accept_retry_limit - j - 1);
+#ifdef HAVE_EPOLL
+	for (int i = 0; i &lt; n; i++) {
+		int listen_socket = ev_list[i].data.fd;
+#else
+	for (int i = 0; i &lt; this-&gt;_listen_socket_index; i++) {
+		if (!FD_ISSET(this-&gt;_listen_socket[i], &amp;fds)) {
 			continue;
+		}
+		int listen_socket = this-&gt;_listen_socket[i];
+#endif
+
+		struct sockaddr addr;
+		struct sockaddr_in* addr_inet = NULL;
+		struct sockaddr_un* addr_unix = NULL;
+		socklen_t addr_len;
+		int sock, j;
+		for (j = 0; j &lt; server::accept_retry_limit; j++) {
+			addr_len = sizeof(addr);
+			sock = accept(listen_socket, &amp;addr, &amp;addr_len);
+			if (sock &gt;= 0) {
+				break;
+			}
+			if (errno == EAGAIN || errno == EINTR) {
+				log_info(&quot;eagain or eintr -&gt; retrying accept() (%d times left)&quot;, server::accept_retry_limit - j - 1);
+				continue;
+			} else {
+				break;
+			}
+		}
+		if (sock &lt; 0) {
+			log_err(&quot;accept() failed: %s (%d)&quot;, util::strerror(errno), errno);
+			return connection_list;
+		}
+
+		if (addr.sa_family == AF_UNIX) {
+			addr_unix = reinterpret_cast&lt;sockaddr_un*&gt;(&amp;addr);
 		} else {
-			break;
+			addr_inet = reinterpret_cast&lt;sockaddr_in*&gt;(&amp;addr);
+		}
+
+		// socket option/attr
+		int flag = fcntl(sock, F_GETFL, 0);
+		if (fcntl(sock, F_SETFL, flag | O_NONBLOCK) &lt; 0) {
+			log_err(&quot;fcntl() failed: %s (%d)&quot;, util::strerror(errno), errno);
+			::close(sock);	// try
+			return connection_list;
+		}
+
+		flag = 1;
+		if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast&lt;char*&gt;(&amp;flag), sizeof(flag)) &lt; 0) {
+			log_err(&quot;setsockopt() failed: %s (%d) - SO_KEEPALIVE&quot;, util::strerror(errno), errno);
+			return connection_list;
 		}
+
+		if (addr.sa_family != AF_UNIX) {
+			flag = 1;
+			if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast&lt;char*&gt;(&amp;flag), sizeof(flag)) &lt; 0) {
+				log_err(&quot;setsockopt() failed: %s (%d) - TCP_NODELAY&quot;, util::strerror(errno), errno);
+				return connection_list;
+			}
+		}
+
+		log_info(&quot;socket accepted (fd=%d remote=%s)&quot;, sock, addr.sa_family == AF_UNIX ? &quot;unix domain socket&quot; : inet_ntoa(addr_inet-&gt;sin_addr));
+		shared_connection c;
+		try {
+			if (addr.sa_family == AF_UNIX) {
+				c = shared_connection(new connection(sock, *addr_unix));
+			} else {
+				c = shared_connection(new connection(sock, *addr_inet));
+			}
+		} catch (int e) {
+			return connection_list;
+		}
+		connection_list.push_back(c);
 	}
-	if (sock &lt; 0) {
-		log_err(&quot;accept() failed: %s (%d)&quot;, util::strerror(errno), errno);
-		return connection_list;
+
+	return connection_list;
+}
+// }}}
+
+// {{{ protected methods
+/**
+ *	setup sever socket option
+ */
+int server::_set_listen_socket_option(int sock, int domain) {
+	int tmp = 1;
+
+	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast&lt;char *&gt;(&amp;tmp), sizeof(tmp)) &lt; 0) {
+		log_err(&quot;setsockopt() for SO_REUSEADDR failed: %s (%d)&quot;, util::strerror(errno), errno);
+		return -1;
+	}
+
+	if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast&lt;char *&gt;(&amp;tmp), sizeof(tmp)) &lt; 0) {
+		log_err(&quot;setsockopt() SO_KEEPALIVE failed: %s (%d)&quot;, util::strerror(errno), errno);
+		return -1;
+	}
+
+	if (domain != PF_UNIX) {
+		if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast&lt;char*&gt;(&amp;tmp), sizeof(tmp)) &lt; 0) {
+			log_err(&quot;setsockopt() TCP_NODELAY failed: %s (%d)&quot;, util::strerror(errno), errno);
+			return -1;
+		}
 	}
+
 	int flag = fcntl(sock, F_GETFL, 0);
 	if (fcntl(sock, F_SETFL, flag | O_NONBLOCK) &lt; 0) {
 		log_err(&quot;fcntl() failed: %s (%d)&quot;, util::strerror(errno), errno);
-		::close(sock);	// try
-		return connection_list;
-	}
-	flag = 1;
-	if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast&lt;char*&gt;(&amp;flag), sizeof(flag)) &lt; 0) {
-		log_err(&quot;setsockopt() failed: %s (%d) - SO_KEEPALIVE&quot;, util::strerror(errno), errno);
-		return connection_list;
+		return -1;
 	}
-	flag = 1;
-	if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast&lt;char*&gt;(&amp;flag), sizeof(flag)) &lt; 0) {
-		log_err(&quot;setsockopt() failed: %s (%d) - TCP_NODELAY&quot;, util::strerror(errno), errno);
-		return connection_list;
+
+	return 0;
+}
+
+#ifdef HAVE_EPOLL
+/**
+ *	add listen socket to epoll
+ */
+int server::_add_epoll_socket(int sock) {
+	if (this-&gt;_epoll_socket &lt;= 0) {
+		this-&gt;_epoll_socket = epoll_create(this-&gt;max_listen_socket);
+		if (this-&gt;_epoll_socket &lt; 0) {
+			log_err(&quot;epoll_create() failed: %s (%d)&quot;, util::strerror(errno), errno);
+			return -1;
+		}
 	}
-	log_info(&quot;socket accepted (fd=%d remote=%s)&quot;, sock, inet_ntoa(addr_remote.sin_addr));
-	shared_connection c;
-	try {
-		c = shared_connection(new connection(sock, addr_remote));
-	} catch (int e) {
-		return connection_list;
+
+	struct epoll_event ev;
+	memset(&amp;ev, 0, sizeof(ev));
+
+	// we can use edge trigger here but use leve trigger for safe for a while...
+	ev.events = EPOLLIN;
+	ev.data.fd = sock;
+	if (epoll_ctl(this-&gt;_epoll_socket, EPOLL_CTL_ADD, sock, &amp;ev) &lt; 0) {
+		log_err(&quot;epoll_ctl() failed: %s (%d) (sock=%d)&quot;, util::strerror(errno), errno, sock);
+		return -1;
+	} else {
+		log_debug(&quot;added listen socket to epoll (epoll_socket=%d, listen_socket=%d)&quot;, this-&gt;_epoll_socket, sock);
 	}
-	connection_list.push_back(c);
 
-	return connection_list;
+	return 0;
 }
-// }}}
-
-// {{{ protected methods
+#endif
 // }}}
 
 // {{{ private methods</diff>
      <filename>src/lib/server.cc</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,16 @@
 #ifndef __NET_SERVER_H__
 #define __NET_SERVER_H__
 
+#include &quot;config.h&quot;
+
 #include &lt;netinet/tcp.h&gt;
+#include &lt;sys/un.h&gt;
+#include &lt;sys/types.h&gt;
+#include &lt;sys/stat.h&gt;
+
+#ifdef HAVE_EPOLL
+#include &lt;sys/epoll.h&gt;
+#endif
 
 #include &quot;connection.h&quot;
 
@@ -21,19 +30,35 @@ namespace flare {
  *	@todo	support multi-port-listening (w/ epoll, kequeue, etc...)
  */
 class server : public net {
-protected:
-	int		_port;
-
 public:
+	static const int max_listen_socket = 256;
 	static const int accept_retry_limit = 16;
 
+protected:
+	int		_listen_socket[max_listen_socket];
+	int		_listen_socket_index;
+#ifdef HAVE_EPOLL
+	int		_epoll_socket;
+#endif
+	int		_back_log;
+
+public:
 	server();
 	virtual ~server();
 
-	int get_port() { return this-&gt;_port; };
+	int get_back_log() { return this-&gt;_back_log; };
+	int set_back_log(int back_log) { this-&gt;_back_log = back_log; return 0; };
 
-	int listen(int port, int backlog = 10);
+	int close();
+	int listen(int port);
+	int listen(string uds);
 	vector&lt;shared_connection&gt; wait();
+
+protected:
+	int _set_listen_socket_option(int sock, int domain = PF_INET);
+#ifdef HAVE_EPOLL
+	int _add_epoll_socket(int sock);
+#endif
 };
 
 }	// namespace flare</diff>
      <filename>src/lib/server.h</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>cf45f8965ee6673a787915424c65adc5884c8275</id>
    </parent>
  </parents>
  <author>
    <name>Masaki Fujimoto</name>
    <email>fujimoto@php.net</email>
  </author>
  <url>http://github.com/fujimoto/flare/commit/36e94778c5126a72a3db890dd9f0df847cdff96a</url>
  <id>36e94778c5126a72a3db890dd9f0df847cdff96a</id>
  <committed-date>2009-09-29T00:57:20-07:00</committed-date>
  <authored-date>2009-09-29T00:57:20-07:00</authored-date>
  <message>added unix domain socket support (option &quot;server-socket&quot; is now available)
and try to use epoll if available</message>
  <tree>4c36cbe406a9cb83301a59f14e3f88cf4722ac7c</tree>
  <committer>
    <name>Masaki Fujimoto</name>
    <email>fujimoto@php.net</email>
  </committer>
</commit>
