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; }
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; }
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; }
/* * 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; }
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; }