Beispiel #1
0
static void li_memcached_con_free(liMemcachedCon* con) {
	if (!con) return;

	if (-1 != con->con_watcher.fd) {
		close(con->con_watcher.fd);
		/* as io has a reference on con, we don't need to stop it here */
		ev_io_set(&con->con_watcher, -1, 0);
		con->fd = -1;
	}

	send_queue_reset(&con->out);
	cancel_all_requests(con);

	li_buffer_release(con->buf);
	li_buffer_release(con->line);
	li_buffer_release(con->remaining);
	li_buffer_release(con->data);
	reset_item(&con->curitem);

	li_sockaddr_clear(&con->addr);
	g_string_free(con->tmpstr, TRUE);

	g_clear_error(&con->err);

	g_slice_free(liMemcachedCon, con);
}
Beispiel #2
0
static void li_memcached_con_free(liMemcachedCon* con) {
	if (!con) return;

	if (-1 != li_event_io_fd(&con->con_watcher)) {
		close(li_event_io_fd(&con->con_watcher));
		li_event_clear(&con->con_watcher);
		con->fd = -1;
	}

	send_queue_reset(&con->out);
	cancel_all_requests(con);

	li_buffer_release(con->buf);
	li_buffer_release(con->line);
	li_buffer_release(con->remaining);
	li_buffer_release(con->data);
	reset_item(&con->curitem);

	li_sockaddr_clear(&con->addr);
	g_string_free(con->tmpstr, TRUE);

	g_clear_error(&con->err);

	g_slice_free(liMemcachedCon, con);
}
Beispiel #3
0
void pop_tick(void)
{
	static int last_reset = 0;
	int nr;

	if (globs->ticker - last_reset>=RESETTICKER)      // reset one character per minute
	{
		nr = (globs->ticker / RESETTICKER) % MAXTCHARS;
		if (nr>0 && nr<MAXTCHARS)               // yes, we're paranoid :)
		{
			reset_char(nr);
		}
		last_reset = globs->ticker;
	}

	if (globs->reset_char)
	{
		reset_char(globs->reset_char);
		globs->reset_char = 0;
	}
	if (globs->reset_item)
	{
		reset_item(globs->reset_item);
		globs->reset_item = 0;
	}
}
Beispiel #4
0
void reset_changed_items(void)
{
	static int changelist[] = {};
	int n;

	for (n = 0; n<sizeof(changelist) / sizeof(int); n++)
	{
		reset_item(changelist[n]);
	}
}
Beispiel #5
0
static void close_con(liMemcachedCon *con) {
	if (con->line) con->line->used = 0;
	if (con->remaining) con->remaining->used = 0;
	if (con->data) con->data->used = 0;
	if (con->buf) con->buf->used = 0;
	reset_item(&con->curitem);
	send_queue_reset(&con->out);

	memcached_stop_io(con);
	close(li_event_io_fd(&con->con_watcher));
	con->fd = -1;
	li_event_io_set_fd(&con->con_watcher, -1);
	con->cur_req = NULL;
	cancel_all_requests(con);
	memcached_connect(con);
}
Beispiel #6
0
void pop_reset_all(void)
{
	int n;

	for (n = 1; n<MAXTCHARS; n++)
	{
		if (ch_temp[n].used!=USE_EMPTY)
		{
			reset_char(n);
		}
	}
	for (n = 1; n<MAXTITEM; n++)
	{
		if (it_temp[n].used!=USE_EMPTY && it_temp[n].driver!=36 && it_temp[n].driver!=38)
		{
			reset_item(n);
		}
	}
}
Beispiel #7
0
static void handle_read(liMemcachedCon *con) {
	int_request *cur;

	if (NULL == (cur = con->cur_req)) {
		cur = con->cur_req = g_queue_peek_head(&con->req_queue);

		if (NULL == cur) {
			/* unexpected read event, perhaps just eof */
			g_clear_error(&con->err);
			g_set_error(&con->err, LI_MEMCACHED_ERROR, LI_MEMCACHED_CONNECTION, "Connection closed: unexpected read event");
			close_con(con);
			return;
		}

		reset_item(&con->curitem);
		if (con->data) con->data->used = 0;
		if (con->line) con->line->used = 0;

		/* init read state */
		switch (cur->type) {
		case REQ_GET:
			con->get_data_size = 0;
			con->get_have_header = FALSE;
			break;
		case REQ_SET:
			break;
		}
	}

	switch (cur->type) {
	case REQ_GET:
		if (!con->get_have_header) {
			char *pos, *next;

			/* wait for header line */
			if (!try_read_line(con)) return;

			con->get_have_header = TRUE;

			if (3 == con->line->used && 0 == memcmp("END", con->line->addr, 3)) {
				/* key not found */
				if (cur->req.callback) {
					cur->req.callback(&cur->req, LI_MEMCACHED_NOT_FOUND, NULL, NULL);
				}
				con->cur_req = NULL;
				free_request(con, cur);
				return;
			}

			/* con->line is 0 terminated */

			if (0 != strncmp("VALUE ", con->line->addr, 6)) {
				g_clear_error(&con->err);
				g_set_error(&con->err, LI_MEMCACHED_ERROR, LI_MEMCACHED_CONNECTION, "Protocol error: Unexpected response for GET: '%s'", con->line->addr);
				close_con(con);
				return;
			}

			/* VALUE <key> <flags> <bytes> [<cas unique>]\r\n */

			/* <key> */
			pos = con->line->addr + 6;
			next = strchr(pos, ' ');
			if (NULL == next) goto req_get_header_error;

			con->curitem.key = g_string_new_len(pos, next - pos);

			/* <flags> */
			pos = next + 1;
			con->curitem.flags = strtoul(pos, &next, 10);
			if (' ' != *next || pos == next) goto req_get_header_error;

			/* <bytes> */
			pos = next + 1;
			con->get_data_size = g_ascii_strtoll(pos, &next, 10);
			if (pos == next) goto req_get_header_error;

			/* [<cas unique>] */
			if (' ' == *next) {
				pos = next + 1;
				con->curitem.cas = g_ascii_strtoll(pos, &next, 10);
				if (pos == next) goto req_get_header_error;
			}

			if ('\0' != *next) {
				goto req_get_header_error;
			}

			con->line->used = 0;

			goto req_get_header_done;

req_get_header_error:
			g_clear_error(&con->err);
			g_set_error(&con->err, LI_MEMCACHED_ERROR, LI_MEMCACHED_CONNECTION, "Protocol error: Couldn't parse VALUE respone: '%s'", con->line->addr);
			close_con(con);
			return;

req_get_header_done: ;
		}
		if (NULL == con->data || con->data->used < con->get_data_size) {
			/* wait for data */
			if (!try_read_data(con, con->get_data_size)) return;
		}
		/* wait for END\r\n */
		if (!try_read_line(con)) return;

		if (3 == con->line->used && 0 == memcmp("END", con->line->addr, 3)) {
			/* Move data to item */
			con->curitem.data = con->data;
			con->data = NULL;
			if (cur->req.callback) {
				cur->req.callback(&cur->req, LI_MEMCACHED_OK, &con->curitem, NULL);
			}
			reset_item(&con->curitem);
		} else {
			g_clear_error(&con->err);
			g_set_error(&con->err, LI_MEMCACHED_ERROR, LI_MEMCACHED_CONNECTION, "Protocol error: GET response not terminated with END (got '%s')", con->line->addr);
			close_con(con);
			return;
		}

		con->cur_req = NULL;
		free_request(con, cur);
		return;

	case REQ_SET:
		if (!try_read_line(con)) return;

		if (6 == con->line->used && 0 == memcmp("STORED", con->line->addr, 6)) {
			if (cur->req.callback) {
				cur->req.callback(&cur->req, LI_MEMCACHED_OK, NULL, NULL);
			}
		} else {
			g_clear_error(&con->err);
			g_set_error(&con->err, LI_MEMCACHED_ERROR, LI_MEMCACHED_CONNECTION, "Protocol error: unepxected SET response: '%s'", con->line->addr);
			close_con(con);
			return;
		}

		con->cur_req = NULL;
		free_request(con, cur);
		return;
	}
}