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; }
void test_boundary_args() { header(); const int max_update_op_cnt = 4000; printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%d", 0, 1); insert_tuple(tuple); tnt_tuple_free(tuple); printf("# test: try to do update w/o operations\n"); struct tnt_stream *stream = tnt_buf(NULL); update(0, stream); tnt_stream_free(stream); printf("# test: update w/ maximal allowed opearions count\n"); stream = tnt_buf(NULL); for (int i = 0; i < max_update_op_cnt; ++i) tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); update(0, stream); tnt_stream_free(stream); printf("# test: update w/ grater than maximal allowed opearions count\n"); stream = tnt_buf(NULL); for (int i = 0; i < max_update_op_cnt + 1; ++i) tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); update(0, stream); tnt_stream_free(stream); footer(); }
void test_simple_set() { header(); /* insert tuple */ printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%d%d%s", 1, 2, 0, ""); insert_tuple(tuple); tnt_tuple_free(tuple); printf("# test simple set field\n"); struct tnt_stream *stream = tnt_buf(NULL); update_set_str(stream, 1, "new field value"); update_set_str(stream, 2, ""); update_set_str(stream, 3, "fLaC"); update(1, stream); tnt_stream_free(stream); printf("# set field\n"); stream = tnt_buf(NULL); update_set_str(stream, 1, "value?"); update_set_str(stream, 1, "very very very very very long field value?"); update_set_str(stream, 1, "field's new value"); update(1, stream); tnt_stream_free(stream); stream = tnt_buf(NULL); printf("# test set primary key\n"); update_set_i32(stream, 0, 2); update(1, stream); tnt_stream_free(stream); footer(); }
void test_long_set() { header(); printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%s%s%s", 1, "first", "", "third"); insert_tuple(tuple); tnt_tuple_free(tuple); printf("# test set big value in empty field\n"); struct tnt_stream *stream = tnt_buf(NULL); update_set_str(stream, 2, long_string); update(1, stream); tnt_stream_free(stream); printf("# test replace long value to short\n"); stream = tnt_buf(NULL); update_set_str(stream, 2, "short string"); update(1, stream); tnt_stream_free(stream); footer(); }
void test_splice() { header(); printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%s%s%s", 1, "first", "hi, this is a test string!", "third"); insert_tuple(tuple); tnt_tuple_free(tuple); struct tnt_stream *stream = tnt_buf(NULL); printf("# test cut from begin\n"); update_splice_str(stream, 2, 0, 4, ""); update(1, stream); tnt_stream_free(stream); printf("# test cut from middle\n"); stream = tnt_buf(NULL); update_splice_str(stream, 2, 9, -8, ""); update(1, stream); tnt_stream_free(stream); printf("# test cut from end\n"); stream = tnt_buf(NULL); update_splice_str(stream, 2, -1, 1, ""); update(1, stream); tnt_stream_free(stream); printf("# test insert before begin\n"); stream = tnt_buf(NULL); update_splice_str(stream, 2, 0, 0, "Bonjour, "); update(1, stream); tnt_stream_free(stream); printf("# test insert after end\n"); stream = tnt_buf(NULL); update_splice_str(stream, 2, 10000, 0, " o_O!?"); update(1, stream); tnt_stream_free(stream); printf("# test replace in begin\n"); stream = tnt_buf(NULL); update_splice_str(stream, 2, 0, 7, "Hello"); update(1, stream); tnt_stream_free(stream); printf("# test replace in middle\n"); stream = tnt_buf(NULL); update_splice_str(stream, 2, 17, -6, "field"); update(1, stream); tnt_stream_free(stream); printf("# test replace in end\n"); stream = tnt_buf(NULL); update_splice_str(stream, 2, -6, 4, "! Is this Sparta"); update(1, stream); tnt_stream_free(stream); footer(); }
void test_append() { header(); /* insert tuple */ printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%s", 1, "first"); insert_tuple(tuple); tnt_tuple_free(tuple); /* test append field */ struct tnt_stream *stream = tnt_buf(NULL); printf("# test append field\n"); update_set_str(stream, 2, "second"); update(1, stream); tnt_stream_free(stream); /* test multi append field */ stream = tnt_buf(NULL); printf("# test multi append\n"); update_set_str(stream, 3, "3"); update_set_str(stream, 3, "new field value"); update_set_str(stream, 3, "other new field value"); update_set_str(stream, 3, "third"); update(1, stream); tnt_stream_free(stream); /* test append many field */ stream = tnt_buf(NULL); printf("# test append many fields\n"); update_set_str(stream, 4, "fourth"); update_set_str(stream, 5, "fifth"); update_set_str(stream, 6, "sixth"); update_set_str(stream, 7, "seventh"); update_set_str(stream, 8, long_string); update(1, stream); tnt_stream_free(stream); /* test append and change field */ stream = tnt_buf(NULL); printf("# test append and change field\n"); update_set_str(stream, 9, long_string); update_splice_str(stream, 9, 1, 544, "ac"); tnt_update_arith_i32(stream, 9, TNT_UPDATE_XOR, 0x3ffffff); tnt_update_arith_i32(stream, 9, TNT_UPDATE_ADD, 1024); update(1, stream); tnt_stream_free(stream); /* test set to not an exist field */ stream = tnt_buf(NULL); printf("# test set to not an exist field\n"); update_set_str(stream, 0xDEADBEEF, "invalid!"); update(1, stream); tnt_stream_free(stream); footer(); }
/** update fields test case: 64-bit arithmetics operations test */ void test_arith_i64() { header(); printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%ll%ll%ll", 1, 2, 0, 0, 0); insert_tuple(tuple); tnt_tuple_free(tuple); printf("# test add\n"); struct tnt_stream *stream = tnt_buf(NULL); tnt_update_arith_i64(stream, 1, TNT_UPDATE_ADD, 16); update(1, stream); tnt_stream_free(stream); printf("# test overflow add\n"); stream = tnt_buf(NULL); tnt_update_arith_i64(stream, 1, TNT_UPDATE_ADD, INT64_MAX); update(1, stream); tnt_stream_free(stream); printf("# test underflow add\n"); stream = tnt_buf(NULL); tnt_update_arith_i64(stream, 1, TNT_UPDATE_ADD, INT64_MIN); update(1, stream); tnt_stream_free(stream); printf("# test or\n"); stream = tnt_buf(NULL); tnt_update_arith_i64(stream, 2, TNT_UPDATE_OR, 0xbacfbacfbacfbacf); tnt_update_arith_i64(stream, 3, TNT_UPDATE_OR, 0xfabcfabcfabcfabc); update(1, stream); tnt_stream_free(stream); printf("# test xor\n"); stream = tnt_buf(NULL); tnt_update_arith_i64(stream, 2, TNT_UPDATE_XOR, 0xffffffffffffffff); tnt_update_arith_i64(stream, 3, TNT_UPDATE_XOR, 0xffffffffffffffff); update(1, stream); tnt_stream_free(stream); printf("# test and\n"); stream = tnt_buf(NULL); tnt_update_arith_i64(stream, 2, TNT_UPDATE_AND, 0xf0f0f0f0f0f0f0f0); tnt_update_arith_i64(stream, 3, TNT_UPDATE_AND, 0x0f0f0f0f0f0f0f0f); update(1, stream); tnt_stream_free(stream); printf("# test casting 32-bit operand to 64-bit\n"); stream = tnt_buf(NULL); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 16); update(1, stream); tnt_stream_free(stream); footer(); }
void update(int32_t key, struct tnt_stream *stream) { struct tnt_tuple *k = tnt_tuple(NULL, "%d", key); if (tnt_update(tnt, 0, TNT_FLAG_RETURN, k, stream) < 0) fail_tnt_perror("tnt_update"); if (tnt_flush(tnt) < 0) fail_tnt_perror("tnt_flush"); tnt_tuple_free(k); recv_command("update fields"); }
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; }
/* * tnt_request_free() * * free request object; * * r - request object pointer */ void tnt_request_free(struct tnt_request *r) { switch (r->h.type) { case TNT_OP_INSERT: tnt_tuple_free(&r->r.insert.t); break; case TNT_OP_DELETE: tnt_tuple_free(&r->r.del.t); break; case TNT_OP_CALL: if (r->r.call.proc) { tnt_mem_free(r->r.call.proc); r->r.call.proc = NULL; } tnt_tuple_free(&r->r.call.t); break; case TNT_OP_SELECT: tnt_list_free(&r->r.select.l); break; case TNT_OP_UPDATE: 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; } break; case TNT_OP_PING: break; } if (r->v) { tnt_mem_free(r->v); r->v = NULL; } }
void test_multi_arith() { header(); printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%s%d%s", 1, "first", 128, "third"); insert_tuple(tuple); tnt_tuple_free(tuple); printf("# test simple and\n"); struct tnt_stream *stream = tnt_buf(NULL); update_set_i32(stream, 2, 0); update_set_str(stream, 1, "first field new value"); tnt_update_arith_i32(stream, 2, TNT_UPDATE_XOR, 0xF00F); update_set_str(stream, 3, "third field new value"); tnt_update_arith_i32(stream, 2, TNT_UPDATE_OR, 0xF00F); update(1, stream); tnt_stream_free(stream); footer(); }
static int tnt_log_process_snapshot(struct tnt_log *l, char *buf, uint32_t size, union tnt_log_value *value) { (void)size; /* freeing previously allocated tuple */ tnt_tuple_free(&value->t); /* copying snapshot row data */ memcpy(&l->current.row_snap, buf, sizeof(l->current.row_snap)); /* reading and validating tuple */ struct tnt_tuple *tu = tnt_tuple_set_as(&value->t, buf + sizeof(l->current.row_snap), l->current.row_snap.data_size, l->current.row_snap.tuple_size); if (tu == NULL) return tnt_log_seterr(l, TNT_LOG_ECORRUPT); return (tu) ? 0 : -1; }
void test_set_and_splice() { header(); printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%s%s%s", 1, "first", "hi, this is a test string!", "third"); insert_tuple(tuple); tnt_tuple_free(tuple); printf("# test set long string and splice to short\n"); struct tnt_stream *stream = tnt_buf(NULL); update_set_str(stream, 2, long_string); update_splice_str(stream, 2, 45, 500, " away away away"); update(1, stream); tnt_stream_free(stream); printf("# test set short value and splice to long\n"); stream = tnt_buf(NULL); update_set_str(stream, 2, "test"); update_splice_str(stream, 2, -4, 4, long_string); update(1, stream); tnt_stream_free(stream); printf("# test splice to long and set to short\n"); stream = tnt_buf(NULL); update_splice_str(stream, 3, -5, 5, long_string); update_set_str(stream, 2, "short name"); update(1, stream); tnt_stream_free(stream); footer(); }
void test_delete_field() { header(); printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%s%s%s%d%d%d%d%d%d%d%d%d%d", 1, "first", "hi, this is a test string!", "third", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); insert_tuple(tuple); tnt_tuple_free(tuple); printf("# test simple delete fields\n"); struct tnt_stream *stream = tnt_buf(NULL); update_delete_field(stream, 2); update(1, stream); tnt_stream_free(stream); printf("# test useless operations with delete fields\n"); stream = tnt_buf(NULL); update_set_i32(stream, 1, 0); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); update_delete_field(stream, 1); update(1, stream); tnt_stream_free(stream); printf("# test multi delete fields\n"); stream = tnt_buf(NULL); update_delete_field(stream, 2); update_delete_field(stream, 3); update_delete_field(stream, 4); update_delete_field(stream, 5); update_delete_field(stream, 6); update_delete_field(stream, 7); update_delete_field(stream, 8); update_delete_field(stream, 9); update_delete_field(stream, 10); update(1, stream); tnt_stream_free(stream); printf("# test multi delete fields\n"); stream = tnt_buf(NULL); update_delete_field(stream, 1); update_set_i32(stream, 1, 3); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); tnt_update_arith_i32(stream, 1, TNT_UPDATE_ADD, 1); update(1, stream); tnt_stream_free(stream); printf("# test append and delete\n"); stream = tnt_buf(NULL); update_set_str(stream, 3, "second"); update_delete_field(stream, 3); update_set_str(stream, 3, "third"); update_set_str(stream, 4, "third"); update_delete_field(stream, 4); update_set_str(stream, 4, "third"); update_set_str(stream, 4, "fourth"); update_set_str(stream, 5, "fifth"); update_set_str(stream, 6, "sixth"); update_set_str(stream, 7, "seventh"); update_set_str(stream, 8, "eighth"); update_set_str(stream, 9, "ninth"); update_delete_field(stream, 7); update_delete_field(stream, 6); update(1, stream); tnt_stream_free(stream); printf("# test double delete\n"); stream = tnt_buf(NULL); update_delete_field(stream, 3); update_delete_field(stream, 3); update(1, stream); tnt_stream_free(stream); select_tuple(1); printf("# test delete not an exist field\n"); stream = tnt_buf(NULL); update_delete_field(stream, 0xDEADBEEF); update(1, stream); tnt_stream_free(stream); select_tuple(1); footer(); }
static bool tnt_sql_stmt(struct tnt_sql *sql) { struct tnt_tuple tu; struct tnt_list tuples; struct tnt_stream update; tnt_tuple_init(&tu); tnt_list_init(&tuples); tnt_buf(&update); int flags = 0; struct tnt_tk *tk = NULL, *tn = NULL; bool rc = false; switch (tnt_lex(sql->l, &tk)) { /* <INSERT|REPLACE> [INTO] TABLE VALUES ( list ) */ case TNT_TK_INSERT: case TNT_TK_REPLACE: tnt_sqltry(sql, TNT_TK_INTO); if (sql->error) goto error; tnt_expect(tnt_sqltkv(sql, TNT_TK_TABLE, &tn)); tnt_expect(tnt_sqltk(sql, TNT_TK_VALUES)); tnt_expect(tnt_sqltk(sql, '(')); while (1) { tnt_expect(tnt_sql_kv(sql, &tu, false)); if (tnt_sqltry(sql, ',')) continue; if (sql->error) goto error; break; } flags = TNT_FLAG_ADD; if (tk->tk == TNT_TK_REPLACE) flags = TNT_FLAG_REPLACE; tnt_expect(tnt_sqltk(sql, ')')); tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_insert(sql->s, TNT_TK_I32(tn), flags, &tu) == -1) { tnt_sql_error(sql, tk, "insert failed"); goto error; } break; /* UPDATE TABLE SET operations WHERE predicate */ case TNT_TK_UPDATE: if (!tnt_sql_stmt_update(sql, &tu, &update)) goto error; break; /* DELETE FROM TABLE WHERE predicate */ case TNT_TK_DELETE: tnt_expect(tnt_sqltk(sql, TNT_TK_FROM)); tnt_expect(tnt_sqltkv(sql, TNT_TK_TABLE, &tn)); tnt_expect(tnt_sqltk(sql, TNT_TK_WHERE)); /* predicate */ tnt_expect(tnt_sql_kv(sql, &tu, true)); tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_delete(sql->s, TNT_TK_I32(tn), 0, &tu) == -1) { tnt_sql_error(sql, tk, "delete failed"); goto error; } break; /* SELECT * FROM TABLE WHERE predicate OR predicate... LIMIT NUM */ case TNT_TK_SELECT: { tnt_expect(tnt_sqltk(sql, '*')); tnt_expect(tnt_sqltk(sql, TNT_TK_FROM)); tnt_expect(tnt_sqltkv(sql, TNT_TK_TABLE, &tn)); tnt_expect(tnt_sqltk(sql, TNT_TK_WHERE)); int32_t index = -1; while (1) { struct tnt_tuple *tup = tnt_list_at(&tuples, NULL); while (1) { tnt_expect(tnt_sql_kv_select(sql, tup, &index)); if (tnt_sqltry(sql, TNT_TK_AND)) continue; if (sql->error) goto error; break; } if (tnt_sqltry(sql, TNT_TK_OR)) continue; if (sql->error) goto error; break; } uint32_t limit = UINT32_MAX; if (tnt_sqltry(sql, TNT_TK_LIMIT)) { struct tnt_tk *ltk; tnt_expect(tnt_sqltkv(sql, TNT_TK_NUM32, <k)); limit = TNT_TK_I32(ltk); } else if (sql->error) goto error; tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_select(sql->s, TNT_TK_I32(tn), index, 0, limit, &tuples) == -1) { tnt_sql_error(sql, tk, "select failed"); goto error; } break; } /* CALL NAME[{.NAME}+](STRING [{,STRING}+]) */ case TNT_TK_CALL: { char proc[512]; int len = 0; while (1) { struct tnt_tk *name = NULL; tnt_lex_idonly(sql->l, true); tnt_expect(tnt_sqltkv(sql, TNT_TK_ID, &name)); tnt_lex_idonly(sql->l, false); len += snprintf(proc + len, sizeof(proc) - len, "%.*s", (int)TNT_TK_S(name)->size, TNT_TK_S(name)->data); if (!tnt_sqltry(sql, '.')) break; if (sql->error) goto error; len += snprintf(proc + len, sizeof(proc) - len, "%s", "."); } tnt_expect(tnt_sqltk(sql, '(')); if (tnt_sqltry(sql, ')')) goto noargs; if (sql->error) goto error; while (1) { tnt_expect(tnt_sql_kv(sql, &tu, false)); if (tnt_sqltry(sql, ',')) continue; if (sql->error) goto error; break; } tnt_expect(tnt_sqltk(sql, ')')); noargs: tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_call(sql->s, 0, proc, &tu) == -1) { tnt_sql_error(sql, tk, "call failed"); goto error; } break; } /* PING */ case TNT_TK_PING: tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_ping(sql->s) == -1) { tnt_sql_error(sql, tk, "ping failed"); goto error; } break; case TNT_TK_EOF: break; case TNT_TK_ERROR: return tnt_sql_error(sql, tk, "%s", sql->l->error); default: return tnt_sql_error(sql, tk, "insert, replace, update, delete, select, call, ping are expected"); } rc = true; error: tnt_tuple_free(&tu); tnt_list_free(&tuples); tnt_stream_free(&update); return rc; }
void test_insert_field() { header(); printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%s", 9, "eleven"); insert_tuple(tuple); tnt_tuple_free(tuple); printf("# insert new field before primary key\n"); struct tnt_stream *stream = tnt_buf(NULL); update_insert_i32(stream, 0, 7); update_insert_i32(stream, 0, 8); update(9, stream); tnt_stream_free(stream); printf("# insert a new field before last field\n"); stream = tnt_buf(NULL); update_insert_i32(stream, 3, 10); update(7, stream); tnt_stream_free(stream); printf("# double insert at the end\n"); stream = tnt_buf(NULL); update_set_i32(stream, 5, 14); update_insert_i32(stream, 6, 12); update_insert_i32(stream, 5, 13); update(7, stream); tnt_stream_free(stream); printf("# multi insert \n"); stream = tnt_buf(NULL); update_insert_i32(stream, 5, 15); update_insert_i32(stream, 5, 14); update_insert_i32(stream, 5, 13); update_insert_i32(stream, 5, 12); update(7, stream); tnt_stream_free(stream); printf("# insert before next to last field\n"); stream = tnt_buf(NULL); update_insert_i32(stream, 8, 15); update(7, stream); tnt_stream_free(stream); printf("# insert before next to last field\n"); stream = tnt_buf(NULL); update_set_i32(stream, 9, 17); update_insert_i32(stream, 9, 16); update_set_i32(stream, 10, 19); update_insert_i32(stream, 10, 18); update(7, stream); tnt_stream_free(stream); printf("# insert second tuple\n"); tuple = tnt_tuple(NULL, "%d%s%d", 0, "one", 11); insert_tuple(tuple); tnt_tuple_free(tuple); stream = tnt_buf(NULL); printf("# multi insert\n"); update_set_i32(stream, 1, -11); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 1); update_insert_i32(stream, 1, 1); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 2); update_insert_i32(stream, 1, 2); update_insert_i32(stream, 1, 3); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 3); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 4); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 5); update_insert_i32(stream, 1, 4); update_insert_i32(stream, 1, 5); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 6); update_insert_i32(stream, 1, 6); update_insert_i32(stream, 1, 7); update_insert_i32(stream, 1, 8); update_insert_i32(stream, 1, 9); update(0, stream); tnt_stream_free(stream); printf("# insert before invalid field number\n"); stream = tnt_buf(NULL); update_insert_str(stream, 100000, "ooppps!"); update(7, stream); tnt_stream_free(stream); footer(); }
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; }