[-]
[+]
|
Changed |
glb.changes
|
|
[-]
[+]
|
Changed |
glb.spec
^
|
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/ChangeLog
^
|
@@ -1,3 +1,12 @@
+2013-01-18 alex
+- New option -T|--top: all policies use only top-weighted destinations for
+ routing. E.g. in the presence of destinations with weights 1 and 2 only
+ the latter will be used to route connections to until all of them fail.
+- New policy 'single': all connections are directed to only one destination
+ chosen by highest weight.
+- Added SO_KEEPALIVE option to server side sockets to avoid stalled connections
+ Version 0.9.2
+
2013-01-10 alex
- Added asynchronous connection processing by default. -Y option to turn back
old synchronous (one-at-a-time) bevaviour.
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/README
^
|
@@ -38,19 +38,28 @@
BALANCING POLICIES:
===================
-GLB supports four balancing "policies":
+GLB supports five balancing "policies":
-a) "least connected" - new connection will be directed to the server with least
- connections (corrected for server "weight"). This is the default policy.
+a) "least connected" - new connection will be directed to the server with
+ least connections (corrected for server "weight"). This policy is default.
b) "round-robin" - each new connection is routed to the next destination
- in the list in circular order. This policy does not use node weights.
+ in the list in circular order.
-c) "random" - connections are distributed randomly between the servers.
+c) "single" - all connections are routed to a single server with the highest
+ weight available. All routing will stick to that server until it fails or
+ a server with a strictly higher weight is introduced.
-d) "source tracking" - connections originating from the same address are
+d) "random" - connections are distributed randomly between the servers.
+
+e) "source tracking" - connections originating from the same address are
directed to the same server. For details about this policy see below.
+-T|--top option was introduced in GLB 0.9.2. It restricts all balancing
+policies to a subset of destinations with top weight. E.g. if there are servers
+configured with weight 1 and 2, all balancing will happen only between servers
+with weight 2 as long as at least one of them is avaialble.
+
MAXIMUM CONCURRENT CONNECTIONS:
===============================
@@ -197,16 +206,16 @@
Server version: 5.5.28 Source distribution, wsrep_24dev.7.r3830
...
-Here GLB_VIP=3306 is interpreted as 127.0.0.1:3306, and GLB_TARGETS as
+Here GLB_BIND=3306 is interpreted as 127.0.0.1:3306, and GLB_TARGETS as
192.168.0.1:3306,192.168.0.2:3306,192.168.0.3:3306 (note port in GLB_BIND).
Note that mysql is connecting to 127.0.0.1:3306 as well and since this
-address matches GLB_BIND, connection is intecepted and directed to the real
-server.
+address matches GLB_BIND, connection is intecepted and directed to the server
+from the GLB_TARGETS list.
Additional libglb parameters:
GLB_POLICY=random|source
- Default libglb balancing policy is "round-robin", "random" and
+ Default libglb balancing policy is "round-robin", "single", "random" and
"source tracking" policies can be specified with GLB_POLICY variable.
(The meaning of GLB_POLICY=source in this case is that all connections from
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/configure
^
|
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for glb 0.9.1.
+# Generated by GNU Autoconf 2.69 for glb 0.9.2.
#
# Report bugs to <info@codership.com>.
#
@@ -590,8 +590,8 @@
# Identity of this package.
PACKAGE_NAME='glb'
PACKAGE_TARNAME='glb'
-PACKAGE_VERSION='0.9.1'
-PACKAGE_STRING='glb 0.9.1'
+PACKAGE_VERSION='0.9.2'
+PACKAGE_STRING='glb 0.9.2'
PACKAGE_BUGREPORT='info@codership.com'
PACKAGE_URL=''
@@ -1332,7 +1332,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures glb 0.9.1 to adapt to many kinds of systems.
+\`configure' configures glb 0.9.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1403,7 +1403,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of glb 0.9.1:";;
+ short | recursive ) echo "Configuration of glb 0.9.2:";;
esac
cat <<\_ACEOF
@@ -1513,7 +1513,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-glb configure 0.9.1
+glb configure 0.9.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2057,7 +2057,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by glb $as_me 0.9.1, which was
+It was created by glb $as_me 0.9.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2987,7 +2987,7 @@
# Define the identity of the package.
PACKAGE='glb'
- VERSION='0.9.1'
+ VERSION='0.9.2'
cat >>confdefs.h <<_ACEOF
@@ -16676,7 +16676,7 @@
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by glb $as_me 0.9.1, which was
+This file was extended by glb $as_me 0.9.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -16742,7 +16742,7 @@
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-glb config.status 0.9.1
+glb config.status 0.9.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/configure.ac
^
|
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.50)
-AC_INIT(glb, 0.9.1, info@codership.com)
+AC_INIT(glb, 0.9.2, info@codership.com)
AC_CONFIG_SRCDIR([src/glb_main.c])
AC_CONFIG_HEADER([config.h])
AC_CANONICAL_SYSTEM
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/src/glb_cmd.c
^
|
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2008-2013 Codership Oy <info@codership.com>
*
- * $Id: glb_cmd.c 126 2013-01-08 03:36:55Z alex $
+ * $Id: glb_cmd.c 138 2013-01-18 12:07:31Z alex $
*/
#include "glb_cmd.h"
@@ -20,6 +20,9 @@
typedef enum cmd_opt
{
+ CMD_OPT_KEEPALIVE = 'K',
+ CMD_OPT_SINGLE = 'S',
+ CMD_OPT_TOP = 'T',
CMD_OPT_VERSION = 'V',
CMD_OPT_SYNCHRONOUS = 'Y',
CMD_OPT_DEFER_ACCEPT = 'a',
@@ -38,6 +41,9 @@
static option_t cmd_options[] =
{
+ { "keepalive", NA, NULL, CMD_OPT_KEEPALIVE },
+ { "single", NA, NULL, CMD_OPT_SINGLE },
+ { "top", NA, NULL, CMD_OPT_TOP },
{ "version", NA, NULL, CMD_OPT_VERSION },
{ "defer-accept", NA, NULL, CMD_OPT_DEFER_ACCEPT },
{ "round", NA, NULL, CMD_OPT_ROUND_ROBIN },
@@ -59,86 +65,29 @@
{ 0, 0, 0, 0 }
};
-void
-glb_cmd_help (FILE* out, const char* progname)
-{
- fprintf (out,
- "Usage:\n %s [OPTIONS] LISTEN_ADDRESS "
- "[DESTINATION_LIST]\nOPTIONS:\n", progname);
- fprintf (out,
- " -h|--help this help message.\n");
- fprintf (out,
- " -a|--defer-accept "
- "enable TCP_DEFER_ACCEPT on the listening socket\n"
- " (default: disabled).\n");
- fprintf (out,
- " -b|--round "
- "round-robin destination selection policy.\n");
- fprintf (out,
- " -c|--control [HOST:]PORT "
- "listen for control requests on this address.\n");
- fprintf (out,
- " -d|--daemon run as a daemon.\n");
- fprintf (out,
- " -f|--fifo <fifo name> name of the FIFO file for control.\n");
- fprintf (out,
- " -m|--max_conn N "
- "maximum allowed number of client connections (OS dependent).\n");
- fprintf (out,
- " -n|--nodelay "
- "*DISABLE* TCP_NODELAY socket option\n"
- " (default: enabled).\n");
- fprintf (out,
- " -r|--random "
- "route connections to randomly selected destination.\n");
- fprintf (out,
- " -s|--source "
- "turn on source tracking: route connections from one\n"
- " source to the same destination.\n");
- fprintf (out,
- " -t|--threads N "
- "number of working threads (connection pools).\n");
- fprintf (out,
- " -v|--verbose turn on verbose reporting.\n");
- fprintf (out,
- " -Y "
- "connect synchronously (one-at-a-time).\n");
- fprintf (out,
- " -V|--version print program version.\n");
- fprintf (out, "LISTEN_ADDRESS:\n"
- " [IP:]PORT "
- "where to listen for incoming TCP connections at.\n"
- " "
- "(without IP part - bind to all interfaces)\n"
- );
- fprintf (out, "DESTINATION_LIST:\n"
- " [H1[:P1[:W1]]] [H2[:P2[:W2]]]... "
- " - a space-separated list of destinations\n"
- " in the form address:port:weight.\n");
- exit (EXIT_FAILURE);
-}
-
// Defaults relevant to CLI
static const char cmd_inc_addr_default[] = "0.0.0.0";
static const char cmd_ctrl_addr_default[] = "127.0.0.1";
-glb_cnf_t*
-glb_cmd_parse (int argc, char* argv[])
+static void
+cmd_parse_options (int argc, char* argv[], glb_cnf_t* tmp)
{
- glb_cnf_t* tmp = glb_cnf_init(); // initialize to defaults
- const char** dst_list = NULL;
- int opt = 0;
- int opt_idx = 0;
- char* endptr;
- uint16_t inc_port;
+ int opt = 0;
+ int opt_idx = 0;
+ char* endptr;
- if (!tmp) exit (EXIT_FAILURE);
-
- // parse options
- while ((opt = getopt_long (argc, argv, "VYabc:dfhm:nt:rsv", cmd_options,
+ while ((opt = getopt_long (argc, argv, "KSTVYabc:dfhm:nt:rsv", cmd_options,
&opt_idx)) != -1) {
switch (opt) {
+ case CMD_OPT_KEEPALIVE:
+ tmp->keepalive = false;
+ break;
+ case CMD_OPT_SINGLE:
+ tmp->policy = GLB_POLICY_SINGLE; // implies CMD_OPT_TOP
+ case CMD_OPT_TOP:
+ tmp->top = true;
+ break;
case CMD_OPT_VERSION:
glb_print_version (stdout);
if (argc == 2) exit(0);
@@ -201,6 +150,91 @@
cmd_options[opt_idx].name, opt);
}
}
+}
+
+void
+glb_cmd_help (FILE* out, const char* progname)
+{
+ fprintf (out,
+ "Usage:\n %s [OPTIONS] LISTEN_ADDRESS "
+ "[DESTINATION_LIST]\nOPTIONS:\n", progname);
+ fprintf (out,
+ " -h|--help this help message.\n");
+ fprintf (out,
+ " -a|--defer-accept "
+ "enable TCP_DEFER_ACCEPT on the listening socket\n"
+ " (default: disabled).\n");
+ fprintf (out,
+ " -b|--round "
+ "round-robin destination selection policy.\n");
+ fprintf (out,
+ " -c|--control [HOST:]PORT "
+ "listen for control requests on this address.\n");
+ fprintf (out,
+ " -d|--daemon run as a daemon.\n");
+ fprintf (out,
+ " -f|--fifo <fifo name> name of the FIFO file for control.\n");
+ fprintf (out,
+ " -m|--max_conn N "
+ "maximum allowed number of client connections (OS dependent).\n");
+ fprintf (out,
+ " -n|--nodelay "
+ "*DISABLE* TCP_NODELAY socket option\n"
+ " (default: enabled).\n");
+ fprintf (out,
+ " -r|--random "
+ "route connections to randomly selected destination.\n");
+ fprintf (out,
+ " -s|--source "
+ "turn on source tracking: route connections from one\n"
+ " source to the same destination.\n");
+ fprintf (out,
+ " -t|--threads N "
+ "number of working threads (connection pools).\n");
+ fprintf (out,
+ " -v|--verbose turn on verbose reporting.\n");
+ fprintf (out,
+ " -K|--keepalive "
+ "*DISABLE* SO_KEEPALIVE socket option on server-side\n"
+ " sockets (default: enabled).\n");
+ fprintf (out,
+ " -S|--single "
+ "direct all connections to a single destination\n"
+ " "
+ "with top weight.\n");
+ fprintf (out,
+ " -T|--top "
+ "only balance between destinations with top weight.\n");
+ fprintf (out,
+ " -V|--version print program version.\n");
+ fprintf (out,
+ " -Y "
+ "connect synchronously (one-at-a-time).\n");
+ fprintf (out, "LISTEN_ADDRESS:\n"
+ " [IP:]PORT "
+ "where to listen for incoming TCP connections at.\n"
+ " "
+ "(without IP part - bind to all interfaces)\n"
+ );
+ fprintf (out, "DESTINATION_LIST:\n"
+ " [H1[:P1[:W1]]] [H2[:P2[:W2]]]... "
+ " - a space-separated list of destinations\n"
+ " in the form address:port:weight.\n");
+ exit (EXIT_FAILURE);
+}
+
+
+glb_cnf_t*
+glb_cmd_parse (int argc, char* argv[])
+{
+ glb_cnf_t* tmp = glb_cnf_init(); // initialize to defaults
+ const char** dst_list = NULL;
+ uint16_t inc_port;
+
+ if (!tmp) exit (EXIT_FAILURE);
+
+ // parse options
+ cmd_parse_options (argc, argv, tmp);
// first non-option argument
if (optind >= argc) {
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/src/glb_cnf.c
^
|
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2012-2013 Codership Oy <info@codership.com>
*
- * $Id: glb_cnf.c 126 2013-01-08 03:36:55Z alex $
+ * $Id: glb_cnf.c 138 2013-01-18 12:07:31Z alex $
*/
#include "../config.h" // for version
@@ -30,6 +30,7 @@
ret->n_threads = 1;
ret->max_conn = glb_get_conn_limit();
ret->nodelay = true;
+ ret->keepalive = true;
ret->policy = GLB_POLICY_LEAST;
#else
ret->policy = GLB_POLICY_ROUND;
@@ -145,7 +146,7 @@
static const char* policy_str[GLB_POLICY_MAX] =
{
- "least connected", "round-robin", "random", "source"
+ "least connected", "round-robin", "single", "random", "source"
};
void
@@ -160,12 +161,15 @@
fprintf (out, "Control address: %s\n",
cnf->ctrl_set ? glb_socket_addr_to_string (&cnf->ctrl_addr) :
"none");
- fprintf (out, "Number of threads: %d, max conn: %d, policy: '%s', "
- "nodelay: %s, defer accept: %s, verbose: %s, daemon: %s\n",
+ fprintf (out, "Number of threads: %d, max conn: %d, policy: '%s', top: %s, "
+ "nodelay: %s, keepalive: %s, defer accept: %s, verbose: %s, "
+ "daemon: %s\n",
cnf->n_threads,
cnf->max_conn,
policy_str[cnf->policy],
+ cnf->top ? "YES" : "NO",
cnf->nodelay ? "ON" : "OFF",
+ cnf->keepalive ? "ON" : "OFF",
cnf->defer_accept ? "ON" : "OFF",
cnf->verbose ? "ON" : "OFF",
cnf->daemonize ? "YES" : "NO");
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/src/glb_cnf.h
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2012 Codership Oy <info@codership.com>
+ * Copyright (C) 2012-2013 Codership Oy <info@codership.com>
*
- * $Id: glb_cnf.h 126 2013-01-08 03:36:55Z alex $
+ * $Id: glb_cnf.h 138 2013-01-18 12:07:31Z alex $
*/
#ifndef _glb_cnf_h_
@@ -16,8 +16,9 @@
{
GLB_POLICY_LEAST = 0, /* least connected */
GLB_POLICY_ROUND, /* round-robin */
+ GLB_POLICY_SINGLE, /* single dest. with the top weight */
GLB_POLICY_RANDOM, /* random choice */
- GLB_POLICY_SOURCE /* same for one source */
+ GLB_POLICY_SOURCE /* same dest. for same source */
} glb_policy_t;
#define GLB_POLICY_MAX (GLB_POLICY_SOURCE + 1)
@@ -31,11 +32,13 @@
int n_threads; // number of routing threads (1 .. oo)
int max_conn; // max allowed client connections
bool nodelay; // use TCP_NODELAY?
+ bool keepalive; // use SO_KEEPALIVE?
bool defer_accept; // use TCP_DEFER_ACCEPT?
bool verbose; // be verbose?
bool daemonize; // become a daemon?
bool synchronous; // connect synchronously
#endif /* GLBD */
+ bool top; // only use top weighted destinations
bool ctrl_set; // was set? (false)
glb_policy_t policy; // algorithm to use for load-balancing
size_t n_dst; // number of destinations
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/src/glb_env.c
^
|
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2008-2012 Codership Oy <info@codership.com>
*
- * $Id: glb_env.c 98 2012-12-08 19:47:15Z alex $
+ * $Id: glb_env.c 138 2013-01-18 12:07:31Z alex $
*/
#include "glb_env.h"
@@ -16,6 +16,7 @@
#include <assert.h>
/* Environment variable names */
+static const char env_options[] = "GLB_OPTIONS"; // options string, same as cmd
static const char env_bind[] = "GLB_BIND"; // address that should be balanced
static const char env_policy[] = "GLB_POLICY";
static const char env_ctrl[] = "GLB_CONTROL"; // address to accept control
@@ -26,20 +27,25 @@
static const char env_ctrl_addr_default[] = "127.0.0.1";
static const char env_bind_addr_default[] = "127.0.0.1";
-/* convert string into array of tokens */
+/*!
+ * convert string into array of tokens
+ *
+ * @param sep - additional separator to whitespace
+ */
static bool
-env_parse_target_string (char* targets,
- const char*** dst_list,
- int* dst_num)
+env_parse_token_string (char* tok_str,
+ const char*** tok_list,
+ int* tok_num,
+ int sep)
{
- assert (targets);
+ assert (tok_str);
- *dst_list = NULL;
- *dst_num = 0;
+ *tok_list = NULL;
+ *tok_num = 0;
- if (!targets) return true;
+ if (!tok_str) return true;
- size_t const tlen = strlen(targets);
+ size_t const tlen = strlen(tok_str);
if (!tlen) return true;
const char** list = NULL;
@@ -48,38 +54,72 @@
size_t i;
for (i = 1; i <= tlen; i++) /* we can skip the first string char */
{
- if (isspace(targets[i]) || ',' == targets[i]) targets[i] = '\0';
- if (targets[i] == '\0' && targets[i-1] != '\0') num++;/* end of token */
+ if (isspace(tok_str[i]) || sep == tok_str[i]) tok_str[i] = '\0';
+ if (tok_str[i] == '\0' && tok_str[i-1] != '\0') num++;/* end of token */
}
list = calloc (num, sizeof(const char*));
if (!list) return true;
- list[0] = targets;
+ list[0] = tok_str;
num = 1;
for (i = 1; i <= tlen; i++)
{
- if (targets[i-1] == '\0' && targets[i] != '\0') /* beginning of token */
+ if (tok_str[i-1] == '\0' && tok_str[i] != '\0') /* beginning of token */
{
- list[num] = &targets[i];
+ list[num] = &tok_str[i];
num++;
}
}
- *dst_list = list;
- *dst_num = num;
+ *tok_list = list;
+ *tok_num = num;
return false;
}
+static inline bool
+env_option_is (const char* opt, const char* shopt, const char* lopt)
+{
+ return false; //stub until 1.0
+}
+
+static void
+env_parse_options (glb_cnf_t* cnf, char* o)
+{
+ if (!o) return;
+
+ int argc = 0;
+ char** argv = NULL;
+
+ if (env_parse_token_string (o, (const char***)&argv, &argc, '\0'))
+ return;
+
+ int i;
+ for (i = 0; i < argc; i++)
+ {
+ // stub
+ }
+
+ free (argv);
+}
+
static void
env_parse_policy (glb_cnf_t* cnf, const char* p)
{
cnf->policy = GLB_POLICY_ROUND; // default
- if (p && !strcmp(p, "random")) cnf->policy = GLB_POLICY_RANDOM;
- if (p && !strcmp(p, "source")) cnf->policy = GLB_POLICY_SOURCE;
+ if (p)
+ {
+ if (!strcmp(p, "single"))
+ {
+ cnf->policy = GLB_POLICY_SINGLE;
+ cnf->top = true;
+ }
+ else if (p && !strcmp(p, "random")) cnf->policy = GLB_POLICY_RANDOM;
+ else if (p && !strcmp(p, "source")) cnf->policy = GLB_POLICY_SOURCE;
+ }
}
static void
@@ -105,14 +145,15 @@
glb_cnf_t* ret = glb_cnf_init(); // initialize to defaults
if (!ret) return NULL;
- err = glb_parse_addr(&ret->inc_addr, getenv(env_bind), env_bind_addr_default);
+ err = glb_parse_addr (&ret->inc_addr, getenv (env_bind),
+ env_bind_addr_default);
if (err) goto failure;
const char** dst_list = NULL;
int dst_num = 0;
uint16_t bind_port = glb_socket_addr_get_port (&ret->inc_addr);
- if (!env_parse_target_string (getenv (env_targets), &dst_list, &dst_num))
+ if (!env_parse_token_string (getenv(env_targets), &dst_list, &dst_num, ','))
{
assert(dst_list);
assert(dst_num >= 0);
@@ -123,6 +164,7 @@
{
ret = tmp;
+ env_parse_options (ret, getenv (env_options));
env_parse_policy (ret, getenv (env_policy));
env_parse_control (ret, getenv (env_ctrl));
}
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/src/glb_pool.c
^
|
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2008-2013 Codership Oy <info@codership.com>
*
- * $Id: glb_pool.c 132 2013-01-10 15:10:04Z alex $
+ * $Id: glb_pool.c 141 2013-01-19 19:13:32Z alex $
*/
#include "glb_misc.h"
@@ -334,8 +334,12 @@
pool_handle_async_conn (pool_t* pool,
pool_conn_end_t* dst_end)
{
+ uint32_t const ka_opt = pool->cnf->keepalive * GLB_SOCK_KEEPALIVE;
+
dst_end->sock = glb_socket_create(&pool->addr_out,
- GLB_SOCK_NODELAY | GLB_SOCK_NONBLOCK);
+ GLB_SOCK_NODELAY |
+ GLB_SOCK_NONBLOCK |
+ ka_opt);
int error;
if (dst_end->sock > 0) {
int ret = connect (dst_end->sock, (struct sockaddr*)&dst_end->addr,
@@ -1100,12 +1104,14 @@
);
if (len == buf_len) {
buf[len - 1] = '\0';
+ GLB_MUTEX_UNLOCK (&pool->lock);
return (len - 1);
}
#else
len += snprintf (buf + len, buf_len - len," %5d",pool->pool[i].n_conns);
if (len == buf_len) {
buf[len - 1] = '\0';
+ GLB_MUTEX_UNLOCK (&pool->lock);
return (len - 1);
}
#endif
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/src/glb_router.c
^
|
@@ -4,7 +4,7 @@
* NOTE: connection count and usage make sense only for standalone balancer
* so all operations on them are #ifdef GLBD ... #endif
*
- * $Id: glb_router.c 134 2013-01-11 15:43:49Z alex $
+ * $Id: glb_router.c 142 2013-01-20 12:36:55Z alex $
*/
#define _GNU_SOURCE 1 /* for function overloading */
@@ -22,6 +22,9 @@
#include <unistd.h> // for close()
#include <time.h>
#include <sys/time.h>
+#include <float.h> // for DBL_EPSILON
+
+static double const GLB_DBL_EPSILON = DBL_EPSILON;
#ifdef GLBD
# include <stdio.h>
@@ -59,7 +62,9 @@
unsigned int seed; // seed for rng
int rrb_next; // round-robin cursor
int n_dst;
- time_t map_failed;
+ time_t map_failed; // last time the map was redone after failed dst
+ time_t top_failed; // last time top dst was redone after failed dst
+ router_dst_t* top_dst;
router_dst_t* dst;
};
@@ -69,21 +74,61 @@
static const double DST_RETRY_INTERVAL = 2.0;
static inline bool
-router_dst_is_good (const router_dst_t* const d, time_t const now)
+router_dst_is_good (const router_dst_t* const d,
+ double const min_weight,
+ time_t const now)
{
- return (d->dst.weight > 0.0 &&
+ return (d->dst.weight >= min_weight &&
difftime (now, d->failed) > DST_RETRY_INTERVAL);
}
static inline bool
+router_top_dst_is_good (const router_dst_t* const d, time_t const now)
+{
+ return (d && router_dst_is_good (d, GLB_DBL_EPSILON, now));
+}
+
+static inline double
+router_min_weight (const glb_router_t* const router, time_t const now)
+{
+ return (router_top_dst_is_good (router->top_dst, now) ?
+ router->top_dst->dst.weight : GLB_DBL_EPSILON);
+}
+
+static inline bool
router_uses_map (const glb_router_t* const router)
{
return (router->cnf->policy >= GLB_POLICY_RANDOM);
}
static void
+router_redo_top (glb_router_t* router, time_t now)
+{
+ int i;
+ static double const factor = 1.0 + GLB_DBL_EPSILON;
+ double top_weight = router_min_weight (router, now) * factor;
+
+ /* If router->top_dst is not failed, it will be changed only if there is a
+ * a non-failed dst with weight strictly higher than that of top_dst.
+ * If router->top_dst is failed, then it will be changed only if there is
+ * a non-failed dst with weight > 0. */
+
+ for (i = 0; i < router->n_dst; i++)
+ {
+ router_dst_t* d = &router->dst[i];
+
+ if (router_dst_is_good (d, top_weight, now))
+ {
+ top_weight = d->dst.weight * factor;
+ router->top_dst = d;
+ }
+ }
+}
+
+static void
router_redo_map (glb_router_t* router, time_t now)
{
+ double min_weight = router_min_weight(router, now);
int i;
// pass 1: calculate total weight of available destinations
@@ -92,7 +137,7 @@
{
router_dst_t* d = &router->dst[i];
- if (router_dst_is_good (d, now))
+ if (router_dst_is_good (d, min_weight, now))
{
total += d->dst.weight;
d->map = d->dst.weight;
@@ -172,6 +217,7 @@
}
else {
router->dst = tmp;
+ router->top_dst = NULL;
d = router->dst + router->n_dst;
router->n_dst++;
d->dst = *dst;
@@ -186,6 +232,7 @@
assert (d);
assert (i >= 0 && i < router->n_dst);
+ router->top_dst = NULL;
#ifdef GLBD
router->conns -= d->conns; assert (router->conns >= 0);
#endif
@@ -220,7 +267,9 @@
#endif
}
- if (router_uses_map(router)) router_redo_map (router, time (NULL));
+ time_t const now = time (NULL);
+ if (router->cnf->top) router_redo_top (router, now);
+ if (router_uses_map(router)) router_redo_map (router, now);
assert (router->n_dst >= 0);
assert (0 == router->busy_count);
@@ -304,20 +353,20 @@
#ifdef GLBD
// find a ready destination with minimal usage
static router_dst_t*
-router_choose_dst_least (glb_router_t* router)
+router_choose_dst_least (glb_router_t* const router, time_t const now)
{
+ double min_weight = router_min_weight (router, now);
router_dst_t* ret = NULL;
if (router->n_dst > 0) {
double max_usage = 0.0;
int i;
- time_t now = time(NULL);
for (i = 0; i < router->n_dst; i++) {
router_dst_t* d = &router->dst[i];
if (d->usage > max_usage &&
- difftime (now, d->failed) > DST_RETRY_INTERVAL) {
+ router_dst_is_good (d, min_weight, now)) {
ret = d;
max_usage = d->usage;
}
@@ -330,9 +379,9 @@
// find next suitable destination by round robin
static router_dst_t*
-router_choose_dst_round (glb_router_t* router)
+router_choose_dst_round (glb_router_t* const router, time_t const now)
{
- time_t now = time(NULL);
+ double min_weight = router_min_weight (router, now);
int offset;
for (offset = 0; offset < router->n_dst; offset++)
@@ -341,7 +390,7 @@
router->rrb_next = (router->rrb_next + 1) % router->n_dst;
- if (router_dst_is_good (d, now)) return d;
+ if (router_dst_is_good (d, min_weight, now)) return d;
}
return NULL;
@@ -349,12 +398,12 @@
// find a ready destination by client source hint
static router_dst_t*
-router_choose_dst_hint (glb_router_t* router, uint32_t hint)
+router_choose_dst_hint (glb_router_t* const router,
+ uint32_t const hint,
+ time_t const now)
{
if (router->n_dst <= 0) return NULL;
- time_t now = time(NULL);
-
#if OLD // old way
/* First we attempt target predefined by hint (hint % router->n_dst).
* If that fails, we iterate over the rest. But for every client
@@ -401,6 +450,13 @@
return NULL;
}
+static inline router_dst_t*
+router_choose_dst_single (glb_router_t* const router, time_t const now)
+{
+ return (router_top_dst_is_good (router->top_dst, now) ?
+ router->top_dst : NULL);
+}
+
static inline uint32_t
router_random_hint (glb_router_t* router)
{
@@ -415,15 +471,24 @@
#define glb_connect connect
static inline router_dst_t*
-router_choose_dst (glb_router_t* router, uint32_t hint)
+router_choose_dst (glb_router_t* const router, uint32_t hint)
{
+ time_t const now = time(NULL);
router_dst_t* ret = NULL;
+ if (router->cnf->top && router->top_failed != 0 &&
+ difftime (now, router->top_failed) > DST_RETRY_INTERVAL)
+ {
+ router_redo_top (router, now);
+ router->top_failed = 0;
+ }
+
switch (router->cnf->policy) {
- case GLB_POLICY_LEAST: ret = router_choose_dst_least (router); break;
- case GLB_POLICY_ROUND: ret = router_choose_dst_round (router); break;
+ case GLB_POLICY_LEAST: ret = router_choose_dst_least (router, now); break;
+ case GLB_POLICY_ROUND: ret = router_choose_dst_round (router, now); break;
+ case GLB_POLICY_SINGLE: ret = router_choose_dst_single(router, now); break;
case GLB_POLICY_RANDOM: hint = router_random_hint (router);
- case GLB_POLICY_SOURCE: ret = router_choose_dst_hint (router, hint);
+ case GLB_POLICY_SOURCE: ret = router_choose_dst_hint (router, hint, now);
}
if (GLB_LIKELY(ret != NULL)) {
@@ -465,11 +530,21 @@
static inline router_dst_t*
router_choose_dst (glb_router_t* router, uint32_t hint)
{
+ time_t const now = time(NULL);
+
+ if (router->cnf->top && router->top_failed != 0 &&
+ difftime (now, router->top_failed) > DST_RETRY_INTERVAL)
+ {
+ router_redo_top (router, now);
+ router->top_failed = 0;
+ }
+
switch (router->cnf->policy) {
case GLB_POLICY_LEAST: return NULL;
- case GLB_POLICY_ROUND: return router_choose_dst_round (router);
+ case GLB_POLICY_ROUND: return router_choose_dst_round (router, now);
+ case GLB_POLICY_SINGLE: return router_choose_dst_single (router, now);
case GLB_POLICY_RANDOM: hint = router_random_hint (router);
- case GLB_POLICY_SOURCE: return router_choose_dst_hint (router, hint);
+ case GLB_POLICY_SOURCE: return router_choose_dst_hint (router, hint, now);
}
return NULL;
}
@@ -477,13 +552,25 @@
#endif /* GLBD */
static inline void
-router_dst_failed (glb_router_t* router, router_dst_t* dst)
+router_dst_failed (glb_router_t* const router, router_dst_t* const dst)
{
- time_t now = time(NULL);
- if (router_uses_map (router) && router_dst_is_good (dst, now))
+ time_t const now = time(NULL);
+ double const min_weight = router_min_weight (router, now);
+ bool const dst_was_good = router_dst_is_good (dst, min_weight, now);
+
+ dst->failed = now;
+
+ if (dst == router->top_dst)
+ {
+ router_redo_top (router, now);
+ router->top_failed = now;
+ }
+
+ if (router_uses_map (router) && dst_was_good)
+ {
router_redo_map(router, now);
- dst->failed = now;
- router->map_failed = now;
+ router->map_failed = now;
+ }
}
// connect to a best destination, possiblly failing over to a next best
@@ -575,8 +662,9 @@
}
else {
// prepare a socket
- *sock = glb_socket_create (&router->sock_out,
- GLB_SOCK_NODELAY /*| GLB_SOCK_NONBLOCK*/);
+ uint32_t const ka_opt = router->cnf->keepalive * GLB_SOCK_KEEPALIVE;
+
+ *sock = glb_socket_create (&router->sock_out,GLB_SOCK_NODELAY | ka_opt);
if (*sock < 0) {
glb_log_error ("glb_socket_create() failed");
@@ -706,6 +794,7 @@
if (len == buf_len) {
buf[len - 1] = '\0';
+ GLB_MUTEX_UNLOCK (&router->lock);
return (len - 1);
}
}
@@ -792,6 +881,7 @@
d->dst.weight, d->map);
if (len == buf_len) {
buf[len - 1] = '\0';
+ GLB_MUTEX_UNLOCK (&router->lock);
return (len - 1);
}
}
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/src/glb_socket.c
^
|
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2008-2012 Codership Oy <info@codership.com>
*
- * $Id: glb_socket.c 126 2013-01-08 03:36:55Z alex $
+ * $Id: glb_socket.c 138 2013-01-18 12:07:31Z alex $
*/
#include "glb_socket.h"
@@ -150,6 +150,53 @@
}
#endif
+ if ((optflags & GLB_SOCK_KEEPALIVE) &&
+ setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)))
+ {
+ glb_log_warn ("Setting TCP_DEFER_ACCEPT failed: %d (%s)",
+ errno, strerror(errno));
+ ret = -errno;
+ }
+ else
+ {
+#if defined(TCP_KEEPIDLE)
+ int idle_seconds = 10;
+ if (!setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
+ &idle_seconds, sizeof(idle_seconds)))
+ {
+#if defined(TCP_KEEPINTVL)
+ int interval = 5;
+ if (!setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
+ &interval, sizeof(interval)))
+ {
+#if defined(TCP_KEEPCNT)
+ int tries = 3;
+ if (setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
+ &tries, sizeof(tries)))
+ {
+ glb_log_warn ("Setting TCP_KEEPINTVL failed: %d (%s)",
+ errno, strerror(errno));
+ ret = -errno;
+ }
+#endif /* TCP_KEEPCNT */
+ }
+ else
+ {
+ glb_log_warn ("Setting TCP_KEEPCNT failed: %d (%s)",
+ errno, strerror(errno));
+ ret = -errno;
+ }
+#endif /* TCP_KEEPINTVL */
+ }
+ else
+ {
+ glb_log_warn ("Setting TCP_KEEPIDLE failed: %d (%s)",
+ errno, strerror(errno));
+ ret = -errno;
+ }
+#endif /* TCP_KEEPIDLE */
+ }
+
if ((optflags & GLB_SOCK_NODELAY) && glb_cnf->nodelay &&
setsockopt(sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one)))
{
@@ -171,7 +218,7 @@
if ((optflags & GLB_SOCK_NONBLOCK) &&
glb_fd_set_flag (sock, O_NONBLOCK, true))
{
- glb_log_warn ("Setting O_NONBLCK failed: %d (%s)",
+ glb_log_warn ("Setting O_NONBLOCK failed: %d (%s)",
errno, strerror(errno));
ret = -errno;
}
|
[-]
[+]
|
Changed |
glb-0.9.2.tar.bz2/src/glb_socket.h
^
|
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2008-2012 Codership Oy <info@codership.com>
*
- * $Id: glb_socket.h 126 2013-01-08 03:36:55Z alex $
+ * $Id: glb_socket.h 138 2013-01-18 12:07:31Z alex $
*/
#ifndef _glb_socket_h_
@@ -48,6 +48,7 @@
#define GLB_SOCK_NODELAY 1U
#define GLB_SOCK_DEFER_ACCEPT 2U
#define GLB_SOCK_NONBLOCK 4U
+#define GLB_SOCK_KEEPALIVE 8U
// Returns socket (file descriptor) bound to a given address
// with default options set
|