From: Marko Kreen Date: Mon, 11 Jan 2010 05:59:41 +0000 (+0200) Subject: X-Git-Tag: pgbouncer_1_4_rc3~75 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9dc4f2f42154bcdd7586bd0e1618d36215bbc449;p=pgbouncer --- diff --git a/Makefile b/Makefile index 4c69b1a..1ddb63d 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ # sources SRCS = client.c loader.c objects.c pooler.c proto.c sbuf.c server.c util.c \ - admin.c stats.c takeover.c md5.c janitor.c pktbuf.c system.c main.c \ - varcache.c slab.c + admin.c stats.c takeover.c janitor.c pktbuf.c system.c main.c \ + varcache.c HDRS = client.h loader.h objects.h pooler.h proto.h sbuf.h server.h util.h \ - admin.h stats.h takeover.h md5.h janitor.h pktbuf.h system.h bouncer.h \ - mbuf.h varcache.h slab.h iobuf.h + admin.h stats.h takeover.h janitor.h pktbuf.h system.h bouncer.h \ + mbuf.h varcache.h iobuf.h # data & dirs to include in tgz DOCS = doc/overview.txt doc/usage.txt doc/config.txt doc/todo.txt diff --git a/include/bouncer.h b/include/bouncer.h index 2bc431b..441dee0 100644 --- a/include/bouncer.h +++ b/include/bouncer.h @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -82,7 +83,6 @@ extern int cf_sbuf_len; #include "sbuf.h" #include "pktbuf.h" #include "varcache.h" -#include "slab.h" #include "admin.h" #include "loader.h" diff --git a/include/md5.h b/include/md5.h deleted file mode 100644 index 1e78b05..0000000 --- a/include/md5.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * MD5 implementation based on RFC1321. - * - * Copyright (c) 2008 Marko Kreen, Skype Technologies OÜ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __MD5_H__ -#define __MD5_H__ - -#define MD5_BLOCK_LENGTH 64 -#define MD5_DIGEST_LENGTH 16 - -struct md5_ctx { - uint64_t nbytes; - uint32_t a, b, c, d; - uint32_t buf[16]; -}; - -void md5_reset(struct md5_ctx *ctx); -void md5_update(struct md5_ctx *ctx, const void *data, unsigned int len); -void md5_final(uint8_t *dst, struct md5_ctx *ctx); - -#ifndef AVOID_MD5_COMPAT -typedef struct md5_ctx MD5_CTX; -#define MD5_Init(c) md5_reset(c) -#define MD5_Update(c, d, l) md5_update(c, d, l) -#define MD5_Final(d, c) md5_final(d, c) -#endif - -#endif - diff --git a/include/objects.h b/include/objects.h index 2d7ae80..ac03c6f 100644 --- a/include/objects.h +++ b/include/objects.h @@ -22,12 +22,12 @@ extern struct StatList pool_list; extern struct StatList database_list; extern struct StatList autodatabase_idle_list; extern struct StatList login_client_list; -extern ObjectCache *client_cache; -extern ObjectCache *server_cache; -extern ObjectCache *db_cache; -extern ObjectCache *pool_cache; -extern ObjectCache *user_cache; -extern ObjectCache *iobuf_cache; +extern struct Slab *client_cache; +extern struct Slab *server_cache; +extern struct Slab *db_cache; +extern struct Slab *pool_cache; +extern struct Slab *user_cache; +extern struct Slab *iobuf_cache; PgDatabase *find_database(const char *name); PgUser *find_user(const char *name); diff --git a/include/slab.h b/include/slab.h deleted file mode 100644 index f05ee9d..0000000 --- a/include/slab.h +++ /dev/null @@ -1,21 +0,0 @@ - -typedef struct ObjectCache ObjectCache; - -typedef void (*obj_init_fn)(void *obj); - -ObjectCache *objcache_create(const char *name, unsigned obj_size, unsigned align, - obj_init_fn init_func); -void objcache_destroy(ObjectCache *cache); - -void * obj_alloc(ObjectCache *cache) _MALLOC _MUSTCHECK; -void obj_free(ObjectCache *cache, void *obj); - -int objcache_total_count(const ObjectCache *cache); -int objcache_free_count(const ObjectCache *cache); -int objcache_active_count(const ObjectCache *cache); - -typedef void (*slab_stat_fn)(void *arg, const char *slab_name, - unsigned size, unsigned free, - unsigned total); -void objcache_stats(slab_stat_fn fn, void *arg); - diff --git a/src/admin.c b/src/admin.c index 545d118..731b972 100644 --- a/src/admin.c +++ b/src/admin.c @@ -451,11 +451,11 @@ static bool admin_show_lists(PgSocket *admin, const char *arg) SENDLIST("databases", statlist_count(&database_list)); SENDLIST("users", statlist_count(&user_list)); SENDLIST("pools", statlist_count(&pool_list)); - SENDLIST("free_clients", objcache_free_count(client_cache)); - SENDLIST("used_clients", objcache_active_count(client_cache)); + SENDLIST("free_clients", slab_free_count(client_cache)); + SENDLIST("used_clients", slab_active_count(client_cache)); SENDLIST("login_clients", statlist_count(&login_client_list)); - SENDLIST("free_servers", objcache_free_count(server_cache)); - SENDLIST("used_servers", objcache_active_count(server_cache)); + SENDLIST("free_servers", slab_free_count(server_cache)); + SENDLIST("used_servers", slab_active_count(server_cache)); admin_flush(admin, buf, "SHOW"); return true; } @@ -736,7 +736,7 @@ static bool admin_show_mem(PgSocket *admin, const char *arg) } pktbuf_write_RowDescription(buf, "siiii", "name", "size", "used", "free", "memtotal"); - objcache_stats(slab_stat_cb, buf); + slab_stats(slab_stat_cb, buf); admin_flush(admin, buf, "SHOW"); return true; } diff --git a/src/janitor.c b/src/janitor.c index 5131db8..40ffb56 100644 --- a/src/janitor.c +++ b/src/janitor.c @@ -578,7 +578,7 @@ static void kill_pool(PgPool *pool) list_del(&pool->map_head); statlist_remove(&pool_list, &pool->head); - obj_free(pool_cache, pool); + slab_free(pool_cache, pool); } static void kill_database(PgDatabase *db) @@ -594,14 +594,14 @@ static void kill_database(PgDatabase *db) kill_pool(pool); } if (db->forced_user) - obj_free(user_cache, db->forced_user); + slab_free(user_cache, db->forced_user); if (db->connect_query) free((void *)db->connect_query); if (db->inactive_time) statlist_remove(&autodatabase_idle_list, &db->head); else statlist_remove(&database_list, &db->head); - obj_free(db_cache, db); + slab_free(db_cache, db); } /* as [pgbouncer] section can be loaded after databases, diff --git a/src/md5.c b/src/md5.c deleted file mode 100644 index 8e133f9..0000000 --- a/src/md5.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * MD5 implementation based on RFC1321. - * - * Copyright (c) 2008 Marko Kreen, Skype Technologies OÜ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "system.h" -#include "md5.h" - -/* - * Support functions. - */ - -#define bufpos(ctx) ((ctx)->nbytes & (MD5_BLOCK_LENGTH - 1)) - -static inline uint32_t rol(uint32_t v, int s) -{ - return (v << s) | (v >> (32 - s)); -} - -static inline void swap_words(uint32_t *w, int n) -{ -#ifdef WORDS_BIGENDIAN - for (; n > 0; w++, n--) { - uint32_t v = rol(*w, 16); - *w = ((v >> 8) & 0x00FF00FF) | ((v << 8) & 0xFF00FF00); - } -#endif -} - -static inline void put_word(uint8_t *dst, uint32_t val) -{ -#ifdef WORDS_BIGENDIAN - dst[0] = val; - dst[1] = val >> 8; - dst[2] = val >> 16; - dst[3] = val >> 24; -#else - memcpy(dst, &val, 4); -#endif -} - -/* - * MD5 core. - */ - -#define F(X,Y,Z) ((X & Y) | ((~X) & Z)) -#define G(X,Y,Z) ((X & Z) | (Y & (~Z))) -#define H(X,Y,Z) (X ^ Y ^ Z) -#define I(X,Y,Z) (Y ^ (X | (~Z))) - -#define OP(fn, a, b, c, d, k, s, T_i) \ - a = b + rol(a + fn(b, c, d) + X[k] + T_i, s) - -static void md5_mix(struct md5_ctx *ctx, const uint32_t *X) -{ - uint32_t a, b, c, d; - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - - /* Round 1. */ - OP(F, a, b, c, d, 0, 7, 0xd76aa478); - OP(F, d, a, b, c, 1, 12, 0xe8c7b756); - OP(F, c, d, a, b, 2, 17, 0x242070db); - OP(F, b, c, d, a, 3, 22, 0xc1bdceee); - OP(F, a, b, c, d, 4, 7, 0xf57c0faf); - OP(F, d, a, b, c, 5, 12, 0x4787c62a); - OP(F, c, d, a, b, 6, 17, 0xa8304613); - OP(F, b, c, d, a, 7, 22, 0xfd469501); - OP(F, a, b, c, d, 8, 7, 0x698098d8); - OP(F, d, a, b, c, 9, 12, 0x8b44f7af); - OP(F, c, d, a, b, 10, 17, 0xffff5bb1); - OP(F, b, c, d, a, 11, 22, 0x895cd7be); - OP(F, a, b, c, d, 12, 7, 0x6b901122); - OP(F, d, a, b, c, 13, 12, 0xfd987193); - OP(F, c, d, a, b, 14, 17, 0xa679438e); - OP(F, b, c, d, a, 15, 22, 0x49b40821); - - /* Round 2. */ - OP(G, a, b, c, d, 1, 5, 0xf61e2562); - OP(G, d, a, b, c, 6, 9, 0xc040b340); - OP(G, c, d, a, b, 11, 14, 0x265e5a51); - OP(G, b, c, d, a, 0, 20, 0xe9b6c7aa); - OP(G, a, b, c, d, 5, 5, 0xd62f105d); - OP(G, d, a, b, c, 10, 9, 0x02441453); - OP(G, c, d, a, b, 15, 14, 0xd8a1e681); - OP(G, b, c, d, a, 4, 20, 0xe7d3fbc8); - OP(G, a, b, c, d, 9, 5, 0x21e1cde6); - OP(G, d, a, b, c, 14, 9, 0xc33707d6); - OP(G, c, d, a, b, 3, 14, 0xf4d50d87); - OP(G, b, c, d, a, 8, 20, 0x455a14ed); - OP(G, a, b, c, d, 13, 5, 0xa9e3e905); - OP(G, d, a, b, c, 2, 9, 0xfcefa3f8); - OP(G, c, d, a, b, 7, 14, 0x676f02d9); - OP(G, b, c, d, a, 12, 20, 0x8d2a4c8a); - - /* Round 3. */ - OP(H, a, b, c, d, 5, 4, 0xfffa3942); - OP(H, d, a, b, c, 8, 11, 0x8771f681); - OP(H, c, d, a, b, 11, 16, 0x6d9d6122); - OP(H, b, c, d, a, 14, 23, 0xfde5380c); - OP(H, a, b, c, d, 1, 4, 0xa4beea44); - OP(H, d, a, b, c, 4, 11, 0x4bdecfa9); - OP(H, c, d, a, b, 7, 16, 0xf6bb4b60); - OP(H, b, c, d, a, 10, 23, 0xbebfbc70); - OP(H, a, b, c, d, 13, 4, 0x289b7ec6); - OP(H, d, a, b, c, 0, 11, 0xeaa127fa); - OP(H, c, d, a, b, 3, 16, 0xd4ef3085); - OP(H, b, c, d, a, 6, 23, 0x04881d05); - OP(H, a, b, c, d, 9, 4, 0xd9d4d039); - OP(H, d, a, b, c, 12, 11, 0xe6db99e5); - OP(H, c, d, a, b, 15, 16, 0x1fa27cf8); - OP(H, b, c, d, a, 2, 23, 0xc4ac5665); - - /* Round 4. */ - OP(I, a, b, c, d, 0, 6, 0xf4292244); - OP(I, d, a, b, c, 7, 10, 0x432aff97); - OP(I, c, d, a, b, 14, 15, 0xab9423a7); - OP(I, b, c, d, a, 5, 21, 0xfc93a039); - OP(I, a, b, c, d, 12, 6, 0x655b59c3); - OP(I, d, a, b, c, 3, 10, 0x8f0ccc92); - OP(I, c, d, a, b, 10, 15, 0xffeff47d); - OP(I, b, c, d, a, 1, 21, 0x85845dd1); - OP(I, a, b, c, d, 8, 6, 0x6fa87e4f); - OP(I, d, a, b, c, 15, 10, 0xfe2ce6e0); - OP(I, c, d, a, b, 6, 15, 0xa3014314); - OP(I, b, c, d, a, 13, 21, 0x4e0811a1); - OP(I, a, b, c, d, 4, 6, 0xf7537e82); - OP(I, d, a, b, c, 11, 10, 0xbd3af235); - OP(I, c, d, a, b, 2, 15, 0x2ad7d2bb); - OP(I, b, c, d, a, 9, 21, 0xeb86d391); - - ctx->a += a; - ctx->b += b; - ctx->c += c; - ctx->d += d; -} - -/* - * Public API. - */ - -void md5_reset(struct md5_ctx *ctx) -{ - ctx->nbytes = 0; - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; -} - -void md5_update(struct md5_ctx *ctx, const void *data, unsigned int len) -{ - unsigned int n; - const uint8_t *ptr = data; - uint8_t *buf = (uint8_t *)ctx->buf; - - while (len > 0) { - n = MD5_BLOCK_LENGTH - bufpos(ctx); - if (n > len) - n = len; - memcpy(buf + bufpos(ctx), ptr, n); - ptr += n; - len -= n; - ctx->nbytes += n; - if (bufpos(ctx) == 0) { - swap_words(ctx->buf, 16); - md5_mix(ctx, ctx->buf); - } - } -} - -void md5_final(uint8_t *dst, struct md5_ctx *ctx) -{ - static const uint8_t padding[MD5_BLOCK_LENGTH] = { 0x80 }; - uint64_t final_len = ctx->nbytes * 8; - int pad_len, pos = bufpos(ctx); - - /* add padding */ - pad_len = MD5_BLOCK_LENGTH - 8 - pos; - if (pad_len <= 0) - pad_len += MD5_BLOCK_LENGTH; - md5_update(ctx, padding, pad_len); - - /* add length directly */ - swap_words(ctx->buf, 14); - ctx->buf[14] = final_len; - ctx->buf[15] = final_len >> 32; - - /* final result */ - md5_mix(ctx, ctx->buf); - put_word(dst, ctx->a); - put_word(dst + 4, ctx->b); - put_word(dst + 8, ctx->c); - put_word(dst + 12, ctx->d); -} - diff --git a/src/objects.c b/src/objects.c index 9eff2ed..966ca0a 100644 --- a/src/objects.c +++ b/src/objects.c @@ -36,12 +36,12 @@ struct AATree user_tree; */ STATLIST(login_client_list); -ObjectCache *server_cache; -ObjectCache *client_cache; -ObjectCache *db_cache; -ObjectCache *pool_cache; -ObjectCache *user_cache; -ObjectCache *iobuf_cache; +struct Slab *server_cache; +struct Slab *client_cache; +struct Slab *db_cache; +struct Slab *pool_cache; +struct Slab *user_cache; +struct Slab *iobuf_cache; /* * libevent may still report events when event_del() @@ -57,13 +57,13 @@ STATLIST(autodatabase_idle_list); /* fast way to get number of active clients */ int get_active_client_count(void) { - return objcache_active_count(client_cache); + return slab_active_count(client_cache); } /* fast way to get number of active servers */ int get_active_server_count(void) { - return objcache_active_count(server_cache); + return slab_active_count(server_cache); } static void construct_client(void *obj) @@ -98,9 +98,9 @@ static int user_node_cmp(long userptr, struct AANode *node) void init_objects(void) { aatree_init(&user_tree, user_node_cmp, NULL); - user_cache = objcache_create("user_cache", sizeof(PgUser), 0, NULL); - db_cache = objcache_create("db_cache", sizeof(PgDatabase), 0, NULL); - pool_cache = objcache_create("pool_cache", sizeof(PgPool), 0, NULL); + user_cache = slab_create("user_cache", sizeof(PgUser), 0, NULL); + db_cache = slab_create("db_cache", sizeof(PgDatabase), 0, NULL); + pool_cache = slab_create("pool_cache", sizeof(PgPool), 0, NULL); if (!user_cache || !db_cache || !pool_cache) fatal("cannot create initial caches"); @@ -115,9 +115,9 @@ static void do_iobuf_reset(void *arg) /* initialization after config loading */ void init_caches(void) { - server_cache = objcache_create("server_cache", sizeof(PgSocket), 0, construct_server); - client_cache = objcache_create("client_cache", sizeof(PgSocket), 0, construct_client); - iobuf_cache = objcache_create("iobuf_cache", IOBUF_SIZE, 0, do_iobuf_reset); + server_cache = slab_create("server_cache", sizeof(PgSocket), 0, construct_server); + client_cache = slab_create("client_cache", sizeof(PgSocket), 0, construct_client); + iobuf_cache = slab_create("iobuf_cache", IOBUF_SIZE, 0, do_iobuf_reset); } /* state change means moving between lists */ @@ -153,7 +153,7 @@ void change_client_state(PgSocket *client, SocketState newstate) /* put to new location */ switch (client->state) { case CL_FREE: - obj_free(client_cache, client); + slab_free(client_cache, client); break; case CL_JUSTFREE: statlist_append(&justfree_client_list, &client->head); @@ -211,7 +211,7 @@ void change_server_state(PgSocket *server, SocketState newstate) /* put to new location */ switch (server->state) { case SV_FREE: - obj_free(server_cache, server); + slab_free(server_cache, server); break; case SV_JUSTFREE: statlist_append(&justfree_server_list, &server->head); @@ -296,7 +296,7 @@ PgDatabase *add_database(const char *name) /* create new object if needed */ if (db == NULL) { - db = obj_alloc(db_cache); + db = slab_alloc(db_cache); if (!db) return NULL; @@ -345,7 +345,7 @@ PgUser *add_user(const char *name, const char *passwd) PgUser *user = find_user(name); if (user == NULL) { - user = obj_alloc(user_cache); + user = slab_alloc(user_cache); if (!user) return NULL; @@ -365,7 +365,7 @@ PgUser *force_user(PgDatabase *db, const char *name, const char *passwd) { PgUser *user = db->forced_user; if (!user) { - user = obj_alloc(user_cache); + user = slab_alloc(user_cache); if (!user) return NULL; list_init(&user->head); @@ -416,7 +416,7 @@ static PgPool *new_pool(PgDatabase *db, PgUser *user) { PgPool *pool; - pool = obj_alloc(pool_cache); + pool = slab_alloc(pool_cache); if (!pool) return NULL; @@ -834,7 +834,7 @@ void launch_new_connection(PgPool *pool) allow_new: /* get free conn object */ - server = obj_alloc(server_cache); + server = slab_alloc(server_cache); if (!server) { log_debug("launch_new_connection: no memory"); return; @@ -871,7 +871,7 @@ PgSocket * accept_client(int sock, PgSocket *client; /* get free PgSocket */ - client = obj_alloc(client_cache); + client = slab_alloc(client_cache); if (!client) { log_warning("cannot allocate client struct"); safe_close(sock); @@ -1065,7 +1065,7 @@ bool use_server_socket(int fd, PgAddr *addr, if (!pool) return false; - server = obj_alloc(server_cache); + server = slab_alloc(server_cache); if (!server) return false; diff --git a/src/sbuf.c b/src/sbuf.c index ea7189f..3bef8f8 100644 --- a/src/sbuf.c +++ b/src/sbuf.c @@ -270,7 +270,7 @@ bool sbuf_close(SBuf *sbuf) sbuf->pkt_remain = 0; sbuf->pkt_action = sbuf->wait_type = 0; if (sbuf->io) { - obj_free(iobuf_cache, sbuf->io); + slab_free(iobuf_cache, sbuf->io); sbuf->io = NULL; } return true; @@ -546,7 +546,7 @@ static void sbuf_try_resync(SBuf *sbuf, bool release) return; if (release && iobuf_empty(io)) { - obj_free(iobuf_cache, io); + slab_free(iobuf_cache, io); sbuf->io = NULL; } else iobuf_try_resync(io, SBUF_SMALL_PKT); @@ -585,7 +585,7 @@ static void sbuf_recv_cb(int sock, short flags, void *arg) static bool allocate_iobuf(SBuf *sbuf) { if (sbuf->io == NULL) { - sbuf->io = obj_alloc(iobuf_cache); + sbuf->io = slab_alloc(iobuf_cache); if (sbuf->io == NULL) { sbuf_call_proto(sbuf, SBUF_EV_RECV_FAILED); return false; diff --git a/src/slab.c b/src/slab.c deleted file mode 100644 index 23484c6..0000000 --- a/src/slab.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * PgBouncer - Lightweight connection pooler for PostgreSQL. - * - * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Primitive slab allocator. - * - * - On each alloc initializer is called. - * - if init func is not given, memset() is done - */ - -#include - -#include "bouncer.h" - -/* - * Store for pre-initialized objects of one type. - */ -struct ObjectCache { - struct List head; - struct StatList freelist; - struct StatList slablist; - char name[32]; - unsigned final_size; - unsigned total_count; - obj_init_fn init_func; -}; - -/* - * Header for each slab. - */ -struct Slab { - struct List head; -}; - -/* keep track of all caches */ -static STATLIST(objcache_list); - -/* cache for cache headers */ -static ObjectCache *objcache_cache = NULL; - -/* fill struct contents */ -static void init_objcache(ObjectCache *cache, - const char *name, - unsigned obj_size, - unsigned align, - obj_init_fn init_func) -{ - list_init(&cache->head); - statlist_init(&cache->freelist, name); - statlist_init(&cache->slablist, name); - safe_strcpy(cache->name, name, sizeof(cache->name)); - cache->total_count = 0; - cache->init_func = init_func; - statlist_append(&objcache_list, &cache->head); - - if (align == 0) - cache->final_size = ALIGN(obj_size); - else - cache->final_size = CUSTOM_ALIGN(obj_size, align); - - log_noise("new cache: %s, size=%u", name, cache->final_size); -} - -/* make new cache */ -ObjectCache * objcache_create(const char *name, - unsigned obj_size, - unsigned align, - obj_init_fn init_func) -{ - ObjectCache *cache; - - /* main cache */ - if (!objcache_cache) { - objcache_cache = malloc(sizeof(ObjectCache)); - if (!objcache_cache) - return NULL; - init_objcache(objcache_cache, "objcache_cache", - sizeof(ObjectCache), 0, NULL); - } - - /* new cache object */ - cache = obj_alloc(objcache_cache); - if (cache) - init_objcache(cache, name, obj_size, align, init_func); - return cache; -} - -/* free all storage associated by cache */ -void objcache_destroy(ObjectCache *cache) -{ - struct List *item, *tmp; - struct Slab *slab; - - statlist_for_each_safe(item, &cache->slablist, tmp) { - slab = container_of(item, struct Slab, head); - free(slab); - } - statlist_remove(&objcache_list, &cache->head); - memset(cache, 0, sizeof(*cache)); - obj_free(objcache_cache, cache); -} - -/* add new block of objects to cache */ -static void grow(ObjectCache *cache) -{ - unsigned count, i, size; - char *area; - struct Slab *slab; - - /* calc new slab size */ - count = cache->total_count; - if (count < 50) - count = 16 * 1024 / cache->final_size; - if (count < 50) - count = 50; - size = count * cache->final_size; - - /* allocate & init */ - slab = malloc(size + sizeof(struct Slab)); - if (!slab) - return; - list_init(&slab->head); - area = (char *)slab + sizeof(struct Slab); - memset(area, 0, size); - - /* init objects */ - for (i = 0; i < count; i++) { - void *obj = area + i * cache->final_size; - struct List *head = (struct List *)obj; - list_init(head); - statlist_append(&cache->freelist, head); - } - - /* register to cache */ - cache->total_count += count; - statlist_append(&cache->slablist, &slab->head); -} - -/* get free object from cache */ -void *obj_alloc(ObjectCache *cache) -{ - struct List *item = statlist_pop(&cache->freelist); - if (!item) { - grow(cache); - item = statlist_pop(&cache->freelist); - } - if (item) { - if (cache->init_func) - cache->init_func(item); - else - memset(item, 0, cache->final_size); - } - return item; -} - -/* put object back to cache */ -void obj_free(ObjectCache *cache, void *obj) -{ - struct List *item = obj; - list_init(item); - statlist_prepend(&cache->freelist, item); -} - -/* total number of objects allocated from cache */ -int objcache_total_count(const ObjectCache *cache) -{ - return cache->total_count; -} - -/* free objects in cache */ -int objcache_free_count(const ObjectCache *cache) -{ - return statlist_count(&cache->freelist); -} - -/* number of objects in use */ -int objcache_active_count(const ObjectCache *cache) -{ - return objcache_total_count(cache) - objcache_free_count(cache); -} - -static void run_slab_stats(ObjectCache *cache, slab_stat_fn fn, void *arg) -{ - unsigned free = statlist_count(&cache->freelist); - fn(arg, cache->name, cache->final_size, free, cache->total_count); -} - -void objcache_stats(slab_stat_fn fn, void *arg) -{ - ObjectCache *cache; - struct List *item; - - statlist_for_each(item, &objcache_list) { - cache = container_of(item, ObjectCache, head); - run_slab_stats(cache, fn, arg); - } -} - diff --git a/src/util.c b/src/util.c index 8f1a0f0..1633456 100644 --- a/src/util.c +++ b/src/util.c @@ -22,7 +22,8 @@ #include "bouncer.h" -#include "md5.h" +#define MD5_COMPAT +#include int log_socket_prefix(enum LogLevel lev, void *ctx, char *dst, unsigned int dstlen) {