PageRenderTime 64ms CodeModel.GetById 49ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/pool.c

http://github.com/nicolasff/webdis
C | 181 lines | 133 code | 40 blank | 8 comment | 28 complexity | a48c0574a82a566a62d3879ea4907f54 MD5 | raw file
  1#include "pool.h"
  2#include "worker.h"
  3#include "conf.h"
  4#include "server.h"
  5
  6#include <stdlib.h>
  7#include <string.h>
  8#include <event.h>
  9#include <hiredis/adapters/libevent.h>
 10
 11static void
 12pool_schedule_reconnect(struct pool* p);
 13
 14struct pool *
 15pool_new(struct worker *w, int count) {
 16
 17	struct pool *p = calloc(1, sizeof(struct pool));
 18
 19	p->count = count;
 20	p->ac = calloc(count, sizeof(redisAsyncContext*));
 21
 22	p->w = w;
 23	p->cfg = w->s->cfg;
 24
 25	return p;
 26}
 27
 28void
 29pool_free_context(redisAsyncContext *ac) {
 30
 31	if (ac)	{
 32		redisAsyncDisconnect(ac);
 33		redisAsyncFree(ac);
 34	}
 35}
 36
 37static void
 38pool_on_connect(const redisAsyncContext *ac, int status) {
 39	struct pool *p = ac->data;
 40	int i = 0;
 41
 42	if(!p || status == REDIS_ERR || ac->err) {
 43		if (p) {
 44			pool_schedule_reconnect(p);
 45		}
 46		return;
 47	}
 48	/* connected to redis! */
 49
 50	/* add to pool */
 51	for(i = 0; i < p->count; ++i) {
 52		if(p->ac[i] == NULL) {
 53			p->ac[i] = ac;
 54			return;
 55		}
 56	}
 57}
 58
 59struct pool_reconnect {
 60	struct event ev;
 61	struct pool *p;
 62
 63	struct timeval tv;
 64};
 65
 66static void
 67pool_can_connect(int fd, short event, void *ptr) {
 68	struct pool_reconnect *pr = ptr;
 69	struct pool *p = pr->p;
 70
 71	(void)fd;
 72	(void)event;
 73
 74	free(pr);
 75
 76	pool_connect(p, p->cfg->database, 1);
 77}
 78static void
 79pool_schedule_reconnect(struct pool *p) {
 80
 81	struct pool_reconnect *pr = malloc(sizeof(struct pool_reconnect));
 82	pr->p = p;
 83
 84	pr->tv.tv_sec = 0;
 85	pr->tv.tv_usec = 100*1000; /* 0.1 sec*/
 86
 87	evtimer_set(&pr->ev, pool_can_connect, pr);
 88	event_base_set(p->w->base, &pr->ev);
 89	evtimer_add(&pr->ev, &pr->tv);
 90}
 91
 92
 93
 94static void
 95pool_on_disconnect(const redisAsyncContext *ac, int status) {
 96
 97	struct pool *p = ac->data;
 98	int i = 0;
 99	if (status != REDIS_OK) {
100		/* fprintf(stderr, "Error: %s\n", ac->errstr); */
101	}
102
103	if(p == NULL) { /* no need to clean anything here. */
104		return;
105	}
106
107	/* remove from the pool */
108	for(i = 0; i < p->count; ++i) {
109		if(p->ac[i] == ac) {
110			p->ac[i] = NULL;
111			break;
112		}
113	}
114
115	/* schedule reconnect */
116	pool_schedule_reconnect(p);
117}
118
119/**
120 * Create new connection.
121 */
122redisAsyncContext *
123pool_connect(struct pool *p, int db_num, int attach) {
124
125	struct redisAsyncContext *ac;
126	if(p->cfg->redis_host[0] == '/') { /* unix socket */
127		ac = redisAsyncConnectUnix(p->cfg->redis_host);
128	} else {
129		ac = redisAsyncConnect(p->cfg->redis_host, p->cfg->redis_port);
130	}
131
132	if(attach) {
133		ac->data = p;
134	} else {
135		ac->data = NULL;
136	}
137
138	if(ac->err) {
139		char msg[] = "Connection failed: %s";
140		size_t errlen = strlen(ac->errstr);
141		char *err = malloc(sizeof(msg) + errlen);
142		if (err) {
143			size_t sz = sprintf(err, msg, ac->errstr);
144			slog(p->w->s, WEBDIS_ERROR, err, sz);
145			free(err);
146		}
147		redisAsyncFree(ac);
148		pool_schedule_reconnect(p);
149		return NULL;
150	}
151
152	redisLibeventAttach(ac, p->w->base);
153	redisAsyncSetConnectCallback(ac, pool_on_connect);
154	redisAsyncSetDisconnectCallback(ac, pool_on_disconnect);
155
156	if(p->cfg->redis_auth) { /* authenticate. */
157		redisAsyncCommand(ac, NULL, NULL, "AUTH %s", p->cfg->redis_auth);
158	}
159	if(db_num) { /* change database. */
160		redisAsyncCommand(ac, NULL, NULL, "SELECT %d", db_num);
161	}
162	return ac;
163}
164
165const redisAsyncContext *
166pool_get_context(struct pool *p) {
167
168	int orig = p->cur++;
169
170	do {
171		p->cur++;
172		p->cur %= p->count;
173		if(p->ac[p->cur] != NULL) {
174			return p->ac[p->cur];
175		}
176	} while(p->cur != orig);
177
178	return NULL;
179
180}
181