Browse Source

* Add lua bindings for upstream API.

tags/0.5.0
Vsevolod Stakhov 12 years ago
parent
commit
7e440d6f43
8 changed files with 626 additions and 38 deletions
  1. 17
    0
      src/cfg_file.h
  2. 45
    13
      src/cfg_utils.c
  3. 2
    1
      src/lua/CMakeLists.txt
  4. 1
    0
      src/lua/lua_common.c
  5. 2
    1
      src/lua/lua_common.h
  6. 521
    0
      src/lua/lua_upstream.c
  7. 25
    10
      src/upstream.c
  8. 13
    13
      src/upstream.h

+ 17
- 0
src/cfg_file.h View File

@@ -335,6 +335,15 @@ struct config_file {
};


/**
* Parse host[:port[:priority]] line
* @param ina host address
* @param port port
* @param priority priority
* @return TRUE if string was parsed
*/
gboolean parse_host_port_priority (const gchar *str, struct in_addr *ina, guint16 *port, guint *priority);

/**
* Parse host:port line
* @param ina host address
@@ -343,6 +352,14 @@ struct config_file {
*/
gboolean parse_host_port (const gchar *str, struct in_addr *ina, guint16 *port);

/**
* Parse host:priority line
* @param ina host address
* @param priority priority
* @return TRUE if string was parsed
*/
gboolean parse_host_priority (const gchar *str, struct in_addr *ina, guint *priority);

/**
* Parse bind credits
* @param cf config file to use

+ 45
- 13
src/cfg_utils.c View File

@@ -41,11 +41,11 @@


gboolean
parse_host_port (const gchar *str, struct in_addr *ina, guint16 *port)
parse_host_port_priority (const gchar *str, struct in_addr *ina, guint16 *port, guint *priority)
{
gchar **tokens, *err_str;
gchar **tokens, *err_str, *cur_tok;
struct hostent *hent;
guint port_parsed, saved_errno = errno;
guint port_parsed, priority_parsed, saved_errno = errno;

tokens = g_strsplit_set (str, ":", 0);
if (!tokens || !tokens[0]) {
@@ -72,18 +72,38 @@ parse_host_port (const gchar *str, struct in_addr *ina, guint16 *port)
}
if (tokens[1] != NULL) {
/* Port part */
errno = 0;
port_parsed = strtoul (tokens[1], &err_str, 10);
if (*err_str != '\0' || errno != 0) {
msg_warn ("cannot parse port: %s, at symbol %c, error: %s", tokens[1], *err_str, strerror (errno));
goto err;
if (port != NULL) {
errno = 0;
port_parsed = strtoul (tokens[1], &err_str, 10);
if (*err_str != '\0' || errno != 0) {
msg_warn ("cannot parse port: %s, at symbol %c, error: %s", tokens[1], *err_str, strerror (errno));
goto err;
}
if (port_parsed > G_MAXUINT16) {
errno = ERANGE;
msg_warn ("cannot parse port: %s, error: %s", tokens[1], *err_str, strerror (errno));
goto err;
}
*port = port_parsed;
}
if (port_parsed > G_MAXUINT16) {
errno = ERANGE;
msg_warn ("cannot parse port: %s, error: %s", tokens[1], *err_str, strerror (errno));
goto err;
if (priority != NULL) {
if (port != NULL) {
cur_tok = tokens[2];
}
else {
cur_tok = tokens[1];
}
if (cur_tok != NULL) {
/* Priority part */
errno = 0;
priority_parsed = strtoul (cur_tok, &err_str, 10);
if (*err_str != '\0' || errno != 0) {
msg_warn ("cannot parse priority: %s, at symbol %c, error: %s", tokens[1], *err_str, strerror (errno));
goto err;
}
*priority = priority_parsed;
}
}
*port = port_parsed;
}
/* Restore errno */
@@ -97,6 +117,18 @@ err:
return FALSE;
}

gboolean
parse_host_port (const gchar *str, struct in_addr *ina, guint16 *port)
{
return parse_host_port_priority (str, ina, port, NULL);
}

gboolean
parse_host_priority (const gchar *str, struct in_addr *ina, guint *priority)
{
return parse_host_port_priority (str, ina, NULL, priority);
}

gint
parse_bind_line (struct config_file *cfg, struct worker_conf *cf, gchar *str)
{

+ 2
- 1
src/lua/CMakeLists.txt View File

@@ -9,7 +9,8 @@ SET(LUASRC lua_common.c
lua_cdb.c
lua_xmlrpc.c
lua_http.c
lua_redis.c)
lua_redis.c
lua_upstream.c)

ADD_LIBRARY(rspamd_lua STATIC ${LUASRC})
TARGET_LINK_LIBRARIES(rspamd_lua ${LUALIB})

+ 1
- 0
src/lua/lua_common.c View File

@@ -252,6 +252,7 @@ init_lua (struct config_file *cfg)
(void)luaopen_xmlrpc (L);
(void)luaopen_http (L);
(void)luaopen_redis (L);
(void)luaopen_upstream (L);
cfg->lua_state = L;
memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)lua_close, L);


+ 2
- 1
src/lua/lua_common.h View File

@@ -17,7 +17,7 @@
extern const luaL_reg null_reg[];
extern GMutex *lua_mtx;

#define RSPAMD_LUA_API_VERSION 9
#define RSPAMD_LUA_API_VERSION 10

/* Common utility functions */

@@ -61,6 +61,7 @@ gint luaopen_cdb (lua_State *L);
gint luaopen_xmlrpc (lua_State * L);
gint luaopen_http (lua_State * L);
gint luaopen_redis (lua_State * L);
gint luaopen_upstream (lua_State * L);
void init_lua (struct config_file *cfg);
gboolean init_lua_filters (struct config_file *cfg);


+ 521
- 0
src/lua/lua_upstream.c View File

@@ -0,0 +1,521 @@
/* Copyright (c) 2010-2011, Vsevolod Stakhov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "config.h"
#include "lua_common.h"
#include "upstream.h"
#include "cfg_file.h"

/* Upstream timeouts */
#define DEFAULT_UPSTREAM_ERROR_TIME 10
#define DEFAULT_UPSTREAM_DEAD_TIME 300
#define DEFAULT_UPSTREAM_MAXERRORS 10

/**
* This module implements upstreams manipulation from lua
*/
/* Upstream list functions */
LUA_FUNCTION_DEF (upstream_list, create);
LUA_FUNCTION_DEF (upstream_list, destroy);
LUA_FUNCTION_DEF (upstream_list, get_upstream_by_hash);
LUA_FUNCTION_DEF (upstream_list, get_upstream_round_robin);
LUA_FUNCTION_DEF (upstream_list, get_upstream_master_slave);

static const struct luaL_reg upstream_list_m[] = {

LUA_INTERFACE_DEF (upstream_list, get_upstream_by_hash),
LUA_INTERFACE_DEF (upstream_list, get_upstream_round_robin),
LUA_INTERFACE_DEF (upstream_list, get_upstream_master_slave),
{"__tostring", lua_class_tostring},
{"__gc", lua_upstream_list_destroy},
{NULL, NULL}
};
static const struct luaL_reg upstream_list_f[] = {
LUA_INTERFACE_DEF (upstream_list, create),
{NULL, NULL}
};

/* Upstream functions */
LUA_FUNCTION_DEF (upstream, create);
LUA_FUNCTION_DEF (upstream, destroy);
LUA_FUNCTION_DEF (upstream, ok);
LUA_FUNCTION_DEF (upstream, fail);
LUA_FUNCTION_DEF (upstream, get_ip);
LUA_FUNCTION_DEF (upstream, get_port);
LUA_FUNCTION_DEF (upstream, get_ip_string);
LUA_FUNCTION_DEF (upstream, get_priority);

static const struct luaL_reg upstream_m[] = {
LUA_INTERFACE_DEF (upstream, ok),
LUA_INTERFACE_DEF (upstream, fail),
LUA_INTERFACE_DEF (upstream, get_ip),
LUA_INTERFACE_DEF (upstream, get_ip_string),
LUA_INTERFACE_DEF (upstream, get_port),
LUA_INTERFACE_DEF (upstream, get_priority),
{"__tostring", lua_class_tostring},
{"__gc", lua_upstream_destroy},
{NULL, NULL}
};
static const struct luaL_reg upstream_f[] = {
LUA_INTERFACE_DEF (upstream, create),
{NULL, NULL}
};

/* Upstream class */
struct lua_upstream {
struct upstream up;
gchar *def;
guint16 port;
struct in_addr addr;
};

static struct lua_upstream *
lua_check_upstream (lua_State * L)
{
void *ud = luaL_checkudata (L, 1, "rspamd{upstream}");

luaL_argcheck (L, ud != NULL, 1, "'upstream' expected");
return ud ? *((struct lua_upstream **)ud) : NULL;
}

/**
* Create new upstream from its string definition like 'ip[:port[:priority]]' or 'host[:port[:priority]]'
* @param L
* @return upstream structure
*/
static gint
lua_upstream_create (lua_State *L)
{
struct lua_upstream *new, **pnew;
const gchar *def;

def = luaL_checkstring (L, 1);
if (def) {
new = g_slice_alloc0 (sizeof (struct lua_upstream));
new->def = g_strdup (def);
if (!parse_host_port_priority (new->def, &new->addr, &new->port, &new->up.priority)) {
g_free (new->def);
g_slice_free1 (sizeof (struct lua_upstream), new);
lua_pushnil (L);
}
else {
pnew = lua_newuserdata (L, sizeof (struct lua_upstream *));
lua_setclass (L, "rspamd{upstream}", -1);
*pnew = new;
}
}

return 1;
}

/**
* Destroy a single upstream object
* @param L
* @return
*/
static gint
lua_upstream_destroy (lua_State *L)
{
struct lua_upstream *up = lua_check_upstream (L);

if (up) {
g_free (up->def);
g_slice_free1 (sizeof (struct lua_upstream), up);
}

return 0;
}

/**
* Get ip of upstream in numeric form (guint32)
* @param L
* @return
*/
static gint
lua_upstream_get_ip (lua_State *L)
{
struct lua_upstream *up = lua_check_upstream (L);

if (up) {
lua_pushinteger (L, up->addr.s_addr);
}
else {
lua_pushnil (L);
}

return 1;
}

/**
* Get ip of upstream in string form
* @param L
* @return
*/
static gint
lua_upstream_get_ip_string (lua_State *L)
{
struct lua_upstream *up = lua_check_upstream (L);

if (up) {
lua_pushstring (L, inet_ntoa (up->addr));
}
else {
lua_pushnil (L);
}

return 1;
}

/**
* Get port of upstream in numeric form
* @param L
* @return
*/
static gint
lua_upstream_get_port (lua_State *L)
{
struct lua_upstream *up = lua_check_upstream (L);

if (up) {
lua_pushinteger (L, up->port);
}
else {
lua_pushnil (L);
}

return 1;
}

/**
* Get port of upstream in numeric form
* @param L
* @return
*/
static gint
lua_upstream_get_priority (lua_State *L)
{
struct lua_upstream *up = lua_check_upstream (L);

if (up) {
lua_pushinteger (L, up->up.priority);
}
else {
lua_pushnil (L);
}

return 1;
}

/**
* Make upstream fail, the second argument is time, if absent the current time is used
* @param L
* @return
*/
static gint
lua_upstream_fail (lua_State *L)
{
struct lua_upstream *up = lua_check_upstream (L);
time_t now;

if (up) {
if (lua_gettop (L) >= 2) {
now = luaL_checkinteger (L, 2);
}
else {
now = time (NULL);
}
upstream_fail (&up->up, now);
}

return 0;
}

/**
* Make upstream success, the second argument is time, if absent the current time is used
* @param L
* @return
*/
static gint
lua_upstream_ok (lua_State *L)
{
struct lua_upstream *up = lua_check_upstream (L);
time_t now;

if (up) {
if (lua_gettop (L) >= 2) {
now = luaL_checkinteger (L, 2);
}
else {
now = time (NULL);
}
upstream_ok (&up->up, now);
}

return 0;
}

/* Upstream list class */
struct lua_upstream_list {
struct lua_upstream *upstreams;
guint count;
};

static struct lua_upstream_list *
lua_check_upstream_list (lua_State * L)
{
void *ud = luaL_checkudata (L, 1, "rspamd{upstream_list}");

luaL_argcheck (L, ud != NULL, 1, "'upstream_list' expected");
return ud ? *((struct lua_upstream_list **)ud) : NULL;
}

/**
* Create new upstream list from its string definition like '<upstream>,<upstream>;<upstream>'
* @param L
* @return upstream list structure
*/
static gint
lua_upstream_list_create (lua_State *L)
{
struct lua_upstream_list *new, **pnew;
struct lua_upstream *cur;
const gchar *def;
char **tokens;
guint i, default_port = 0;

def = luaL_checkstring (L, 1);
if (def) {
if (lua_gettop (L) >= 2) {
default_port = luaL_checkinteger (L, 2);
}
new = g_slice_alloc0 (sizeof (struct lua_upstream_list));

tokens = g_strsplit_set (def, ",;", 0);
if (!tokens || !tokens[0]) {
goto err;
}
new->count = g_strv_length (tokens);
new->upstreams = g_slice_alloc0 (new->count * sizeof (struct lua_upstream));

for (i = 0; i < new->count; i ++) {
cur = &new->upstreams[i];
if (!parse_host_port_priority (tokens[i], &cur->addr, &cur->port, &cur->up.priority)) {
goto err;
}
if (cur->port == 0) {
cur->port = default_port;
}
}
pnew = lua_newuserdata (L, sizeof (struct upstream_list *));
lua_setclass (L, "rspamd{upstream_list}", -1);
*pnew = new;
}

return 1;
err:
if (tokens) {
g_strfreev (tokens);
}
if (new->upstreams) {
g_slice_free1 (new->count * sizeof (struct lua_upstream), new->upstreams);
}
g_slice_free1 (sizeof (struct lua_upstream_list), new);
lua_pushnil (L);
return 1;
}

/**
* Destroy a single upstream list object
* @param L
* @return
*/
static gint
lua_upstream_list_destroy (lua_State *L)
{
struct lua_upstream_list *upl = lua_check_upstream_list (L);

if (upl) {
if (upl->upstreams) {
g_slice_free1 (upl->count * sizeof (struct lua_upstream), upl->upstreams);
}
g_slice_free1 (sizeof (struct lua_upstream_list), upl);
}

return 0;
}

/**
* Get upstream by hash from key, params are: key and time (optional)
* @param L
* @return
*/
static gint
lua_upstream_list_get_upstream_by_hash (lua_State *L)
{
struct lua_upstream_list *upl;
struct lua_upstream *selected, **pselected;
time_t now;
const gchar *key;

upl = lua_check_upstream_list (L);
if (upl) {
key = luaL_checkstring (L, 2);
if (key) {
if (lua_gettop (L) >= 3) {
now = luaL_checkinteger (L, 3);
}
else {
now = time (NULL);
}
selected = (struct lua_upstream *)get_upstream_by_hash (upl->upstreams, upl->count,
sizeof (struct lua_upstream), now,
DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS,
key, 0);
if (selected) {
pselected = lua_newuserdata (L, sizeof (struct lua_upstream *));
lua_setclass (L, "rspamd{upstream}", -1);
*pselected = selected;
}
else {
lua_pushnil (L);
}
}
else {
lua_pushnil (L);
}
}
else {
lua_pushnil (L);
}

return 1;
}

/**
* Get upstream round robin (by current weight), params are: time (optional)
* @param L
* @return
*/
static gint
lua_upstream_list_get_upstream_round_robin (lua_State *L)
{
struct lua_upstream_list *upl;
struct lua_upstream *selected, **pselected;
time_t now;

upl = lua_check_upstream_list (L);
if (upl) {
if (lua_gettop (L) >= 2) {
now = luaL_checkinteger (L, 2);
}
else {
now = time (NULL);
}
selected = (struct lua_upstream *)get_upstream_round_robin (upl->upstreams, upl->count,
sizeof (struct lua_upstream), now,
DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS);
if (selected) {
pselected = lua_newuserdata (L, sizeof (struct lua_upstream *));
lua_setclass (L, "rspamd{upstream}", -1);
*pselected = selected;
}
else {
lua_pushnil (L);
}
}
else {
lua_pushnil (L);
}

return 1;
}

/**
* Get upstream master slave order (by static priority), params are: time (optional)
* @param L
* @return
*/
static gint
lua_upstream_list_get_upstream_master_slave (lua_State *L)
{
struct lua_upstream_list *upl;
struct lua_upstream *selected, **pselected;
time_t now;

upl = lua_check_upstream_list (L);
if (upl) {
if (lua_gettop (L) >= 2) {
now = luaL_checkinteger (L, 2);
}
else {
now = time (NULL);
}
selected = (struct lua_upstream *)get_upstream_master_slave (upl->upstreams, upl->count,
sizeof (struct lua_upstream), now,
DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS);
if (selected) {
pselected = lua_newuserdata (L, sizeof (struct lua_upstream *));
lua_setclass (L, "rspamd{upstream}", -1);
*pselected = selected;
}
else {
lua_pushnil (L);
}
}
else {
lua_pushnil (L);
}

return 1;
}


gint
luaopen_upstream (lua_State * L)
{
luaL_newmetatable (L, "rspamd{upstream_list}");
lua_pushstring (L, "__index");
lua_pushvalue (L, -2);
lua_settable (L, -3);

lua_pushstring (L, "class");
lua_pushstring (L, "rspamd{upstream_list}");
lua_rawset (L, -3);

luaL_openlib (L, NULL, upstream_list_m, 0);
luaL_openlib (L, "upstream_list", upstream_list_f, 0);

luaL_newmetatable (L, "rspamd{upstream}");
lua_pushstring (L, "__index");
lua_pushvalue (L, -2);
lua_settable (L, -3);

lua_pushstring (L, "class");
lua_pushstring (L, "rspamd{upstream}");
lua_rawset (L, -3);

luaL_openlib (L, NULL, upstream_m, 0);
luaL_openlib (L, "upstream", upstream_f, 0);

return 1;
}

+ 25
- 10
src/upstream.c View File

@@ -38,6 +38,7 @@ pthread_rwlock_t upstream_mtx = PTHREAD_RWLOCK_INITIALIZER;
#endif

#define MAX_TRIES 20
#define HASH_COMPAT

/*
* Poly: 0xedb88320
@@ -248,17 +249,26 @@ get_upstream_by_number (void *ups, size_t members, size_t msize, gint selected)
* Get hash key for specified key (perl hash)
*/
static guint32
get_hash_for_key (guint32 hash, gchar *key, size_t keylen)
get_hash_for_key (guint32 hash, const gchar *key, size_t keylen)
{
guint32 h, index;
const gchar *end = key + keylen;

h = ~hash;

while (key < end) {
index = (h ^ (u_char) * key) & 0x000000ffU;
h = (h >> 8) ^ crc32lookup[index];
++key;
if (end != key) {
while (key < end) {
index = (h ^ (u_char) * key) & 0x000000ffU;
h = (h >> 8) ^ crc32lookup[index];
++key;
}
}
else {
while (*key) {
index = (h ^ (u_char) * key) & 0x000000ffU;
h = (h >> 8) ^ crc32lookup[index];
++key;
}
}

return (~h);
@@ -268,7 +278,8 @@ get_hash_for_key (guint32 hash, gchar *key, size_t keylen)
* Recheck all upstreams and return random active upstream
*/
struct upstream *
get_random_upstream (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors)
get_random_upstream (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout,
time_t revive_timeout, size_t max_errors)
{
gint alive, selected;

@@ -282,7 +293,8 @@ get_random_upstream (void *ups, size_t members, size_t msize, time_t now, time_t
* Return upstream by hash, that is calculated from active upstreams number
*/
struct upstream *
get_upstream_by_hash (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors, gchar *key, size_t keylen)
get_upstream_by_hash (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout,
time_t revive_timeout, size_t max_errors, const gchar *key, size_t keylen)
{
gint alive, tries = 0, r;
guint32 h = 0, ht;
@@ -332,7 +344,8 @@ get_upstream_by_hash (void *ups, size_t members, size_t msize, time_t now, time_
* Recheck all upstreams and return upstream in round-robin order according to weight and priority
*/
struct upstream *
get_upstream_round_robin (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors)
get_upstream_round_robin (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout,
time_t revive_timeout, size_t max_errors)
{
guint max_weight, i;
struct upstream *cur, *selected = NULL;
@@ -381,7 +394,8 @@ get_upstream_round_robin (void *ups, size_t members, size_t msize, time_t now, t
* Recheck all upstreams and return upstream in round-robin order according to only priority (master-slaves)
*/
struct upstream *
get_upstream_master_slave (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors)
get_upstream_master_slave (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout,
time_t revive_timeout, size_t max_errors)
{
guint max_weight, i;
struct upstream *cur, *selected = NULL;
@@ -459,7 +473,8 @@ upstream_ketama_add (struct upstream *up, gchar *up_key, size_t keylen, size_t k
* Return upstream by hash and find nearest ketama point in some server
*/
struct upstream *
get_upstream_by_hash_ketama (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors, gchar *key, size_t keylen)
get_upstream_by_hash_ketama (void *ups, size_t members, size_t msize,
time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors, const gchar *key, size_t keylen)
{
guint alive, i;
guint32 h = 0, step, middle, d, min_diff = UINT_MAX;

+ 13
- 13
src/upstream.h View File

@@ -4,7 +4,7 @@
#include <sys/types.h>
#include <stdint.h>

/*
/**
* Structure of generic upstream
*/
struct upstream {
@@ -17,7 +17,7 @@ struct upstream {
size_t ketama_points_size; /**< Ketama array size */
};

/*
/**
* Upstream error logic
* 1. During error time we count upstream_ok and upstream_fail
* 2. If failcount is more then maxerrors then we mark upstream as unavailable for dead time
@@ -25,27 +25,27 @@ struct upstream {
* 4. If all upstreams are dead, marks every upstream as alive
*/

/*
/**
* Add an error to an upstream
*/
void upstream_fail (struct upstream *up, time_t now);

/*
/**
* Increase upstream successes count
*/
void upstream_ok (struct upstream *up, time_t now);

/*
/**
* Make all upstreams alive
*/
void revive_all_upstreams (void *ups, size_t members, size_t msize);

/*
/**
* Add ketama points for upstream
*/
gint upstream_ketama_add (struct upstream *up, gchar *up_key, size_t keylen, size_t keypoints);

/*
/**
* Get a random upstream from array of upstreams
* @param ups array of structures that contains struct upstream as their first element
* @param members number of elements in array
@@ -59,7 +59,7 @@ struct upstream* get_random_upstream (void *ups, size_t members, size_t msize,
time_t now, time_t error_timeout,
time_t revive_timeout, size_t max_errors);

/*
/**
* Get upstream based on hash from array of upstreams
* @param ups array of structures that contains struct upstream as their first element
* @param members number of elements in array
@@ -74,9 +74,9 @@ struct upstream* get_random_upstream (void *ups, size_t members, size_t msize,
struct upstream* get_upstream_by_hash (void *ups, size_t members, size_t msize,
time_t now, time_t error_timeout,
time_t revive_timeout, size_t max_errors,
gchar *key, size_t keylen);
const gchar *key, size_t keylen);

/*
/**
* Get an upstream from array of upstreams based on its current weight
* @param ups array of structures that contains struct upstream as their first element
* @param members number of elements in array
@@ -90,7 +90,7 @@ struct upstream* get_upstream_round_robin (void *ups, size_t members, size_t msi
time_t now, time_t error_timeout,
time_t revive_timeout, size_t max_errors);

/*
/**
* Get upstream based on hash from array of upstreams, this functions is using ketama algorithm
* @param ups array of structures that contains struct upstream as their first element
* @param members number of elements in array
@@ -104,9 +104,9 @@ struct upstream* get_upstream_round_robin (void *ups, size_t members, size_t msi
*/
struct upstream* get_upstream_by_hash_ketama (void *ups, size_t members, size_t msize, time_t now,
time_t error_timeout, time_t revive_timeout, size_t max_errors,
gchar *key, size_t keylen);
const gchar *key, size_t keylen);

/*
/**
* Get an upstream from array of upstreams based on its current priority (not weight)
* @param ups array of structures that contains struct upstream as their first element
* @param members number of elements in array

Loading…
Cancel
Save