Exemplo n.º 1
0
static int
tnt_request_insert(struct tnt_request *r, tnt_request_t rcv, void *ptr)
{
	if (rcv(ptr, (char*)&r->r.insert, sizeof(struct tnt_header_insert)) == -1)
		return -1;
	uint32_t size = r->h.len - sizeof(struct tnt_header_insert);
	char *buf = tnt_mem_alloc(size);
	if (buf == NULL)
		return -1;
	if (rcv(ptr, buf, size) == -1) {
		tnt_mem_free(buf);
		return -1;
	}
	if (tnt_tuple_set(&r->r.insert.t, buf, size) == NULL) {
		tnt_mem_free(buf);
		return -1;
	}
	/* creating resend io vector */
	r->vc = 3;
	r->v = tnt_mem_alloc(r->vc * sizeof(struct iovec));
	if (r->v == NULL) {
		tnt_tuple_free(&r->r.insert.t);
		tnt_mem_free(buf);
		return -1;
	}
	r->v[0].iov_base = &r->h;
	r->v[0].iov_len  = sizeof(struct tnt_header);
	r->v[1].iov_base = &r->r.insert.h;
	r->v[1].iov_len  = sizeof(struct tnt_header_insert);
	r->v[2].iov_base = r->r.insert.t.data;
	r->v[2].iov_len  = r->r.insert.t.size;
	tnt_mem_free(buf);
	return 0;
}
Exemplo n.º 2
0
static int
tnt_request_call(struct tnt_request *r, tnt_request_t rcv, void *ptr)
{
	if (rcv(ptr, (char*)&r->r.call, sizeof(struct tnt_header_call)) == -1)
		return -1;
	uint32_t size = r->h.len - sizeof(struct tnt_header_call);
	char *buf = tnt_mem_alloc(size);
	if (buf == NULL)
		goto error;
	if (rcv(ptr, buf, size) == -1)
		goto error;
	int esize = tnt_enc_read(buf, &r->r.call.proc_len);
	if (esize == -1 || esize >= 5)
		goto error;
	memcpy(r->r.call.proc_enc, buf, esize);
	/* function name */
	r->r.call.proc_enc_len = esize;
	r->r.call.proc = tnt_mem_alloc(r->r.call.proc_len + 1);
	if (r->r.call.proc == NULL)
		goto error;
	memcpy(r->r.call.proc, buf + esize, r->r.call.proc_len);
	r->r.call.proc[r->r.call.proc_len] = 0;
	/* function arguments */
	size -= esize + r->r.call.proc_len;
	if (tnt_tuple_set(&r->r.call.t, buf + esize + r->r.call.proc_len, size) == NULL) {
		tnt_mem_free(r->r.call.proc);
		r->r.call.proc = NULL;
		goto error;
	}
	/* creating resend io vector */
	r->vc = 5;
	r->v = tnt_mem_alloc(r->vc * sizeof(struct iovec));
	if (r->v == NULL)
		goto error;
	r->v[0].iov_base = &r->h;
	r->v[0].iov_len  = sizeof(struct tnt_header);
	r->v[1].iov_base = &r->r.call.h;
	r->v[1].iov_len  = sizeof(struct tnt_header_call);
	r->v[2].iov_base = r->r.call.proc_enc;
	r->v[2].iov_len  = r->r.call.proc_enc_len;
	r->v[3].iov_base = r->r.call.proc;
	r->v[3].iov_len  = r->r.call.proc_len;
	r->v[4].iov_base = r->r.call.t.data;
	r->v[4].iov_len  = r->r.call.t.size;
	tnt_mem_free(buf);
	return 0;
error:
	tnt_tuple_free(&r->r.call.t);
	if (buf)
		tnt_mem_free(buf);
	return -1;
}
Exemplo n.º 3
0
/*
 * tnt_rpl()
 *
 * create and initialize replication stream;
 *
 * s - stream pointer, maybe NULL
 * 
 * if stream pointer is NULL, then new stream will be created. 
 *
 * returns stream pointer, or NULL on error.
*/
struct tnt_stream *tnt_rpl(struct tnt_stream *s)
{
	int allocated = s == NULL;
	s = tnt_stream_init(s);
	if (s == NULL)
		return NULL;
	/* allocating stream data */
	s->data = tnt_mem_alloc(sizeof(struct tnt_stream_rpl));
	if (s->data == NULL)
		goto error;
	memset(s->data, 0, sizeof(struct tnt_stream_rpl));
	/* initializing interfaces */
	s->read = NULL;
	s->read_request = tnt_rpl_request;
	s->read_reply = NULL;
	s->read_tuple = NULL;
	s->write = NULL;
	s->writev = NULL;
	s->free = tnt_rpl_free;
	/* initializing internal data */
	struct tnt_stream_rpl *sr = TNT_RPL_CAST(s);
	sr->net = NULL;
	return s;
error:
	if (s->data) {
		tnt_mem_free(s->data);
		s->data = NULL;
	}
	if (allocated)
		tnt_stream_free(s);
	return NULL;
}
Exemplo n.º 4
0
/*
 * tnt_net()
 *
 * create and initialize network stream;
 *
 * s - stream pointer, maybe NULL
 * 
 * if stream pointer is NULL, then new stream will be created. 
 *
 * returns stream pointer, or NULL on error.
*/
struct tnt_stream *tnt_net(struct tnt_stream *s) {
	int allocated = s == NULL;
	s = tnt_net_tryalloc(s);
	if (s == NULL)
		return NULL;
	/* allocating stream data */
	s->data = tnt_mem_alloc(sizeof(struct tnt_stream_net));
	if (s->data == NULL) {
		if (allocated)
			tnt_stream_free(s);
		return NULL;
	}
	memset(s->data, 0, sizeof(struct tnt_stream_net));
	/* initializing interfaces */
	s->read = tnt_net_read;
	s->reply = tnt_net_reply;
	s->write = tnt_net_write;
	s->writev = tnt_net_writev;
	s->free = tnt_net_free;
	/* initializing internal data */
	struct tnt_stream_net *sn = TNT_SNET_CAST(s);
	sn->fd = -1;
	tnt_opt_init(&sn->opt);
	return s;
}
Exemplo n.º 5
0
/*
 * tnt_buf()
 *
 * create and initialize buffer stream;
 *
 * s - stream pointer, maybe NULL
 * 
 * if stream pointer is NULL, then new stream will be created. 
 *
 * returns stream pointer, or NULL on error.
*/
struct tnt_stream *tnt_buf(struct tnt_stream *s) {
	int allocated = s == NULL;
	s = tnt_stream_init(s);
	if (s == NULL)
		return NULL;
	/* allocating stream data */
	s->data = tnt_mem_alloc(sizeof(struct tnt_stream_buf));
	if (s->data == NULL) {
		if (allocated)
			tnt_stream_free(s);
		return NULL;
	}
	/* initializing interfaces */
	s->read = tnt_buf_read;
	s->read_reply = tnt_buf_reply;
	s->read_request = tnt_buf_request;
	s->read_tuple = NULL;
	s->write = tnt_buf_write;
	s->writev = tnt_buf_writev;
	s->write_request = tnt_buf_write_request;
	s->free = tnt_buf_free;
	/* initializing internal data */
	struct tnt_stream_buf *sb = TNT_SBUF_CAST(s);
	sb->rdoff = 0;
	sb->size = 0;
	sb->data = NULL;
	return s;
}
Exemplo n.º 6
0
/*
 * tnt_xlog()
 *
 * create and initialize xlog stream;
 *
 * s - stream pointer, maybe NULL
 * 
 * if stream pointer is NULL, then new stream will be created. 
 *
 * returns stream pointer, or NULL on error.
*/
struct tnt_stream *tnt_xlog(struct tnt_stream *s)
{
	int allocated = s == NULL;
	s = tnt_stream_init(s);
	if (s == NULL)
		return NULL;
	/* allocating stream data */
	s->data = tnt_mem_alloc(sizeof(struct tnt_stream_xlog));
	if (s->data == NULL) {
		if (allocated)
			tnt_stream_free(s);
		return NULL;
	}
	memset(s->data, 0, sizeof(struct tnt_stream_xlog));
	/* initializing interfaces */
	s->read = NULL;
	s->read_request = tnt_xlog_request;
	s->read_reply = NULL;
	s->read_tuple = NULL;
	s->write = NULL;
	s->writev = NULL;
	s->free = tnt_xlog_free;
	/* initializing internal data */
	return s;
}
Exemplo n.º 7
0
/*
 * tnt_update_splice()
 *
 * write update splice operation to buffer stream;
 *
 * s      - stream buffer pointer
 * field  - field number
 * offset - splice offset
 * length - splice length
 * data   - splice operation data
 * value  - splice operation data size
 * 
 * returns number of bytes written, or -1 on error.
*/
ssize_t
tnt_update_splice(struct tnt_stream *s, uint32_t field,
		  uint32_t offset,
		  int32_t length, char *data, size_t size)
{
	/* calculating splice data sizes */
	uint32_t offset_len = tnt_enc_size(sizeof(offset)),
	         length_len = tnt_enc_size(sizeof(length)),
	         data_len   = tnt_enc_size(size);
	uint32_t sz = offset_len + sizeof(offset) +
		      length_len + sizeof(length) + data_len + size;
	/* allocating splice request buffer */
	char *buf = tnt_mem_alloc(sz);
	if (buf == NULL)
		return -1;
	/* filling splice request data */
	char *p = buf;
	tnt_enc_write(p, sizeof(offset));
	p += offset_len;
	memcpy(p, &offset, sizeof(offset));
	p += sizeof(offset);
	tnt_enc_write(p, sizeof(length));
	p += length_len;
	memcpy(p, &length, sizeof(length));
	p += sizeof(length);
	tnt_enc_write(p, size);
	p += data_len;
	memcpy(p, data, size);
	p += size;
	/* writing splice request */
	ssize_t rc = tnt_update_op(s, field, TNT_UPDATE_SPLICE, buf, sz);
	tnt_mem_free(buf);
	return rc;
}
Exemplo n.º 8
0
static struct tnt_iter *tnt_iter_init(struct tnt_iter *i) {
	int alloc = (i == NULL);
	if (alloc) {
		i = tnt_mem_alloc(sizeof(struct tnt_iter));
		if (i == NULL)
			return NULL;
	}
	memset(i, 0, sizeof(struct tnt_iter));
	i->status = TNT_ITER_OK;
	i->alloc = alloc;
	return i;
}
Exemplo n.º 9
0
static struct tnt_stream *tnt_net_tryalloc(struct tnt_stream *s) {
	if (s) {
		memset(s, 0, sizeof(struct tnt_stream));
		return s;
	}
	s = tnt_mem_alloc(sizeof(struct tnt_stream));
	if (s == NULL)
		return NULL;
	memset(s, 0, sizeof(struct tnt_stream));
	s->alloc = 1;
	return s;
}
Exemplo n.º 10
0
/*
 * tnt_select()
 *
 * write select request to stream;
 *
 * s     - stream pointer
 * ns    - space
 * index - request index
 * offset- request offset
 * limit - request limit
 * keys  - list of tuples keys
 * 
 * returns number of bytes written, or -1 on error.
*/
ssize_t
tnt_select(struct tnt_stream *s,
	   uint32_t ns,
	   uint32_t index, uint32_t offset, uint32_t limit,
	   struct tnt_list *keys)
{
	/* calculating tuples sizes */
	size_t size = 0;
	struct tnt_iter i;
	tnt_iter_list(&i, keys);
	while (tnt_next(&i)) {
		struct tnt_tuple *t = TNT_ILIST_TUPLE(&i);
		size += t->size;
	}
	/* filling major header */
	struct tnt_header hdr;
	hdr.type = TNT_OP_SELECT;
	hdr.len = sizeof(struct tnt_header_select) + 4 + size;
	hdr.reqid = s->reqid;
	/* filling select header */
	struct tnt_header_select hdr_sel;
	hdr_sel.ns = ns;
	hdr_sel.index = index;
	hdr_sel.offset = offset;
	hdr_sel.limit = limit;
	/* allocating write vector */
	int vc = 3 + keys->count;
	struct iovec *v = tnt_mem_alloc(sizeof(struct iovec) * vc);
	if (v == NULL) {
		tnt_iter_free(&i);
		return -1;
	}
	/* filling write vector */
	v[0].iov_base = &hdr;
	v[0].iov_len  = sizeof(struct tnt_header);
	v[1].iov_base = &hdr_sel;
	v[1].iov_len  = sizeof(struct tnt_header_select);
	v[2].iov_base = &keys->count;
	v[2].iov_len  = 4;
	int vi = 3;
	tnt_rewind(&i);
	while (tnt_next(&i)) {
		struct tnt_tuple *t = TNT_ILIST_TUPLE(&i);
		v[vi].iov_base = t->data;
		v[vi].iov_len  = t->size;
		vi++;
	}
	tnt_iter_free(&i);
	/* writing data to stream */
	ssize_t rc = s->writev(s, v, vc);
	tnt_mem_free(v);
	return rc;
}
Exemplo n.º 11
0
static int tnt_log_read(struct tnt_log *l, char **buf, uint32_t *size)
{
	/* current record offset (before marker) */
	l->current_offset = ftello(l->fd);

	/* reading marker */
	char *data = NULL;
	uint32_t marker = 0;
	if (fread(&marker, sizeof(marker), 1, l->fd) != 1)
		return tnt_log_eof(l, data);

	/* seeking for marker if necessary */
	while (marker != tnt_log_marker_v11) {
		int c = fgetc(l->fd);
		if (c == EOF)
			return tnt_log_eof(l, data);
		marker = marker >> 8 | ((uint32_t) c & 0xff) <<
			 (sizeof(marker) * 8 - 8);
	}

	/* reading header */
	if (fread(&l->current.hdr, sizeof(l->current.hdr), 1, l->fd) != 1)
		return tnt_log_eof(l, data);

	/* updating offset */
	l->offset = ftello(l->fd);

	/* checking header crc, starting from lsn */
	uint32_t crc32_hdr =
		crc32c(0, (unsigned char*)&l->current.hdr + sizeof(uint32_t),
		       sizeof(struct tnt_log_header_v11) -
		       sizeof(uint32_t));
	if (crc32_hdr != l->current.hdr.crc32_hdr)
		return tnt_log_seterr(l, TNT_LOG_ECORRUPT);

	/* allocating memory and reading data */
	data = tnt_mem_alloc(l->current.hdr.len);
	if (data == NULL)
		return tnt_log_seterr(l, TNT_LOG_EMEMORY);
	if (fread(data, l->current.hdr.len, 1, l->fd) != 1)
		return tnt_log_eof(l, data);

	/* checking data crc */
	uint32_t crc32_data = crc32c(0, (unsigned char*)data, l->current.hdr.len);
	if (crc32_data != l->current.hdr.crc32_data) {
		tnt_mem_free(data);
		return tnt_log_seterr(l, TNT_LOG_ECORRUPT);
	}

	*buf = data;
	*size = l->current.hdr.len;
	return 0;
}
Exemplo n.º 12
0
static struct tnt_iter *tnt_iter_init(struct tnt_iter *i) {
	if (i) {
		memset(i, 0, sizeof(struct tnt_iter));
		return i;
	}
	i = tnt_mem_alloc(sizeof(struct tnt_iter));
	if (i == NULL)
		return NULL;
	memset(i, 0, sizeof(struct tnt_iter));
	i->alloc = 1;
	i->status = TNT_ITER_OK;
	return i;
}
Exemplo n.º 13
0
bool
tnt_utf8_init(struct tnt_utf8 *u, unsigned char *data, size_t size)
{
	u->size = size;
	u->data = (unsigned char*)tnt_mem_alloc(u->size + 1);
	u->data[u->size] = 0;
	memcpy(u->data, data, u->size);
	ssize_t len = tnt_utf8_strlen(u->data, u->size);
	if (len == -1) {
		tnt_mem_free(u->data);
		return false;
	}
	u->len = len;
	return true;
}
Exemplo n.º 14
0
ssize_t
tnt_update_splice(struct tnt_stream *ops, uint32_t fieldno,
		  uint32_t position, uint32_t offset,
		  const char *buffer, size_t buffer_len) {
	size_t buf_size = mp_sizeof_uint(position) +
		          mp_sizeof_uint(offset) +
			  mp_sizeof_str(buffer_len);
	char *buf = tnt_mem_alloc(buf_size), *data = NULL;
	if (!buf) return -1;
	data = buf;
	data = mp_encode_uint(data, position);
	data = mp_encode_uint(data, offset);
	data = mp_encode_str(data, buffer, buffer_len);
	ssize_t retval = tnt_update_op(ops, ':', fieldno, buf, buf_size);
	tnt_mem_free(buf);
	return retval;
}
Exemplo n.º 15
0
int
tnt_iob_init(struct tnt_iob *iob, size_t size,
	     tnt_iob_tx_t tx,
	     tnt_iob_txv_t txv, void *ptr)
{
	iob->tx = tx;
	iob->txv = txv;
	iob->ptr = ptr;
	iob->size = size;
	iob->off = 0;
	iob->top = 0;
	iob->buf = NULL;
	if (size > 0) {
		iob->buf = tnt_mem_alloc(size);
		if (iob->buf == NULL)
			return -1;
		memset(iob->buf, 0, size);
	}
	return 0;
}
Exemplo n.º 16
0
static int
tnt_request_select(struct tnt_request *r, tnt_request_t rcv, void *ptr)
{
	if (rcv(ptr, (char*)&r->r.select, sizeof(struct tnt_header_select)) == -1)
		return -1;
	uint32_t size = r->h.len - sizeof(struct tnt_header_select);
	char *buf = tnt_mem_alloc(size);
	if (buf == NULL)
		goto error;
	if (rcv(ptr, buf, size) == -1)
		goto error;
	/* count of tuples */
	uint32_t i, count = *(uint32_t*)buf;
	uint32_t off = 4;
	/* processing tuples */
	tnt_list_init(&r->r.select.l);
	for (i = 0 ; i < count ; i++) {
		/* calculating tuple size */
		uint32_t j, cardinality = *(uint32_t*)(buf + off);
		uint32_t size = 4;
		for (j = 0 ; j < cardinality ; j++) {
			uint32_t fld_size = 0;
			int fld_esize = tnt_enc_read(buf + off + size, &fld_size);
			if (fld_esize == -1)
				goto error;
			size += fld_esize + fld_size;
		}
		/* initializing tuple and adding to list */
		struct tnt_tuple *tu = tnt_list_at(&r->r.select.l, NULL);
		if (tnt_tuple_set(tu, buf + off, size) == NULL)
			goto error;
		off += size;
	}
	tnt_mem_free(buf);
	return 0;
error:
	tnt_list_free(&r->r.select.l);
	if (buf)
		tnt_mem_free(buf);
	return -1;
}
Exemplo n.º 17
0
int
nb_mc_get_recv(struct tnt_stream *t, char **data, int *data_size)
{
	struct tnt_stream_net *sn = TNT_SNET_CAST(t);
	/* VALUE <key> <flags> <bytes> [<cas unique>]\r\n
	 * <data block>\r\n
	 * ...
	 * END\r\n
	*/
	*data = NULL;
	if (nb_io_expect(t, "VALUE ") == -1)
		return -1;
	/* key */
	int key_len = 0;
	char key[128], ch[1];
	for (;; key_len++) {
		if (key_len > (int)sizeof(key)) {
			sn->error = TNT_EBIG;
			goto error;
		}
		if (nb_io_getc(t, ch) == -1)
			goto error;
		if (ch[0] == ' ') {
			key[key_len] = 0;
			break;
		}
		key[key_len] = ch[0];
	}
	/* flags */
	int flags = 0;
	while (1) {
		if (nb_io_getc(t, ch) == -1)
			goto error;
		if (!isdigit(ch[0])) {
			if (ch[0] == ' ')
				break;
			sn->error = TNT_EFAIL;
			goto error;
		}
		flags *= 10;
		flags += ch[0] - 48;
	}
	/* bytes */
	int value_size = 0;
	while (1) {
		if (nb_io_getc(t, ch) == -1)
			goto error;
		if (!isdigit(ch[0])) {
			if (ch[0] == '\r')
				break;
			sn->error = TNT_EFAIL;
			goto error;
		}
		value_size *= 10;
		value_size += ch[0] - 48;
	}
	/* \n */
	if (nb_io_getc(t, ch) == -1)
		goto error;
	/* data */
	*data_size = value_size;
	*data = tnt_mem_alloc(*data_size);
	if (*data == NULL) {
		sn->error = TNT_EMEMORY;
		goto error;
	}
	if (tnt_io_recv(sn, *data, *data_size) == -1)
		goto error;
	if (nb_io_expect(t, "\r\n") == -1)
		goto error;
	if (nb_io_expect(t, "END\r\n") == -1)
		goto error;
	return 0;
error:
	if (*data)
		tnt_mem_free(*data);
	return -1;
}
Exemplo n.º 18
0
static int
tnt_request_update(struct tnt_request *r, tnt_request_t rcv, void *ptr)
{
	if (rcv(ptr, (char*)&r->r.update, sizeof(struct tnt_header_update)) == -1)
		return -1;
	r->r.update.opc = 0;
	r->r.update.opv = NULL;
	uint32_t size = r->h.len - sizeof(struct tnt_header_update);
	char *buf = tnt_mem_alloc(size);
	if (buf == NULL)
		goto error;
	if (rcv(ptr, buf, size) == -1)
		goto error;
	/* calculating key tuple size */
	uint32_t i, cardinality = *(uint32_t*)(buf);
	uint32_t ks = 4;
	for (i = 0 ; i < cardinality ; i++) {
		uint32_t fld_size = 0;
		int fld_esize = tnt_enc_read(buf + ks, &fld_size);
		if (fld_esize == -1)
			goto error;
		ks += fld_esize + fld_size;
	}
	/* initializing tuple */
	if (tnt_tuple_set(&r->r.update.t, buf, ks) == NULL)
		goto error;
	size -= ks - 4;

	/* ops data */
	r->r.update.opc = *(uint32_t*)(buf + ks);
	uint32_t opvsz = sizeof(struct tnt_request_update_op) * r->r.update.opc;
	r->r.update.opv = tnt_mem_alloc(opvsz);
	if (r->r.update.opv == NULL)
		goto error;
	memset(r->r.update.opv, 0, sizeof(opvsz));

	/* allocating ops buffer */
	r->r.update.ops_size = 0;
	r->r.update.ops = tnt_mem_alloc(size);
	if (r->r.update.ops == NULL)
		goto error;
	memcpy(r->r.update.ops, buf + ks + 4, size);

	/* parsing operations */
	char *p = r->r.update.ops;
	for (i = 0 ; i < r->r.update.opc ; i++) {
		struct tnt_request_update_op *op = &r->r.update.opv[i];
		/* field */
		op->field = *(uint32_t*)(p);
		p += 4;
		/* operation */
		op->op = *(uint8_t*)(p);
		p += 1;
		/* enc_size */
		int esize = tnt_enc_read(p, &op->size);
		if (esize == -1 || esize >= 5)
			goto error;
		op->size_enc_len = esize;
		memcpy(op->size_enc, p, op->size_enc_len);
		p += op->size_enc_len;
		op->data = p;
		p += op->size;
		r->r.update.ops_size += 4 + 1 + op->size_enc_len + op->size;
	}

	/* creating resend io vector */
	r->vc = 5;
	r->v = tnt_mem_alloc(r->vc * sizeof(struct iovec));
	if (r->v == NULL)
		goto error;
	r->v[0].iov_base = &r->h;
	r->v[0].iov_len  = sizeof(struct tnt_header);
	r->v[1].iov_base = &r->r.update.h;
	r->v[1].iov_len  = sizeof(struct tnt_header_update);
	r->v[2].iov_base = r->r.update.t.data;
	r->v[2].iov_len  = r->r.update.t.size;
	r->v[3].iov_base = &r->r.update.opc;
	r->v[3].iov_len  = 4;
	r->v[4].iov_base = r->r.update.ops;
	r->v[4].iov_len  = r->r.update.ops_size;
	tnt_mem_free(buf);
	return 0;
error:
	tnt_tuple_free(&r->r.update.t);
	if (r->r.update.ops) {
		tnt_mem_free(r->r.update.ops);
		r->r.update.ops = NULL;
	}
	if (r->r.update.opv) {
		tnt_mem_free(r->r.update.opv);
		r->r.update.opv = NULL;
	}
	if (buf)
		tnt_mem_free(buf);
	return -1;
}
Exemplo n.º 19
0
/*
 * tnt_reply_from()
 *
 * process iproto reply with supplied recv function;
 *
 * r   - reply object pointer
 * rcv - supplied recv function
 * ptr - recv function argument
 * 
 * returns zero on fully read reply, or -1 on error.
*/
int tnt_reply_from(struct tnt_reply *r, tnt_replyf_t rcv, void *ptr) {
	/* reading iproto header */
	struct tnt_header hdr;
	if (rcv(ptr, (char*)&hdr, sizeof(struct tnt_header)) == -1)
		return -1;
	uint32_t size = hdr.len;

	tnt_list_init(&r->tuples);
	r->count = 0;
	r->error = NULL;
	r->reqid = hdr.reqid;
	r->code = 0;
	r->op = hdr.type;

	/* ping is the simplest case */
	if (r->op == TNT_OP_PING)
		return 0;

	/* checking validity of operation */
	if (r->op != TNT_OP_INSERT &&
	    r->op != TNT_OP_UPDATE &&
	    r->op != TNT_OP_DELETE &&
	    r->op != TNT_OP_SELECT &&
	    r->op != TNT_OP_CALL)
		return -1;

	/* reading code */
	if (rcv(ptr, (char*)&r->code, sizeof(r->code)) == -1)
		return -1;
	size -= 4;

	/* error handling */
	if (r->code != 0) {
		r->error = tnt_mem_alloc(size);
		if (r->error == NULL)
			return -1;
		if (rcv(ptr, r->error, size) == -1) {
			tnt_mem_free(r->error);
			return -1;
		}
		return 0;
	}

	/* code only (BOX_QUIET flag) */
	if (size == 0)
		return 0;

	/* reading count */
	if (rcv(ptr, (char*)&r->count, sizeof(r->count)) == -1)
		return -1;
	size -= 4;

	/* count only */
	if (size == 0)
		return 0;

	/* allocating and reading data */
	char *buf = tnt_mem_alloc(size);
	if (buf == NULL)
		return -1;
	if (rcv(ptr, buf, size) == -1) {
		free(buf);
		return -1;
	}
	char *p = buf;

	/* processing tuples */
	uint32_t total = 0;
	uint32_t i;
	for (i = 0 ; i < r->count ; i++) {
		uint32_t tsize = *(uint32_t*)(p); /* tuple size */
		if (tsize > (size - total))
			goto rollback;
		p += 4;
		/* [count, enc0, data0, ...] */
		struct tnt_tuple *t = tnt_tuple_set(NULL, p, tsize + 4 /* count */);
		if (t == NULL)
			goto rollback;
		tnt_list_at(&r->tuples, t);
		p += tsize + 4;
		total += (4 + 4 + tsize); /* length + cardinality + tuple size */
	}
	free(buf);
	return 0;

rollback:
	tnt_list_free(&r->tuples);
	free(buf);
	return -1;
}