diff options
Diffstat (limited to 'src/libutil/memcached.c')
-rw-r--r-- | src/libutil/memcached.c | 831 |
1 files changed, 0 insertions, 831 deletions
diff --git a/src/libutil/memcached.c b/src/libutil/memcached.c deleted file mode 100644 index e4c9be9d2..000000000 --- a/src/libutil/memcached.c +++ /dev/null @@ -1,831 +0,0 @@ -/* - * Copyright (c) 2009-2012, 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 BY AUTHOR ''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. - */ - -#ifdef _THREAD_SAFE -# include <pthread.h> -#endif - -#include <stdarg.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sysexits.h> -#include <unistd.h> -#include <syslog.h> - -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/socket.h> -#include <sys/poll.h> -#include <errno.h> -#include <fcntl.h> -#include <sys/uio.h> -#include <event.h> -#include <glib.h> - -#include "memcached.h" - -#define CRLF "\r\n" -#define END_TRAILER "END" CRLF -#define STORED_TRAILER "STORED" CRLF -#define NOT_STORED_TRAILER "NOT STORED" CRLF -#define EXISTS_TRAILER "EXISTS" CRLF -#define DELETED_TRAILER "DELETED" CRLF -#define NOT_FOUND_TRAILER "NOT_FOUND" CRLF -#define CLIENT_ERROR_TRAILER "CLIENT_ERROR" -#define SERVER_ERROR_TRAILER "SERVER_ERROR" - -#define READ_BUFSIZ 1500 -#define MAX_RETRIES 3 - -/* Header for udp protocol */ -struct memc_udp_header { - guint16 req_id; - guint16 seq_num; - guint16 dg_sent; - guint16 unused; -}; - -static void socket_callback (gint fd, short what, void *arg); -static gint memc_parse_header (gchar *buf, size_t * len, gchar **end); - -/* - * Write to syslog if OPT_DEBUG is specified - */ -static void -memc_log (const memcached_ctx_t * ctx, gint line, const gchar *fmt, ...) -{ - va_list args; - if (ctx->options & MEMC_OPT_DEBUG) { - va_start (args, fmt); - g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "memc_debug(%d): host: %s, port: %d", line, inet_ntoa (ctx->addr), ntohs (ctx->port)); - g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, fmt, args); - va_end (args); - } -} - -/* - * Callback for write command - */ -static void -write_handler (gint fd, short what, memcached_ctx_t * ctx) -{ - gchar read_buf[READ_BUFSIZ]; - gint retries; - ssize_t r; - struct memc_udp_header header; - struct iovec iov[4]; - - /* Write something to memcached */ - if (what == EV_WRITE) { - if (ctx->protocol == UDP_TEXT) { - /* Send udp header */ - bzero (&header, sizeof (header)); - header.dg_sent = htons (1); - header.req_id = ctx->count; - } - - r = snprintf (read_buf, READ_BUFSIZ, "%s %s 0 %d %zu" CRLF, ctx->cmd, ctx->param->key, ctx->param->expire, ctx->param->bufsize); - memc_log (ctx, __LINE__, "memc_write: send write request to memcached: %s", read_buf); - - if (ctx->protocol == UDP_TEXT) { - iov[0].iov_base = &header; - iov[0].iov_len = sizeof (struct memc_udp_header); - if (ctx->param->bufpos == 0) { - iov[1].iov_base = read_buf; - iov[1].iov_len = r; - } - else { - iov[1].iov_base = NULL; - iov[1].iov_len = 0; - } - iov[2].iov_base = ctx->param->buf + ctx->param->bufpos; - iov[2].iov_len = ctx->param->bufsize - ctx->param->bufpos; - iov[3].iov_base = CRLF; - iov[3].iov_len = sizeof (CRLF) - 1; - if (writev (ctx->sock, iov, 4) == -1) { - memc_log (ctx, __LINE__, "memc_write: writev failed: %s", strerror (errno)); - } - } - else { - iov[0].iov_base = read_buf; - iov[0].iov_len = r; - iov[1].iov_base = ctx->param->buf + ctx->param->bufpos; - iov[1].iov_len = ctx->param->bufsize - ctx->param->bufpos; - iov[2].iov_base = CRLF; - iov[2].iov_len = sizeof (CRLF) - 1; - if (writev (ctx->sock, iov, 3) == -1) { - memc_log (ctx, __LINE__, "memc_write: writev failed: %s", strerror (errno)); - } - } - event_del (&ctx->mem_ev); - event_set (&ctx->mem_ev, ctx->sock, EV_READ | EV_PERSIST | EV_TIMEOUT, socket_callback, (void *)ctx); - event_add (&ctx->mem_ev, &ctx->timeout); - } - else if (what == EV_READ) { - /* Read header */ - retries = 0; - while (ctx->protocol == UDP_TEXT) { - iov[0].iov_base = &header; - iov[0].iov_len = sizeof (struct memc_udp_header); - iov[1].iov_base = read_buf; - iov[1].iov_len = READ_BUFSIZ; - if ((r = readv (ctx->sock, iov, 2)) == -1) { - event_del (&ctx->mem_ev); - ctx->callback (ctx, SERVER_ERROR, ctx->callback_data); - } - if (header.req_id != ctx->count && retries < MAX_RETRIES) { - retries++; - /* Not our reply packet */ - continue; - } - break; - } - if (ctx->protocol != UDP_TEXT) { - r = read (ctx->sock, read_buf, READ_BUFSIZ - 1); - } - memc_log (ctx, __LINE__, "memc_write: read reply from memcached: %s", read_buf); - /* Increment count */ - ctx->count++; - event_del (&ctx->mem_ev); - if (strncmp (read_buf, STORED_TRAILER, sizeof (STORED_TRAILER) - 1) == 0) { - ctx->callback (ctx, OK, ctx->callback_data); - } - else if (strncmp (read_buf, NOT_STORED_TRAILER, sizeof (NOT_STORED_TRAILER) - 1) == 0) { - ctx->callback (ctx, CLIENT_ERROR, ctx->callback_data); - } - else if (strncmp (read_buf, EXISTS_TRAILER, sizeof (EXISTS_TRAILER) - 1) == 0) { - ctx->callback (ctx, EXISTS, ctx->callback_data); - } - else { - ctx->callback (ctx, SERVER_ERROR, ctx->callback_data); - } - } - else if (what == EV_TIMEOUT) { - event_del (&ctx->mem_ev); - ctx->callback (ctx, SERVER_TIMEOUT, ctx->callback_data); - } -} - -/* - * Callback for read command - */ -static void -read_handler (gint fd, short what, memcached_ctx_t * ctx) -{ - gchar read_buf[READ_BUFSIZ]; - gchar *p; - ssize_t r; - size_t datalen; - struct memc_udp_header header; - struct iovec iov[2]; - gint retries = 0, t; - - if (what == EV_WRITE) { - /* Send command to memcached */ - if (ctx->protocol == UDP_TEXT) { - /* Send udp header */ - bzero (&header, sizeof (header)); - header.dg_sent = htons (1); - header.req_id = ctx->count; - } - - r = snprintf (read_buf, READ_BUFSIZ, "%s %s" CRLF, ctx->cmd, ctx->param->key); - memc_log (ctx, __LINE__, "memc_read: send read request to memcached: %s", read_buf); - if (ctx->protocol == UDP_TEXT) { - iov[0].iov_base = &header; - iov[0].iov_len = sizeof (struct memc_udp_header); - iov[1].iov_base = read_buf; - iov[1].iov_len = r; - if (writev (ctx->sock, iov, 2) == -1) { - memc_log (ctx, __LINE__, "memc_write: writev failed: %s", strerror (errno)); - } - } - else { - if (write (ctx->sock, read_buf, r) == -1) { - memc_log (ctx, __LINE__, "memc_write: write failed: %s", strerror (errno)); - } - } - event_del (&ctx->mem_ev); - event_set (&ctx->mem_ev, ctx->sock, EV_READ | EV_PERSIST | EV_TIMEOUT, socket_callback, (void *)ctx); - event_add (&ctx->mem_ev, &ctx->timeout); - } - else if (what == EV_READ) { - while (ctx->protocol == UDP_TEXT) { - iov[0].iov_base = &header; - iov[0].iov_len = sizeof (struct memc_udp_header); - iov[1].iov_base = read_buf; - iov[1].iov_len = READ_BUFSIZ; - if ((r = readv (ctx->sock, iov, 2)) == -1) { - event_del (&ctx->mem_ev); - ctx->callback (ctx, SERVER_ERROR, ctx->callback_data); - return; - } - memc_log (ctx, __LINE__, "memc_read: got read_buf: %s", read_buf); - if (header.req_id != ctx->count && retries < MAX_RETRIES) { - memc_log (ctx, __LINE__, "memc_read: got wrong packet id: %d, %d was awaited", header.req_id, ctx->count); - retries++; - /* Not our reply packet */ - continue; - } - break; - } - if (ctx->protocol != UDP_TEXT) { - r = read (ctx->sock, read_buf, READ_BUFSIZ - 1); - } - - if (r > 0) { - read_buf[r] = 0; - if (ctx->param->bufpos == 0) { - t = memc_parse_header (read_buf, &datalen, &p); - if (t < 0) { - event_del (&ctx->mem_ev); - memc_log (ctx, __LINE__, "memc_read: cannot parse memcached reply"); - ctx->callback (ctx, SERVER_ERROR, ctx->callback_data); - return; - } - else if (t == 0) { - memc_log (ctx, __LINE__, "memc_read: record does not exists"); - event_del (&ctx->mem_ev); - ctx->callback (ctx, NOT_EXISTS, ctx->callback_data); - return; - } - - if (datalen > ctx->param->bufsize) { - memc_log (ctx, __LINE__, "memc_read: user's buffer is too small: %zd, %zd required", ctx->param->bufsize, datalen); - event_del (&ctx->mem_ev); - ctx->callback (ctx, WRONG_LENGTH, ctx->callback_data); - return; - } - /* Check if we already have all data in buffer */ - if (r >= (ssize_t)(datalen + sizeof (END_TRAILER) + sizeof (CRLF) - 2)) { - /* Store all data in param's buffer */ - memcpy (ctx->param->buf + ctx->param->bufpos, p, datalen); - /* Increment count */ - ctx->count++; - event_del (&ctx->mem_ev); - ctx->callback (ctx, OK, ctx->callback_data); - return; - } - /* Subtract from sum parsed header's length */ - r -= p - read_buf; - } - else { - p = read_buf; - } - - if (strncmp (ctx->param->buf + ctx->param->bufpos + r - sizeof (END_TRAILER) - sizeof (CRLF) + 2, END_TRAILER, sizeof (END_TRAILER) - 1) == 0) { - r -= sizeof (END_TRAILER) - sizeof (CRLF) - 2; - memcpy (ctx->param->buf + ctx->param->bufpos, p, r); - event_del (&ctx->mem_ev); - ctx->callback (ctx, OK, ctx->callback_data); - return; - } - /* Store this part of data in param's buffer */ - memcpy (ctx->param->buf + ctx->param->bufpos, p, r); - ctx->param->bufpos += r; - } - else { - memc_log (ctx, __LINE__, "memc_read: read(v) failed: %d, %s", r, strerror (errno)); - event_del (&ctx->mem_ev); - ctx->callback (ctx, SERVER_ERROR, ctx->callback_data); - return; - } - - ctx->count++; - } - else if (what == EV_TIMEOUT) { - event_del (&ctx->mem_ev); - ctx->callback (ctx, SERVER_TIMEOUT, ctx->callback_data); - } - -} - -/* - * Callback for delete command - */ -static void -delete_handler (gint fd, short what, memcached_ctx_t * ctx) -{ - gchar read_buf[READ_BUFSIZ]; - gint retries; - ssize_t r; - struct memc_udp_header header; - struct iovec iov[2]; - - /* Write something to memcached */ - if (what == EV_WRITE) { - if (ctx->protocol == UDP_TEXT) { - /* Send udp header */ - bzero (&header, sizeof (header)); - header.dg_sent = htons (1); - header.req_id = ctx->count; - } - r = snprintf (read_buf, READ_BUFSIZ, "delete %s" CRLF, ctx->param->key); - memc_log (ctx, __LINE__, "memc_delete: send delete request to memcached: %s", read_buf); - - if (ctx->protocol == UDP_TEXT) { - iov[0].iov_base = &header; - iov[0].iov_len = sizeof (struct memc_udp_header); - iov[1].iov_base = read_buf; - iov[1].iov_len = r; - ctx->param->bufpos = writev (ctx->sock, iov, 2); - if (ctx->param->bufpos == (size_t)-1) { - memc_log (ctx, __LINE__, "memc_write: writev failed: %s", strerror (errno)); - } - } - else { - if (write (ctx->sock, read_buf, r) == -1) { - memc_log (ctx, __LINE__, "memc_write: write failed: %s", strerror (errno)); - } - } - event_del (&ctx->mem_ev); - event_set (&ctx->mem_ev, ctx->sock, EV_READ | EV_PERSIST | EV_TIMEOUT, socket_callback, (void *)ctx); - event_add (&ctx->mem_ev, &ctx->timeout); - } - else if (what == EV_READ) { - /* Read header */ - retries = 0; - while (ctx->protocol == UDP_TEXT) { - iov[0].iov_base = &header; - iov[0].iov_len = sizeof (struct memc_udp_header); - iov[1].iov_base = read_buf; - iov[1].iov_len = READ_BUFSIZ; - if ((r = readv (ctx->sock, iov, 2)) == -1) { - event_del (&ctx->mem_ev); - ctx->callback (ctx, SERVER_ERROR, ctx->callback_data); - return; - } - if (header.req_id != ctx->count && retries < MAX_RETRIES) { - retries++; - /* Not our reply packet */ - continue; - } - break; - } - if (ctx->protocol != UDP_TEXT) { - r = read (ctx->sock, read_buf, READ_BUFSIZ - 1); - } - /* Increment count */ - ctx->count++; - event_del (&ctx->mem_ev); - if (strncmp (read_buf, DELETED_TRAILER, sizeof (STORED_TRAILER) - 1) == 0) { - ctx->callback (ctx, OK, ctx->callback_data); - } - else if (strncmp (read_buf, NOT_FOUND_TRAILER, sizeof (NOT_FOUND_TRAILER) - 1) == 0) { - ctx->callback (ctx, NOT_EXISTS, ctx->callback_data); - } - else { - ctx->callback (ctx, SERVER_ERROR, ctx->callback_data); - } - } - else if (what == EV_TIMEOUT) { - event_del (&ctx->mem_ev); - ctx->callback (ctx, SERVER_TIMEOUT, ctx->callback_data); - } -} - -/* - * Callback for our socket events - */ -static void -socket_callback (gint fd, short what, void *arg) -{ - memcached_ctx_t *ctx = (memcached_ctx_t *) arg; - - switch (ctx->op) { - case CMD_NULL: - /* Do nothing here */ - break; - case CMD_CONNECT: - /* We have write readiness after connect call, so reinit event */ - ctx->cmd = "connect"; - if (what == EV_WRITE) { - event_del (&ctx->mem_ev); - event_set (&ctx->mem_ev, ctx->sock, EV_READ | EV_PERSIST | EV_TIMEOUT, socket_callback, (void *)ctx); - event_add (&ctx->mem_ev, NULL); - ctx->callback (ctx, OK, ctx->callback_data); - ctx->alive = 1; - } - else { - ctx->callback (ctx, SERVER_TIMEOUT, ctx->callback_data); - ctx->alive = 0; - } - break; - case CMD_WRITE: - write_handler (fd, what, ctx); - break; - case CMD_READ: - read_handler (fd, what, ctx); - break; - case CMD_DELETE: - delete_handler (fd, what, ctx); - break; - } -} - -/* - * Common callback function for memcached operations if no user's callback is specified - */ -static void -common_memc_callback (memcached_ctx_t * ctx, memc_error_t error, void *data) -{ - memc_log (ctx, __LINE__, "common_memc_callback: result of memc command '%s' is '%s'", ctx->cmd, memc_strerror (error)); -} - -/* - * Make socket for udp connection - */ -static gint -memc_make_udp_sock (memcached_ctx_t * ctx) -{ - struct sockaddr_in sc; - gint ofl; - - bzero (&sc, sizeof (struct sockaddr_in *)); - sc.sin_family = AF_INET; - sc.sin_port = ctx->port; - memcpy (&sc.sin_addr, &ctx->addr, sizeof (struct in_addr)); - - ctx->sock = socket (PF_INET, SOCK_DGRAM, 0); - - if (ctx->sock == -1) { - memc_log (ctx, __LINE__, "memc_make_udp_sock: socket() failed: %s", strerror (errno)); - return -1; - } - - /* set nonblocking */ - ofl = fcntl (ctx->sock, F_GETFL, 0); - fcntl (ctx->sock, F_SETFL, ofl | O_NONBLOCK); - - /* - * Call connect to set default destination for datagrams - * May not block - */ - ctx->op = CMD_CONNECT; - event_set (&ctx->mem_ev, ctx->sock, EV_WRITE | EV_TIMEOUT, socket_callback, (void *)ctx); - event_add (&ctx->mem_ev, NULL); - return connect (ctx->sock, (struct sockaddr *)&sc, sizeof (struct sockaddr_in)); -} - -/* - * Make socket for tcp connection - */ -static gint -memc_make_tcp_sock (memcached_ctx_t * ctx) -{ - struct sockaddr_in sc; - gint ofl, r; - - bzero (&sc, sizeof (struct sockaddr_in *)); - sc.sin_family = AF_INET; - sc.sin_port = ctx->port; - memcpy (&sc.sin_addr, &ctx->addr, sizeof (struct in_addr)); - - ctx->sock = socket (PF_INET, SOCK_STREAM, 0); - - if (ctx->sock == -1) { - memc_log (ctx, __LINE__, "memc_make_tcp_sock: socket() failed: %s", strerror (errno)); - return -1; - } - - /* set nonblocking */ - ofl = fcntl (ctx->sock, F_GETFL, 0); - fcntl (ctx->sock, F_SETFL, ofl | O_NONBLOCK); - - if ((r = connect (ctx->sock, (struct sockaddr *)&sc, sizeof (struct sockaddr_in))) == -1) { - if (errno != EINPROGRESS) { - close (ctx->sock); - ctx->sock = -1; - memc_log (ctx, __LINE__, "memc_make_tcp_sock: connect() failed: %s", strerror (errno)); - return -1; - } - } - ctx->op = CMD_CONNECT; - event_set (&ctx->mem_ev, ctx->sock, EV_WRITE | EV_TIMEOUT, socket_callback, (void *)ctx); - event_add (&ctx->mem_ev, &ctx->timeout); - return 0; -} - -/* - * Parse VALUE reply from server and set len argument to value returned by memcached - */ -static gint -memc_parse_header (gchar *buf, size_t * len, gchar **end) -{ - gchar *p, *c; - gint i; - - /* VALUE <key> <flags> <bytes> [<cas unique>]\r\n */ - c = strstr (buf, CRLF); - if (c == NULL) { - return -1; - } - *end = c + sizeof (CRLF) - 1; - - if (strncmp (buf, "VALUE ", sizeof ("VALUE ") - 1) == 0) { - p = buf + sizeof ("VALUE ") - 1; - - /* Read bytes value and ignore all other fields, such as flags and key */ - for (i = 0; i < 2; i++) { - while (p++ < c && *p != ' '); - - if (p > c) { - return -1; - } - } - *len = strtoul (p, &c, 10); - return 1; - } - /* If value not found memcached return just END\r\n , in this case return 0 */ - else if (strncmp (buf, END_TRAILER, sizeof (END_TRAILER) - 1) == 0) { - return 0; - } - - return -1; -} - - -/* - * Common read command handler for memcached - */ -memc_error_t -memc_read (memcached_ctx_t * ctx, const gchar *cmd, memcached_param_t * param) -{ - ctx->cmd = cmd; - ctx->op = CMD_READ; - ctx->param = param; - event_set (&ctx->mem_ev, ctx->sock, EV_WRITE | EV_TIMEOUT, socket_callback, (void *)ctx); - event_add (&ctx->mem_ev, &ctx->timeout); - - return OK; -} - -/* - * Common write command handler for memcached - */ -memc_error_t -memc_write (memcached_ctx_t * ctx, const gchar *cmd, memcached_param_t * param, gint expire) -{ - ctx->cmd = cmd; - ctx->op = CMD_WRITE; - ctx->param = param; - param->expire = expire; - event_set (&ctx->mem_ev, ctx->sock, EV_WRITE | EV_TIMEOUT, socket_callback, (void *)ctx); - event_add (&ctx->mem_ev, &ctx->timeout); - - return OK; -} - -/* - * Delete command handler - */ -memc_error_t -memc_delete (memcached_ctx_t * ctx, memcached_param_t * param) -{ - ctx->cmd = "delete"; - ctx->op = CMD_DELETE; - ctx->param = param; - event_set (&ctx->mem_ev, ctx->sock, EV_WRITE | EV_TIMEOUT, socket_callback, (void *)ctx); - event_add (&ctx->mem_ev, &ctx->timeout); - - return OK; -} - -/* - * Write handler for memcached mirroring - * writing is done to each memcached server - */ -memc_error_t -memc_write_mirror (memcached_ctx_t * ctx, size_t memcached_num, const gchar *cmd, memcached_param_t * param, gint expire) -{ - memc_error_t r, result = OK; - - while (memcached_num--) { - if (ctx[memcached_num].alive == 1) { - r = memc_write (&ctx[memcached_num], cmd, param, expire); - if (r != OK) { - memc_log (&ctx[memcached_num], __LINE__, "memc_write_mirror: cannot write to mirror server: %s", memc_strerror (r)); - result = r; - ctx[memcached_num].alive = 0; - } - } - } - - return result; -} - -/* - * Read handler for memcached mirroring - * reading is done from first active memcached server - */ -memc_error_t -memc_read_mirror (memcached_ctx_t * ctx, size_t memcached_num, const gchar *cmd, memcached_param_t * param) -{ - memc_error_t r, result = OK; - - while (memcached_num--) { - if (ctx[memcached_num].alive == 1) { - r = memc_read (&ctx[memcached_num], cmd, param); - if (r != OK) { - result = r; - if (r != NOT_EXISTS) { - ctx[memcached_num].alive = 0; - memc_log (&ctx[memcached_num], __LINE__, "memc_read_mirror: cannot write read from mirror server: %s", memc_strerror (r)); - } - else { - memc_log (&ctx[memcached_num], __LINE__, "memc_read_mirror: record not exists", memc_strerror (r)); - } - } - else { - break; - } - } - } - - return result; -} - -/* - * Delete handler for memcached mirroring - * deleting is done for each active memcached server - */ -memc_error_t -memc_delete_mirror (memcached_ctx_t * ctx, size_t memcached_num, const gchar *cmd, memcached_param_t * param) -{ - memc_error_t r, result = OK; - - while (memcached_num--) { - if (ctx[memcached_num].alive == 1) { - r = memc_delete (&ctx[memcached_num], param); - if (r != OK) { - result = r; - if (r != NOT_EXISTS) { - ctx[memcached_num].alive = 0; - memc_log (&ctx[memcached_num], __LINE__, "memc_delete_mirror: cannot delete from mirror server: %s", memc_strerror (r)); - } - } - } - } - - return result; -} - - -/* - * Initialize memcached context for specified protocol - */ -gint -memc_init_ctx (memcached_ctx_t * ctx) -{ - if (ctx == NULL) { - return -1; - } - - ctx->count = 0; - ctx->alive = 0; - ctx->op = CMD_NULL; - /* Set default callback */ - if (ctx->callback == NULL) { - ctx->callback = common_memc_callback; - } - - switch (ctx->protocol) { - case UDP_TEXT: - return memc_make_udp_sock (ctx); - break; - case TCP_TEXT: - return memc_make_tcp_sock (ctx); - break; - /* Not implemented */ - case UDP_BIN: - case TCP_BIN: - default: - return -1; - } -} - -/* - * Mirror init - */ -gint -memc_init_ctx_mirror (memcached_ctx_t * ctx, size_t memcached_num) -{ - gint r, result = -1; - while (memcached_num--) { - if (ctx[memcached_num].alive == 1) { - r = memc_init_ctx (&ctx[memcached_num]); - if (r == -1) { - ctx[memcached_num].alive = 0; - memc_log (&ctx[memcached_num], __LINE__, "memc_init_ctx_mirror: cannot connect to server"); - } - else { - result = 1; - } - } - } - - return result; -} - -/* - * Close context connection - */ -gint -memc_close_ctx (memcached_ctx_t * ctx) -{ - if (ctx != NULL && ctx->sock != -1) { - event_del (&ctx->mem_ev); - return close (ctx->sock); - } - - return -1; -} - -/* - * Mirror close - */ -gint -memc_close_ctx_mirror (memcached_ctx_t * ctx, size_t memcached_num) -{ - gint r = 0; - while (memcached_num--) { - if (ctx[memcached_num].alive == 1) { - r = memc_close_ctx (&ctx[memcached_num]); - if (r == -1) { - memc_log (&ctx[memcached_num], __LINE__, "memc_close_ctx_mirror: cannot close connection to server properly"); - ctx[memcached_num].alive = 0; - } - } - } - - return r; -} - - -const gchar * -memc_strerror (memc_error_t err) -{ - const gchar *p; - - switch (err) { - case OK: - p = "Ok"; - break; - case BAD_COMMAND: - p = "Bad command"; - break; - case CLIENT_ERROR: - p = "Client error"; - break; - case SERVER_ERROR: - p = "Server error"; - break; - case SERVER_TIMEOUT: - p = "Server timeout"; - break; - case NOT_EXISTS: - p = "Key not found"; - break; - case EXISTS: - p = "Key already exists"; - break; - case WRONG_LENGTH: - p = "Wrong result length"; - break; - default: - p = "Unknown error"; - break; - } - - return p; -} - -/* - * vi:ts=4 - */ |