From 19aed0634ce249e9c521698b4f1cd88b4064c825 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Tue, 27 Aug 2024 09:44:29 -0400 Subject: [PATCH 01/21] make LOCAL work for single node clusters --- db/fdb_fend.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index be7788f820..49571dfddf 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -3699,7 +3699,11 @@ const char *fdb_dbname_name(fdb_t *fdb) { return fdb->dbname; } const char *fdb_dbname_class_routing(fdb_t *fdb) { if (fdb->local) + /* return "LOCAL"; + */ + /* need to match tier setting from disttxn.c */ + return gbl_machine_class ? gbl_machine_class : gbl_myhostname; return mach_class_class2name(fdb->class); } const char *fdb_table_entry_tblname(fdb_tbl_ent_t *ent) From 5c6a4c3503d69662eaa86ca97328f79bb88be21d Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Tue, 3 Sep 2024 13:50:01 -0400 Subject: [PATCH 02/21] detect case, start refactoring push --- db/db_tunables.c | 1 + db/db_tunables.h | 1 + db/dohast.c | 62 +++++-- db/fdb_comm.h | 1 + db/fdb_fend.c | 275 +++++++++++++++++++++----------- db/fdb_fend.h | 33 ++-- db/fdb_push.c | 20 ++- db/osqlsqlthr.c | 1 + db/process_message.c | 1 + db/sql.h | 36 ++++- db/sqlexplain.c | 1 + db/sqlglue.c | 26 +-- db/sqlinterfaces.c | 16 +- db/sqloffload.c | 1 + db/tag.c | 1 + db/typessql.c | 1 + db/views.c | 6 +- lua/sp.c | 2 + plugins/remsql/fdb_comm.c | 9 +- sqlite/ext/comdb2/functions.c | 1 + sqlite/ext/comdb2/logicalops.c | 1 + sqlite/ext/comdb2/permissions.c | 1 + sqlite/src/build.c | 5 + sqlite/src/insert.c | 9 +- 24 files changed, 343 insertions(+), 168 deletions(-) diff --git a/db/db_tunables.c b/db/db_tunables.c index 6285753bc3..a18e216fc1 100644 --- a/db/db_tunables.c +++ b/db/db_tunables.c @@ -102,6 +102,7 @@ extern int gbl_fdb_allow_cross_classes; extern int gbl_fdb_resolve_local; extern int gbl_fdb_push_redirect_foreign; extern int gbl_fdb_push_remote; +extern int gbl_fdb_push_remote_write; extern int gbl_fdb_remsql_cdb2api; extern int gbl_goslow; extern int gbl_heartbeat_send; diff --git a/db/db_tunables.h b/db/db_tunables.h index 5c889942bd..c59dd124d1 100644 --- a/db/db_tunables.h +++ b/db/db_tunables.h @@ -551,6 +551,7 @@ REGISTER_TUNABLE("foreign_db_allow_cross_class", NULL, TUNABLE_BOOLEAN, &gbl_fdb REGISTER_TUNABLE("foreign_db_resolve_local", NULL, TUNABLE_BOOLEAN, &gbl_fdb_resolve_local, READONLY | NOARG | READEARLY, NULL, NULL, NULL, NULL); REGISTER_TUNABLE("foreign_db_push_remote", NULL, TUNABLE_BOOLEAN, &gbl_fdb_push_remote, NOARG, NULL, NULL, NULL, NULL); +REGISTER_TUNABLE("foreign_db_push_remote_write", NULL, TUNABLE_BOOLEAN, &gbl_fdb_push_remote_write, NOARG, NULL, NULL, NULL, NULL); REGISTER_TUNABLE("foreign_db_push_redirect", "Redirect fdb query to run via client instead of on server. (Default: off)", TUNABLE_BOOLEAN, &gbl_fdb_push_redirect_foreign, NOARG, NULL, NULL, NULL, NULL); diff --git a/db/dohast.c b/db/dohast.c index 64c9bc0fd3..001f25735b 100644 --- a/db/dohast.c +++ b/db/dohast.c @@ -20,6 +20,7 @@ #include "ast.h" #include "dohsql.h" #include "sql.h" +#include "fdb_fend.h" int gbl_dohast_disable = 0; int gbl_dohast_verbose = 0; @@ -947,36 +948,71 @@ int comdb2_check_parallel(Parse *pParse) return 0; } -int comdb2_check_push_remote(Parse *pParse) +ast_node_t *_get_ast_node(Parse *pParse) { if (comdb2IsPrepareOnly(pParse)) - return 0; + return NULL; + + if (pParse->explain) + return NULL; ast_t *ast = pParse->ast; - dohsql_node_t *node; + if (ast && ast->unsupported) + return NULL; + if (!ast->stack[0].obj) + return NULL; + + return ast->stack; +} + +int comdb2_check_push_remote(Parse *pParse) +{ GET_CLNT; if (!gbl_fdb_push_remote && !clnt->force_fdb_push_remote && !clnt->force_fdb_push_redirect) return 0; - if (ast && ast->unsupported) - return 0; if (has_parallel_sql(NULL) == 0) return 0; - if (ast->nused > 1) + + ast_node_t * anode = _get_ast_node(pParse); + if (!anode) return 0; - if (!ast->stack[0].obj) + + if (anode->op != AST_TYPE_SELECT) return 0; - node = (dohsql_node_t *)ast->stack[0].obj; + if (pParse->ast->nused > 1) + return 0; + + dohsql_node_t *node = (dohsql_node_t*)anode->obj; + + if (node->remotedb > 1) + if (!fdb_push_setup(pParse, node)) + return 1; + + return 0; +} - if (node->type != AST_TYPE_SELECT) +int comdb2_check_push_remote_write(Parse *pParse) +{ + if (!gbl_fdb_push_remote_write) return 0; - if (!pParse->explain) - if (node->remotedb > 1) - if (!fdb_push_run(pParse, node)) - return 1; + ast_node_t *anode = _get_ast_node(pParse); + if (!anode) + return 0; + + if (anode->op != AST_TYPE_INSERT) + return 0; + + Table *pTab = (Table*)anode->obj; + if (!pTab) + return 0; + + if (pTab->iDb > 1) + if (!fdb_push_write_setup(pParse, pTab)) + return 1; return 0; } diff --git a/db/fdb_comm.h b/db/fdb_comm.h index 15bfad2fd1..69521f5643 100644 --- a/db/fdb_comm.h +++ b/db/fdb_comm.h @@ -20,6 +20,7 @@ #include #include "comdb2.h" #include "sql.h" +#include "fdb_fend.h" enum { /* all previous versions 0-4 are legacy and reserved */ diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 49571dfddf..475f3cb34a 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -58,6 +58,7 @@ #include "ssl_bend.h" #include "comdb2_query_preparer.h" #include "alias.h" +#include "dohsql.h" extern int gbl_fdb_resolve_local; extern int gbl_fdb_allow_cross_classes; @@ -68,7 +69,8 @@ int gbl_fdb_default_ver = FDB_VER; int gbl_fdb_track = 0; int gbl_fdb_track_times = 0; int gbl_test_io_errors = 0; -int gbl_fdb_push_remote = 0; +int gbl_fdb_push_remote = 1; +int gbl_fdb_push_remote_write = 1; int gbl_fdb_push_redirect_foreign = 0; int gbl_fdb_incoherence_percentage = 0; int gbl_fdb_io_error_retries = 16; @@ -277,12 +279,12 @@ static int fdb_cursor_find_sql_cdb2api(BtCursor *pCur, Mem *key, int nfields, int bias); /* REMSQL WRITE frontend */ -static int fdb_cursor_insert(BtCursor *pCur, struct sqlclntstate *clnt, +static int fdb_cursor_insert(BtCursor *pCur, sqlclntstate *clnt, fdb_tran_t *trans, unsigned long long genid, int datalen, char *data); -static int fdb_cursor_delete(BtCursor *pCur, struct sqlclntstate *clnt, +static int fdb_cursor_delete(BtCursor *pCur, sqlclntstate *clnt, fdb_tran_t *trans, unsigned long long genid); -static int fdb_cursor_update(BtCursor *pCur, struct sqlclntstate *clnt, +static int fdb_cursor_update(BtCursor *pCur, sqlclntstate *clnt, fdb_tran_t *trans, unsigned long long oldgenid, unsigned long long genid, int datalen, char *data); @@ -299,13 +301,13 @@ static int __lock_wrlock_exclusive(char *dbname); which case it will move to another one; error will not impact other concurrent clnt-s */ -static char *_fdb_get_affinity_node(struct sqlclntstate *clnt, const fdb_t *fdb, +static char *_fdb_get_affinity_node(sqlclntstate *clnt, const fdb_t *fdb, int *was_bad); -static int _fdb_set_affinity_node(struct sqlclntstate *clnt, const fdb_t *fdb, +static int _fdb_set_affinity_node(sqlclntstate *clnt, const fdb_t *fdb, char *host, int status); -void _fdb_clear_clnt_node_affinities(struct sqlclntstate *clnt); +void _fdb_clear_clnt_node_affinities(sqlclntstate *clnt); -static int _get_protocol_flags(struct sqlclntstate *clnt, fdb_t *fdb, +static int _get_protocol_flags(sqlclntstate *clnt, fdb_t *fdb, int *flags); static int _validate_existing_table(fdb_t *fdb, int cls, int local); @@ -970,7 +972,7 @@ static int check_table_fdb(fdb_t *fdb, fdb_tbl_t *tbl, int initial, init_cursor(cur, NULL, (Btree *)(cur + 1)); cur->bt->fdb = fdb; cur->bt->is_remote = 1; - struct sqlclntstate *clnt = cur->clnt; + sqlclntstate *clnt = cur->clnt; cur->rootpage = 1; run: @@ -1284,7 +1286,7 @@ static int _failed_AddAndLockTable(const char *dbname, int errcode, const char *prefix) { struct sql_thread *thd = pthread_getspecific(query_info_key); - struct sqlclntstate *clnt = thd->clnt; + sqlclntstate *clnt = thd->clnt; logmsg(LOGMSG_WARN, "Error rc %d \"%s\" for db \"%s\"\n", errcode, prefix, dbname); @@ -2171,7 +2173,7 @@ static char *fdb_generate_dist_txnid() * 5) If still don't have a connection, return error, otherwise return FDB_NOERR * */ -static int _fdb_send_open_retries(struct sqlclntstate *clnt, fdb_t *fdb, +static int _fdb_send_open_retries(sqlclntstate *clnt, fdb_t *fdb, fdb_cursor_t *fdbc, int source_rootpage, fdb_tran_t *trans, int flags, int version, fdb_msg_t *msg, int use_ssl) @@ -2247,7 +2249,7 @@ static int _fdb_send_open_retries(struct sqlclntstate *clnt, fdb_t *fdb, if (fdbc) { psb = &fdbc->fcon.sock.sb; } else { - psb = &trans->sb; + psb = &trans->fcon.sb; } if ((rc = _fdb_remote_reconnect(fdb, psb, host, (fdbc)?1:0)) == FDB_NOERR) { @@ -2279,9 +2281,9 @@ static int _fdb_send_open_retries(struct sqlclntstate *clnt, fdb_t *fdb, char *coordinator_tier = gbl_machine_class ? strdup(gbl_machine_class) : strdup(gbl_myhostname); char *dist_txnid = strdup(clnt->dist_txnid); rc = fdb_send_2pc_begin(clnt, msg, trans, clnt->dbtran.mode, tran_flags, dist_txnid, - coordinator_dbname, coordinator_tier, clnt->dist_timestamp, trans->sb); + coordinator_dbname, coordinator_tier, clnt->dist_timestamp, trans->fcon.sb); } else { - rc = fdb_send_begin(clnt, msg, trans, clnt->dbtran.mode, tran_flags, trans->sb); + rc = fdb_send_begin(clnt, msg, trans, clnt->dbtran.mode, tran_flags, trans->fcon.sb); } if (rc == FDB_NOERR) { trans->host = host; @@ -2424,7 +2426,7 @@ static void _cursor_set_common(fdb_cursor_if_t *fdbc_if, char *tid, int flags, fdbc->intf = fdbc_if; } -static fdb_cursor_if_t *_cursor_open_remote_cdb2api(struct sqlclntstate *clnt, +static fdb_cursor_if_t *_cursor_open_remote_cdb2api(sqlclntstate *clnt, fdb_t *fdb, int server_version, int flags, int version, int rootpage, int use_ssl) @@ -2504,7 +2506,7 @@ static fdb_cursor_if_t *_cursor_open_remote_cdb2api(struct sqlclntstate *clnt, goto done; } -static fdb_cursor_if_t *_cursor_open_remote(struct sqlclntstate *clnt, +static fdb_cursor_if_t *_cursor_open_remote(sqlclntstate *clnt, fdb_t *fdb, int server_version, fdb_tran_t *trans, int flags, int version, int rootpage, @@ -2583,7 +2585,7 @@ static fdb_cursor_if_t *_cursor_open_remote(struct sqlclntstate *clnt, return fdbc_if; } -static fdb_cursor_if_t *_fdb_cursor_open_remote(struct sqlclntstate *clnt, +static fdb_cursor_if_t *_fdb_cursor_open_remote(sqlclntstate *clnt, fdb_t *fdb, fdb_tran_t *trans, int flags, int version, int rootpage, int use_ssl) @@ -2615,7 +2617,7 @@ static fdb_cursor_if_t *_fdb_cursor_open_remote(struct sqlclntstate *clnt, * NOTE: populates clnt->fdb_state error fields, if any error * */ -fdb_cursor_if_t *fdb_cursor_open(struct sqlclntstate *clnt, BtCursor *pCur, +fdb_cursor_if_t *fdb_cursor_open(sqlclntstate *clnt, BtCursor *pCur, int rootpage, fdb_tran_t *trans, int *ixnum, int use_ssl) { @@ -3048,7 +3050,7 @@ static void *fdb_cursor_get_hint(BtCursor *pCur) static int fdb_cursor_reopen(BtCursor *pCur) { struct sql_thread *thd; - struct sqlclntstate *clnt; + sqlclntstate *clnt; int rc; fdb_tran_t *tran; int need_ssl = 0; @@ -3521,7 +3523,7 @@ fdb_sqlstat_cache_t *fdb_sqlstats_get(fdb_t *fdb) { int rc = 0; struct sql_thread *thd; - struct sqlclntstate *clnt; + sqlclntstate *clnt; int interval = bdb_attr_get(thedb->bdb_attr, BDB_ATTR_FDB_SQLSTATS_CACHE_LOCK_WAITTIME_NSEC); if (!interval) @@ -3735,7 +3737,7 @@ static inline char *_get_tblname(fdb_cursor_t *fdbc) : NULL; } -static int fdb_cursor_insert(BtCursor *pCur, struct sqlclntstate *clnt, +static int fdb_cursor_insert(BtCursor *pCur, sqlclntstate *clnt, fdb_tran_t *trans, unsigned long long genid, int datalen, char *data) { @@ -3765,7 +3767,7 @@ static int fdb_cursor_insert(BtCursor *pCur, struct sqlclntstate *clnt, fdbc->ent->source_rootpage, genid, 0, ixnum, *((int *)clnt->idxInsert[ixnum]), (char *)clnt->idxInsert[ixnum] + sizeof(int), - trans->seq, trans->sb); + trans->seq, trans->fcon.sb); if (rc) return rc; } @@ -3777,7 +3779,7 @@ static int fdb_cursor_insert(BtCursor *pCur, struct sqlclntstate *clnt, (gbl_partial_indexes && pCur->fdbc->tbl_has_partidx(pCur)) ? clnt->ins_keys : -1ULL, - datalen, data, trans->seq, trans->sb); + datalen, data, trans->seq, trans->fcon.sb); trans->seq++; trans->nwrites++; @@ -3785,7 +3787,7 @@ static int fdb_cursor_insert(BtCursor *pCur, struct sqlclntstate *clnt, return rc; } -static int fdb_cursor_delete(BtCursor *pCur, struct sqlclntstate *clnt, +static int fdb_cursor_delete(BtCursor *pCur, sqlclntstate *clnt, fdb_tran_t *trans, unsigned long long genid) { fdb_cursor_t *fdbc = pCur->fdbc->impl; @@ -3814,7 +3816,7 @@ static int fdb_cursor_delete(BtCursor *pCur, struct sqlclntstate *clnt, fdbc->ent->source_rootpage, genid, 1, ixnum, *((int *)clnt->idxDelete[ixnum]), (char *)clnt->idxDelete[ixnum] + sizeof(int), - trans->seq, trans->sb); + trans->seq, trans->fcon.sb); if (rc) return rc; } @@ -3826,7 +3828,7 @@ static int fdb_cursor_delete(BtCursor *pCur, struct sqlclntstate *clnt, (gbl_partial_indexes && pCur->fdbc->tbl_has_partidx(pCur)) ? clnt->del_keys : -1ULL, - trans->seq, trans->sb); + trans->seq, trans->fcon.sb); trans->seq++; trans->nwrites++; @@ -3840,7 +3842,7 @@ static int fdb_cursor_delete(BtCursor *pCur, struct sqlclntstate *clnt, return rc; } -static int fdb_cursor_update(BtCursor *pCur, struct sqlclntstate *clnt, +static int fdb_cursor_update(BtCursor *pCur, sqlclntstate *clnt, fdb_tran_t *trans, unsigned long long oldgenid, unsigned long long genid, int datalen, char *data) { @@ -3869,7 +3871,7 @@ static int fdb_cursor_update(BtCursor *pCur, struct sqlclntstate *clnt, fdbc->ent->source_rootpage, oldgenid, 1, ixnum, *((int *)clnt->idxDelete[ixnum]), (char *)clnt->idxDelete[ixnum] + sizeof(int), - trans->seq, trans->sb); + trans->seq, trans->fcon.sb); if (rc) return rc; @@ -3881,7 +3883,7 @@ static int fdb_cursor_update(BtCursor *pCur, struct sqlclntstate *clnt, fdbc->ent->source_rootpage, genid, 0, ixnum, *((int *)clnt->idxInsert[ixnum]), (char *)clnt->idxInsert[ixnum] + sizeof(int), - trans->seq, trans->sb); + trans->seq, trans->fcon.sb); if (rc) return rc; } @@ -3896,7 +3898,7 @@ static int fdb_cursor_update(BtCursor *pCur, struct sqlclntstate *clnt, (gbl_partial_indexes && pCur->fdbc->tbl_has_partidx(pCur)) ? clnt->del_keys : -1ULL, - datalen, data, trans->seq, trans->sb); + datalen, data, trans->seq, trans->fcon.sb); trans->seq++; trans->nwrites++; @@ -3910,7 +3912,7 @@ static int fdb_cursor_update(BtCursor *pCur, struct sqlclntstate *clnt, return rc; } -static fdb_distributed_tran_t *fdb_trans_create_dtran(struct sqlclntstate *clnt) +static fdb_distributed_tran_t *fdb_trans_create_dtran(sqlclntstate *clnt) { fdb_distributed_tran_t *dtran = clnt->dbtran.dtran; @@ -3937,58 +3939,78 @@ static fdb_distributed_tran_t *fdb_trans_create_dtran(struct sqlclntstate *clnt) return dtran; } -static fdb_tran_t *fdb_trans_dtran_get_subtran(struct sqlclntstate *clnt, +static fdb_tran_t *_dtran_get_subtran(sqlclntstate *clnt, fdb_t *fdb, int use_ssl) +{ + fdb_tran_t *tran; + int rc; + + tran = (fdb_tran_t *)calloc(1, sizeof(*tran)); + if (!tran) { + logmsg(LOGMSG_ERROR, "%s: malloc 2\n", __func__); + return NULL; + } + memcpy(tran->magic, "FDBT", 4); + tran->tid = (char *)tran->tiduuid; + comdb2uuid((unsigned char *)tran->tid); + + tran->fdb = fdb; + + fdb_msg_t *msg = (fdb_msg_t *)calloc(1, fdb_msg_size()); + if (!msg) { + logmsg(LOGMSG_ERROR, "%s malloc\n", __func__); + free(tran); + return NULL; + } + + /* NOTE: expect x_retries to fill in clnt error fields, if any */ + rc = _fdb_send_open_retries(clnt, fdb, NULL /* tran_begin */, + -1 /*unused*/, tran, 0 /*flags*/, + 0 /*TODO: version */, msg, use_ssl); + if (rc != FDB_NOERR || !tran->fcon.sb) { + logmsg(LOGMSG_ERROR, "%s unable to connect to %s %s\n", __func__, + fdb->dbname, tran->host); + free(tran); + free(msg); + return NULL; + } + free(msg); + + /* need hbeats */ + Pthread_mutex_init(&tran->hbeats.sb_mtx, NULL); + sbuf2setuserptr(tran->fcon.sb, tran); + tran->hbeats.tran = tran; + enable_fdb_heartbeats(&tran->hbeats); + + tran->seq++; + + return tran; +} + +static fdb_tran_t *_dtran_get_subtran_cdb2api(sqlclntstate *clnt, fdb_t *fdb, + int use_ssl) +{ + + return NULL; +} + +static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, fdb_distributed_tran_t *dtran, fdb_t *fdb, int use_ssl) { fdb_tran_t *tran; - fdb_msg_t *msg; - int rc = 0; uuidstr_t us; tran = fdb_get_subtran(dtran, fdb); if (!tran) { - msg = (fdb_msg_t *)calloc(1, fdb_msg_size()); - if (!msg) { - logmsg(LOGMSG_ERROR, "%s malloc\n", __func__); - return NULL; - } - - tran = (fdb_tran_t *)calloc(1, sizeof(*tran)); - if (!tran) { - logmsg(LOGMSG_ERROR, "%s: malloc 2\n", __func__); - free(msg); + if (gbl_fdb_push_remote_write && fdb->server_version >= FDB_VER_CDB2API) + tran = _dtran_get_subtran_cdb2api(clnt, fdb, use_ssl); + else + tran = _dtran_get_subtran(clnt, fdb, use_ssl); + if (!tran) return NULL; - } - memcpy(tran->magic, "FDBT", 4); - tran->tid = (char *)tran->tiduuid; - comdb2uuid((unsigned char *)tran->tid); - - tran->fdb = fdb; - - /* NOTE: expect x_retries to fill in clnt error fields, if any */ - rc = _fdb_send_open_retries(clnt, fdb, NULL /* tran_begin */, - -1 /*unused*/, tran, 0 /*flags*/, - 0 /*TODO: version */, msg, use_ssl); - if (rc != FDB_NOERR || !tran->sb) { - logmsg(LOGMSG_ERROR, "%s unable to connect to %s %s\n", __func__, - fdb->dbname, tran->host); - free(tran); - free(msg); - return NULL; - } - - /* need hbeats */ - Pthread_mutex_init(&tran->hbeats.sb_mtx, NULL); - sbuf2setuserptr(tran->sb, tran); - tran->hbeats.tran = tran; - enable_fdb_heartbeats(&tran->hbeats); - - tran->seq++; listc_atl(&dtran->fdb_trans, tran); - free(msg); if (gbl_fdb_track) { logmsg(LOGMSG_USER, "%s Created tid=%s db=\"%s\"\n", __func__, @@ -4007,8 +4029,7 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(struct sqlclntstate *clnt, return tran; } -fdb_tran_t *fdb_trans_begin_or_join(struct sqlclntstate *clnt, fdb_t *fdb, - char *ptid, int use_ssl) +fdb_tran_t *fdb_trans_begin_or_join(sqlclntstate *clnt, fdb_t *fdb, int use_ssl) { fdb_distributed_tran_t *dtran; fdb_tran_t *tran; @@ -4025,25 +4046,19 @@ fdb_tran_t *fdb_trans_begin_or_join(struct sqlclntstate *clnt, fdb_t *fdb, } tran = fdb_trans_dtran_get_subtran(clnt, dtran, fdb, use_ssl); - if (tran) { - comdb2uuidcpy((unsigned char *)ptid, (unsigned char *)tran->tid); - } Pthread_mutex_unlock(&clnt->dtran_mtx); return tran; } -fdb_tran_t *fdb_trans_join(struct sqlclntstate *clnt, fdb_t *fdb, char *ptid) +fdb_tran_t *fdb_trans_join(sqlclntstate *clnt, fdb_t *fdb) { fdb_distributed_tran_t *dtran = clnt->dbtran.dtran; fdb_tran_t *tran = NULL; if (dtran) { tran = fdb_get_subtran(dtran, fdb); - if (tran) { - comdb2uuidcpy((unsigned char *)ptid, (unsigned char *)tran->tid); - } } return tran; @@ -4069,7 +4084,7 @@ static void _free_fdb_tran(fdb_distributed_tran_t *dtran, fdb_tran_t *tran) extern char gbl_dbname[]; -int fdb_trans_commit(struct sqlclntstate *clnt, enum trans_clntcomm sideeffects) +int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects) { fdb_distributed_tran_t *dtran = clnt->dbtran.dtran; fdb_tran_t *tran, *tmp; @@ -4112,7 +4127,7 @@ int fdb_trans_commit(struct sqlclntstate *clnt, enum trans_clntcomm sideeffects) if (sideeffects == TRANS_CLNTCOMM_CHUNK && tran->nwrites == 0) continue; - rc = fdb_send_commit(msg, tran, clnt->dbtran.mode, tran->sb); + rc = fdb_send_commit(msg, tran, clnt->dbtran.mode, tran->fcon.sb); if (clnt->use_2pc && !rc) { const char *tier = fdb_dbname_class_routing(tran->fdb); if ((rc = add_participant(clnt, tran->fdb->dbname, tier)) != 0) { @@ -4183,7 +4198,7 @@ int fdb_trans_commit(struct sqlclntstate *clnt, enum trans_clntcomm sideeffects) return rc; } -int fdb_trans_rollback(struct sqlclntstate *clnt) +int fdb_trans_rollback(sqlclntstate *clnt) { fdb_distributed_tran_t *dtran = clnt->dbtran.dtran; fdb_tran_t *tran, *tmp; @@ -4214,7 +4229,7 @@ int fdb_trans_rollback(struct sqlclntstate *clnt) LISTC_FOR_EACH(&dtran->fdb_trans, tran, lnk) { - rc = fdb_send_rollback(msg, tran, clnt->dbtran.mode, tran->sb); + rc = fdb_send_rollback(msg, tran, clnt->dbtran.mode, tran->fcon.sb); if (gbl_fdb_track) logmsg(LOGMSG_USER, "%s Send Commit tid=%llx db=\"%s\" rc=%d\n", @@ -4305,7 +4320,7 @@ void fdb_sanity_check(void) int fdb_cursor_access(BtCursor *pCur, int how) { struct sql_thread *thd; - struct sqlclntstate *clnt; + sqlclntstate *clnt; int rc; const char *dbname; const char *tblname; @@ -4784,7 +4799,7 @@ int fdb_table_version(unsigned long long version) * Clear sqlclntstate fdb_state object * */ -void fdb_clear_sqlclntstate(struct sqlclntstate *clnt) +void fdb_clear_sqlclntstate(sqlclntstate *clnt) { _fdb_clear_clnt_node_affinities(clnt); @@ -4845,7 +4860,7 @@ int fdb_table_exists(int rootpage) * The lock prevents the flush racing against running remote access * */ -int fdb_lock_table(sqlite3_stmt *pStmt, struct sqlclntstate *clnt, Table *tab, +int fdb_lock_table(sqlite3_stmt *pStmt, sqlclntstate *clnt, Table *tab, fdb_tbl_ent_t **p_ent) { fdb_tbl_ent_t *ent; @@ -4931,7 +4946,7 @@ int fdb_heartbeats(fdb_hbeats_type *hbeats) fdb_msg_t *msg = alloca(fdb_msg_size()); fdb_tran_t *tran = hbeats->tran; bzero(msg, fdb_msg_size()); - int rc = fdb_send_heartbeat(msg, tran->tid, tran->sb); + int rc = fdb_send_heartbeat(msg, tran->tid, tran->fcon.sb); if (gbl_fdb_track) { uuidstr_t us; comdb2uuidstr((unsigned char *)tran->tid, us); @@ -4947,8 +4962,8 @@ int fdb_heartbeats(fdb_hbeats_type *hbeats) */ void fdb_heartbeat_free_tran(fdb_hbeats_type *hbeats) { - if (hbeats->tran->sb) { - sbuf2close(hbeats->tran->sb); + if (hbeats->tran->fcon.sb) { + sbuf2close(hbeats->tran->fcon.sb); } Pthread_mutex_destroy(&hbeats->sb_mtx); free(hbeats->tran); @@ -4956,7 +4971,7 @@ void fdb_heartbeat_free_tran(fdb_hbeats_type *hbeats) /* check if the mentioned fdb has a preferred node, and get the status of last * op */ -static char *_fdb_get_affinity_node(struct sqlclntstate *clnt, const fdb_t *fdb, +static char *_fdb_get_affinity_node(sqlclntstate *clnt, const fdb_t *fdb, int *was_bad) { sqlclntstate_fdb_t *fdb_state = &clnt->fdb_state; @@ -4990,7 +5005,7 @@ static char *_fdb_get_affinity_node(struct sqlclntstate *clnt, const fdb_t *fdb, } /* save the last successful node for this fdb */ -static int _fdb_set_affinity_node(struct sqlclntstate *clnt, const fdb_t *fdb, +static int _fdb_set_affinity_node(sqlclntstate *clnt, const fdb_t *fdb, char *host, int status) { sqlclntstate_fdb_t *fdb_state = &clnt->fdb_state; @@ -5044,7 +5059,7 @@ static int _fdb_set_affinity_node(struct sqlclntstate *clnt, const fdb_t *fdb, * Free the cached fdb node affinities * */ -void _fdb_clear_clnt_node_affinities(struct sqlclntstate *clnt) +void _fdb_clear_clnt_node_affinities(sqlclntstate *clnt) { if (clnt->fdb_state.fdb_ids) { for (int i = 0; i < clnt->fdb_state.n_fdb_affinities; i++) @@ -5067,7 +5082,7 @@ void _fdb_clear_clnt_node_affinities(struct sqlclntstate *clnt) * Convert the protocol version in an appropriate cursor open flag * */ -static int _get_protocol_flags(struct sqlclntstate *clnt, fdb_t *fdb, +static int _get_protocol_flags(sqlclntstate *clnt, fdb_t *fdb, int *flags) { if (fdb->server_version < FDB_VER_SSL) { @@ -5425,7 +5440,7 @@ static int _fdb_cdb2api_send_set(fdb_cursor_t *fdbc) } \ } while (0); -static int _fdb_client_set_options(struct sqlclntstate *clnt, +static int _fdb_client_set_options(sqlclntstate *clnt, cdb2_hndl_tp *hndl) { char str[256]; @@ -5685,8 +5700,8 @@ static int fdb_cursor_find_sql_cdb2api(BtCursor *pCur, Mem *key, int nfields, } \ } while (0); -int process_fdb_set_cdb2api(struct sqlclntstate *clnt, char *sqlstr, - char *err, int errlen) +int process_fdb_set_cdb2api(sqlclntstate *clnt, char *sqlstr, char *err, + int errlen) { int tmp; @@ -5784,3 +5799,69 @@ int fdb_default_ver_set(int val) } return 0; } + +/** + * Same as fdb_push_setup, but for remote writes + * + */ +int fdb_push_write_setup(Parse *pParse, Table *pTab) +{ + GET_CLNT; + struct Db *pDb = &pParse->db->aDb[pTab->iDb]; + fdb_t *fdb; + + assert(pTab->iDb > 1); + logmsg(LOGMSG_DEBUG, + "%s query %s (gbl_fdb_push_remote_write=%d)\n", + __func__, clnt->sql, gbl_fdb_push_remote_write); + if (!gbl_fdb_push_remote_write) + return -1; + + if (clnt->disable_fdb_push) + return -1; + + fdb = get_fdb(pDb->zDbSName); + if (!fdb) { + logmsg(LOGMSG_ERROR, "%s: missing fdb %s\n", __func__, pDb->zDbSName); + return -1; + } + + if (fdb->local != pDb->local) { + logmsg(LOGMSG_ERROR, "%s: fdb %s different local %d %d\n", __func__, + pDb->zDbSName, fdb->local, pDb->local); + return -1; + } + + if (!fdb->local) { + if (pDb->class_override && pDb->class_override != fdb->class) { + logmsg(LOGMSG_ERROR, "%s: fdb %s different class override %d %d\n", __func__, + pDb->zDbSName, fdb->class, pDb->class_override); + return -1; + } + + if (!pDb->class_override && pDb->class != fdb->class) { + logmsg(LOGMSG_ERROR, "%s: fdb %s different class %d %d\n", __func__, + pDb->zDbSName, fdb->class, pDb->class); + return -1; + } + } + + if (pDb->version < FDB_VER_CDB2API) + return -1; + +#if 0 + /* fdb is the remote db we want, and it supports remote writes */ + + /* begin/join the transaction */ + fdb_tran_t *tran = fdb_trans_begin_or_join(clnt, fdb, fdb->ssl >= SSL_REQUIRE); + if (!tran) + return -1; + + + if (!clnt->in_client_trans) { + /* standalone remote write, commit here */ + } +#endif + return 0; +} + diff --git a/db/fdb_fend.h b/db/fdb_fend.h index 179bef2f7d..15f39376c2 100644 --- a/db/fdb_fend.h +++ b/db/fdb_fend.h @@ -30,7 +30,7 @@ #include "comdb2.h" #include "sql.h" -#include "sqliteInt.h" +//#include "sqliteInt.h" #include "vdbeInt.h" #include "comdb2uuid.h" #include "net_int.h" @@ -148,6 +148,7 @@ enum fdb_errors { }; extern int gbl_fdb_push_remote; +extern int gbl_fdb_push_remote_write; extern int gbl_fdb_push_redirect_foreign; #define fdb_is_error(n) ((n) < FDB_NOERR) @@ -175,7 +176,11 @@ struct fdb_tran { int errstrlen; /* length of err string, if any */ char *errstr; /* error string */ fdb_t *fdb; /* pointer to the foreign db */ - SBUF2 *sb; /* connection to this fdb */ + int is_cdb2api; + union { + SBUF2 *sb; /* connection to this fdb */ + cdb2_hndl_tp *hndl; /* cdb2api connection, iff is_cdb2api == 1 */ + } fcon; LINKC_T( struct fdb_tran) lnk; /* chain of subtransactions, part of the same @@ -236,13 +241,14 @@ typedef struct fdb_cursor_if { int (*tbl_has_expridx)(BtCursor *pCur); char *(*dbname)(BtCursor *pCur); - int (*insert)(BtCursor *pCur, struct sqlclntstate *clnt, fdb_tran_t *trans, + int (*insert)(BtCursor *pCur, sqlclntstate *clnt, fdb_tran_t *trans, unsigned long long genid, int datalen, char *data); - int (*delete)(BtCursor *pCur, struct sqlclntstate *clnt, fdb_tran_t *trans, + int (*delete)(BtCursor *pCur, sqlclntstate *clnt, fdb_tran_t *trans, unsigned long long genid); - int (*update)(BtCursor *pCur, struct sqlclntstate *clnt, fdb_tran_t *trans, + int (*update)(BtCursor *pCur, sqlclntstate *clnt, fdb_tran_t *trans, unsigned long long oldgenid, unsigned long long genid, int datalen, char *data); + int (*create_tran)(sqlclntstate *clnt, fdb_t *fdb, int use_ssl); fdb_tbl_ent_t *(*table_entry)(BtCursor *pCur); @@ -301,7 +307,7 @@ char *fdb_sqlexplain_get_field_name(Vdbe *v, int rootpage, int ixnum, * Create a connection to fdb * */ -fdb_cursor_if_t *fdb_cursor_open(struct sqlclntstate *clnt, BtCursor *pCur, +fdb_cursor_if_t *fdb_cursor_open(sqlclntstate *clnt, BtCursor *pCur, int rootpage, fdb_tran_t *trans, int *ixnum, int need_ssl); @@ -329,11 +335,10 @@ fdb_tbl_ent_t *fdb_table_entry_by_name(fdb_t *fdb, const char *name); int fdb_is_sqlite_stat(fdb_t *fdb, int rootpage); /* transactional api */ -fdb_tran_t *fdb_trans_begin_or_join(struct sqlclntstate *clnt, fdb_t *fdb, - char *ptid, int use_ssl); -fdb_tran_t *fdb_trans_join(struct sqlclntstate *clnt, fdb_t *fdb, char *ptid); -int fdb_trans_commit(struct sqlclntstate *clnt, enum trans_clntcomm sideeffects); -int fdb_trans_rollback(struct sqlclntstate *clnt); +fdb_tran_t *fdb_trans_begin_or_join(sqlclntstate *clnt, fdb_t *fdb, int use_ssl); +fdb_tran_t *fdb_trans_join(sqlclntstate *clnt, fdb_t *fdb); +int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects); +int fdb_trans_rollback(sqlclntstate *clnt); char *fdb_trans_id(fdb_tran_t *trans); char *fdb_get_alias(const char **p_tablename); @@ -377,7 +382,7 @@ int fdb_table_version(unsigned long long version); * Clear sqlclntstate fdb_state object * */ -void fdb_clear_sqlclntstate(struct sqlclntstate *clnt); +void fdb_clear_sqlclntstate(sqlclntstate *clnt); /** * Clear sqlite* schema for a certain remote table @@ -395,7 +400,7 @@ void fdb_clear_sqlite_cache(sqlite3 *sqldb, const char *dbname, * The lock prevents the flush racing against running remote access * */ -int fdb_lock_table(sqlite3_stmt *pStmt, struct sqlclntstate *clnt, Table *tab, +int fdb_lock_table(sqlite3_stmt *pStmt, sqlclntstate *clnt, Table *tab, fdb_tbl_ent_t **p_ent); /** @@ -444,7 +449,7 @@ int fdb_is_genid_deleted(fdb_tran_t *, unsigned long long); extern int gbl_fdb_incoherence_percentage; extern int gbl_fdb_io_error_retries; -int process_fdb_set_cdb2api(struct sqlclntstate *clnt, char *sqlstr, +int process_fdb_set_cdb2api(sqlclntstate *clnt, char *sqlstr, char *err, int errlen); #endif diff --git a/db/fdb_push.c b/db/fdb_push.c index a393e92faf..00aaaed1a6 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -16,6 +16,7 @@ #include "sql.h" #include "dohsql.h" +#include "fdb_fend.h" extern char *gbl_cdb2api_policy_override; extern int gbl_fdb_auth_enabled; @@ -60,7 +61,7 @@ static int convert_policy_override_string_to_cdb2api_flag(char *policy) { * refers to a remote table * */ -int fdb_push_run(Parse *pParse, dohsql_node_t *node) +int fdb_push_setup(Parse *pParse, dohsql_node_t *node) { GET_CLNT; fdb_push_connector_t *push = NULL; @@ -257,10 +258,10 @@ int handle_fdb_push(struct sqlclntstate *clnt, struct errstat *err) goto reset; } logmsg(LOGMSG_DEBUG, - "CALLING FDB PUSH on query %s (redirect tunable on? %d) (clnt force remote? %d) (clnt force redirect? %d) " - "(clnt can redirect? %d)\n", - clnt->sql, gbl_fdb_push_redirect_foreign, clnt->force_fdb_push_remote, clnt->force_fdb_push_redirect, - clnt->can_redirect_fdb); + "%s query %s (redirect tunable on? %d) (clnt force remote? %d) " + "(clnt force redirect? %d) (clnt can redirect? %d)\n", + __func__, clnt->sql, gbl_fdb_push_redirect_foreign, clnt->force_fdb_push_remote, + clnt->force_fdb_push_redirect, clnt->can_redirect_fdb); char *conf = getenv("CDB2_CONFIG"); if (conf) @@ -384,6 +385,15 @@ int handle_fdb_push(struct sqlclntstate *clnt, struct errstat *err) return rc; } +/** + * Same as handle_fdb_push, but for writes + * + */ +int handle_fdb_push_write(struct sqlclntstate *clnt, struct errstat *err) +{ + return -2; +} + static int _get_remote_cost(struct sqlclntstate *clnt, cdb2_hndl_tp *hndl) { int rc; diff --git a/db/osqlsqlthr.c b/db/osqlsqlthr.c index 97e2c798c2..148b29dab6 100644 --- a/db/osqlsqlthr.c +++ b/db/osqlsqlthr.c @@ -54,6 +54,7 @@ #include "osqlsqlnet.h" #include "schemachange.h" #include "db_access.h" +#include "fdb_fend.h" extern int gbl_partial_indexes; extern int gbl_expressions_indexes; diff --git a/db/process_message.c b/db/process_message.c index e683897da6..309fa3eb85 100644 --- a/db/process_message.c +++ b/db/process_message.c @@ -66,6 +66,7 @@ extern int __berkdb_read_alarm_ms; #include "reverse_conn.h" #include "phys_rep.h" #include "disttxn.h" +#include "fdb_fend.h" extern struct ruleset *gbl_ruleset; extern int gbl_exit_alarm_sec; diff --git a/db/sql.h b/db/sql.h index 45b81ebf2b..a0ff0da8c4 100644 --- a/db/sql.h +++ b/db/sql.h @@ -33,10 +33,10 @@ #include "osqlshadtbl.h" #include "fwd_types.h" #include "comdb2_ruleset.h" -#include "fdb_fend.h" #include #include "sql_stmt_cache.h" #include "db_access.h" +#include "sqliteInt.h" /* Modern transaction modes, more or less */ enum transaction_level { @@ -244,6 +244,22 @@ enum trans_clntcomm { void sql_set_sqlengine_state(struct sqlclntstate *clnt, char *file, int line, int newstate); + +struct fdb_distributed_tran; +typedef struct fdb_distributed_tran fdb_distributed_tran_t; +struct fdb_tbl_ent; +typedef struct fdb_tbl_ent fdb_tbl_ent_t; +struct fdb_access; +typedef struct fdb_access fdb_access_t; +struct fdb_affinity; +typedef struct fdb_affinity fdb_affinity_t; +struct fdb; +typedef struct fdb fdb_t; +struct Table; +typedef struct Table Table; +struct Parse; +typedef struct Parse Parse; + typedef struct { enum transaction_level mode; /* TRANLEVEL_SOSQL, TRANLEVEL_RECOM, ... */ @@ -991,6 +1007,7 @@ struct sqlclntstate { // coordinator participant information LISTC_T(struct participant) participants; }; +typedef struct sqlclntstate sqlclntstate; /* Query stats. */ struct query_path_component { @@ -1102,7 +1119,7 @@ struct BtCursor { /* special case for master table: the table is fake, just keep track of which entry we are pointing to */ int tblpos; - fdb_tbl_ent_t *crt_sqlite_master_row; + struct fdb_tbl_ent *crt_sqlite_master_row; /* special case for a temp table: pointer to a temp table handle */ struct temptable *tmptable; @@ -1167,7 +1184,7 @@ struct BtCursor { unsigned long long last_cached_genid; /* remotes */ - fdb_cursor_if_t *fdbc; + struct fdb_cursor_if *fdbc; /* cursor access range */ CurRange *range; @@ -1338,7 +1355,13 @@ int fdb_add_remote_time(BtCursor *pCur, unsigned long long start, * refers to a remote table * */ -int fdb_push_run(Parse *pParse, struct dohsql_node *node); +int fdb_push_setup(Parse *pParse, struct dohsql_node *node); + +/** + * Same as fdb_push_setup, but for remote writes + * + */ +int fdb_push_write_setup(Parse *pParse, Table *pTab); /** * Free remote push support @@ -1362,6 +1385,11 @@ void fdb_sqlite_row_free(Mem *res); * */ int handle_fdb_push(struct sqlclntstate *clnt, struct errstat *err); +/** + * Same as handle_fdb_push, but for writes + * + */ +int handle_fdb_push_write(struct sqlclntstate *clnt, struct errstat *err); int sqlite3LockStmtTables(sqlite3_stmt *pStmt); int sqlite3UnlockStmtTablesRemotes(struct sqlclntstate *clnt); diff --git a/db/sqlexplain.c b/db/sqlexplain.c index 6c363e0437..1fe64910d9 100644 --- a/db/sqlexplain.c +++ b/db/sqlexplain.c @@ -42,6 +42,7 @@ #include "sqlite3.h" #include "views.h" #include "logmsg.h" +#include "fdb_fend.h" static char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; diff --git a/db/sqlglue.c b/db/sqlglue.c index de87117f78..4dc01d4834 100644 --- a/db/sqlglue.c +++ b/db/sqlglue.c @@ -3977,9 +3977,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int usage) } else { /* make sure we have a distributed transaction and use that to * update remote */ - uuid_t tid; - fdb_tran_t *trans = fdb_trans_begin_or_join( - clnt, pCur->bt->fdb, (char *)tid, 0 /*TODO*/); + fdb_tran_t *trans = fdb_trans_join(clnt, pCur->bt->fdb); if (!trans) { logmsg(LOGMSG_ERROR, @@ -8138,9 +8136,8 @@ sqlite3BtreeCursor_remote(Btree *pBt, /* The btree */ { extern int gbl_ssl_allow_remsql; struct sqlclntstate *clnt = thd->clnt; - fdb_tran_t *trans; + fdb_tran_t *trans = NULL; fdb_t *fdb; - uuid_t tid; assert(pBt != 0); @@ -8174,14 +8171,10 @@ sqlite3BtreeCursor_remote(Btree *pBt, /* The btree */ /* I would like to open here a transaction if this is an actual update */ if (!clnt->isselect /* TODO: maybe only create one if we write to remote && fdb_write_is_remote()*/) { - trans = - fdb_trans_begin_or_join(clnt, fdb, (char *)tid, 0 /* TODO */); + trans = fdb_trans_begin_or_join(clnt, fdb, 0); } else { - trans = fdb_trans_join(clnt, fdb, (char *)tid); + trans = fdb_trans_join(clnt, fdb); } - } else { - *(unsigned long long *)tid = 0ULL; - trans = NULL; } if (trans) @@ -8203,8 +8196,8 @@ sqlite3BtreeCursor_remote(Btree *pBt, /* The btree */ "%s Created cursor cid=%s with tid=%s rootp=%d " "db:tbl=\"%s:%s\"\n", __func__, (pStr) ? comdb2uuidstr(pStr, cus) : "UNK", - comdb2uuidstr(tid, tus), iTable, pBt->zFilename, - cur->fdbc->name(cur)); + trans ? comdb2uuidstr(*(uuid_t*)trans->tid, tus) : "" , + iTable, pBt->zFilename, cur->fdbc->name(cur)); } if (trans) @@ -8715,7 +8708,6 @@ static int chunk_transaction(BtCursor *pCur, struct sqlclntstate *clnt, int bdberr = 0; fdb_t *fdb = NULL; fdb_tran_t *trans = NULL; - uuid_t tid; int need_ssl = 0; uint8_t **pIdxInsert = NULL, **pIdxDelete = NULL; @@ -8791,7 +8783,7 @@ static int chunk_transaction(BtCursor *pCur, struct sqlclntstate *clnt, SQLENG_PRE_STRT_STATE); if (pCur->cursor_class == CURSORCLASS_REMOTE) { /* restart a remote transaction, and open a new remote cursor */ - trans = fdb_trans_begin_or_join(clnt, fdb, (char *)tid, 0); + trans = fdb_trans_begin_or_join(clnt, fdb, 0); pCur->fdbc = fdb_cursor_open(clnt, pCur, pCur->rootpage, trans, &pCur->ixnum, need_ssl); } rc = handle_sql_begin(clnt->thd, clnt, TRANS_CLNTCOMM_CHUNK); @@ -9180,9 +9172,7 @@ int sqlite3BtreeInsert( } else { /* make sure we have a distributed transaction and use that to * update remote */ - uuid_t tid; - fdb_tran_t *trans = fdb_trans_begin_or_join( - clnt, pCur->bt->fdb, (char *)tid, 0 /*TODO*/); + fdb_tran_t *trans = fdb_trans_join(clnt, pCur->bt->fdb); if (!trans) { logmsg(LOGMSG_ERROR, diff --git a/db/sqlinterfaces.c b/db/sqlinterfaces.c index 9745ceb9ec..1491bc9825 100644 --- a/db/sqlinterfaces.c +++ b/db/sqlinterfaces.c @@ -4009,13 +4009,17 @@ int handle_sqlite_requests(struct sqlthdstate *thd, struct sqlclntstate *clnt) continue; } if (rc == SQLITE_SCHEMA_PUSH_REMOTE) { - rc = handle_fdb_push(clnt, &err); - if (rc == -2) { - /* remote server does not support proxy, retry without */ - clnt->disable_fdb_push = 1; - goto retry_legacy_remote; + if (clnt->isselect) { + rc = handle_fdb_push(clnt, &err); + if (rc == -2) { + /* remote server does not support proxy, retry without */ + clnt->disable_fdb_push = 1; + goto retry_legacy_remote; + } + goto done; + } else { + rc = handle_fdb_push_write(clnt, &err); } - goto done; } if (rc) { diff --git a/db/sqloffload.c b/db/sqloffload.c index 481a8a7ea5..bd1cfccec0 100644 --- a/db/sqloffload.c +++ b/db/sqloffload.c @@ -56,6 +56,7 @@ #include #include "sc_callbacks.h" #include "views.h" +#include "fdb_fend.h" #if 0 #define TEST_QSQL_REQ diff --git a/db/tag.c b/db/tag.c index 445851c511..f541a3f4fd 100644 --- a/db/tag.c +++ b/db/tag.c @@ -59,6 +59,7 @@ #include "logmsg.h" #include "schemachange.h" /* sc_errf() */ #include "dynschematypes.h" +#include "fdb_fend.h" extern struct dbenv *thedb; extern pthread_mutex_t csc2_subsystem_mtx; diff --git a/db/typessql.c b/db/typessql.c index 34829e700e..9866529416 100644 --- a/db/typessql.c +++ b/db/typessql.c @@ -1,4 +1,5 @@ #include +#include "fdb_fend.h" int gbl_typessql = 0; int gbl_typessql_records_max = 1000; diff --git a/db/views.c b/db/views.c index bb66a0b09f..0ddaa66a4c 100644 --- a/db/views.c +++ b/db/views.c @@ -1033,7 +1033,7 @@ _view_cron_schedule_next_rollout(timepart_view_t *view, int timeCrtRollout, logmsg(LOGMSG_ERROR, "%s: failed rc=%d errstr=%s\n", __func__, err->errval, err->errstr); free(removeShardName); - return FDB_ERR_GENERIC; + return VIEW_ERR_GENERIC; } } @@ -1049,10 +1049,10 @@ _view_cron_schedule_next_rollout(timepart_view_t *view, int timeCrtRollout, if (tmp_str) { free(tmp_str); } - return FDB_ERR_GENERIC; + return VIEW_ERR_GENERIC; } - return FDB_NOERR; + return VIEW_NOERR; } /** diff --git a/lua/sp.c b/lua/sp.c index 583a752178..c315a5232b 100644 --- a/lua/sp.c +++ b/lua/sp.c @@ -77,6 +77,8 @@ #include #include +#include "fdb_fend.h" + extern int gbl_dump_sql_dispatched; /* dump all sql strings dispatched */ extern int gbl_return_long_column_names; extern int gbl_max_sqlcache; diff --git a/plugins/remsql/fdb_comm.c b/plugins/remsql/fdb_comm.c index 4bee5bd117..d98306c41b 100644 --- a/plugins/remsql/fdb_comm.c +++ b/plugins/remsql/fdb_comm.c @@ -17,6 +17,7 @@ #include #include "sql.h" +#include "fdb_fend.h" #include "fdb_comm.h" #include "fdb_bend.h" #include "fdb_bend_sql.h" @@ -611,7 +612,7 @@ int fdb_recv_2pc_rc(fdb_msg_t *msg, fdb_tran_t *trans) { int rc; - rc = fdb_msg_read_message(trans->sb, msg, 0); + rc = fdb_msg_read_message(trans->fcon.sb, msg, 0); if (rc != FDB_NOERR) { logmsg(LOGMSG_ERROR, "%s: failed to receive remote row rc=%d\n", __func__, rc); trans->rc = FDB_ERR_READ_IO; @@ -621,7 +622,7 @@ int fdb_recv_2pc_rc(fdb_msg_t *msg, fdb_tran_t *trans) } if (gbl_fdb_track) { - fdb_msg_print_message(trans->sb, msg, "received 2pc-rc message"); + fdb_msg_print_message(trans->fcon.sb, msg, "received 2pc-rc message"); } msg->hd.type &= FD_MSG_TYPE; @@ -659,7 +660,7 @@ int fdb_recv_rc(fdb_msg_t *msg, fdb_tran_t *trans) { int rc; - rc = fdb_msg_read_message(trans->sb, msg, 0); + rc = fdb_msg_read_message(trans->fcon.sb, msg, 0); if (rc != FDB_NOERR) { logmsg(LOGMSG_ERROR, "%s: failed to receive remote row rc=%d\n", __func__, rc); @@ -670,7 +671,7 @@ int fdb_recv_rc(fdb_msg_t *msg, fdb_tran_t *trans) } if (gbl_fdb_track) { - fdb_msg_print_message(trans->sb, msg, "received message"); + fdb_msg_print_message(trans->fcon.sb, msg, "received message"); } msg->hd.type &= FD_MSG_TYPE; diff --git a/sqlite/ext/comdb2/functions.c b/sqlite/ext/comdb2/functions.c index c0aeda2403..114334dd21 100644 --- a/sqlite/ext/comdb2/functions.c +++ b/sqlite/ext/comdb2/functions.c @@ -25,6 +25,7 @@ #include "sql.h" #include "ezsystables.h" #include "cdb2api.h" +#include "sqliteInt.h" static int get_functions(void **data, int *npoints) { diff --git a/sqlite/ext/comdb2/logicalops.c b/sqlite/ext/comdb2/logicalops.c index 3295a4f86e..10566f395d 100644 --- a/sqlite/ext/comdb2/logicalops.c +++ b/sqlite/ext/comdb2/logicalops.c @@ -33,6 +33,7 @@ #include #include "llog_ext.h" #include "comdb2systbl.h" +#include "sqliteInt.h" /* Allocate maximum for unpacking */ #define PACKED_MEMORY_SIZE (MAXBLOBLENGTH + 7) diff --git a/sqlite/ext/comdb2/permissions.c b/sqlite/ext/comdb2/permissions.c index 0f37c81166..1e6d10b371 100644 --- a/sqlite/ext/comdb2/permissions.c +++ b/sqlite/ext/comdb2/permissions.c @@ -26,6 +26,7 @@ #include "sql.h" #include "plhash.h" #include "timepart_systable.h" +#include "sqliteInt.h" typedef struct table_entry { char *table; diff --git a/sqlite/src/build.c b/sqlite/src/build.c index 1e59654b25..8bf19d1c5a 100644 --- a/sqlite/src/build.c +++ b/sqlite/src/build.c @@ -38,6 +38,7 @@ int fdb_validate_existing_table(const char *zDatabase); char *fdb_get_alias(const char **p_tablename); int comdb2_check_parallel(Parse*); int comdb2_check_push_remote(Parse*); +int comdb2_check_push_remote_write(Parse*); void comdb2_create_view(Parse *pParse, const char *view_name, int view_name_len, const char *zStmt, int temp); void comdb2_drop_view(Parse *pParse, SrcList *pName); @@ -281,6 +282,10 @@ void sqlite3FinishCoding(Parse *pParse){ pParse->rc = SQLITE_SCHEMA_PUSH_REMOTE; return; } + if( comdb2_check_push_remote_write(pParse) ){ + pParse->rc = SQLITE_SCHEMA_PUSH_REMOTE; + return; + } if( comdb2_check_parallel(pParse) ){ pParse->rc = SQLITE_SCHEMA_DOHSQL; return; diff --git a/sqlite/src/insert.c b/sqlite/src/insert.c index 80ba36ef16..5b0f6c9761 100644 --- a/sqlite/src/insert.c +++ b/sqlite/src/insert.c @@ -746,6 +746,11 @@ void sqlite3Insert( } } +#if defined(SQLITE_BUILDING_FOR_COMDB2) + ast_t *ast = ast_init(pParse, __func__); + if( ast ) ast_push(ast, AST_TYPE_INSERT, v, (iDb>1) ? pTab : NULL); +#endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */ + /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The @@ -758,10 +763,6 @@ void sqlite3Insert( int addrTop; /* Top of the co-routine */ int rc; /* Result code */ -#if defined(SQLITE_BUILDING_FOR_COMDB2) - ast_t *ast = ast_init(pParse, __func__); - if( ast ) ast_push(ast, AST_TYPE_INSERT, v, NULL); -#endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */ regYield = ++pParse->nMem; addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); From b9ffac9fec7e5f6c764b666aa094b33689690ee2 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Tue, 3 Sep 2024 14:30:23 -0400 Subject: [PATCH 03/21] start fdb_tran --- db/fdb_fend.c | 56 ++++--------------- db/fdb_fend.h | 7 +++ db/fdb_push.c | 118 +++++++++++++++++++++++++++++++---------- db/sqlglue.c | 5 ++ db/sqlinterfaces.c | 18 +++---- sqlite/src/build.c | 2 +- sqlite/src/sqlite.h.in | 1 + sqlite/src/sqlite3.h | 1 + sqlite/src/vdbe.c | 1 + 9 files changed, 125 insertions(+), 84 deletions(-) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 475f3cb34a..82ac525f38 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -5801,67 +5801,29 @@ int fdb_default_ver_set(int val) } /** - * Same as fdb_push_setup, but for remote writes + * Check that fdb class matches a specific class * */ -int fdb_push_write_setup(Parse *pParse, Table *pTab) +int fdb_check_class_match(fdb_t *fdb, int local, enum mach_class class, + int class_override) { - GET_CLNT; - struct Db *pDb = &pParse->db->aDb[pTab->iDb]; - fdb_t *fdb; - - assert(pTab->iDb > 1); - logmsg(LOGMSG_DEBUG, - "%s query %s (gbl_fdb_push_remote_write=%d)\n", - __func__, clnt->sql, gbl_fdb_push_remote_write); - if (!gbl_fdb_push_remote_write) - return -1; - - if (clnt->disable_fdb_push) - return -1; - - fdb = get_fdb(pDb->zDbSName); - if (!fdb) { - logmsg(LOGMSG_ERROR, "%s: missing fdb %s\n", __func__, pDb->zDbSName); - return -1; - } - - if (fdb->local != pDb->local) { + if (fdb->local != local) { logmsg(LOGMSG_ERROR, "%s: fdb %s different local %d %d\n", __func__, - pDb->zDbSName, fdb->local, pDb->local); + fdb->dbname, fdb->local, local); return -1; } - if (!fdb->local) { - if (pDb->class_override && pDb->class_override != fdb->class) { + if (class_override && class_override != fdb->class) { logmsg(LOGMSG_ERROR, "%s: fdb %s different class override %d %d\n", __func__, - pDb->zDbSName, fdb->class, pDb->class_override); + fdb->dbname, fdb->class, class_override); return -1; } - if (!pDb->class_override && pDb->class != fdb->class) { + if (!class_override && class != fdb->class) { logmsg(LOGMSG_ERROR, "%s: fdb %s different class %d %d\n", __func__, - pDb->zDbSName, fdb->class, pDb->class); + fdb->dbname, fdb->class, class); return -1; } } - - if (pDb->version < FDB_VER_CDB2API) - return -1; - -#if 0 - /* fdb is the remote db we want, and it supports remote writes */ - - /* begin/join the transaction */ - fdb_tran_t *tran = fdb_trans_begin_or_join(clnt, fdb, fdb->ssl >= SSL_REQUIRE); - if (!tran) - return -1; - - - if (!clnt->in_client_trans) { - /* standalone remote write, commit here */ - } -#endif return 0; } - diff --git a/db/fdb_fend.h b/db/fdb_fend.h index 15f39376c2..917f7ca940 100644 --- a/db/fdb_fend.h +++ b/db/fdb_fend.h @@ -452,5 +452,12 @@ extern int gbl_fdb_io_error_retries; int process_fdb_set_cdb2api(sqlclntstate *clnt, char *sqlstr, char *err, int errlen); +/** + * Check that fdb class matches a specific class + * + */ +int fdb_check_class_match(fdb_t *fdb, int local, enum mach_class class, + int class_override); + #endif diff --git a/db/fdb_push.c b/db/fdb_push.c index 00aaaed1a6..961945d9d1 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -34,7 +34,7 @@ struct fdb_push_connector { struct param_data *params; /* bound parameters */ }; -static void _master_clnt_set(struct sqlclntstate *clnt); +static void _master_clnt_set(sqlclntstate *clnt); static int set_bound_parameters(fdb_push_connector_t *push, cdb2_hndl_tp *hndl, const char *tzname, struct errstat *err, cdb2_client_datetime_t *dts); @@ -55,6 +55,32 @@ static int convert_policy_override_string_to_cdb2api_flag(char *policy) { } } +fdb_push_connector_t *_push_setup(Parse *pParse, struct Db *pDb, int minver) +{ + fdb_push_connector_t *push = NULL; + + if (pDb->version < minver) + return NULL; + + push = calloc(1, sizeof(fdb_push_connector_t)); + if (!push) { + logmsg(LOGMSG_ERROR, "Failed to allocate fdb_push\n"); + return NULL; + } + push->remotedb = strdup(pDb->zDbSName); + if (!push->remotedb) { + logmsg(LOGMSG_ERROR, "Failed to allocate remotedb name\n"); + free(push); + return NULL; + } + push->class = pDb->class; + push->local = pDb->local; + push->class_override = pDb->class_override; + + return push; +} + + /** * Remote query push support * Save in clnt information that this is a standalone select that @@ -64,7 +90,6 @@ static int convert_policy_override_string_to_cdb2api_flag(char *policy) { int fdb_push_setup(Parse *pParse, dohsql_node_t *node) { GET_CLNT; - fdb_push_connector_t *push = NULL; struct Db *pDb = &pParse->db->aDb[node->remotedb]; logmsg(LOGMSG_DEBUG, @@ -81,24 +106,10 @@ int fdb_push_setup(Parse *pParse, dohsql_node_t *node) if (clnt->intrans || clnt->in_client_trans) return -1; - if (pDb->version < FDB_VER_PROXY) + fdb_push_connector_t *push = _push_setup(pParse, pDb, FDB_VER_PROXY); + if (!push) return -1; - push = calloc(1, sizeof(fdb_push_connector_t)); - if (!push) { - logmsg(LOGMSG_ERROR, "Failed to allocate fdb_push\n"); - return -1; - } - push->remotedb = strdup(pDb->zDbSName); - if (!push->remotedb) { - logmsg(LOGMSG_ERROR, "Failed to allocate remotedb name\n"); - free(push); - return -1; - } - push->class = pDb->class; - push->local = pDb->local; - push->class_override = pDb->class_override; - push->ncols = node->ncols; if (node->params) { @@ -117,6 +128,32 @@ int fdb_push_setup(Parse *pParse, dohsql_node_t *node) return 0; } +/** + * Same as fdb_push_setup, but for remote writes + * + */ +int fdb_push_write_setup(Parse *pParse, Table *pTab) +{ + GET_CLNT; + struct Db *pDb = &pParse->db->aDb[pTab->iDb]; + + assert(pTab->iDb > 1); + logmsg(LOGMSG_DEBUG, + "%s query %s (gbl_fdb_push_remote_write=%d)\n", + __func__, clnt->sql, gbl_fdb_push_remote_write); + if (!gbl_fdb_push_remote_write) + return -1; + + if (clnt->disable_fdb_push) + return -1; + + fdb_push_connector_t *push = _push_setup(pParse, pDb, FDB_VER_CDB2API); + if (!push) + return -1; + + return 0; +} + /** * Free remote push support */ @@ -137,14 +174,14 @@ void fdb_push_free(fdb_push_connector_t **pp) } /* override sqlite engine */ -static int fdb_push_column_count(struct sqlclntstate *clnt, sqlite3_stmt *_) +static int fdb_push_column_count(sqlclntstate *clnt, sqlite3_stmt *_) { return clnt->fdb_push->ncols; } /* Typecasting may reallocate zMalloc. So do it while holding master_mem_mtx. */ #define FUNC_COLUMN_TYPE(ret, type, err_ret) \ - static ret fdb_push_column_##type(struct sqlclntstate *clnt, \ + static ret fdb_push_column_##type(sqlclntstate *clnt, \ sqlite3_stmt *stmt, int iCol) \ { \ fdb_push_connector_t *p = clnt->fdb_push; \ @@ -168,7 +205,7 @@ FUNC_COLUMN_TYPE(const unsigned char *, text, NULL) FUNC_COLUMN_TYPE(const void *, blob, NULL) FUNC_COLUMN_TYPE(const dttz_t *, datetime, NULL) -static const intv_t *fdb_push_column_interval(struct sqlclntstate *clnt, +static const intv_t *fdb_push_column_interval(sqlclntstate *clnt, sqlite3_stmt *stmt, int iCol, int type) { @@ -185,12 +222,12 @@ static const intv_t *fdb_push_column_interval(struct sqlclntstate *clnt, return rv; } -static char *_get_tzname(struct sqlclntstate *clnt, sqlite3_stmt *_) +static char *_get_tzname(sqlclntstate *clnt, sqlite3_stmt *_) { return clnt->tzname; } -static void _master_clnt_set(struct sqlclntstate *clnt) +static void _master_clnt_set(sqlclntstate *clnt) { clnt->backup = clnt->plugin; clnt->adapter_backup = clnt->adapter; @@ -208,7 +245,7 @@ static void _master_clnt_set(struct sqlclntstate *clnt) clnt->plugin.tzname = _get_tzname; } -static int _get_remote_cost(struct sqlclntstate *clnt, cdb2_hndl_tp *hndl); +static int _get_remote_cost(sqlclntstate *clnt, cdb2_hndl_tp *hndl); void *(*externalComdb2getAuthIdBlob)(void *ID) = NULL; @@ -220,7 +257,7 @@ void *(*externalComdb2getAuthIdBlob)(void *ID) = NULL; * -1 if unrecoverable error * -2 if remote is too old (7.0 or older) */ -int handle_fdb_push(struct sqlclntstate *clnt, struct errstat *err) +int handle_fdb_push(sqlclntstate *clnt, struct errstat *err) { fdb_push_connector_t *push = clnt->fdb_push; cdb2_hndl_tp *hndl = NULL; @@ -389,12 +426,39 @@ int handle_fdb_push(struct sqlclntstate *clnt, struct errstat *err) * Same as handle_fdb_push, but for writes * */ -int handle_fdb_push_write(struct sqlclntstate *clnt, struct errstat *err) +int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) { + fdb_push_connector_t *push = clnt->fdb_push; + fdb_t *fdb; + int rc; + + if (!push) + return -2; + + fdb = get_fdb(push->remotedb); + if (!fdb) + return -2; + + rc = fdb_check_class_match(fdb, push->local, push->class, push->class_override); + if (rc) + return -2; + + /* fdb is the remote db we want, and it supports remote writes */ + + /* begin/join the transaction */ + fdb_tran_t *tran = fdb_trans_begin_or_join(clnt, fdb, 0/*TODO*/); + if (!tran) + return -1; + + + if (!clnt->in_client_trans) { + /* standalone remote write, commit here */ + } + return -2; } -static int _get_remote_cost(struct sqlclntstate *clnt, cdb2_hndl_tp *hndl) +static int _get_remote_cost(sqlclntstate *clnt, cdb2_hndl_tp *hndl) { int rc; diff --git a/db/sqlglue.c b/db/sqlglue.c index 4dc01d4834..5e8f0242b7 100644 --- a/db/sqlglue.c +++ b/db/sqlglue.c @@ -8172,6 +8172,11 @@ sqlite3BtreeCursor_remote(Btree *pBt, /* The btree */ an actual update */ if (!clnt->isselect /* TODO: maybe only create one if we write to remote && fdb_write_is_remote()*/) { trans = fdb_trans_begin_or_join(clnt, fdb, 0); + if (!trans) { + logmsg(LOGMSG_ERROR, "%s: failed to create fdb_tran\n", + __func__); + return -1; + } } else { trans = fdb_trans_join(clnt, fdb); } diff --git a/db/sqlinterfaces.c b/db/sqlinterfaces.c index 1491bc9825..1d1d037a22 100644 --- a/db/sqlinterfaces.c +++ b/db/sqlinterfaces.c @@ -4008,18 +4008,18 @@ int handle_sqlite_requests(struct sqlthdstate *thd, struct sqlclntstate *clnt) rec.sql = (const char *)allocd_str; continue; } - if (rc == SQLITE_SCHEMA_PUSH_REMOTE) { - if (clnt->isselect) { + if (rc == SQLITE_SCHEMA_PUSH_REMOTE || + rc == SQLITE_SCHEMA_PUSH_REMOTE_WRITE) { + if (rc == SQLITE_SCHEMA_PUSH_REMOTE) rc = handle_fdb_push(clnt, &err); - if (rc == -2) { - /* remote server does not support proxy, retry without */ - clnt->disable_fdb_push = 1; - goto retry_legacy_remote; - } - goto done; - } else { + else rc = handle_fdb_push_write(clnt, &err); + if (rc == -2) { + /* remote server does not support proxy, retry without */ + clnt->disable_fdb_push = 1; + goto retry_legacy_remote; } + goto done; } if (rc) { diff --git a/sqlite/src/build.c b/sqlite/src/build.c index 8bf19d1c5a..6aa80e7eb9 100644 --- a/sqlite/src/build.c +++ b/sqlite/src/build.c @@ -283,7 +283,7 @@ void sqlite3FinishCoding(Parse *pParse){ return; } if( comdb2_check_push_remote_write(pParse) ){ - pParse->rc = SQLITE_SCHEMA_PUSH_REMOTE; + pParse->rc = SQLITE_SCHEMA_PUSH_REMOTE_WRITE; return; } if( comdb2_check_parallel(pParse) ){ diff --git a/sqlite/src/sqlite.h.in b/sqlite/src/sqlite.h.in index cf7d75c990..ecacf3e40b 100644 --- a/sqlite/src/sqlite.h.in +++ b/sqlite/src/sqlite.h.in @@ -464,6 +464,7 @@ int sqlite3_exec( #define SQLITE_SCHEMA_DOHSQL 51 /* see dohsql */ #define SQLITE_EARLYSTOP_DOHSQL 52 /* see dohsql */ #define SQLITE_SCHEMA_PUSH_REMOTE 53 /* push query to remote node */ +#define SQLITE_SCHEMA_PUSH_REMOTE_WRITE 54 /* push write query to remote node */ #define SQLITE_DEADLOCK 200 /* deadlock happened, transaction aborted */ #define SQLITE_ACCESS 201 /* failed permissions */ #define SQLITE_LIMIT_DEPRECATED 202 /* SQLITE_LIMIT -- no longer used */ diff --git a/sqlite/src/sqlite3.h b/sqlite/src/sqlite3.h index 4b362637d6..793eb4943c 100644 --- a/sqlite/src/sqlite3.h +++ b/sqlite/src/sqlite3.h @@ -464,6 +464,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_SCHEMA_DOHSQL 51 /* see dohsql */ #define SQLITE_EARLYSTOP_DOHSQL 52 /* see dohsql */ #define SQLITE_SCHEMA_PUSH_REMOTE 53 /* push query to remote node */ +#define SQLITE_SCHEMA_PUSH_REMOTE_WRITE 54 /* push write query to remote node */ #define SQLITE_DEADLOCK 200 /* deadlock happened, transaction aborted */ #define SQLITE_ACCESS 201 /* failed permissions */ #define SQLITE_LIMIT_DEPRECATED 202 /* SQLITE_LIMIT -- no longer used */ diff --git a/sqlite/src/vdbe.c b/sqlite/src/vdbe.c index ada7f66b52..d39b2a651a 100644 --- a/sqlite/src/vdbe.c +++ b/sqlite/src/vdbe.c @@ -8892,6 +8892,7 @@ default: { /* This is really OP_Noop, OP_Explain */ && rc!=SQLITE_SCHEMA_REMOTE && rc!=SQLITE_SCHEMA_DOHSQL && rc!=SQLITE_SCHEMA_PUSH_REMOTE + && rc!=SQLITE_SCHEMA_PUSH_REMOTE_WRITE ){ #endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */ rc = SQLITE_ERROR; From 00c52741349425bf93b653e81b87022631c7637d Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Mon, 9 Sep 2024 11:54:16 -0400 Subject: [PATCH 04/21] special handling in_client_trans, partially --- db/fdb_fend.c | 56 +++++++++++---- db/fdb_fend.h | 11 ++- db/fdb_push.c | 196 ++++++++++++++++++++++++++++++++++++++++---------- db/sqlglue.c | 4 +- 4 files changed, 211 insertions(+), 56 deletions(-) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 82ac525f38..94cb3109fd 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -3939,10 +3939,9 @@ static fdb_distributed_tran_t *fdb_trans_create_dtran(sqlclntstate *clnt) return dtran; } -static fdb_tran_t *_dtran_get_subtran(sqlclntstate *clnt, fdb_t *fdb, int use_ssl) +static fdb_tran_t *_dtran_get_subtran_common(sqlclntstate *clnt, fdb_t *fdb) { fdb_tran_t *tran; - int rc; tran = (fdb_tran_t *)calloc(1, sizeof(*tran)); if (!tran) { @@ -3955,6 +3954,18 @@ static fdb_tran_t *_dtran_get_subtran(sqlclntstate *clnt, fdb_t *fdb, int use_ss tran->fdb = fdb; + return tran; +} + +static fdb_tran_t *_dtran_get_subtran(sqlclntstate *clnt, fdb_t *fdb, int use_ssl) +{ + fdb_tran_t *tran; + int rc; + + tran = _dtran_get_subtran_common(clnt, fdb); + if (!tran) + return NULL; + fdb_msg_t *msg = (fdb_msg_t *)calloc(1, fdb_msg_size()); if (!msg) { logmsg(LOGMSG_ERROR, "%s malloc\n", __func__); @@ -3989,13 +4000,21 @@ static fdb_tran_t *_dtran_get_subtran(sqlclntstate *clnt, fdb_t *fdb, int use_ss static fdb_tran_t *_dtran_get_subtran_cdb2api(sqlclntstate *clnt, fdb_t *fdb, int use_ssl) { + fdb_tran_t *tran; + + tran = _dtran_get_subtran_common(clnt, fdb); + if (!tran) + return NULL; + + tran->is_cdb2api = 1; - return NULL; + return tran; } static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, fdb_distributed_tran_t *dtran, - fdb_t *fdb, int use_ssl) + fdb_t *fdb, int use_ssl, + int *created) { fdb_tran_t *tran; uuidstr_t us; @@ -4017,6 +4036,9 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, comdb2uuidstr((unsigned char *)tran->tid, us), fdb->dbname); } + + if (created) + *created = 1; } else { if (gbl_fdb_track) { uuidstr_t us; @@ -4024,12 +4046,21 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, comdb2uuidstr((unsigned char *)tran->tid, us), fdb->dbname); } + /* this is a bug, probably sharing the wrong fdb_tran after switching to + * a lower version protocol + */ + if (clnt->disable_fdb_push && tran->is_cdb2api) + abort(); + + if (created) + *created = 0; } return tran; } -fdb_tran_t *fdb_trans_begin_or_join(sqlclntstate *clnt, fdb_t *fdb, int use_ssl) +fdb_tran_t *fdb_trans_begin_or_join(sqlclntstate *clnt, fdb_t *fdb, + int use_ssl, int *created) { fdb_distributed_tran_t *dtran; fdb_tran_t *tran; @@ -4045,7 +4076,7 @@ fdb_tran_t *fdb_trans_begin_or_join(sqlclntstate *clnt, fdb_t *fdb, int use_ssl) } } - tran = fdb_trans_dtran_get_subtran(clnt, dtran, fdb, use_ssl); + tran = fdb_trans_dtran_get_subtran(clnt, dtran, fdb, use_ssl, created); Pthread_mutex_unlock(&clnt->dtran_mtx); @@ -5813,15 +5844,10 @@ int fdb_check_class_match(fdb_t *fdb, int local, enum mach_class class, return -1; } if (!fdb->local) { - if (class_override && class_override != fdb->class) { - logmsg(LOGMSG_ERROR, "%s: fdb %s different class override %d %d\n", __func__, - fdb->dbname, fdb->class, class_override); - return -1; - } - - if (!class_override && class != fdb->class) { - logmsg(LOGMSG_ERROR, "%s: fdb %s different class %d %d\n", __func__, - fdb->dbname, fdb->class, class); + if (class != fdb->class) { + logmsg(LOGMSG_ERROR, "%s: fdb %s different class %s%d %d\n", + __func__, fdb->dbname, class_override ? "override " : "", + fdb->class, class); return -1; } } diff --git a/db/fdb_fend.h b/db/fdb_fend.h index 917f7ca940..3fa0840f4c 100644 --- a/db/fdb_fend.h +++ b/db/fdb_fend.h @@ -335,7 +335,8 @@ fdb_tbl_ent_t *fdb_table_entry_by_name(fdb_t *fdb, const char *name); int fdb_is_sqlite_stat(fdb_t *fdb, int rootpage); /* transactional api */ -fdb_tran_t *fdb_trans_begin_or_join(sqlclntstate *clnt, fdb_t *fdb, int use_ssl); +fdb_tran_t *fdb_trans_begin_or_join(sqlclntstate *clnt, fdb_t *fdb, + int use_ssl, int *created); fdb_tran_t *fdb_trans_join(sqlclntstate *clnt, fdb_t *fdb); int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects); int fdb_trans_rollback(sqlclntstate *clnt); @@ -459,5 +460,13 @@ int process_fdb_set_cdb2api(sqlclntstate *clnt, char *sqlstr, int fdb_check_class_match(fdb_t *fdb, int local, enum mach_class class, int class_override); +/** + * Connect to a remote cluster based of push connector information + * and additional configuration options + * + */ +cdb2_hndl_tp *fdb_push_connect(sqlclntstate *clnt, int *client_redir, + struct errstat *err); + #endif diff --git a/db/fdb_push.c b/db/fdb_push.c index 961945d9d1..21d1f9a9e0 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -55,7 +55,7 @@ static int convert_policy_override_string_to_cdb2api_flag(char *policy) { } } -fdb_push_connector_t *_push_setup(Parse *pParse, struct Db *pDb, int minver) +fdb_push_connector_t *_new_push(Parse *pParse, struct Db *pDb, int minver) { fdb_push_connector_t *push = NULL; @@ -106,7 +106,7 @@ int fdb_push_setup(Parse *pParse, dohsql_node_t *node) if (clnt->intrans || clnt->in_client_trans) return -1; - fdb_push_connector_t *push = _push_setup(pParse, pDb, FDB_VER_PROXY); + fdb_push_connector_t *push = _new_push(pParse, pDb, FDB_VER_PROXY); if (!push) return -1; @@ -147,10 +147,12 @@ int fdb_push_write_setup(Parse *pParse, Table *pTab) if (clnt->disable_fdb_push) return -1; - fdb_push_connector_t *push = _push_setup(pParse, pDb, FDB_VER_CDB2API); + fdb_push_connector_t *push = _new_push(pParse, pDb, FDB_VER_CDB2API); if (!push) return -1; + clnt->fdb_push = push; + return 0; } @@ -249,37 +251,18 @@ static int _get_remote_cost(sqlclntstate *clnt, cdb2_hndl_tp *hndl); void *(*externalComdb2getAuthIdBlob)(void *ID) = NULL; -/** - * Proxy receiving sqlite rows from remote and forwarding them to - * client after conversion to comdb2 format - * - * Returns: 0 if ok - * -1 if unrecoverable error - * -2 if remote is too old (7.0 or older) - */ -int handle_fdb_push(sqlclntstate *clnt, struct errstat *err) +static int _is_client_redirect(sqlclntstate *clnt, const char *class, + int cdb2api_policy_flag) { fdb_push_connector_t *push = clnt->fdb_push; - cdb2_hndl_tp *hndl = NULL; - uint64_t row_id = 0; - int first_row = 1; - int rc, irc; - - const char *class = "default"; - int cdb2api_policy_flag = push->local ? 0 : convert_policy_override_string_to_cdb2api_flag(gbl_cdb2api_policy_override); - if (push->local) - class = "local"; - else if (push->class_override) { - class = mach_class_class2name(push->class); - assert(class); - } if ((gbl_fdb_push_redirect_foreign || clnt->force_fdb_push_redirect) && clnt->can_redirect_fdb && !clnt->force_fdb_push_remote) { logmsg(LOGMSG_DEBUG, - "CALLING FDB PUSH REDIRECT on query %s (redirect tunable on %d) (clnt force remote? %d) (clnt force " - "redirect? %d)\n", - clnt->sql, gbl_fdb_push_redirect_foreign, clnt->force_fdb_push_remote, clnt->force_fdb_push_redirect); + "%s on query %s (redirect tunable on %d) (clnt force remote? %d)" + " (clnt force redirect? %d)\n", + __func__, clnt->sql, gbl_fdb_push_redirect_foreign, + clnt->force_fdb_push_remote, clnt->force_fdb_push_redirect); // tell cdb2api to run query directly on foreign db // send back db, tier, flag // NOTE: Cost will not work for this @@ -287,13 +270,23 @@ int handle_fdb_push(sqlclntstate *clnt, struct errstat *err) cdb2api_policy_flag |= CDB2_DIRECT_CPU; class = gbl_myhostname; } - rc = 0; const char *foreign_db[2]; foreign_db[0] = push->remotedb; foreign_db[1] = class; write_response(clnt, RESPONSE_REDIRECT_FOREIGN, foreign_db, cdb2api_policy_flag); - goto reset; + clnt_plugin_reset(clnt); + return 1; } + return 0; +} + +static cdb2_hndl_tp *_hndl_open_int(sqlclntstate *clnt, const char *class, + int flags, struct errstat *err) +{ + fdb_push_connector_t *push = clnt->fdb_push; + cdb2_hndl_tp *hndl = NULL; + int rc; + logmsg(LOGMSG_DEBUG, "%s query %s (redirect tunable on? %d) (clnt force remote? %d) " "(clnt force redirect? %d) (clnt can redirect? %d)\n", @@ -304,29 +297,103 @@ int handle_fdb_push(sqlclntstate *clnt, struct errstat *err) if (conf) cdb2_set_comdb2db_config(conf); - rc = cdb2_open(&hndl, push->remotedb, class, CDB2_SQL_ROWS | cdb2api_policy_flag); + rc = cdb2_open(&hndl, push->remotedb, class, flags); if (rc) { errstat_set_rcstrf(err, rc, "Failed to open db %s local", push->remotedb); - return -1; + return NULL; } rc = forward_set_commands(clnt, hndl, err); if (rc) { - return -1; + return NULL; + } + + if (gbl_uses_externalauth && gbl_fdb_auth_enabled && externalComdb2getAuthIdBlob) + cdb2_setIdentityBlob(hndl, externalComdb2getAuthIdBlob(clnt->authdata)); + + return hndl; +} + +/** + * Connect to a remote cluster based of push connector information + * and additional configuration options + * + */ +static cdb2_hndl_tp *_hndl_open(sqlclntstate *clnt, int *client_redir, + int flags, struct errstat *err) +{ + fdb_push_connector_t *push = clnt->fdb_push; + + const char *class = "default"; + if (push->local) + class = "local"; + else if (push->class_override) { + class = mach_class_class2name(push->class); + assert(class); + } + + int cdb2api_policy_flag = push->local ? 0 : + convert_policy_override_string_to_cdb2api_flag(gbl_cdb2api_policy_override); + + if (client_redir) { + /* bounce through client standalone queries, if so config-ed */ + if(!clnt->in_client_trans && _is_client_redirect(clnt, class, cdb2api_policy_flag)) { + *client_redir = 1; + return NULL; + } else { + *client_redir = 0; + } } + return _hndl_open_int(clnt, class, flags | cdb2api_policy_flag, err); +} + +static int _run_statement(sqlclntstate *clnt, cdb2_hndl_tp *hndl, + struct errstat *err) +{ + fdb_push_connector_t *push = clnt->fdb_push; + int rc; + cdb2_client_datetime_t *dts = calloc(push->nparams, sizeof(*dts)); + if (!dts) + return -1; + rc = set_bound_parameters(push, hndl, clnt->tzname, err, dts); if (rc) { free(dts); return -1; } - if (gbl_uses_externalauth && gbl_fdb_auth_enabled && externalComdb2getAuthIdBlob) - cdb2_setIdentityBlob(hndl, externalComdb2getAuthIdBlob(clnt->authdata)); - rc = cdb2_run_statement(hndl, clnt->sql); free(dts); + + return rc; +} + +/** + * Proxy receiving sqlite rows from remote and forwarding them to + * client after conversion to comdb2 format + * + * Returns: 0 if ok + * -1 if unrecoverable error + * -2 if remote is too old (7.0 or older) + */ +int handle_fdb_push(sqlclntstate *clnt, struct errstat *err) +{ + fdb_push_connector_t *push = clnt->fdb_push; + cdb2_hndl_tp *hndl = NULL; + uint64_t row_id = 0; + int first_row = 1; + int rc = 0, irc; + int client_redir; + + hndl = _hndl_open(clnt, &client_redir, CDB2_SQL_ROWS, err); + if (client_redir) + goto reset; + if (!hndl) + return -1; /* TODO: do we need reset here? */ + + rc = _run_statement(clnt, hndl, err); if (rc) { const char *errstr = cdb2_errstr(hndl); if (errstr && @@ -429,7 +496,9 @@ int handle_fdb_push(sqlclntstate *clnt, struct errstat *err) int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) { fdb_push_connector_t *push = clnt->fdb_push; + cdb2_hndl_tp *hndl; fdb_t *fdb; + int created; int rc; if (!push) @@ -446,16 +515,67 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) /* fdb is the remote db we want, and it supports remote writes */ /* begin/join the transaction */ - fdb_tran_t *tran = fdb_trans_begin_or_join(clnt, fdb, 0/*TODO*/); + fdb_tran_t *tran = fdb_trans_begin_or_join(clnt, fdb, 0/*TODO*/, &created); if (!tran) return -1; + /* get a connection */ + tran->is_cdb2api = 1; + tran->fcon.hndl = hndl =_hndl_open(clnt, NULL, + 0 /* no sqlite rows for writes */, err); + if (!tran->fcon.hndl) + return -1; + + /* if not standalone, and this is the first reachout to this fdb, send begin */ + if (clnt->in_client_trans && created) { + rc = cdb2_run_statement(hndl, "begin"); + if (rc != CDB2_OK_DONE) { + errstat_set_rcstrf(err, rc = -1, "failed to begin transaction"); + goto free; + } + } + + /* run the statement */ + rc = _run_statement(clnt, hndl, err); + if (rc != CDB2_OK) { + goto hndl_err; + } + + /* drain the socket */ + while ((rc = cdb2_next_record(hndl)) == CDB2_OK); + if (rc != CDB2_OK_DONE) { + goto hndl_err; + } + + cdb2_effects_tp effects; + + if ((rc = cdb2_get_effects(hndl, &effects))) { + goto hndl_err; + } + + int ncols = cdb2_numcolumns(hndl); + + /* if this is standalone, send answers to client */ if (!clnt->in_client_trans) { + /* write columns info */ + rc = write_response(clnt, RESPONSE_COLUMNS_FDB_PUSH, hndl, ncols); + if (rc) { + errstat_set_rcstrf(err, -1, "failed to retrieve columns"); + return -1; + } + /* standalone remote write, commit here */ + goto free; } - return -2; + return -1; + +hndl_err: + const char *errstr = cdb2_errstr(hndl); + errstat_set_rcstrf(err, rc, "%s", errstr); +free: + return rc; } static int _get_remote_cost(sqlclntstate *clnt, cdb2_hndl_tp *hndl) diff --git a/db/sqlglue.c b/db/sqlglue.c index 5e8f0242b7..de61e293a5 100644 --- a/db/sqlglue.c +++ b/db/sqlglue.c @@ -8171,7 +8171,7 @@ sqlite3BtreeCursor_remote(Btree *pBt, /* The btree */ /* I would like to open here a transaction if this is an actual update */ if (!clnt->isselect /* TODO: maybe only create one if we write to remote && fdb_write_is_remote()*/) { - trans = fdb_trans_begin_or_join(clnt, fdb, 0); + trans = fdb_trans_begin_or_join(clnt, fdb, 0, NULL); if (!trans) { logmsg(LOGMSG_ERROR, "%s: failed to create fdb_tran\n", __func__); @@ -8788,7 +8788,7 @@ static int chunk_transaction(BtCursor *pCur, struct sqlclntstate *clnt, SQLENG_PRE_STRT_STATE); if (pCur->cursor_class == CURSORCLASS_REMOTE) { /* restart a remote transaction, and open a new remote cursor */ - trans = fdb_trans_begin_or_join(clnt, fdb, 0); + trans = fdb_trans_begin_or_join(clnt, fdb, 0, NULL); pCur->fdbc = fdb_cursor_open(clnt, pCur, pCur->rootpage, trans, &pCur->ixnum, need_ssl); } rc = handle_sql_begin(clnt->thd, clnt, TRANS_CLNTCOMM_CHUNK); From 7e5444d6a47f0e1cf6e0f9b670815c9b13eabaf9 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Mon, 9 Sep 2024 16:21:48 -0400 Subject: [PATCH 05/21] working single statement --- db/dohast.c | 4 +++- db/fdb_push.c | 17 +++++++++++++++-- plugins/newsql/newsql.c | 1 + sqlite/src/delete.c | 8 ++++++-- sqlite/src/update.c | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/db/dohast.c b/db/dohast.c index 001f25735b..70254c573a 100644 --- a/db/dohast.c +++ b/db/dohast.c @@ -1003,7 +1003,9 @@ int comdb2_check_push_remote_write(Parse *pParse) if (!anode) return 0; - if (anode->op != AST_TYPE_INSERT) + if (anode->op != AST_TYPE_INSERT && + anode->op != AST_TYPE_DELETE && + anode->op != AST_TYPE_UPDATE) return 0; Table *pTab = (Table*)anode->obj; diff --git a/db/fdb_push.c b/db/fdb_push.c index 21d1f9a9e0..5dd832ab9d 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -561,11 +561,22 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) /* write columns info */ rc = write_response(clnt, RESPONSE_COLUMNS_FDB_PUSH, hndl, ncols); if (rc) { - errstat_set_rcstrf(err, -1, "failed to retrieve columns"); + errstat_set_rcstrf(err, -1, "failed to write columns"); return -1; } - /* standalone remote write, commit here */ + clnt->effects.num_affected = effects.num_affected; + clnt->effects.num_selected = effects.num_selected; + clnt->effects.num_updated = effects.num_updated; + clnt->effects.num_deleted = effects.num_deleted; + clnt->effects.num_inserted = effects.num_inserted; + + /* write answer */ + rc = write_response(clnt, RESPONSE_ROW_LAST, NULL, 0); + if (rc) { + errstat_set_rcstrf(err, -1, "failed to write last row"); + return -1; + } goto free; } @@ -575,6 +586,8 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) const char *errstr = cdb2_errstr(hndl); errstat_set_rcstrf(err, rc, "%s", errstr); free: + /* remote the fdb_tran_t */ + return rc; } diff --git a/plugins/newsql/newsql.c b/plugins/newsql/newsql.c index 184f8fc92e..d9f9575dd6 100644 --- a/plugins/newsql/newsql.c +++ b/plugins/newsql/newsql.c @@ -979,6 +979,7 @@ static int newsql_redirect_foreign(struct sqlclntstate *clnt, char **foreign_db, static int newsql_write_response(struct sqlclntstate *c, int t, void *a, int i) { + fprintf(stderr, "SENDING %d\n", t); switch (t) { case RESPONSE_COLUMNS: return newsql_columns(c, a); case RESPONSE_COLUMNS_LUA: return newsql_columns_lua(c, a); diff --git a/sqlite/src/delete.c b/sqlite/src/delete.c index 7ff5ebe485..e20ae57f74 100644 --- a/sqlite/src/delete.c +++ b/sqlite/src/delete.c @@ -331,8 +331,6 @@ void sqlite3DeleteFrom( if( v==0 ){ goto delete_from_cleanup; } - ast_t *ast = ast_init(pParse, __func__); - if( ast ) ast_push(ast, AST_TYPE_DELETE, v, NULL); #endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */ #ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT @@ -364,6 +362,12 @@ void sqlite3DeleteFrom( } assert(!isView || pTrigger); +#if defined(SQLITE_BUILDING_FOR_COMDB2) + ast_t *ast = ast_init(pParse, __func__); + if( ast ) ast_push(ast, AST_TYPE_DELETE, v, (iDb>1) ? pTab : NULL); +#endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */ + + /* Assign cursor numbers to the table and all its indices. */ assert( pTabList->nSrc==1 ); diff --git a/sqlite/src/update.c b/sqlite/src/update.c index 9b762663cd..6247813563 100644 --- a/sqlite/src/update.c +++ b/sqlite/src/update.c @@ -242,7 +242,7 @@ void sqlite3Update( v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; ast_t *ast = ast_init(pParse, __func__); - if( ast ) ast_push(ast, AST_TYPE_UPDATE, v, NULL); + if( ast ) ast_push(ast, AST_TYPE_UPDATE, v, (iDb>1) ? pTab : NULL); #endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */ #ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT if( !isView ){ From 265b960287dd82be721cda82ba17cf7e47bb97c5 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Mon, 9 Sep 2024 17:18:51 -0400 Subject: [PATCH 06/21] update, delete, insert, no lean tran --- db/fdb_fend.c | 48 +++++++++++++++++++++++++++++++++++++++--------- db/fdb_fend.h | 6 ++++++ db/fdb_push.c | 2 +- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 94cb3109fd..216f1c45e9 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -4101,16 +4101,46 @@ static void _free_fdb_tran(fdb_distributed_tran_t *dtran, fdb_tran_t *tran) listc_rfl(&dtran->fdb_trans, tran); - if (tran->errstr) - free(tran->errstr); - if (tran->dedup_tbl != NULL) { - /* tempcursors are automatically closed in bdb_temp_table_close. */ - if ((rc = bdb_temp_table_close(tran->bdb_state, tran->dedup_tbl, &bdberr))) - logmsg(LOGMSG_ERROR, - "%s: error closing temptable, rc %d, bdberr %d\n", - __func__, rc, bdberr); + free(tran->errstr); + + if (tran->is_cdb2api) { + rc = cdb2_close(tran->fcon.hndl); + if (rc) { + logmsg(LOGMSG_ERROR, "Failed to close handle rc %d\n", + rc); + } + free(tran); + } else { + if (tran->dedup_tbl != NULL) { + /* tempcursors are automatically closed in bdb_temp_table_close. */ + if ((rc = bdb_temp_table_close(tran->bdb_state, tran->dedup_tbl, &bdberr))) + logmsg(LOGMSG_ERROR, + "%s: error closing temptable, rc %d, bdberr %d\n", + __func__, rc, bdberr); + } + disable_fdb_heartbeats_and_free(&tran->hbeats); + } +} + +/** + * Free resources for a specific fdb_tran + * + */ +void fdb_free_tran(sqlclntstate *clnt, fdb_tran_t *tran) +{ + fdb_distributed_tran_t *dtran = clnt->dbtran.dtran; + + if (!dtran) { + logmsg(LOGMSG_ERROR, "%s no dtran\n", __func__); + return; + } + + _free_fdb_tran(dtran, tran); + + if (dtran->fdb_trans.count == 0) { + free(dtran); + clnt->dbtran.dtran = 0; } - disable_fdb_heartbeats_and_free(&tran->hbeats); } extern char gbl_dbname[]; diff --git a/db/fdb_fend.h b/db/fdb_fend.h index 3fa0840f4c..b4d262507d 100644 --- a/db/fdb_fend.h +++ b/db/fdb_fend.h @@ -468,5 +468,11 @@ int fdb_check_class_match(fdb_t *fdb, int local, enum mach_class class, cdb2_hndl_tp *fdb_push_connect(sqlclntstate *clnt, int *client_redir, struct errstat *err); +/** + * Free resources for a specific fdb_tran + * + */ +void fdb_free_tran(sqlclntstate *clnt, fdb_tran_t *tran); + #endif diff --git a/db/fdb_push.c b/db/fdb_push.c index 5dd832ab9d..8f84b89571 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -587,7 +587,7 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) errstat_set_rcstrf(err, rc, "%s", errstr); free: /* remote the fdb_tran_t */ - + fdb_free_tran(clnt, tran); return rc; } From 4984609400fde13ff7b2abf9c01a0ee48ad7a2f3 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Tue, 10 Sep 2024 10:30:10 -0400 Subject: [PATCH 07/21] added the legacy write counter row --- db/fdb_fend.c | 8 +++++++ db/fdb_push.c | 16 ++++++++++++++ db/sql.h | 3 ++- plugins/newsql/newsql.c | 48 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 216f1c45e9..8c28b75d8f 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -4129,15 +4129,23 @@ static void _free_fdb_tran(fdb_distributed_tran_t *dtran, fdb_tran_t *tran) void fdb_free_tran(sqlclntstate *clnt, fdb_tran_t *tran) { fdb_distributed_tran_t *dtran = clnt->dbtran.dtran; + uuidstr_t us; if (!dtran) { logmsg(LOGMSG_ERROR, "%s no dtran\n", __func__); return; } + if (gbl_fdb_track) + logmsg(LOGMSG_USER, "%s Destroyed tid=%s db=\"%s\"\n", __func__, + comdb2uuidstr((unsigned char *)tran->tid, us), + tran->fdb->dbname); + _free_fdb_tran(dtran, tran); if (dtran->fdb_trans.count == 0) { + if (gbl_fdb_track) + logmsg(LOGMSG_USER, "%s Destroyed D-tran %p\n", __func__, dtran); free(dtran); clnt->dbtran.dtran = 0; } diff --git a/db/fdb_push.c b/db/fdb_push.c index 8f84b89571..b8465ca4b3 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -571,6 +571,22 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) clnt->effects.num_deleted = effects.num_deleted; clnt->effects.num_inserted = effects.num_inserted; + int val = 0; + if (clnt->effects.num_inserted > 0) { + val = clnt->effects.num_inserted; + } else if (clnt->effects.num_deleted) { + val = clnt->effects.num_deleted; + } else if (clnt->effects.num_updated) { + val = clnt->effects.num_updated; + } + if (val > 0) { + rc = write_response(clnt, RESPONSE_ROW_REMTRAN, NULL, val); + if (rc) { + errstat_set_rcstrf(err, -1, "failed to write counter"); + return -1; + } + } + /* write answer */ rc = write_response(clnt, RESPONSE_ROW_LAST, NULL, 0); if (rc) { diff --git a/db/sql.h b/db/sql.h index a0ff0da8c4..1d24e273b9 100644 --- a/db/sql.h +++ b/db/sql.h @@ -387,7 +387,8 @@ enum { XRESPONSE(RESPONSE_ROW_LAST_DUMMY) \ XRESPONSE(RESPONSE_ROW_LUA) \ XRESPONSE(RESPONSE_ROW_STR) \ - XRESPONSE(RESPONSE_TRACE) + XRESPONSE(RESPONSE_TRACE) \ + XRESPONSE(RESPONSE_ROW_REMTRAN) #define XRESPONSE(x) x, enum WriteResponsesEnum { RESPONSE_TYPES }; diff --git a/plugins/newsql/newsql.c b/plugins/newsql/newsql.c index d9f9575dd6..ad02ca788b 100644 --- a/plugins/newsql/newsql.c +++ b/plugins/newsql/newsql.c @@ -1,4 +1,5 @@ /* + * return newsql_row_remtran(c, a, i); Copyright 2017, 2023 Bloomberg Finance L.P. Licensed under the Apache License, Version 2.0 (the "License"); @@ -756,6 +757,50 @@ static int newsql_row(struct sqlclntstate *clnt, struct response_data *arg, return newsql_response(clnt, &r, !clnt->rowbuffer); } +static int newsql_row_remtran(struct sqlclntstate *clnt, const char *name, + int val) +{ + struct newsql_appdata *appdata = clnt->appdata; + update_col_info(&appdata->col_info, 1); + assert(1 == appdata->col_info.count); + + int flip = endianness_mismatch(clnt); + + /* nested column values */ + CDB2SQLRESPONSE__Column cols[1]; + CDB2SQLRESPONSE__Column *value[1]; + + /* flat column values */ + ProtobufCBinaryData bd[1]; + protobuf_c_boolean isnulls[1]; + + memset(&bd, 0, sizeof(ProtobufCBinaryData)); + memset(&isnulls, 0, sizeof(protobuf_c_boolean)); + + if (!clnt->flat_col_vals) + value[0] = &cols[0]; + cdb2__sqlresponse__column__init(&cols[0]); + int64_t i64 = val; + newsql_integer(cols, 0, i64, flip); + if (clnt->flat_col_vals) + bd[0] = cols[0].value; + + CDB2SQLRESPONSE r = CDB2__SQLRESPONSE__INIT; + r.response_type = RESPONSE_TYPE__COLUMN_VALUES; + if (clnt->flat_col_vals) { + r.has_flat_col_vals = 1; + r.flat_col_vals = 1; + r.n_values = r.n_isnulls = 1; + r.values = bd; + r.isnulls = isnulls; + } else { + r.n_value = 1; + r.value = value; + } + + return newsql_response(clnt, &r, !clnt->rowbuffer); +} + static int newsql_row_last(struct sqlclntstate *clnt) { CDB2SQLRESPONSE resp = CDB2__SQLRESPONSE__INIT; @@ -979,7 +1024,6 @@ static int newsql_redirect_foreign(struct sqlclntstate *clnt, char **foreign_db, static int newsql_write_response(struct sqlclntstate *c, int t, void *a, int i) { - fprintf(stderr, "SENDING %d\n", t); switch (t) { case RESPONSE_COLUMNS: return newsql_columns(c, a); case RESPONSE_COLUMNS_LUA: return newsql_columns_lua(c, a); @@ -1009,6 +1053,8 @@ static int newsql_write_response(struct sqlclntstate *c, int t, void *a, int i) case RESPONSE_ERROR_PREPARE_RETRY: case RESPONSE_QUERY_STATS: return 0; + case RESPONSE_ROW_REMTRAN: + return newsql_row_remtran(c, a, i); default: abort(); } From 2a51c95e5a74aaf74fde54131fee682820d8aeda Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Wed, 18 Sep 2024 11:27:52 -0400 Subject: [PATCH 08/21] interm --- db/fdb_fend.c | 27 ++++++++++++++++++++++++--- db/fdb_push.c | 13 ++++++++++--- db/sqlinterfaces.c | 2 +- plugins/newsql/newsql.c | 1 + 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 8c28b75d8f..6804869ae7 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -4196,8 +4196,17 @@ int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects) if (sideeffects == TRANS_CLNTCOMM_CHUNK && tran->nwrites == 0) continue; - rc = fdb_send_commit(msg, tran, clnt->dbtran.mode, tran->fcon.sb); - if (clnt->use_2pc && !rc) { + if (tran->is_cdb2api) { + rc = cdb2_run_statement(tran->fcon.hndl, "commit"); + } else { + rc = fdb_send_commit(msg, tran, clnt->dbtran.mode, tran->fcon.sb); + } + if (rc) { + logmsg(LOGMSG_ERROR, "%s: failed to commit %s rc %d\n", + __func__, tran->fdb->dbname, rc); + } + + if (clnt->use_2pc) { const char *tier = fdb_dbname_class_routing(tran->fdb); if ((rc = add_participant(clnt, tran->fdb->dbname, tier)) != 0) { tran->errstr = strdup("multiple participants with same dbname"); @@ -4215,6 +4224,9 @@ int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects) if (sideeffects == TRANS_CLNTCOMM_CHUNK && tran->nwrites == 0) continue; + if (tran->is_cdb2api) + continue; + rc = fdb_recv_rc(msg, tran); if (gbl_fdb_track) { @@ -4298,7 +4310,16 @@ int fdb_trans_rollback(sqlclntstate *clnt) LISTC_FOR_EACH(&dtran->fdb_trans, tran, lnk) { - rc = fdb_send_rollback(msg, tran, clnt->dbtran.mode, tran->fcon.sb); + if (tran->is_cdb2api) { + rc = cdb2_run_statement(tran->fcon.hndl, "rollback"); + } else { + rc = fdb_send_rollback(msg, tran, clnt->dbtran.mode, tran->fcon.sb); + } + + if (rc) { + logmsg(LOGMSG_ERROR, "%s: failed to rollback %s rc %d\n", + __func__, tran->fdb->dbname, rc); + } if (gbl_fdb_track) logmsg(LOGMSG_USER, "%s Send Commit tid=%llx db=\"%s\" rc=%d\n", diff --git a/db/fdb_push.c b/db/fdb_push.c index b8465ca4b3..d9fb0e817d 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -528,10 +528,10 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) /* if not standalone, and this is the first reachout to this fdb, send begin */ if (clnt->in_client_trans && created) { + clnt->intrans = 1; rc = cdb2_run_statement(hndl, "begin"); if (rc != CDB2_OK_DONE) { - errstat_set_rcstrf(err, rc = -1, "failed to begin transaction"); - goto free; + goto hndl_err; } } @@ -594,13 +594,20 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) return -1; } goto free; + } else { + sql_set_sqlengine_state(clnt, __FILE__, __LINE__, SQLENG_INTRANS_STATE); } - return -1; + return 0; hndl_err: const char *errstr = cdb2_errstr(hndl); errstat_set_rcstrf(err, rc, "%s", errstr); + //rc = write_response(clnt, RESPONSE_ERROR_PREPARE, (void*)errstr, rc); + rc = write_response(clnt, RESPONSE_ERROR, (void*)errstr, rc); + if (rc) { + logmsg(LOGMSG_DEBUG, "Failed to write error to client"); + } free: /* remote the fdb_tran_t */ fdb_free_tran(clnt, tran); diff --git a/db/sqlinterfaces.c b/db/sqlinterfaces.c index 1d1d037a22..55bb4004f6 100644 --- a/db/sqlinterfaces.c +++ b/db/sqlinterfaces.c @@ -1402,7 +1402,7 @@ void clear_sqlhist() void sql_set_sqlengine_state(struct sqlclntstate *clnt, char *file, int line, int newstate) { - if (gbl_track_sqlengine_states) + /*if (gbl_track_sqlengine_states)*/ logmsg(LOGMSG_USER, "%p: %p %s:%d %d->%d\n", (void *)pthread_self(), clnt, file, line, clnt->ctrl_sqlengine, newstate); diff --git a/plugins/newsql/newsql.c b/plugins/newsql/newsql.c index ad02ca788b..68d5344dec 100644 --- a/plugins/newsql/newsql.c +++ b/plugins/newsql/newsql.c @@ -1024,6 +1024,7 @@ static int newsql_redirect_foreign(struct sqlclntstate *clnt, char **foreign_db, static int newsql_write_response(struct sqlclntstate *c, int t, void *a, int i) { + fprintf(stderr, "SENDING %d\n", t); switch (t) { case RESPONSE_COLUMNS: return newsql_columns(c, a); case RESPONSE_COLUMNS_LUA: return newsql_columns_lua(c, a); From d9c378846bc2a6500db5dec28d98cd9fb33b2c63 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Thu, 19 Sep 2024 15:07:18 -0400 Subject: [PATCH 09/21] working non_2pc txn Signed-off-by: Dorin Hogea --- db/fdb_fend.c | 17 ++++---- db/fdb_push.c | 42 ++++++++++++------- db/sqlinterfaces.c | 9 ++-- tests/writes_remsql_names.test/runit | 9 +++- .../writes_remsql_names.sh | 10 ++--- 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 6804869ae7..7e6ddf5a46 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -4204,6 +4204,13 @@ int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects) if (rc) { logmsg(LOGMSG_ERROR, "%s: failed to commit %s rc %d\n", __func__, tran->fdb->dbname, rc); + + /* pass the error to clnt */ + bzero(&clnt->osql.xerr, sizeof(clnt->osql.xerr)); + errstat_set_rc(&clnt->osql.xerr, rc); + if (tran->errstr) // TODO: this can be non-null even when no error + errstat_set_str(&clnt->osql.xerr, tran->errstr); + clnt->osql.error_is_remote = 1; } if (clnt->use_2pc) { @@ -4218,7 +4225,7 @@ int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects) tran->fdb->dbname, rc); } - if (!clnt->dist_txnid) { + if (!rc && !clnt->dist_txnid) { LISTC_FOR_EACH(&dtran->fdb_trans, tran, lnk) { if (sideeffects == TRANS_CLNTCOMM_CHUNK && tran->nwrites == 0) @@ -4242,13 +4249,7 @@ int fdb_trans_commit(sqlclntstate *clnt, enum trans_clntcomm sideeffects) } /* store distributed rc in clnt */ - if (rc) { - bzero(&clnt->osql.xerr, sizeof(clnt->osql.xerr)); - errstat_set_rc(&clnt->osql.xerr, rc); - if (tran->errstr) // TODO: this can be non-null even when no error - errstat_set_str(&clnt->osql.xerr, tran->errstr); - clnt->osql.error_is_remote = 1; - } else { + if (!rc) { errstat_set_rc(&clnt->osql.xerr, 0); errstat_set_str(&clnt->osql.xerr, NULL); } diff --git a/db/fdb_push.c b/db/fdb_push.c index d9fb0e817d..1185d03f15 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -504,6 +504,9 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) if (!push) return -2; + /* this was handled back here through an "error"; clear it */ + clnt->had_errors = 0; + fdb = get_fdb(push->remotedb); if (!fdb) return -2; @@ -519,20 +522,26 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) if (!tran) return -1; - /* get a connection */ - tran->is_cdb2api = 1; - tran->fcon.hndl = hndl =_hndl_open(clnt, NULL, - 0 /* no sqlite rows for writes */, err); - if (!tran->fcon.hndl) - return -1; - - /* if not standalone, and this is the first reachout to this fdb, send begin */ - if (clnt->in_client_trans && created) { - clnt->intrans = 1; - rc = cdb2_run_statement(hndl, "begin"); - if (rc != CDB2_OK_DONE) { - goto hndl_err; + if (created) { + /* get a connection */ + tran->is_cdb2api = 1; + hndl = tran->fcon.hndl = _hndl_open(clnt, NULL, + 0 /* no sqlite rows for writes */, err); + if (!tran->fcon.hndl) + return -1; + if (clnt->in_client_trans) { + /* if not standalone, and this is the first reachout to this fdb, send begin */ + clnt->intrans = 1; + rc = cdb2_run_statement(hndl, "begin"); + while (rc == CDB2_OK) { + rc = cdb2_next_record(hndl); + } + if (rc != CDB2_OK_DONE) { + goto hndl_err; + } } + } else { + hndl = tran->fcon.hndl; } /* run the statement */ @@ -550,8 +559,11 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) cdb2_effects_tp effects; - if ((rc = cdb2_get_effects(hndl, &effects))) { - goto hndl_err; + + if (!clnt->in_client_trans) { + if ((rc = cdb2_get_effects(hndl, &effects))) { + goto hndl_err; + } } int ncols = cdb2_numcolumns(hndl); diff --git a/db/sqlinterfaces.c b/db/sqlinterfaces.c index 55bb4004f6..62efb58c63 100644 --- a/db/sqlinterfaces.c +++ b/db/sqlinterfaces.c @@ -2859,13 +2859,14 @@ static void update_schema_remotes(struct sqlclntstate *clnt, } static void _prepare_error(struct sqlthdstate *thd, - struct sqlclntstate *clnt, - struct sql_state *rec, int rc, - struct errstat *err) + struct sqlclntstate *clnt, + struct sql_state *rec, int rc, + struct errstat *err) { const char *errstr; - if (rc == SQLITE_SCHEMA_DOHSQL) + if (rc == SQLITE_SCHEMA_DOHSQL || + rc == SQLITE_SCHEMA_PUSH_REMOTE_WRITE) return; if (in_client_trans(clnt) && diff --git a/tests/writes_remsql_names.test/runit b/tests/writes_remsql_names.test/runit index c32594a4d4..62e975dea5 100755 --- a/tests/writes_remsql_names.test/runit +++ b/tests/writes_remsql_names.test/runit @@ -16,10 +16,15 @@ for required in $vars; do fi done +opt= +if [[ ! -z $2 ]]; then + opt=$2 +fi + #run tests echo "Starting tests" -echo ./writes_remsql_names.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR -./writes_remsql_names.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR +echo ./writes_remsql_names.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR $opt +./writes_remsql_names.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR $opt result=$? if (( $result != 0 )) ; then diff --git a/tests/writes_remsql_names.test/writes_remsql_names.sh b/tests/writes_remsql_names.test/writes_remsql_names.sh index be732b9273..a84b4534e3 100755 --- a/tests/writes_remsql_names.test/writes_remsql_names.sh +++ b/tests/writes_remsql_names.test/writes_remsql_names.sh @@ -24,12 +24,9 @@ checkresult() correct_output_file=$1 run_output_file=$2 - #convert the table to actual dbname - sed "s/dorintdb/${a_remdbname}/g" ${correct_output_file} > ${correct_output_file}.actual - # validate results testcase_output=$(cat ${run_output_file}) - expected_output=$(cat ${correct_output_file}.actual) + expected_output=$(cat ${correct_output_file}) if [[ "$testcase_output" != "$expected_output" ]]; then # generate filename @@ -43,9 +40,9 @@ checkresult() echo "The above testcase (${testcase}) has failed!!!" echo " " echo "Use 'diff ' to see why:" - echo "> diff ${PWD}/${correct_output_file}.actual $tc_out" + echo "> diff ${PWD}/${correct_output_file} $tc_out" echo " " - diff ${PWD}/${correct_output_file}.actual $tc_out + diff ${PWD}/${correct_output_file} $tc_out echo " " exit 1 @@ -81,6 +78,7 @@ run_test() ${CDB2SQL_EXE} ${SRC_CDB2_OPTIONS} --tabs --host $mach $a_dbname "exec procedure sys.cmd.send(\"fdb info db\")" 2>&1 | cut -f 5- -d ' ' >> $output work_exp_output=${exp_output}.actual + echo "CONVERTING GEN ${work_exp_output}" sed "s/ t / LOCAL_${a_remdbname}.${tblname} /g" ${exp_output} > ${work_exp_output} # drop the From 5f2bb3465088f534d2c9946f75b33f2be51c53b4 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Tue, 24 Sep 2024 10:24:30 -0400 Subject: [PATCH 10/21] need remsqlcdb2api enabled for remtrancdb2api --- db/dohast.c | 2 +- db/fdb_fend.c | 13 ++++++++--- db/fdb_push.c | 22 ++++++++++--------- db/sql.h | 2 +- db/sqlinterfaces.c | 2 +- plugins/newsql/newsql.c | 1 - .../writes_remsql_names.sh | 1 - 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/db/dohast.c b/db/dohast.c index 70254c573a..c1f2b24bbc 100644 --- a/db/dohast.c +++ b/db/dohast.c @@ -1013,7 +1013,7 @@ int comdb2_check_push_remote_write(Parse *pParse) return 0; if (pTab->iDb > 1) - if (!fdb_push_write_setup(pParse, pTab)) + if (!fdb_push_write_setup(pParse, anode->op, pTab)) return 1; return 0; } diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 7e6ddf5a46..5362d685e0 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -77,7 +77,7 @@ int gbl_fdb_io_error_retries = 16; int gbl_fdb_io_error_retries_phase_1 = 6; int gbl_fdb_io_error_retries_phase_2_poll = 100; int gbl_fdb_auth_enabled = 1; -int gbl_fdb_remsql_cdb2api = 0; +int gbl_fdb_remsql_cdb2api = 1; int gbl_fdb_emulate_old = 0; struct fdb_tbl; @@ -2593,8 +2593,11 @@ static fdb_cursor_if_t *_fdb_cursor_open_remote(sqlclntstate *clnt, fdb_cursor_if_t *cursor; int server_version = fdb_ver_encoded(fdb->server_version); - /* for now we only support cdb2api for standalone queries, if remote support it */ - if (!trans && gbl_fdb_remsql_cdb2api && + /* non-transactional queries go over cdb2api; + * if there is a transaction running over cdb2api, use cdb2api also + * for cursors + */ + if ((!trans || trans->is_cdb2api) && gbl_fdb_remsql_cdb2api && fdb->server_version >= FDB_VER_CDB2API) cursor = _cursor_open_remote_cdb2api(clnt, fdb, server_version, flags, version, rootpage, use_ssl); @@ -5886,6 +5889,10 @@ int fdb_default_ver_set(int val) if (val < FDB_VER_CDB2API) { /* do not speak cdb2api if we set this too low */ gbl_fdb_remsql_cdb2api = 0; + /* disable also push, otherwise this will break transactional + * queries + */ + gbl_fdb_push_remote_write = 0; } } return 0; diff --git a/db/fdb_push.c b/db/fdb_push.c index 1185d03f15..7b0837b773 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -22,6 +22,7 @@ extern char *gbl_cdb2api_policy_override; extern int gbl_fdb_auth_enabled; struct fdb_push_connector { + enum ast_type type; /* what type of request we override */ char *remotedb; /* name of the remote db; class matches stored fdb */ enum mach_class class; /* what stage this db lives on */ int class_override; /* class was explicit in the remdb name */ @@ -55,7 +56,8 @@ static int convert_policy_override_string_to_cdb2api_flag(char *policy) { } } -fdb_push_connector_t *_new_push(Parse *pParse, struct Db *pDb, int minver) +fdb_push_connector_t *_new_push(Parse *pParse, struct Db *pDb, + enum ast_type type, int minver) { fdb_push_connector_t *push = NULL; @@ -76,6 +78,7 @@ fdb_push_connector_t *_new_push(Parse *pParse, struct Db *pDb, int minver) push->class = pDb->class; push->local = pDb->local; push->class_override = pDb->class_override; + push->type = type; return push; } @@ -106,7 +109,8 @@ int fdb_push_setup(Parse *pParse, dohsql_node_t *node) if (clnt->intrans || clnt->in_client_trans) return -1; - fdb_push_connector_t *push = _new_push(pParse, pDb, FDB_VER_PROXY); + fdb_push_connector_t *push = _new_push(pParse, pDb, AST_TYPE_SELECT, + FDB_VER_PROXY); if (!push) return -1; @@ -132,7 +136,7 @@ int fdb_push_setup(Parse *pParse, dohsql_node_t *node) * Same as fdb_push_setup, but for remote writes * */ -int fdb_push_write_setup(Parse *pParse, Table *pTab) +int fdb_push_write_setup(Parse *pParse, enum ast_type type, Table *pTab) { GET_CLNT; struct Db *pDb = &pParse->db->aDb[pTab->iDb]; @@ -147,7 +151,7 @@ int fdb_push_write_setup(Parse *pParse, Table *pTab) if (clnt->disable_fdb_push) return -1; - fdb_push_connector_t *push = _new_push(pParse, pDb, FDB_VER_CDB2API); + fdb_push_connector_t *push = _new_push(pParse, pDb, type, FDB_VER_CDB2API); if (!push) return -1; @@ -591,12 +595,10 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) } else if (clnt->effects.num_updated) { val = clnt->effects.num_updated; } - if (val > 0) { - rc = write_response(clnt, RESPONSE_ROW_REMTRAN, NULL, val); - if (rc) { - errstat_set_rcstrf(err, -1, "failed to write counter"); - return -1; - } + rc = write_response(clnt, RESPONSE_ROW_REMTRAN, NULL, val); + if (rc) { + errstat_set_rcstrf(err, -1, "failed to write counter"); + return -1; } /* write answer */ diff --git a/db/sql.h b/db/sql.h index 1d24e273b9..0571748012 100644 --- a/db/sql.h +++ b/db/sql.h @@ -1362,7 +1362,7 @@ int fdb_push_setup(Parse *pParse, struct dohsql_node *node); * Same as fdb_push_setup, but for remote writes * */ -int fdb_push_write_setup(Parse *pParse, Table *pTab); +int fdb_push_write_setup(Parse *pParse, enum ast_type type, Table *pTab); /** * Free remote push support diff --git a/db/sqlinterfaces.c b/db/sqlinterfaces.c index 62efb58c63..309c6f509d 100644 --- a/db/sqlinterfaces.c +++ b/db/sqlinterfaces.c @@ -1402,7 +1402,7 @@ void clear_sqlhist() void sql_set_sqlengine_state(struct sqlclntstate *clnt, char *file, int line, int newstate) { - /*if (gbl_track_sqlengine_states)*/ + if (gbl_track_sqlengine_states) logmsg(LOGMSG_USER, "%p: %p %s:%d %d->%d\n", (void *)pthread_self(), clnt, file, line, clnt->ctrl_sqlengine, newstate); diff --git a/plugins/newsql/newsql.c b/plugins/newsql/newsql.c index 68d5344dec..ad02ca788b 100644 --- a/plugins/newsql/newsql.c +++ b/plugins/newsql/newsql.c @@ -1024,7 +1024,6 @@ static int newsql_redirect_foreign(struct sqlclntstate *clnt, char **foreign_db, static int newsql_write_response(struct sqlclntstate *c, int t, void *a, int i) { - fprintf(stderr, "SENDING %d\n", t); switch (t) { case RESPONSE_COLUMNS: return newsql_columns(c, a); case RESPONSE_COLUMNS_LUA: return newsql_columns_lua(c, a); diff --git a/tests/writes_remsql_names.test/writes_remsql_names.sh b/tests/writes_remsql_names.test/writes_remsql_names.sh index a84b4534e3..b19780d7b3 100755 --- a/tests/writes_remsql_names.test/writes_remsql_names.sh +++ b/tests/writes_remsql_names.test/writes_remsql_names.sh @@ -78,7 +78,6 @@ run_test() ${CDB2SQL_EXE} ${SRC_CDB2_OPTIONS} --tabs --host $mach $a_dbname "exec procedure sys.cmd.send(\"fdb info db\")" 2>&1 | cut -f 5- -d ' ' >> $output work_exp_output=${exp_output}.actual - echo "CONVERTING GEN ${work_exp_output}" sed "s/ t / LOCAL_${a_remdbname}.${tblname} /g" ${exp_output} > ${work_exp_output} # drop the From 280410a48b411189fda0f624205449433bcf230a Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Mon, 30 Sep 2024 15:18:07 -0400 Subject: [PATCH 11/21] fdb compatibility test and fixes for it; limit tran support to socksql --- db/fdb_fend.c | 33 ++++-- db/fdb_fend.h | 3 +- db/sqlglue.c | 30 ++++++ sqlite/src/attach.c | 13 ++- tests/fdb_compat.test/Makefile | 10 ++ tests/fdb_compat.test/README | 1 + tests/fdb_compat.test/lrl.options | 2 + tests/fdb_compat.test/output.log | 44 ++++++++ tests/fdb_compat.test/rte_connect.testopts | 1 + tests/fdb_compat.test/runit | 35 +++++++ tests/fdb_compat.test/t.csc2 | 8 ++ tests/fdb_compat.test/test_fdb.sh | 113 +++++++++++++++++++++ 12 files changed, 282 insertions(+), 11 deletions(-) create mode 100644 tests/fdb_compat.test/Makefile create mode 100644 tests/fdb_compat.test/README create mode 100644 tests/fdb_compat.test/lrl.options create mode 100644 tests/fdb_compat.test/output.log create mode 100644 tests/fdb_compat.test/rte_connect.testopts create mode 100644 tests/fdb_compat.test/runit create mode 100644 tests/fdb_compat.test/t.csc2 create mode 100644 tests/fdb_compat.test/test_fdb.sh diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 5362d685e0..1b0be78864 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -2595,10 +2595,12 @@ static fdb_cursor_if_t *_fdb_cursor_open_remote(sqlclntstate *clnt, /* non-transactional queries go over cdb2api; * if there is a transaction running over cdb2api, use cdb2api also - * for cursors + * for cursors, if less then read committed */ - if ((!trans || trans->is_cdb2api) && gbl_fdb_remsql_cdb2api && - fdb->server_version >= FDB_VER_CDB2API) + if (gbl_fdb_remsql_cdb2api && + ((!trans && fdb->server_version >= FDB_VER_CDB2API) || + (trans && fdb->server_version >= FDB_VER_WR_CDB2API && + clnt->dbtran.mode == TRANLEVEL_SOSQL))) cursor = _cursor_open_remote_cdb2api(clnt, fdb, server_version, flags, version, rootpage, use_ssl); else @@ -4025,7 +4027,9 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, tran = fdb_get_subtran(dtran, fdb); if (!tran) { - if (gbl_fdb_push_remote_write && fdb->server_version >= FDB_VER_CDB2API) + if (gbl_fdb_push_remote_write && + fdb->server_version >= FDB_VER_WR_CDB2API && + clnt->dbtran.mode == TRANLEVEL_SOSQL) tran = _dtran_get_subtran_cdb2api(clnt, fdb, use_ssl); else tran = _dtran_get_subtran(clnt, fdb, use_ssl); @@ -4626,12 +4630,21 @@ static void fdb_clear_sqlite_stats(void) */ static void fdb_init(void) { - int rc = FDB_ERR_BUG; + logmsg(LOGMSG_ERROR, "Testing routine clearing fdb structure!\n"); - if (rc) { - /* TODO: fatal? */ - logmsg(LOGMSG_ERROR, "%s: init unimplemented\n", __func__); - } + Pthread_rwlock_wrlock(&fdbs.arr_lock); + + /* + * we leak on purpose instead of adding extra synchronization + * with existing users + */ + bzero(fdbs.arr, fdbs.nused * sizeof(fdbs.arr[0])); + fdbs.nused = 0; + + logmsg(LOGMSG_INFO, "Replicant updating views counter=%d\n", gbl_views_gen); + ++gbl_views_gen; + + pthread_rwlock_unlock(&fdbs.arr_lock); } static int __fdb_info_ent(void *obj, void *arg) @@ -5893,6 +5906,8 @@ int fdb_default_ver_set(int val) * queries */ gbl_fdb_push_remote_write = 0; + } else if (val < FDB_VER_WR_CDB2API) { + gbl_fdb_push_remote_write = 0; } } return 0; diff --git a/db/fdb_fend.h b/db/fdb_fend.h index b4d262507d..9cd6e8b0d6 100644 --- a/db/fdb_fend.h +++ b/db/fdb_fend.h @@ -72,8 +72,9 @@ #define FDB_VER_PROXY 5 #define FDB_VER_AUTH 6 #define FDB_VER_CDB2API 7 +#define FDB_VER_WR_CDB2API 8 -#define FDB_VER FDB_VER_CDB2API +#define FDB_VER FDB_VER_WR_CDB2API extern int gbl_fdb_default_ver; diff --git a/db/sqlglue.c b/db/sqlglue.c index de61e293a5..5a116beb97 100644 --- a/db/sqlglue.c +++ b/db/sqlglue.c @@ -3581,6 +3581,36 @@ int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level, int fullsync) return SQLITE_OK; } +/* + ** Reopen a database file. + ** Only used for remote db files. + ** zFilename is the name of the database file. + */ +int sqlite3BtreeReopen( + const char *zFilename, /* name of the file containing the btree database */ + Btree *pBtree) /* pointer to existing btree object written here */ +{ + int rc = SQLITE_OK; + + assert(zFilename); + assert(pBtree); + + if (gbl_fdb_track) + logmsg(LOGMSG_USER, "XXXXXXXXXXXXX ReOpening \"%s\"\n", zFilename); + + pBtree->fdb = get_fdb(zFilename); + if (!pBtree->fdb) { + logmsg(LOGMSG_ERROR, "%s: fdb not available for %s ?\n", __func__, + zFilename); + rc = SQLITE_ERROR; + } + + reqlog_logf(pBtree->reqlogger, REQL_TRACE, + "ReOpen(file %s, tree %d) = %s\n", + zFilename, pBtree->btreeid, sqlite3ErrStr(rc)); + return rc; +} + /* ** Open a database file. ** diff --git a/sqlite/src/attach.c b/sqlite/src/attach.c index b69acf5a0c..623c60c965 100644 --- a/sqlite/src/attach.c +++ b/sqlite/src/attach.c @@ -202,7 +202,18 @@ static void attachFunc( #if defined(SQLITE_BUILDING_FOR_COMDB2) iFndDb = i; - if( i!=db->nDb ) goto done_with_open; + if( i!=db->nDb ) { + extern int sqlite3BtreeReopen(const char*,Btree*); + + rc = sqlite3BtreeReopen(dbName, db->aDb[iFndDb].pBt); + + db->aDb[iFndDb].zDbSName = dbName; + db->aDb[iFndDb].class = class; + db->aDb[iFndDb].class_override = class_override; + db->aDb[iFndDb].local = local; + db->aDb[iFndDb].version = proto_version; + goto done_with_open; + } #endif /* defined(SQLITE_BUILDING_FOR_COMDB2) */ /* Allocate the new entry in the db->aDb[] array and initialize the schema ** hash tables. diff --git a/tests/fdb_compat.test/Makefile b/tests/fdb_compat.test/Makefile new file mode 100644 index 0000000000..9f4bcc7346 --- /dev/null +++ b/tests/fdb_compat.test/Makefile @@ -0,0 +1,10 @@ +export SECONDARY_DB_PREFIX=s + +ifeq ($(TESTSROOTDIR),) + include ../testcase.mk +else + include $(TESTSROOTDIR)/testcase.mk +endif +ifeq ($(TEST_TIMEOUT),) + export TEST_TIMEOUT=3m +endif diff --git a/tests/fdb_compat.test/README b/tests/fdb_compat.test/README new file mode 100644 index 0000000000..7f274d9842 --- /dev/null +++ b/tests/fdb_compat.test/README @@ -0,0 +1 @@ +This test checks forward and backward compatibility between rem protocols. diff --git a/tests/fdb_compat.test/lrl.options b/tests/fdb_compat.test/lrl.options new file mode 100644 index 0000000000..77c8716465 --- /dev/null +++ b/tests/fdb_compat.test/lrl.options @@ -0,0 +1,2 @@ +table t t.csc2 +foreign_db_push_remote 0 diff --git a/tests/fdb_compat.test/output.log b/tests/fdb_compat.test/output.log new file mode 100644 index 0000000000..8534a7b4d5 --- /dev/null +++ b/tests/fdb_compat.test/output.log @@ -0,0 +1,44 @@ +Current fdb version 8 +(rows inserted=3) +(rows inserted=3) +TEST 1 +remsql run against same version +(id=11) +(id=12) +(id=13) +Table "sqlite_stat1" Rootp 1073741828 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741829 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741827 Remrootp 3 Version=0') +Table "t" Rootp 1073741826 Remrootp 2 Version=0') +TEST 2 +remsql run against a pre cdb2api version +(id=11) +(id=12) +(id=13) +(id=1) +(id=2) +(id=3) +Table "sqlite_stat1" Rootp 1073741832 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741833 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741831 Remrootp 3 Version=0') +Table "t" Rootp 1073741830 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741828 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741829 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741827 Remrootp 3 Version=0') +Table "t" Rootp 1073741826 Remrootp 2 Version=0') +TEST 3 +test against a too new version +(id=11) +(id=12) +(id=13) +(id=1) +(id=2) +(id=3) +Table "sqlite_stat1" Rootp 1073741836 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741837 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741835 Remrootp 3 Version=0') +Table "t" Rootp 1073741834 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741832 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741833 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741831 Remrootp 3 Version=0') +Table "t" Rootp 1073741830 Remrootp 2 Version=0') diff --git a/tests/fdb_compat.test/rte_connect.testopts b/tests/fdb_compat.test/rte_connect.testopts new file mode 100644 index 0000000000..34b2155cd7 --- /dev/null +++ b/tests/fdb_compat.test/rte_connect.testopts @@ -0,0 +1 @@ +connect_remote_rte 1 diff --git a/tests/fdb_compat.test/runit b/tests/fdb_compat.test/runit new file mode 100644 index 0000000000..7bc6199508 --- /dev/null +++ b/tests/fdb_compat.test/runit @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +bash -n "$0" | exit 1 + +# Remote cursor moves testcase for comdb2 +################################################################################ + + +# args +# +echo "main db vars" +vars="TESTCASE DBNAME DBDIR TESTSROOTDIR TESTDIR CDB2_OPTIONS CDB2_CONFIG SECONDARY_DBNAME SECONDARY_DBDIR SECONDARY_CDB2_CONFIG SECONDARY_CDB2_OPTIONS" +for required in $vars; do + q=${!required} + echo "$required=$q" + if [[ -z "$q" ]]; then + echo "$required not set" >&2 + exit 1 + fi +done + + +#run tests +echo "Starting tests" +echo ./test_fdb.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR +./test_fdb.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR +result=$? + + +if (( $result != 0 )) ; then + echo "Failure" + exit 1 +fi + + +echo "Success" diff --git a/tests/fdb_compat.test/t.csc2 b/tests/fdb_compat.test/t.csc2 new file mode 100644 index 0000000000..e3f5409622 --- /dev/null +++ b/tests/fdb_compat.test/t.csc2 @@ -0,0 +1,8 @@ +schema +{ + int id +} +keys +{ + "ID" = id +} diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh new file mode 100644 index 0000000000..f88a152cae --- /dev/null +++ b/tests/fdb_compat.test/test_fdb.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash + +# Remote cursor moves testcase for comdb2 +################################################################################ + +set -x + +# args +# +a_rdbname=$1 +a_rcdb2config=$2 +a_dbname=$3 +a_cdb2config=$4 +a_dbdir=$5 +a_testdir=$6 + +output=run.out + +rm $output + +R_DB2_OPTIONS="--cdb2cfg ${a_rcdb2config}" +S_CDB2_OPTIONS="--cdb2cfg ${a_cdb2config}" + +# Make sure we talk to the same host +mach=`cdb2sql ${S_CDB2_OPTIONS} --tabs $a_dbname default "SELECT comdb2_host()"` + +S_SQLT="cdb2sql ${S_CDB2_OPTIONS} --tabs --host $mach $a_dbname" +S_SQL="cdb2sql ${S_CDB2_OPTIONS} --host $mach $a_dbname" +R_SQLT="cdb2sql ${R_CDB2_OPTIONS} --tabs --host $mach $a_rdbname" +R_SQL="cdb2sql ${R_CDB2_OPTIONS} --host $mach $a_rdbname" + +function check +{ + set -x + $S_SQL "exec procedure sys.cmd.send('fdb info db')" 2>&1 | cut -f 5- -d ' ' >> $output + $S_SQL "exec procedure sys.cmd.send('fdb init')" + $R_SQL "exec procedure sys.cmd.send('fdb info db')" 2>&1 | cut -f 5- -d ' ' >> $output + $R_SQL "exec procedure sys.cmd.send('fdb init')" +} +function header +{ + set -x + echo "TEST $1" + echo "$2" + echo "TEST $1" >> $output + echo "$2" >> $output +} + +#grab current version +ver=`$R_SQLT "select value from comdb2_tunables where name='fdb_default_version'"` +echo "Current fdb version $ver" >> $output 2>&1 + +# populate table on remote +$S_SQL "insert into t select * from generate_series(1, 3)" >> $output 2>&1 +$R_SQL "insert into t select * from generate_series(11, 13)" >> $output 2>&1 + + +header 1 "remsql run against same version" +$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 +check + +echo $R_SQL "put tunable fdb_default_version 6" + +echo $S_SQL "select * from LOCAL_${a_rdbname}.t order by id" +echo $R_SQL "select * from LOCAL_${a_dbname}.t order by id" + +echo $R_SQL "put tunable fdb_default_version $ver" + +header 2 "remsql run against a pre cdb2api version" +$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 + +$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 +$R_SQL "select * from LOCAL_${a_dbname}.t order by id" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +#test 3 remsql +header 3 "test against a too new version" +let newver=ver+1 +$R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 + +$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 +$R_SQL "select * from LOCAL_${a_dbname}.t order by id" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + + + +#convert the table to actual dbname +sed "s/dorintdb/${a_rdbname}/g" output.log > output.log.actual + +# validate results +testcase_output=$(cat $output) +expected_output=$(cat output.log.actual) +if [[ "$testcase_output" != "$expected_output" ]]; then + + # print message + echo " ^^^^^^^^^^^^" + echo "The above testcase (${testcase}) has failed!!!" + echo " " + echo "Use 'diff ' to see why:" + echo "> diff ${PWD}/{output.log.actual,$output}" + echo " " + diff output.log.actual $output + echo " " + + # quit + exit 1 +fi + +echo "Testcase passed." From b99f319f6ba79876d63a7d2dc9df0c5aa690649d Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Tue, 1 Oct 2024 10:23:16 -0400 Subject: [PATCH 12/21] remtran test attempt --- tests/fdb_compat.test/output.log | 16 ++++++++++++++++ tests/fdb_compat.test/test_fdb.sh | 25 ++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/tests/fdb_compat.test/output.log b/tests/fdb_compat.test/output.log index 8534a7b4d5..53f0519965 100644 --- a/tests/fdb_compat.test/output.log +++ b/tests/fdb_compat.test/output.log @@ -42,3 +42,19 @@ Table "sqlite_stat1" Rootp 1073741832 Remrootp 4 Version=0') Table "sqlite_stat4" Rootp 1073741833 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741831 Remrootp 3 Version=0') Table "t" Rootp 1073741830 Remrootp 2 Version=0') +TEST 4 +test against cdb2api remsql but not remtran +(id=11) +(id=12) +(id=13) +(id=1) +(id=2) +(id=3) +Table "sqlite_stat1" Rootp 1073741840 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741841 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741839 Remrootp 3 Version=0') +Table "t" Rootp 1073741838 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741836 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741837 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741835 Remrootp 3 Version=0') +Table "t" Rootp 1073741834 Remrootp 2 Version=0') diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh index f88a152cae..791b70706d 100644 --- a/tests/fdb_compat.test/test_fdb.sh +++ b/tests/fdb_compat.test/test_fdb.sh @@ -75,7 +75,6 @@ check $R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 -#test 3 remsql header 3 "test against a too new version" let newver=ver+1 $R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 @@ -86,6 +85,30 @@ check $R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 +header 4 "test against cdb2api remsql but not remtran" +$R_SQL "put tunable fdb_default_version 7" >> $output 2>&1 + +$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 +$R_SQL "select * from LOCAL_${a_dbname}.t order by id" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + + +header 5 "test insert, delete, update current version" + +exit 1 +$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(100,110)" >> $output 2>&1 +$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(100,110)" >> $output 2>&1 +check + +$S_SQL "update LOCAL_${a_rdbname}.t(id) set id=id+1 where id>-100" >> $output 2>&1 +$R_SQL "update LOCAL_${a_dbname}.t(id) set id=id+1 where id>-100" >> $output 2>&1 +check + +$S_SQL "delete from LOCAL_${a_rdbname}.t(id) where id>-100" >> $output 2>&1 +$R_SQL "delete from LOCAL_${a_dbname}.t(id) where id>-100" >> $output 2>&1 +check #convert the table to actual dbname From a3130742079dffddb42e9d783fb45696908f77e1 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Mon, 7 Oct 2024 11:06:36 -0400 Subject: [PATCH 13/21] working on fdb_compat same mode writes, still having one issue --- db/fdb_fend.c | 4 ++-- tests/fdb_compat.test/lrl.options | 1 - tests/fdb_compat.test/output.log | 29 ++++++++++++++++++++++ tests/fdb_compat.test/test_fdb.sh | 40 ++++++++++++++++++++++++++----- 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 1b0be78864..68b57e6633 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -2600,7 +2600,7 @@ static fdb_cursor_if_t *_fdb_cursor_open_remote(sqlclntstate *clnt, if (gbl_fdb_remsql_cdb2api && ((!trans && fdb->server_version >= FDB_VER_CDB2API) || (trans && fdb->server_version >= FDB_VER_WR_CDB2API && - clnt->dbtran.mode == TRANLEVEL_SOSQL))) + gbl_fdb_push_remote && clnt->dbtran.mode == TRANLEVEL_SOSQL))) cursor = _cursor_open_remote_cdb2api(clnt, fdb, server_version, flags, version, rootpage, use_ssl); else @@ -4027,7 +4027,7 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, tran = fdb_get_subtran(dtran, fdb); if (!tran) { - if (gbl_fdb_push_remote_write && + if (gbl_fdb_push_remote && gbl_fdb_push_remote_write && fdb->server_version >= FDB_VER_WR_CDB2API && clnt->dbtran.mode == TRANLEVEL_SOSQL) tran = _dtran_get_subtran_cdb2api(clnt, fdb, use_ssl); diff --git a/tests/fdb_compat.test/lrl.options b/tests/fdb_compat.test/lrl.options index 77c8716465..868c7850a5 100644 --- a/tests/fdb_compat.test/lrl.options +++ b/tests/fdb_compat.test/lrl.options @@ -1,2 +1 @@ table t t.csc2 -foreign_db_push_remote 0 diff --git a/tests/fdb_compat.test/output.log b/tests/fdb_compat.test/output.log index 53f0519965..cba92c3ebf 100644 --- a/tests/fdb_compat.test/output.log +++ b/tests/fdb_compat.test/output.log @@ -58,3 +58,32 @@ Table "sqlite_stat1" Rootp 1073741836 Remrootp 4 Version=0') Table "sqlite_stat4" Rootp 1073741837 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741835 Remrootp 3 Version=0') Table "t" Rootp 1073741834 Remrootp 2 Version=0') +TEST 5 +test insert, delete, update current version +(rows inserted=10) +Table "sqlite_stat1" Rootp 1073741844 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741845 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741843 Remrootp 3 Version=0') +Table "t" Rootp 1073741842 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741840 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741841 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741839 Remrootp 3 Version=0') +Table "t" Rootp 1073741838 Remrootp 2 Version=0') +(rows updated=10) +Table "sqlite_stat1" Rootp 1073741848 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741849 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741847 Remrootp 3 Version=0') +Table "t" Rootp 1073741846 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741844 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741845 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741843 Remrootp 3 Version=0') +Table "t" Rootp 1073741842 Remrootp 2 Version=0') +(rows deleted=10) +Table "sqlite_stat1" Rootp 1073741852 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741853 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741851 Remrootp 3 Version=0') +Table "t" Rootp 1073741850 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741848 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741849 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741847 Remrootp 3 Version=0') +Table "t" Rootp 1073741846 Remrootp 2 Version=0') diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh index 791b70706d..c5714c92e3 100644 --- a/tests/fdb_compat.test/test_fdb.sh +++ b/tests/fdb_compat.test/test_fdb.sh @@ -46,6 +46,29 @@ function header echo "$2" >> $output } +function runall +{ + cmd=$1 + sql=$2 + + echo $cmd "$sql" + if [[ -n "$CLUSTER" ]]; then + for node in $CLUSTER; do + $cmd "$sql" + if (( $? != 0 )) ; then + echo "FAILURE $node '$sql'" + exit 1 + fi + done + else + $cmd "$sql" + if (( $? != 0 )) ; then + echo "FAILURE '$sql'" + exit 1 + fi + fi +} + #grab current version ver=`$R_SQLT "select value from comdb2_tunables where name='fdb_default_version'"` echo "Current fdb version $ver" >> $output 2>&1 @@ -54,6 +77,9 @@ echo "Current fdb version $ver" >> $output 2>&1 $S_SQL "insert into t select * from generate_series(1, 3)" >> $output 2>&1 $R_SQL "insert into t select * from generate_series(11, 13)" >> $output 2>&1 +#gonna test remsql, disable push +$S_SQL "put tunable foreign_db_push_remote 0" +$R_SQL "put tunable foreign_db_push_remote 0" header 1 "remsql run against same version" $S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 @@ -97,17 +123,19 @@ $R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 header 5 "test insert, delete, update current version" +echo $S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" +echo $R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" exit 1 -$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(100,110)" >> $output 2>&1 -$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(100,110)" >> $output 2>&1 +$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 check -$S_SQL "update LOCAL_${a_rdbname}.t(id) set id=id+1 where id>-100" >> $output 2>&1 -$R_SQL "update LOCAL_${a_dbname}.t(id) set id=id+1 where id>-100" >> $output 2>&1 +$S_SQL "update LOCAL_${a_rdbname}.t set id=id+1 where id>=101" >> $output 2>&1 +$R_SQL "update LOCAL_${a_dbname}.t set id=id+1 where id>=101" >> $output 2>&1 check -$S_SQL "delete from LOCAL_${a_rdbname}.t(id) where id>-100" >> $output 2>&1 -$R_SQL "delete from LOCAL_${a_dbname}.t(id) where id>-100" >> $output 2>&1 +$S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 +$R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 check From 1fdd85b6bfe80b57f81f4d950073faacb579188e Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Thu, 10 Oct 2024 12:08:29 -0400 Subject: [PATCH 14/21] local push coordinates --- db/dohast.c | 7 ------- db/fdb_fend.c | 4 ++-- db/fdb_push.c | 13 +++++++------ db/sql.h | 2 ++ db/sqlinterfaces.c | 8 ++++++++ 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/db/dohast.c b/db/dohast.c index c1f2b24bbc..cded44f81c 100644 --- a/db/dohast.c +++ b/db/dohast.c @@ -968,10 +968,6 @@ ast_node_t *_get_ast_node(Parse *pParse) int comdb2_check_push_remote(Parse *pParse) { - GET_CLNT; - if (!gbl_fdb_push_remote && !clnt->force_fdb_push_remote && !clnt->force_fdb_push_redirect) - return 0; - if (has_parallel_sql(NULL) == 0) return 0; @@ -996,9 +992,6 @@ int comdb2_check_push_remote(Parse *pParse) int comdb2_check_push_remote_write(Parse *pParse) { - if (!gbl_fdb_push_remote_write) - return 0; - ast_node_t *anode = _get_ast_node(pParse); if (!anode) return 0; diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 68b57e6633..531340bebd 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -2600,7 +2600,7 @@ static fdb_cursor_if_t *_fdb_cursor_open_remote(sqlclntstate *clnt, if (gbl_fdb_remsql_cdb2api && ((!trans && fdb->server_version >= FDB_VER_CDB2API) || (trans && fdb->server_version >= FDB_VER_WR_CDB2API && - gbl_fdb_push_remote && clnt->dbtran.mode == TRANLEVEL_SOSQL))) + clnt->fdb_push_remote && clnt->dbtran.mode == TRANLEVEL_SOSQL))) cursor = _cursor_open_remote_cdb2api(clnt, fdb, server_version, flags, version, rootpage, use_ssl); else @@ -4027,7 +4027,7 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, tran = fdb_get_subtran(dtran, fdb); if (!tran) { - if (gbl_fdb_push_remote && gbl_fdb_push_remote_write && + if (clnt->fdb_push_remote && clnt->fdb_push_remote_write && fdb->server_version >= FDB_VER_WR_CDB2API && clnt->dbtran.mode == TRANLEVEL_SOSQL) tran = _dtran_get_subtran_cdb2api(clnt, fdb, use_ssl); diff --git a/db/fdb_push.c b/db/fdb_push.c index 7b0837b773..26a57f43f9 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -96,11 +96,11 @@ int fdb_push_setup(Parse *pParse, dohsql_node_t *node) struct Db *pDb = &pParse->db->aDb[node->remotedb]; logmsg(LOGMSG_DEBUG, - "CALLING FDB PUSH RUN on query %s (gbl_fdb_push_remote=%d) (clnt force remote? %d) (clnt force redirect? " + "CALLING FDB PUSH RUN on query %s (fdb_push_remote=%d) (clnt force remote? %d) (clnt force redirect? " "%d) (clnt can redirect? %d)\n", - clnt->sql, gbl_fdb_push_remote, clnt->force_fdb_push_remote, clnt->force_fdb_push_redirect, + clnt->sql, clnt->fdb_push_remote, clnt->force_fdb_push_remote, clnt->force_fdb_push_redirect, clnt->can_redirect_fdb); - if (!gbl_fdb_push_remote && !clnt->force_fdb_push_remote && !clnt->force_fdb_push_redirect) + if (!clnt->fdb_push_remote && !clnt->force_fdb_push_remote && !clnt->force_fdb_push_redirect) return -1; if (clnt->disable_fdb_push) @@ -143,9 +143,9 @@ int fdb_push_write_setup(Parse *pParse, enum ast_type type, Table *pTab) assert(pTab->iDb > 1); logmsg(LOGMSG_DEBUG, - "%s query %s (gbl_fdb_push_remote_write=%d)\n", - __func__, clnt->sql, gbl_fdb_push_remote_write); - if (!gbl_fdb_push_remote_write) + "%s query %s (fdb_push_remote_write=%d)\n", + __func__, clnt->sql, clnt->fdb_push_remote_write); + if (!clnt->fdb_push_remote && !clnt->fdb_push_remote_write) return -1; if (clnt->disable_fdb_push) @@ -525,6 +525,7 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) fdb_tran_t *tran = fdb_trans_begin_or_join(clnt, fdb, 0/*TODO*/, &created); if (!tran) return -1; + assert(tran->is_cdb2api); if (created) { /* get a connection */ diff --git a/db/sql.h b/db/sql.h index 0571748012..592cd6efb4 100644 --- a/db/sql.h +++ b/db/sql.h @@ -993,6 +993,8 @@ struct sqlclntstate { char *externalAuthUser; struct remsql_set remsql_set; + int fdb_push_remote; /* cache the global on each prepare */ + int fdb_push_remote_write; /* cache the global on each prepare */ // fdb 2pc int use_2pc; diff --git a/db/sqlinterfaces.c b/db/sqlinterfaces.c index 309c6f509d..e7ef2deeab 100644 --- a/db/sqlinterfaces.c +++ b/db/sqlinterfaces.c @@ -3438,6 +3438,14 @@ static int get_prepared_bound_stmt(struct sqlthdstate *thd, int flags) { int rc; + + /* the underlying code might check these variables multiple times + * and we do not wait a prepared system to race with a change + * in the peer global variables + */ + clnt->fdb_push_remote = gbl_fdb_push_remote; + clnt->fdb_push_remote_write = gbl_fdb_push_remote_write; + if ((rc = get_prepared_stmt(thd, clnt, rec, err, flags)) != 0) { return rc; } From 032b1fa03b803c6f631fc70c51f327fff290114b Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Fri, 11 Oct 2024 12:51:17 -0400 Subject: [PATCH 15/21] in progress --- db/fdb_fend.c | 26 ++++++++++++++++---------- tests/fdb_compat.test/lrl.options | 1 + tests/fdb_compat.test/test_fdb.sh | 10 +++++++--- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/db/fdb_fend.c b/db/fdb_fend.c index 531340bebd..f6e02e0913 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -4027,9 +4027,13 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, tran = fdb_get_subtran(dtran, fdb); if (!tran) { - if (clnt->fdb_push_remote && clnt->fdb_push_remote_write && - fdb->server_version >= FDB_VER_WR_CDB2API && - clnt->dbtran.mode == TRANLEVEL_SOSQL) + /* we allow remtran over cdb2api if remote allows and either: + * 1) standalone write and push remote write is enabled + * 2) socksql txn and push remote read and writes are enabled + */ + if (fdb->server_version >= FDB_VER_WR_CDB2API && clnt->fdb_push_remote_write && + (/*1*/!clnt->in_client_trans || + (/*2*/clnt->fdb_push_remote && clnt->dbtran.mode == TRANLEVEL_SOSQL))) tran = _dtran_get_subtran_cdb2api(clnt, fdb, use_ssl); else tran = _dtran_get_subtran(clnt, fdb, use_ssl); @@ -4039,9 +4043,9 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, listc_atl(&dtran->fdb_trans, tran); if (gbl_fdb_track) { - logmsg(LOGMSG_USER, "%s Created tid=%s db=\"%s\"\n", __func__, + logmsg(LOGMSG_USER, "%s Created tid=%s db=\"%s\" cdb2api %d\n", __func__, comdb2uuidstr((unsigned char *)tran->tid, us), - fdb->dbname); + fdb->dbname, tran->is_cdb2api); } if (created) @@ -4049,9 +4053,9 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, } else { if (gbl_fdb_track) { uuidstr_t us; - logmsg(LOGMSG_USER, "%s Reusing tid=%s db=\"%s\"\n", __func__, + logmsg(LOGMSG_USER, "%s Reusing tid=%s db=\"%s\" cdb2api %d\n", __func__, comdb2uuidstr((unsigned char *)tran->tid, us), - fdb->dbname); + fdb->dbname, tran->is_cdb2api); } /* this is a bug, probably sharing the wrong fdb_tran after switching to * a lower version protocol @@ -5902,12 +5906,14 @@ int fdb_default_ver_set(int val) if (val < FDB_VER_CDB2API) { /* do not speak cdb2api if we set this too low */ gbl_fdb_remsql_cdb2api = 0; - /* disable also push, otherwise this will break transactional - * queries - */ + /* disable also push, otherwise this will break transactional queries */ gbl_fdb_push_remote_write = 0; } else if (val < FDB_VER_WR_CDB2API) { + gbl_fdb_remsql_cdb2api = 1; gbl_fdb_push_remote_write = 0; + } else { + gbl_fdb_remsql_cdb2api = 1; + gbl_fdb_push_remote_write = 1; } } return 0; diff --git a/tests/fdb_compat.test/lrl.options b/tests/fdb_compat.test/lrl.options index 868c7850a5..776e44cc67 100644 --- a/tests/fdb_compat.test/lrl.options +++ b/tests/fdb_compat.test/lrl.options @@ -1 +1,2 @@ table t t.csc2 +fdbdebg 1 diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh index c5714c92e3..f8b4828f08 100644 --- a/tests/fdb_compat.test/test_fdb.sh +++ b/tests/fdb_compat.test/test_fdb.sh @@ -123,9 +123,13 @@ $R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 header 5 "test insert, delete, update current version" -echo $S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" -echo $R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" -exit 1 +#gonna test remtran, it needs push code +#$S_SQL "put tunable foreign_db_push_remote 1" +#$R_SQL "put tunable foreign_db_push_remote 1" + +#echo $S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" +#echo $R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" +#exit 1 $S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 $R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 check From 5994e09a6a1b0b5e3d80862ac93b6ee050308b83 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Wed, 16 Oct 2024 10:13:54 -0400 Subject: [PATCH 16/21] regression standalone writes --- db/comdb2.h | 1 + db/db_tunables.c | 11 +++++++ db/db_tunables.h | 2 +- db/fdb_fend.c | 22 +++++++++++--- db/fdb_push.c | 50 +++++++++++++++++++++---------- db/sqlinterfaces.c | 1 + tests/fdb_compat.test/output.log | 3 ++ tests/fdb_compat.test/test_fdb.sh | 10 +++---- 8 files changed, 74 insertions(+), 26 deletions(-) diff --git a/db/comdb2.h b/db/comdb2.h index 4f983d4d75..0190c7a3f9 100644 --- a/db/comdb2.h +++ b/db/comdb2.h @@ -3687,6 +3687,7 @@ extern int gbl_server_admin_mode; void csc2_free_all(void); int fdb_default_ver_set(int val); +int fdb_push_write_set(int val); /* hack to temporary allow bools on production stage */ void csc2_allow_bools(void); diff --git a/db/db_tunables.c b/db/db_tunables.c index a18e216fc1..5f4c9e1a35 100644 --- a/db/db_tunables.c +++ b/db/db_tunables.c @@ -1086,6 +1086,17 @@ static int fdb_default_ver_update(void *context, void *value) return 0; } +static int fdb_push_write_update(void *context, void *value) +{ + comdb2_tunable *tunable = (comdb2_tunable *)context; + int val = *(int*)value; + if (fdb_push_write_set(val)) + return -1; + *(int*)tunable->var = val; + return 0; +} + + /* Forward declaration */ int ctrace_set_rollat(void *unused, void *value); diff --git a/db/db_tunables.h b/db/db_tunables.h index c59dd124d1..561c2cdbf8 100644 --- a/db/db_tunables.h +++ b/db/db_tunables.h @@ -554,7 +554,7 @@ REGISTER_TUNABLE("foreign_db_push_remote", NULL, TUNABLE_BOOLEAN, &gbl_fdb_push_ REGISTER_TUNABLE("foreign_db_push_remote_write", NULL, TUNABLE_BOOLEAN, &gbl_fdb_push_remote_write, NOARG, NULL, NULL, NULL, NULL); REGISTER_TUNABLE("foreign_db_push_redirect", "Redirect fdb query to run via client instead of on server. (Default: off)", TUNABLE_BOOLEAN, - &gbl_fdb_push_redirect_foreign, NOARG, NULL, NULL, NULL, NULL); + &gbl_fdb_push_redirect_foreign, NOARG, NULL, NULL, fdb_push_write_update, NULL); REGISTER_TUNABLE("foreign_db_resolve_local", NULL, TUNABLE_BOOLEAN, &gbl_fdb_resolve_local, READONLY | NOARG | READEARLY, NULL, NULL, NULL, NULL); diff --git a/db/fdb_fend.c b/db/fdb_fend.c index f6e02e0913..e655270610 100644 --- a/db/fdb_fend.c +++ b/db/fdb_fend.c @@ -59,6 +59,7 @@ #include "comdb2_query_preparer.h" #include "alias.h" #include "dohsql.h" +#include "bdb_schemachange.h" extern int gbl_fdb_resolve_local; extern int gbl_fdb_allow_cross_classes; @@ -2600,7 +2601,7 @@ static fdb_cursor_if_t *_fdb_cursor_open_remote(sqlclntstate *clnt, if (gbl_fdb_remsql_cdb2api && ((!trans && fdb->server_version >= FDB_VER_CDB2API) || (trans && fdb->server_version >= FDB_VER_WR_CDB2API && - clnt->fdb_push_remote && clnt->dbtran.mode == TRANLEVEL_SOSQL))) + !clnt->disable_fdb_push && clnt->fdb_push_remote && clnt->dbtran.mode == TRANLEVEL_SOSQL))) cursor = _cursor_open_remote_cdb2api(clnt, fdb, server_version, flags, version, rootpage, use_ssl); else @@ -4031,7 +4032,7 @@ static fdb_tran_t *fdb_trans_dtran_get_subtran(sqlclntstate *clnt, * 1) standalone write and push remote write is enabled * 2) socksql txn and push remote read and writes are enabled */ - if (fdb->server_version >= FDB_VER_WR_CDB2API && clnt->fdb_push_remote_write && + if (fdb->server_version >= FDB_VER_WR_CDB2API && !clnt->disable_fdb_push && clnt->fdb_push_remote_write && (/*1*/!clnt->in_client_trans || (/*2*/clnt->fdb_push_remote && clnt->dbtran.mode == TRANLEVEL_SOSQL))) tran = _dtran_get_subtran_cdb2api(clnt, fdb, use_ssl); @@ -4645,8 +4646,8 @@ static void fdb_init(void) bzero(fdbs.arr, fdbs.nused * sizeof(fdbs.arr[0])); fdbs.nused = 0; - logmsg(LOGMSG_INFO, "Replicant updating views counter=%d\n", gbl_views_gen); - ++gbl_views_gen; + logmsg(LOGMSG_INFO, "FDB testing reset dbopen_gen %d\n", bdb_get_dbopen_gen()); + BDB_BUMP_DBOPEN_GEN(invalid, "fdb_init"); pthread_rwlock_unlock(&fdbs.arr_lock); } @@ -5913,12 +5914,25 @@ int fdb_default_ver_set(int val) gbl_fdb_push_remote_write = 0; } else { gbl_fdb_remsql_cdb2api = 1; + gbl_fdb_push_remote = 1; gbl_fdb_push_remote_write = 1; } } return 0; } +int fdb_push_write_set(int val) +{ + if (val) { + /* enabling push write requires push read */ + gbl_fdb_push_remote = 1; + gbl_fdb_push_remote_write = 1; + } else { + gbl_fdb_push_remote_write = 0; + } + return 0; +} + /** * Check that fdb class matches a specific class * diff --git a/db/fdb_push.c b/db/fdb_push.c index 26a57f43f9..7d2104ed1b 100644 --- a/db/fdb_push.c +++ b/db/fdb_push.c @@ -512,12 +512,18 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) clnt->had_errors = 0; fdb = get_fdb(push->remotedb); - if (!fdb) - return -2; + if (!fdb) { + logmsg(LOGMSG_ERROR, "FDB push missing fdb %s\n", push->remotedb); + rc = -2; + goto free_push; + } rc = fdb_check_class_match(fdb, push->local, push->class, push->class_override); - if (rc) - return -2; + if (rc) { + logmsg(LOGMSG_ERROR, "FDB push class mismatch\n"); + rc = -2; + goto free_push; + } /* fdb is the remote db we want, and it supports remote writes */ @@ -530,24 +536,24 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) if (created) { /* get a connection */ tran->is_cdb2api = 1; - hndl = tran->fcon.hndl = _hndl_open(clnt, NULL, - 0 /* no sqlite rows for writes */, err); - if (!tran->fcon.hndl) - return -1; + tran->fcon.hndl = _hndl_open(clnt, NULL, 0 /* no sqlite rows for writes */, err); + if (!tran->fcon.hndl) { + rc = -2; + goto free; + } if (clnt->in_client_trans) { /* if not standalone, and this is the first reachout to this fdb, send begin */ clnt->intrans = 1; - rc = cdb2_run_statement(hndl, "begin"); + rc = cdb2_run_statement(tran->fcon.hndl, "begin"); while (rc == CDB2_OK) { - rc = cdb2_next_record(hndl); + rc = cdb2_next_record(tran->fcon.hndl); } if (rc != CDB2_OK_DONE) { goto hndl_err; } } - } else { - hndl = tran->fcon.hndl; } + hndl = tran->fcon.hndl; /* run the statement */ rc = _run_statement(clnt, hndl, err); @@ -579,7 +585,8 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) rc = write_response(clnt, RESPONSE_COLUMNS_FDB_PUSH, hndl, ncols); if (rc) { errstat_set_rcstrf(err, -1, "failed to write columns"); - return -1; + rc = -1; + goto free; } clnt->effects.num_affected = effects.num_affected; @@ -599,14 +606,16 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) rc = write_response(clnt, RESPONSE_ROW_REMTRAN, NULL, val); if (rc) { errstat_set_rcstrf(err, -1, "failed to write counter"); - return -1; + rc = -1; + goto free; } /* write answer */ rc = write_response(clnt, RESPONSE_ROW_LAST, NULL, 0); if (rc) { errstat_set_rcstrf(err, -1, "failed to write last row"); - return -1; + rc = -1; + goto free; } goto free; } else { @@ -618,7 +627,6 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) hndl_err: const char *errstr = cdb2_errstr(hndl); errstat_set_rcstrf(err, rc, "%s", errstr); - //rc = write_response(clnt, RESPONSE_ERROR_PREPARE, (void*)errstr, rc); rc = write_response(clnt, RESPONSE_ERROR, (void*)errstr, rc); if (rc) { logmsg(LOGMSG_DEBUG, "Failed to write error to client"); @@ -626,6 +634,16 @@ int handle_fdb_push_write(sqlclntstate *clnt, struct errstat *err) free: /* remote the fdb_tran_t */ fdb_free_tran(clnt, tran); +free_push: + if (rc == -2) { + logmsg(LOGMSG_ERROR, "FDB push returning -2\n"); + /* This will get retried as non-cdb2api, free fdb_push + * so that the postpone message works + */ + clnt->fdb_push = NULL; + free(push->remotedb); + free(push); + } return rc; } diff --git a/db/sqlinterfaces.c b/db/sqlinterfaces.c index e7ef2deeab..a3aa7d66aa 100644 --- a/db/sqlinterfaces.c +++ b/db/sqlinterfaces.c @@ -4024,6 +4024,7 @@ int handle_sqlite_requests(struct sqlthdstate *thd, struct sqlclntstate *clnt) else rc = handle_fdb_push_write(clnt, &err); if (rc == -2) { + logmsg(LOGMSG_ERROR, "QUERY %s disable push\n", clnt->sql); /* remote server does not support proxy, retry without */ clnt->disable_fdb_push = 1; goto retry_legacy_remote; diff --git a/tests/fdb_compat.test/output.log b/tests/fdb_compat.test/output.log index cba92c3ebf..7e2b047a6c 100644 --- a/tests/fdb_compat.test/output.log +++ b/tests/fdb_compat.test/output.log @@ -61,6 +61,7 @@ Table "t" Rootp 1073741834 Remrootp 2 Version=0') TEST 5 test insert, delete, update current version (rows inserted=10) +(rows inserted=10) Table "sqlite_stat1" Rootp 1073741844 Remrootp 4 Version=0') Table "sqlite_stat4" Rootp 1073741845 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741843 Remrootp 3 Version=0') @@ -70,6 +71,7 @@ Table "sqlite_stat4" Rootp 1073741841 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741839 Remrootp 3 Version=0') Table "t" Rootp 1073741838 Remrootp 2 Version=0') (rows updated=10) +(rows updated=10) Table "sqlite_stat1" Rootp 1073741848 Remrootp 4 Version=0') Table "sqlite_stat4" Rootp 1073741849 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741847 Remrootp 3 Version=0') @@ -79,6 +81,7 @@ Table "sqlite_stat4" Rootp 1073741845 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741843 Remrootp 3 Version=0') Table "t" Rootp 1073741842 Remrootp 2 Version=0') (rows deleted=10) +(rows deleted=10) Table "sqlite_stat1" Rootp 1073741852 Remrootp 4 Version=0') Table "sqlite_stat4" Rootp 1073741853 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741851 Remrootp 3 Version=0') diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh index f8b4828f08..d39ece704b 100644 --- a/tests/fdb_compat.test/test_fdb.sh +++ b/tests/fdb_compat.test/test_fdb.sh @@ -124,12 +124,12 @@ $R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 header 5 "test insert, delete, update current version" #gonna test remtran, it needs push code -#$S_SQL "put tunable foreign_db_push_remote 1" -#$R_SQL "put tunable foreign_db_push_remote 1" +$S_SQL "put tunable foreign_db_push_remote 1" +$R_SQL "put tunable foreign_db_push_remote 1" + +#echo cdb2sql $a_dbname localhost "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" +#echo cdb2sql $a_rdbname localhost "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" -#echo $S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" -#echo $R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" -#exit 1 $S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 $R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 check From f86169bbec89a98688a481397fcd1291845a53d4 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Wed, 16 Oct 2024 14:21:03 -0400 Subject: [PATCH 17/21] client txn single writes --- tests/fdb_compat.test/output.log | 74 +++++++++++++++++++++++++ tests/fdb_compat.test/test_fdb.sh | 90 +++++++++++++++++++++++-------- 2 files changed, 141 insertions(+), 23 deletions(-) diff --git a/tests/fdb_compat.test/output.log b/tests/fdb_compat.test/output.log index 7e2b047a6c..2290b5fc24 100644 --- a/tests/fdb_compat.test/output.log +++ b/tests/fdb_compat.test/output.log @@ -90,3 +90,77 @@ Table "sqlite_stat1" Rootp 1073741848 Remrootp 4 Version=0') Table "sqlite_stat4" Rootp 1073741849 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741847 Remrootp 3 Version=0') Table "t" Rootp 1073741846 Remrootp 2 Version=0') +TEST 6 +remtran run against a pre cdb2api version +(rows inserted=10) +(rows inserted=10) +Table "sqlite_stat1" Rootp 1073741856 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741857 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741855 Remrootp 3 Version=0') +Table "t" Rootp 1073741854 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741852 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741853 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741851 Remrootp 3 Version=0') +Table "t" Rootp 1073741850 Remrootp 2 Version=0') +(rows updated=10) +(rows updated=10) +Table "sqlite_stat1" Rootp 1073741860 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741861 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741859 Remrootp 3 Version=0') +Table "t" Rootp 1073741858 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741856 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741857 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741855 Remrootp 3 Version=0') +Table "t" Rootp 1073741854 Remrootp 2 Version=0') +(rows deleted=10) +(rows deleted=10) +Table "sqlite_stat1" Rootp 1073741864 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741865 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741863 Remrootp 3 Version=0') +Table "t" Rootp 1073741862 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741860 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741861 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741859 Remrootp 3 Version=0') +Table "t" Rootp 1073741858 Remrootp 2 Version=0') +TEST 7 +remtran test against a too new version +(rows inserted=10) +(rows inserted=10) +Table "sqlite_stat1" Rootp 1073741868 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741869 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741867 Remrootp 3 Version=0') +Table "t" Rootp 1073741866 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741864 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741865 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741863 Remrootp 3 Version=0') +Table "t" Rootp 1073741862 Remrootp 2 Version=0') +(rows updated=10) +(rows updated=10) +Table "sqlite_stat1" Rootp 1073741872 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741873 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741871 Remrootp 3 Version=0') +Table "t" Rootp 1073741870 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741868 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741869 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741867 Remrootp 3 Version=0') +Table "t" Rootp 1073741866 Remrootp 2 Version=0') +(rows deleted=10) +(rows deleted=10) +Table "sqlite_stat1" Rootp 1073741876 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741877 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741875 Remrootp 3 Version=0') +Table "t" Rootp 1073741874 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741872 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741873 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741871 Remrootp 3 Version=0') +Table "t" Rootp 1073741870 Remrootp 2 Version=0') +TEST 8 +remtran test for client transactions +Table "sqlite_stat1" Rootp 1073741880 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741881 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741879 Remrootp 3 Version=0') +Table "t" Rootp 1073741878 Remrootp 2 Version=0') +Table "sqlite_stat1" Rootp 1073741884 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741885 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741883 Remrootp 3 Version=0') +Table "t" Rootp 1073741882 Remrootp 2 Version=0') diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh index d39ece704b..afbbe42ef7 100644 --- a/tests/fdb_compat.test/test_fdb.sh +++ b/tests/fdb_compat.test/test_fdb.sh @@ -46,29 +46,6 @@ function header echo "$2" >> $output } -function runall -{ - cmd=$1 - sql=$2 - - echo $cmd "$sql" - if [[ -n "$CLUSTER" ]]; then - for node in $CLUSTER; do - $cmd "$sql" - if (( $? != 0 )) ; then - echo "FAILURE $node '$sql'" - exit 1 - fi - done - else - $cmd "$sql" - if (( $? != 0 )) ; then - echo "FAILURE '$sql'" - exit 1 - fi - fi -} - #grab current version ver=`$R_SQLT "select value from comdb2_tunables where name='fdb_default_version'"` echo "Current fdb version $ver" >> $output 2>&1 @@ -142,6 +119,73 @@ $S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 $R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 check +header 6 "remtran run against a pre cdb2api version" +$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 + +$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +check + +$S_SQL "update LOCAL_${a_rdbname}.t set id=id+1 where id>=101" >> $output 2>&1 +$R_SQL "update LOCAL_${a_dbname}.t set id=id+1 where id>=101" >> $output 2>&1 +check + +$S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 +$R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +header 7 "remtran test against a too new version" +$R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 + +$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +check + +$S_SQL "update LOCAL_${a_rdbname}.t set id=id+1 where id>=101" >> $output 2>&1 +$R_SQL "update LOCAL_${a_dbname}.t set id=id+1 where id>=101" >> $output 2>&1 +check + +$S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 +$R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +header 8 "remtran test for client transactions" +echo $S_SQL < output.log.actual From c2eca2440c7280eebbf4ea91707169e7c295d1d4 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Wed, 16 Oct 2024 15:05:30 -0400 Subject: [PATCH 18/21] more client txn single writes tests --- tests/fdb_compat.test/output.log | 65 ++++++++++++++++++++++ tests/fdb_compat.test/test_fdb.sh | 90 +++++++++++++++++++++++++++++-- tests/unsetup | 2 + 3 files changed, 153 insertions(+), 4 deletions(-) diff --git a/tests/fdb_compat.test/output.log b/tests/fdb_compat.test/output.log index 2290b5fc24..086401e7fd 100644 --- a/tests/fdb_compat.test/output.log +++ b/tests/fdb_compat.test/output.log @@ -156,11 +156,76 @@ Index "$ID_52596C31" for table "t" Rootp 1073741871 Remrootp 3 Version=0') Table "t" Rootp 1073741870 Remrootp 2 Version=0') TEST 8 remtran test for client transactions +(id=11) +(id=12) +(id=13) +(id=100) Table "sqlite_stat1" Rootp 1073741880 Remrootp 4 Version=0') Table "sqlite_stat4" Rootp 1073741881 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741879 Remrootp 3 Version=0') Table "t" Rootp 1073741878 Remrootp 2 Version=0') +(id=11) +(id=12) +(id=13) +(id=101) Table "sqlite_stat1" Rootp 1073741884 Remrootp 4 Version=0') Table "sqlite_stat4" Rootp 1073741885 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741883 Remrootp 3 Version=0') Table "t" Rootp 1073741882 Remrootp 2 Version=0') +(id=11) +(id=12) +(id=13) +Table "sqlite_stat1" Rootp 1073741888 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741889 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741887 Remrootp 3 Version=0') +Table "t" Rootp 1073741886 Remrootp 2 Version=0') +TEST 9 +remtran test for client transactions pre-cdb2api +(id=11) +(id=12) +(id=13) +(id=200) +Table "sqlite_stat1" Rootp 1073741892 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741893 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741891 Remrootp 3 Version=0') +Table "t" Rootp 1073741890 Remrootp 2 Version=0') +(id=11) +(id=12) +(id=13) +(id=201) +Table "sqlite_stat1" Rootp 1073741896 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741897 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741895 Remrootp 3 Version=0') +Table "t" Rootp 1073741894 Remrootp 2 Version=0') +(id=11) +(id=12) +(id=13) +Table "sqlite_stat1" Rootp 1073741900 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741901 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741899 Remrootp 3 Version=0') +Table "t" Rootp 1073741898 Remrootp 2 Version=0') +TEST 10 +remtran test for client transactions newer than current +(id=11) +(id=12) +(id=13) +(id=300) +Table "sqlite_stat1" Rootp 1073741904 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741905 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741903 Remrootp 3 Version=0') +Table "t" Rootp 1073741902 Remrootp 2 Version=0') +(id=11) +(id=12) +(id=13) +(id=301) +Table "sqlite_stat1" Rootp 1073741908 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741909 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741907 Remrootp 3 Version=0') +Table "t" Rootp 1073741906 Remrootp 2 Version=0') +(id=11) +(id=12) +(id=13) +Table "sqlite_stat1" Rootp 1073741912 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741913 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741911 Remrootp 3 Version=0') +Table "t" Rootp 1073741910 Remrootp 2 Version=0') diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh index afbbe42ef7..2a5f3ecb81 100644 --- a/tests/fdb_compat.test/test_fdb.sh +++ b/tests/fdb_compat.test/test_fdb.sh @@ -104,9 +104,6 @@ header 5 "test insert, delete, update current version" $S_SQL "put tunable foreign_db_push_remote 1" $R_SQL "put tunable foreign_db_push_remote 1" -#echo cdb2sql $a_dbname localhost "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" -#echo cdb2sql $a_rdbname localhost "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" - $S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 $R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 check @@ -154,7 +151,7 @@ check $R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 header 8 "remtran test for client transactions" -echo $S_SQL <> $output 2>&1 check $S_SQL <> $output 2>&1 check $S_SQL <> $output 2>&1 +check + +header 9 "remtran test for client transactions pre-cdb2api" +$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 check +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +header 10 "remtran test for client transactions newer than current" +$R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + #convert the table to actual dbname sed "s/dorintdb/${a_rdbname}/g" output.log > output.log.actual diff --git a/tests/unsetup b/tests/unsetup index 33951af206..bc70c8cbcf 100755 --- a/tests/unsetup +++ b/tests/unsetup @@ -5,6 +5,8 @@ set -x +exit 0 + [[ $COMDB2_UNITTEST == 1 ]] && exit 0 echo "!$TESTCASE: stopping" From cc9d8f78fe49974a8ed9e373f8f8880877a1a6ff Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Wed, 16 Oct 2024 16:49:27 -0400 Subject: [PATCH 19/21] client txn with selects --- tests/fdb_compat.test/output.log | 25 +++++++++++++++++ tests/fdb_compat.test/test_fdb.sh | 45 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/tests/fdb_compat.test/output.log b/tests/fdb_compat.test/output.log index 086401e7fd..bf5dbb3fd4 100644 --- a/tests/fdb_compat.test/output.log +++ b/tests/fdb_compat.test/output.log @@ -229,3 +229,28 @@ Table "sqlite_stat1" Rootp 1073741912 Remrootp 4 Version=0') Table "sqlite_stat4" Rootp 1073741913 Remrootp 5 Version=0') Index "$ID_52596C31" for table "t" Rootp 1073741911 Remrootp 3 Version=0') Table "t" Rootp 1073741910 Remrootp 2 Version=0') +TEST 11 +remtran test for client transactions with select +(id=11) +(id=12) +(id=13) +(id=400) +Table "sqlite_stat1" Rootp 1073741916 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741917 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741915 Remrootp 3 Version=0') +Table "t" Rootp 1073741914 Remrootp 2 Version=0') +(id=11) +(id=12) +(id=13) +(id=401) +Table "sqlite_stat1" Rootp 1073741920 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741921 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741919 Remrootp 3 Version=0') +Table "t" Rootp 1073741918 Remrootp 2 Version=0') +(id=11) +(id=12) +(id=13) +Table "sqlite_stat1" Rootp 1073741924 Remrootp 4 Version=0') +Table "sqlite_stat4" Rootp 1073741925 Remrootp 5 Version=0') +Index "$ID_52596C31" for table "t" Rootp 1073741923 Remrootp 3 Version=0') +Table "t" Rootp 1073741922 Remrootp 2 Version=0') diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh index 2a5f3ecb81..4132dd4fa1 100644 --- a/tests/fdb_compat.test/test_fdb.sh +++ b/tests/fdb_compat.test/test_fdb.sh @@ -269,6 +269,51 @@ check $R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 +header 11 "remtran test for client transactions with select" +$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + #convert the table to actual dbname sed "s/dorintdb/${a_rdbname}/g" output.log > output.log.actual From b321ab9bfd582e6194f5b6bab47665ddf0506785 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Thu, 17 Oct 2024 10:44:27 -0400 Subject: [PATCH 20/21] chmod --- tests/fdb_compat.test/runit | 35 --- tests/fdb_compat.test/test_fdb.sh | 339 ------------------------------ 2 files changed, 374 deletions(-) delete mode 100644 tests/fdb_compat.test/runit delete mode 100644 tests/fdb_compat.test/test_fdb.sh diff --git a/tests/fdb_compat.test/runit b/tests/fdb_compat.test/runit deleted file mode 100644 index 7bc6199508..0000000000 --- a/tests/fdb_compat.test/runit +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -bash -n "$0" | exit 1 - -# Remote cursor moves testcase for comdb2 -################################################################################ - - -# args -# -echo "main db vars" -vars="TESTCASE DBNAME DBDIR TESTSROOTDIR TESTDIR CDB2_OPTIONS CDB2_CONFIG SECONDARY_DBNAME SECONDARY_DBDIR SECONDARY_CDB2_CONFIG SECONDARY_CDB2_OPTIONS" -for required in $vars; do - q=${!required} - echo "$required=$q" - if [[ -z "$q" ]]; then - echo "$required not set" >&2 - exit 1 - fi -done - - -#run tests -echo "Starting tests" -echo ./test_fdb.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR -./test_fdb.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR -result=$? - - -if (( $result != 0 )) ; then - echo "Failure" - exit 1 -fi - - -echo "Success" diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh deleted file mode 100644 index 4132dd4fa1..0000000000 --- a/tests/fdb_compat.test/test_fdb.sh +++ /dev/null @@ -1,339 +0,0 @@ -#!/usr/bin/env bash - -# Remote cursor moves testcase for comdb2 -################################################################################ - -set -x - -# args -# -a_rdbname=$1 -a_rcdb2config=$2 -a_dbname=$3 -a_cdb2config=$4 -a_dbdir=$5 -a_testdir=$6 - -output=run.out - -rm $output - -R_DB2_OPTIONS="--cdb2cfg ${a_rcdb2config}" -S_CDB2_OPTIONS="--cdb2cfg ${a_cdb2config}" - -# Make sure we talk to the same host -mach=`cdb2sql ${S_CDB2_OPTIONS} --tabs $a_dbname default "SELECT comdb2_host()"` - -S_SQLT="cdb2sql ${S_CDB2_OPTIONS} --tabs --host $mach $a_dbname" -S_SQL="cdb2sql ${S_CDB2_OPTIONS} --host $mach $a_dbname" -R_SQLT="cdb2sql ${R_CDB2_OPTIONS} --tabs --host $mach $a_rdbname" -R_SQL="cdb2sql ${R_CDB2_OPTIONS} --host $mach $a_rdbname" - -function check -{ - set -x - $S_SQL "exec procedure sys.cmd.send('fdb info db')" 2>&1 | cut -f 5- -d ' ' >> $output - $S_SQL "exec procedure sys.cmd.send('fdb init')" - $R_SQL "exec procedure sys.cmd.send('fdb info db')" 2>&1 | cut -f 5- -d ' ' >> $output - $R_SQL "exec procedure sys.cmd.send('fdb init')" -} -function header -{ - set -x - echo "TEST $1" - echo "$2" - echo "TEST $1" >> $output - echo "$2" >> $output -} - -#grab current version -ver=`$R_SQLT "select value from comdb2_tunables where name='fdb_default_version'"` -echo "Current fdb version $ver" >> $output 2>&1 - -# populate table on remote -$S_SQL "insert into t select * from generate_series(1, 3)" >> $output 2>&1 -$R_SQL "insert into t select * from generate_series(11, 13)" >> $output 2>&1 - -#gonna test remsql, disable push -$S_SQL "put tunable foreign_db_push_remote 0" -$R_SQL "put tunable foreign_db_push_remote 0" - -header 1 "remsql run against same version" -$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 -check - -echo $R_SQL "put tunable fdb_default_version 6" - -echo $S_SQL "select * from LOCAL_${a_rdbname}.t order by id" -echo $R_SQL "select * from LOCAL_${a_dbname}.t order by id" - -echo $R_SQL "put tunable fdb_default_version $ver" - -header 2 "remsql run against a pre cdb2api version" -$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 - -$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 -$R_SQL "select * from LOCAL_${a_dbname}.t order by id" >> $output 2>&1 -check - -$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 - -header 3 "test against a too new version" -let newver=ver+1 -$R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 - -$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 -$R_SQL "select * from LOCAL_${a_dbname}.t order by id" >> $output 2>&1 -check - -$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 - -header 4 "test against cdb2api remsql but not remtran" -$R_SQL "put tunable fdb_default_version 7" >> $output 2>&1 - -$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 -$R_SQL "select * from LOCAL_${a_dbname}.t order by id" >> $output 2>&1 -check - -$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 - - -header 5 "test insert, delete, update current version" - -#gonna test remtran, it needs push code -$S_SQL "put tunable foreign_db_push_remote 1" -$R_SQL "put tunable foreign_db_push_remote 1" - -$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 -$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 -check - -$S_SQL "update LOCAL_${a_rdbname}.t set id=id+1 where id>=101" >> $output 2>&1 -$R_SQL "update LOCAL_${a_dbname}.t set id=id+1 where id>=101" >> $output 2>&1 -check - -$S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 -$R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 -check - -header 6 "remtran run against a pre cdb2api version" -$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 - -$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 -$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 -check - -$S_SQL "update LOCAL_${a_rdbname}.t set id=id+1 where id>=101" >> $output 2>&1 -$R_SQL "update LOCAL_${a_dbname}.t set id=id+1 where id>=101" >> $output 2>&1 -check - -$S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 -$R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 -check - -$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 - -header 7 "remtran test against a too new version" -$R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 - -$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 -$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 -check - -$S_SQL "update LOCAL_${a_rdbname}.t set id=id+1 where id>=101" >> $output 2>&1 -$R_SQL "update LOCAL_${a_dbname}.t set id=id+1 where id>=101" >> $output 2>&1 -check - -$S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 -$R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 -check - -$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 - -header 8 "remtran test for client transactions" -$S_SQL <> $output 2>&1 -check - -$S_SQL <> $output 2>&1 -check - -$S_SQL <> $output 2>&1 -check - -header 9 "remtran test for client transactions pre-cdb2api" -$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 - -$S_SQL <> $output 2>&1 -check - -$S_SQL <> $output 2>&1 -check - -$S_SQL <> $output 2>&1 -check - -$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 - -header 10 "remtran test for client transactions newer than current" -$R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 - -$S_SQL <> $output 2>&1 -check - -$S_SQL <> $output 2>&1 -check - -$S_SQL <> $output 2>&1 -check - -$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 - -header 11 "remtran test for client transactions with select" -$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 - -$S_SQL <> $output 2>&1 -check - -$S_SQL <> $output 2>&1 -check - -$S_SQL <> $output 2>&1 -check - -#convert the table to actual dbname -sed "s/dorintdb/${a_rdbname}/g" output.log > output.log.actual - -# validate results -testcase_output=$(cat $output) -expected_output=$(cat output.log.actual) -if [[ "$testcase_output" != "$expected_output" ]]; then - - # print message - echo " ^^^^^^^^^^^^" - echo "The above testcase (${testcase}) has failed!!!" - echo " " - echo "Use 'diff ' to see why:" - echo "> diff ${PWD}/{output.log.actual,$output}" - echo " " - diff output.log.actual $output - echo " " - - # quit - exit 1 -fi - -echo "Testcase passed." From ab0408424b2ca4c3f4b7f74d4ff0dfc46c1a0735 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Thu, 17 Oct 2024 12:03:13 -0400 Subject: [PATCH 21/21] exec --- tests/fdb_compat.test/runit | 35 +++ tests/fdb_compat.test/test_fdb.sh | 339 ++++++++++++++++++++++++++++++ 2 files changed, 374 insertions(+) create mode 100755 tests/fdb_compat.test/runit create mode 100755 tests/fdb_compat.test/test_fdb.sh diff --git a/tests/fdb_compat.test/runit b/tests/fdb_compat.test/runit new file mode 100755 index 0000000000..7bc6199508 --- /dev/null +++ b/tests/fdb_compat.test/runit @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +bash -n "$0" | exit 1 + +# Remote cursor moves testcase for comdb2 +################################################################################ + + +# args +# +echo "main db vars" +vars="TESTCASE DBNAME DBDIR TESTSROOTDIR TESTDIR CDB2_OPTIONS CDB2_CONFIG SECONDARY_DBNAME SECONDARY_DBDIR SECONDARY_CDB2_CONFIG SECONDARY_CDB2_OPTIONS" +for required in $vars; do + q=${!required} + echo "$required=$q" + if [[ -z "$q" ]]; then + echo "$required not set" >&2 + exit 1 + fi +done + + +#run tests +echo "Starting tests" +echo ./test_fdb.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR +./test_fdb.sh $DBNAME $CDB2_CONFIG $SECONDARY_DBNAME $SECONDARY_CDB2_CONFIG $DBDIR $TESTDIR +result=$? + + +if (( $result != 0 )) ; then + echo "Failure" + exit 1 +fi + + +echo "Success" diff --git a/tests/fdb_compat.test/test_fdb.sh b/tests/fdb_compat.test/test_fdb.sh new file mode 100755 index 0000000000..4132dd4fa1 --- /dev/null +++ b/tests/fdb_compat.test/test_fdb.sh @@ -0,0 +1,339 @@ +#!/usr/bin/env bash + +# Remote cursor moves testcase for comdb2 +################################################################################ + +set -x + +# args +# +a_rdbname=$1 +a_rcdb2config=$2 +a_dbname=$3 +a_cdb2config=$4 +a_dbdir=$5 +a_testdir=$6 + +output=run.out + +rm $output + +R_DB2_OPTIONS="--cdb2cfg ${a_rcdb2config}" +S_CDB2_OPTIONS="--cdb2cfg ${a_cdb2config}" + +# Make sure we talk to the same host +mach=`cdb2sql ${S_CDB2_OPTIONS} --tabs $a_dbname default "SELECT comdb2_host()"` + +S_SQLT="cdb2sql ${S_CDB2_OPTIONS} --tabs --host $mach $a_dbname" +S_SQL="cdb2sql ${S_CDB2_OPTIONS} --host $mach $a_dbname" +R_SQLT="cdb2sql ${R_CDB2_OPTIONS} --tabs --host $mach $a_rdbname" +R_SQL="cdb2sql ${R_CDB2_OPTIONS} --host $mach $a_rdbname" + +function check +{ + set -x + $S_SQL "exec procedure sys.cmd.send('fdb info db')" 2>&1 | cut -f 5- -d ' ' >> $output + $S_SQL "exec procedure sys.cmd.send('fdb init')" + $R_SQL "exec procedure sys.cmd.send('fdb info db')" 2>&1 | cut -f 5- -d ' ' >> $output + $R_SQL "exec procedure sys.cmd.send('fdb init')" +} +function header +{ + set -x + echo "TEST $1" + echo "$2" + echo "TEST $1" >> $output + echo "$2" >> $output +} + +#grab current version +ver=`$R_SQLT "select value from comdb2_tunables where name='fdb_default_version'"` +echo "Current fdb version $ver" >> $output 2>&1 + +# populate table on remote +$S_SQL "insert into t select * from generate_series(1, 3)" >> $output 2>&1 +$R_SQL "insert into t select * from generate_series(11, 13)" >> $output 2>&1 + +#gonna test remsql, disable push +$S_SQL "put tunable foreign_db_push_remote 0" +$R_SQL "put tunable foreign_db_push_remote 0" + +header 1 "remsql run against same version" +$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 +check + +echo $R_SQL "put tunable fdb_default_version 6" + +echo $S_SQL "select * from LOCAL_${a_rdbname}.t order by id" +echo $R_SQL "select * from LOCAL_${a_dbname}.t order by id" + +echo $R_SQL "put tunable fdb_default_version $ver" + +header 2 "remsql run against a pre cdb2api version" +$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 + +$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 +$R_SQL "select * from LOCAL_${a_dbname}.t order by id" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +header 3 "test against a too new version" +let newver=ver+1 +$R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 + +$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 +$R_SQL "select * from LOCAL_${a_dbname}.t order by id" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +header 4 "test against cdb2api remsql but not remtran" +$R_SQL "put tunable fdb_default_version 7" >> $output 2>&1 + +$S_SQL "select * from LOCAL_${a_rdbname}.t order by id" >> $output 2>&1 +$R_SQL "select * from LOCAL_${a_dbname}.t order by id" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + + +header 5 "test insert, delete, update current version" + +#gonna test remtran, it needs push code +$S_SQL "put tunable foreign_db_push_remote 1" +$R_SQL "put tunable foreign_db_push_remote 1" + +$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +check + +$S_SQL "update LOCAL_${a_rdbname}.t set id=id+1 where id>=101" >> $output 2>&1 +$R_SQL "update LOCAL_${a_dbname}.t set id=id+1 where id>=101" >> $output 2>&1 +check + +$S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 +$R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 +check + +header 6 "remtran run against a pre cdb2api version" +$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 + +$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +check + +$S_SQL "update LOCAL_${a_rdbname}.t set id=id+1 where id>=101" >> $output 2>&1 +$R_SQL "update LOCAL_${a_dbname}.t set id=id+1 where id>=101" >> $output 2>&1 +check + +$S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 +$R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +header 7 "remtran test against a too new version" +$R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 + +$S_SQL "insert into LOCAL_${a_rdbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +$R_SQL "insert into LOCAL_${a_dbname}.t(id) select * from generate_series(101,110)" >> $output 2>&1 +check + +$S_SQL "update LOCAL_${a_rdbname}.t set id=id+1 where id>=101" >> $output 2>&1 +$R_SQL "update LOCAL_${a_dbname}.t set id=id+1 where id>=101" >> $output 2>&1 +check + +$S_SQL "delete from LOCAL_${a_rdbname}.t where id>=101" >> $output 2>&1 +$R_SQL "delete from LOCAL_${a_dbname}.t where id>=101" >> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +header 8 "remtran test for client transactions" +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +header 9 "remtran test for client transactions pre-cdb2api" +$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +header 10 "remtran test for client transactions newer than current" +$R_SQL "put tunable fdb_default_version $newver" >> $output 2>&1 + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$R_SQL "put tunable fdb_default_version $ver" >> $output 2>&1 + +header 11 "remtran test for client transactions with select" +$R_SQL "put tunable fdb_default_version 6" >> $output 2>&1 + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +$S_SQL <> $output 2>&1 +check + +#convert the table to actual dbname +sed "s/dorintdb/${a_rdbname}/g" output.log > output.log.actual + +# validate results +testcase_output=$(cat $output) +expected_output=$(cat output.log.actual) +if [[ "$testcase_output" != "$expected_output" ]]; then + + # print message + echo " ^^^^^^^^^^^^" + echo "The above testcase (${testcase}) has failed!!!" + echo " " + echo "Use 'diff ' to see why:" + echo "> diff ${PWD}/{output.log.actual,$output}" + echo " " + diff output.log.actual $output + echo " " + + # quit + exit 1 +fi + +echo "Testcase passed."