예제 #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;
}
예제 #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;
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
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;
}