📄 apr_memcache.c
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include "apr_memcache.h"#include "apr_poll.h"#include "apr_version.h"#include <stdlib.h>#define BUFFER_SIZE 512struct apr_memcache_conn_t{ char *buffer; apr_size_t blen; apr_pool_t *p; apr_socket_t *sock; apr_bucket_alloc_t *balloc; apr_bucket_brigade *bb; apr_bucket_brigade *tb; apr_memcache_server_t *ms;}; /* Strings for Client Commands */#define MC_EOL "\r\n"#define MC_EOL_LEN (sizeof(MC_EOL)-1)#define MC_WS " "#define MC_WS_LEN (sizeof(MC_WS)-1)#define MC_GET "get "#define MC_GET_LEN (sizeof(MC_GET)-1)#define MC_SET "set "#define MC_SET_LEN (sizeof(MC_SET)-1)#define MC_ADD "add "#define MC_ADD_LEN (sizeof(MC_ADD)-1)#define MC_REPLACE "replace "#define MC_REPLACE_LEN (sizeof(MC_REPLACE)-1)#define MC_DELETE "delete "#define MC_DELETE_LEN (sizeof(MC_DELETE)-1)#define MC_INCR "incr "#define MC_INCR_LEN (sizeof(MC_INCR)-1)#define MC_DECR "decr "#define MC_DECR_LEN (sizeof(MC_DECR)-1)#define MC_VERSION "version"#define MC_VERSION_LEN (sizeof(MC_VERSION)-1)#define MC_STATS "stats"#define MC_STATS_LEN (sizeof(MC_STATS)-1)#define MC_QUIT "quit"#define MC_QUIT_LEN (sizeof(MC_QUIT)-1)/* Strings for Server Replies */#define MS_STORED "STORED"#define MS_STORED_LEN (sizeof(MS_STORED)-1)#define MS_NOT_STORED "NOT_STORED"#define MS_NOT_STORED_LEN (sizeof(MS_NOT_STORED)-1)#define MS_DELETED "DELETED"#define MS_DELETED_LEN (sizeof(MS_DELETED)-1)#define MS_NOT_FOUND "NOT_FOUND"#define MS_NOT_FOUND_LEN (sizeof(MS_NOT_FOUND)-1)#define MS_VALUE "VALUE"#define MS_VALUE_LEN (sizeof(MS_VALUE)-1)#define MS_ERROR "ERROR"#define MS_ERROR_LEN (sizeof(MS_ERROR)-1)#define MS_VERSION "VERSION"#define MS_VERSION_LEN (sizeof(MS_VERSION)-1)#define MS_STAT "STAT"#define MS_STAT_LEN (sizeof(MS_STAT)-1)#define MS_END "END"#define MS_END_LEN (sizeof(MS_END)-1)/** Server and Query Structure for a multiple get */struct cache_server_query_t { apr_memcache_server_t* ms; apr_memcache_conn_t* conn; struct iovec* query_vec; apr_int32_t query_vec_count;};#define MULT_GET_TIMEOUT 50000static apr_status_t make_server_dead(apr_memcache_t *mc, apr_memcache_server_t *ms){#if APR_HAS_THREADS apr_thread_mutex_lock(ms->lock);#endif ms->status = APR_MC_SERVER_DEAD; ms->btime = apr_time_now();#if APR_HAS_THREADS apr_thread_mutex_unlock(ms->lock);#endif return APR_SUCCESS;}static apr_status_t make_server_live(apr_memcache_t *mc, apr_memcache_server_t *ms){ ms->status = APR_MC_SERVER_LIVE; return APR_SUCCESS;}APU_DECLARE(apr_status_t) apr_memcache_add_server(apr_memcache_t *mc, apr_memcache_server_t *ms){ apr_status_t rv = APR_SUCCESS; if(mc->ntotal >= mc->nalloc) { return APR_ENOMEM; } mc->live_servers[mc->ntotal] = ms; mc->ntotal++; make_server_live(mc, ms); return rv;}static apr_status_t mc_version_ping(apr_memcache_server_t *ms);APU_DECLARE(apr_memcache_server_t *) apr_memcache_find_server_hash(apr_memcache_t *mc, const apr_uint32_t hash){ if (mc->server_func) { return mc->server_func(mc->server_baton, mc, hash); } else { return apr_memcache_find_server_hash_default(NULL, mc, hash); }} APU_DECLARE(apr_memcache_server_t *) apr_memcache_find_server_hash_default(void *baton, apr_memcache_t *mc, const apr_uint32_t hash){ apr_memcache_server_t *ms = NULL; apr_uint32_t h = hash ? hash : 1; apr_uint32_t i = 0; apr_time_t curtime = 0; if(mc->ntotal == 0) { return NULL; } do { ms = mc->live_servers[h % mc->ntotal]; if(ms->status == APR_MC_SERVER_LIVE) { break; } else { if (curtime == 0) { curtime = apr_time_now(); }#if APR_HAS_THREADS apr_thread_mutex_lock(ms->lock);#endif /* Try the the dead server, every 5 seconds */ if (curtime - ms->btime > apr_time_from_sec(5)) { if (mc_version_ping(ms) == APR_SUCCESS) { ms->btime = curtime; make_server_live(mc, ms);#if APR_HAS_THREADS apr_thread_mutex_unlock(ms->lock);#endif break; } }#if APR_HAS_THREADS apr_thread_mutex_unlock(ms->lock);#endif } h++; i++; } while(i < mc->ntotal); if (i == mc->ntotal) { ms = NULL; } return ms;}APU_DECLARE(apr_memcache_server_t *) apr_memcache_find_server(apr_memcache_t *mc, const char *host, apr_port_t port){ int i; for (i = 0; i < mc->ntotal; i++) { if (strcmp(mc->live_servers[i]->host, host) == 0 && mc->live_servers[i]->port == port) { return mc->live_servers[i]; } } return NULL;}static apr_status_t ms_find_conn(apr_memcache_server_t *ms, apr_memcache_conn_t **conn) {#if APR_HAS_THREADS return apr_reslist_acquire(ms->conns, (void **)conn);#else *conn = ms->conn; return APR_SUCCESS;#endif}static apr_status_t ms_bad_conn(apr_memcache_server_t *ms, apr_memcache_conn_t *conn) {#if APR_HAS_THREADS return apr_reslist_invalidate(ms->conns, conn);#else return APR_SUCCESS;#endif}static apr_status_t ms_release_conn(apr_memcache_server_t *ms, apr_memcache_conn_t *conn) {#if APR_HAS_THREADS return apr_reslist_release(ms->conns, conn);#else return APR_SUCCESS;#endif}APU_DECLARE(apr_status_t) apr_memcache_enable_server(apr_memcache_t *mc, apr_memcache_server_t *ms){ apr_status_t rv = APR_SUCCESS; if (ms->status == APR_MC_SERVER_LIVE) { return rv; } rv = make_server_live(mc, ms); return rv;}APU_DECLARE(apr_status_t) apr_memcache_disable_server(apr_memcache_t *mc, apr_memcache_server_t *ms){ return make_server_dead(mc, ms);}static apr_status_t conn_connect(apr_memcache_conn_t *conn){ apr_status_t rv = APR_SUCCESS; apr_sockaddr_t *sa; rv = apr_sockaddr_info_get(&sa, conn->ms->host, APR_INET, conn->ms->port, 0, conn->p); if (rv != APR_SUCCESS) { return rv; } rv = apr_socket_timeout_set(conn->sock, 1 * APR_USEC_PER_SEC); if (rv != APR_SUCCESS) { return rv; } rv = apr_socket_connect(conn->sock, sa); if (rv != APR_SUCCESS) { return rv; } rv = apr_socket_timeout_set(conn->sock, -1); if (rv != APR_SUCCESS) { return rv; } return rv;}static apr_status_t conn_clean(void *data){ apr_memcache_conn_t *conn = data; struct iovec vec[2]; apr_size_t written; /* send a quit message to the memcached server to be nice about it. */ vec[0].iov_base = MC_QUIT; vec[0].iov_len = MC_QUIT_LEN; vec[1].iov_base = MC_EOL; vec[1].iov_len = MC_EOL_LEN; /* Return values not checked, since we just want to make it go away. */ apr_socket_sendv(conn->sock, vec, 2, &written); apr_socket_close(conn->sock); conn->p = NULL; /* so that destructor does not destroy the pool again */ return APR_SUCCESS;}static apr_status_tmc_conn_construct(void **conn_, void *params, apr_pool_t *pool){ apr_status_t rv = APR_SUCCESS; apr_memcache_conn_t *conn; apr_bucket *e; apr_pool_t *np; apr_memcache_server_t *ms = params; rv = apr_pool_create(&np, pool); if (rv != APR_SUCCESS) { return rv; }#if APR_HAS_THREADS conn = malloc(sizeof( apr_memcache_conn_t )); /* non-pool space! */#else conn = apr_palloc(np, sizeof( apr_memcache_conn_t ));#endif conn->p = np; rv = apr_socket_create(&conn->sock, APR_INET, SOCK_STREAM, 0, np); if (rv != APR_SUCCESS) { apr_pool_destroy(np);#if APR_HAS_THREADS free(conn);#endif return rv; } conn->balloc = apr_bucket_alloc_create(conn->p); conn->bb = apr_brigade_create(conn->p, conn->balloc); conn->tb = apr_brigade_create(conn->p, conn->balloc); conn->buffer = apr_palloc(conn->p, BUFFER_SIZE); conn->blen = 0; conn->ms = ms; e = apr_bucket_socket_create(conn->sock, conn->balloc); APR_BRIGADE_INSERT_TAIL(conn->bb, e); rv = conn_connect(conn); if (rv != APR_SUCCESS) { apr_pool_destroy(np);#if APR_HAS_THREADS free(conn);#endif } else { apr_pool_cleanup_register(np, conn, conn_clean, apr_pool_cleanup_null); *conn_ = conn; } return rv;}#if APR_HAS_THREADSstatic apr_status_tmc_conn_destruct(void *conn_, void *params, apr_pool_t *pool){ apr_memcache_conn_t *conn = (apr_memcache_conn_t*)conn_; if (conn->p) { apr_pool_destroy(conn->p); } free(conn); /* free non-pool space */ return APR_SUCCESS;}#endifAPU_DECLARE(apr_status_t) apr_memcache_server_create(apr_pool_t *p, const char *host, apr_port_t port, apr_uint32_t min, apr_uint32_t smax, apr_uint32_t max, apr_uint32_t ttl, apr_memcache_server_t **ms){ apr_status_t rv = APR_SUCCESS; apr_memcache_server_t *server; apr_pool_t *np; rv = apr_pool_create(&np, p); server = apr_palloc(np, sizeof(apr_memcache_server_t)); server->p = np; server->host = apr_pstrdup(np, host); server->port = port; server->status = APR_MC_SERVER_DEAD;#if APR_HAS_THREADS rv = apr_thread_mutex_create(&server->lock, APR_THREAD_MUTEX_DEFAULT, np); if (rv != APR_SUCCESS) { return rv; } rv = apr_reslist_create(&server->conns, min, /* hard minimum */ smax, /* soft maximum */ max, /* hard maximum */ ttl, /* Time to live */ mc_conn_construct, /* Make a New Connection */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -