From d20f0861c5b9d9a20be2adf5f5b260b3aa0ed899 Mon Sep 17 00:00:00 2001 From: Dorin Hogea Date: Thu, 23 May 2024 11:45:37 -0400 Subject: [PATCH] Default schema change saving to 7.0 format to allow schema changes to race with server upgrade. To run the testcase you need to setup a mixed cluster by hand and run the script like ./runit dbname oneofthenodes Signed-off-by: Dorin Hogea --- bdb/llmeta.c | 50 ---- db/db_tunables.c | 1 + db/db_tunables.h | 4 + db/osqlcomm.c | 38 +-- schemachange/sc_struct.c | 327 +++++++++++++++++++++-- schemachange/schemachange.c | 8 + schemachange/schemachange.h | 6 +- tests/mixedcluster_sc.test/Makefile | 8 + tests/mixedcluster_sc.test/README | 3 + tests/mixedcluster_sc.test/lrl.options | 1 + tests/mixedcluster_sc.test/run.log.alpha | 22 ++ tests/mixedcluster_sc.test/runit | 154 +++++++++++ 12 files changed, 512 insertions(+), 110 deletions(-) create mode 100644 tests/mixedcluster_sc.test/Makefile create mode 100644 tests/mixedcluster_sc.test/README create mode 100644 tests/mixedcluster_sc.test/lrl.options create mode 100644 tests/mixedcluster_sc.test/run.log.alpha create mode 100755 tests/mixedcluster_sc.test/runit diff --git a/bdb/llmeta.c b/bdb/llmeta.c index bfa41469af..11086131b8 100644 --- a/bdb/llmeta.c +++ b/bdb/llmeta.c @@ -11061,53 +11061,3 @@ int bdb_del_view(tran_type *t, const char *view_name) } return rc; } - -#include "schemachange.h" - -/* - DRQS-170879936: - - In version R8, some backwards incompatible changes got introduced into - the schema change object that broke the object's original deserializer - function (buf_get_schemachange()). As a result, reading an sc status object - created by R7 would fail if read by R8 (via comdb2_sc_status). - - The fix was to keep the both the versions of the deserializer functions and - invoke them appropriately. - - The current (potential hackish) method to pick the right version on the - deserializer function is based on the content of the first 4 bytes of the - LLMETA_SCHEMACHANGE_STATUS payload, where it is assumed that the valid - values of s->kind (between SC_INVALID and SC_LAST, exclusive) will not - coincide with the first 4 bytes of the rqid (fastseed) stored as the first - member in old (7.0's) LLMETA_SCHEMACHANGE_STATUS payload. -*/ -static int buf_get_schemachange_key_type(void *p_buf, void *p_buf_end) -{ - int first = 0; - - if (p_buf >= p_buf_end) return -1; - - buf_get(&first, sizeof(first), p_buf, p_buf_end); - - if (first > SC_INVALID && first < SC_LAST) { - return LLMETA_SCHEMACHANGE_STATUS_V2; - } - return LLMETA_SCHEMACHANGE_STATUS; -} - -void *buf_get_schemachange(struct schema_change_type *s, void *p_buf, - void *p_buf_end) -{ - int sc_key_type = buf_get_schemachange_key_type(p_buf, p_buf_end); - - switch (sc_key_type) { - case LLMETA_SCHEMACHANGE_STATUS: - return buf_get_schemachange_v1(s, (void *)p_buf, (void *)p_buf_end); - case LLMETA_SCHEMACHANGE_STATUS_V2: - return buf_get_schemachange_v2(s, (void *)p_buf, (void *)p_buf_end); - default: - break; - } - return NULL; -} diff --git a/db/db_tunables.c b/db/db_tunables.c index 21070e7fcb..8153ff216d 100644 --- a/db/db_tunables.c +++ b/db/db_tunables.c @@ -483,6 +483,7 @@ extern int gbl_timer_warn_interval; int gbl_incoherent_clnt_wait = 0; int gbl_new_leader_duration = 3; extern int gbl_transaction_grace_period; +extern int gbl_sc_7format; extern int gbl_dohsql_joins; extern int gbl_sc_history_max_rows; extern int gbl_sc_status_max_rows; diff --git a/db/db_tunables.h b/db/db_tunables.h index eb8cbad5c1..88f0397d29 100644 --- a/db/db_tunables.h +++ b/db/db_tunables.h @@ -2504,6 +2504,10 @@ REGISTER_TUNABLE("transaction_grace_period", "Time to wait for connections with pending transactions to go away on exit. (Default: 60)", TUNABLE_INTEGER, &gbl_transaction_grace_period, 0, NULL, NULL, NULL, NULL); +REGISTER_TUNABLE("sc_7format", + "Save schema change object in 7.0 format. (Default: off)", + TUNABLE_BOOLEAN, &gbl_sc_7format, INTERNAL, NULL, NULL, NULL, NULL); + REGISTER_TUNABLE("dohsql_joins", "Enable to support joins in parallel sql execution (default: on)", TUNABLE_BOOLEAN, &gbl_dohsql_joins, 0, NULL, NULL, NULL, NULL); diff --git a/db/osqlcomm.c b/db/osqlcomm.c index 14d0ad989a..f821aad867 100644 --- a/db/osqlcomm.c +++ b/db/osqlcomm.c @@ -7759,10 +7759,7 @@ int osql_send_schemachange(osql_target_t *target, unsigned long long rqid, { schemachange_packed_size(sc); - size_t osql_rpl_size = - ((rqid == OSQL_RQID_USE_UUID) ? OSQLCOMM_UUID_RPL_TYPE_LEN - : OSQLCOMM_RPL_TYPE_LEN) + - sc->packed_len; + size_t osql_rpl_size = OSQLCOMM_UUID_RPL_TYPE_LEN + sc->packed_len; uint8_t *buf = alloca(osql_rpl_size); uint8_t *p_buf = buf; uint8_t *p_buf_end = p_buf + osql_rpl_size; @@ -7773,32 +7770,17 @@ int osql_send_schemachange(osql_target_t *target, unsigned long long rqid, strcpy(sc->original_master_node, target->host); - if (rqid == OSQL_RQID_USE_UUID) { - osql_uuid_rpl_t hd_uuid = {0}; + osql_uuid_rpl_t hd_uuid = {0}; - hd_uuid.type = OSQL_SCHEMACHANGE; - comdb2uuidcpy(hd_uuid.uuid, uuid); - if (!(p_buf = osqlcomm_schemachange_uuid_rpl_type_put( - &hd_uuid, sc, p_buf, p_buf_end))) { - logmsg(LOGMSG_ERROR, "%s:%s returns NULL\n", __func__, - "osqlcomm_schemachange_uuid_rpl_type_put"); - return -1; - } - - type = osql_net_type_to_net_uuid_type(NET_OSQL_SOCK_RPL); - } else { - osql_rpl_t hd = {0}; - - hd.type = OSQL_SCHEMACHANGE; - hd.sid = rqid; - - if (!(p_buf = osqlcomm_schemachange_rpl_type_put(&hd, sc, p_buf, - p_buf_end))) { - logmsg(LOGMSG_ERROR, "%s:%s returns NULL\n", __func__, - "osqlcomm_schemachange_rpl_type_put"); - return -1; - } + hd_uuid.type = OSQL_SCHEMACHANGE; + comdb2uuidcpy(hd_uuid.uuid, uuid); + if (!(p_buf = osqlcomm_schemachange_uuid_rpl_type_put( + &hd_uuid, sc, p_buf, p_buf_end))) { + logmsg(LOGMSG_ERROR, "%s:%s returns NULL\n", __func__, + "osqlcomm_schemachange_uuid_rpl_type_put"); + return -1; } + type = osql_net_type_to_net_uuid_type(NET_OSQL_SOCK_RPL); if (gbl_enable_osql_logging) { logmsg(LOGMSG_DEBUG, "[%llu %s] send OSQL_SCHEMACHANGE %s\n", rqid, diff --git a/schemachange/sc_struct.c b/schemachange/sc_struct.c index 653c05475c..3918222586 100644 --- a/schemachange/sc_struct.c +++ b/schemachange/sc_struct.c @@ -21,6 +21,8 @@ #include "sc_schema.h" #include "macc_glue.h" +int gbl_sc_7format = 0; + /************ SCHEMACHANGE TO BUF UTILITY FUNCTIONS * *****************************/ @@ -44,6 +46,7 @@ struct schema_change_type *init_schemachange_type(struct schema_change_type *sc) sc->original_master_node[0] = 0; sc->timepartition_name = NULL; sc->partition.type = PARTITION_NONE; + sc->version = gbl_sc_7format ? 7 : 8; listc_init(&sc->dests, offsetof(struct dest, lnk)); Pthread_mutex_init(&sc->mtx, NULL); Pthread_mutex_init(&sc->livesc_mtx, NULL); @@ -146,26 +149,51 @@ size_t schemachange_packed_size(struct schema_change_type *s) s->spname_len = strlen(s->spname) + 1; s->newcsc2_len = (s->newcsc2) ? strlen(s->newcsc2) + 1 : 0; - s->packed_len = - sizeof(s->kind) + sizeof(s->rqid) + sizeof(s->uuid) + - sizeof(s->tablename_len) + s->tablename_len + sizeof(s->fname_len) + - s->fname_len + sizeof(s->aname_len) + s->aname_len + - sizeof(s->avgitemsz) + sizeof(s->newdtastripe) + sizeof(s->blobstripe) + - sizeof(s->live) + sizeof(s->newcsc2_len) + s->newcsc2_len + - sizeof(s->scanmode) + sizeof(s->delay_commit) + - sizeof(s->force_rebuild) + sizeof(s->force_dta_rebuild) + - sizeof(s->force_blob_rebuild) + sizeof(s->force) + sizeof(s->headers) + - sizeof(s->header_change) + sizeof(s->compress) + - sizeof(s->compress_blobs) + sizeof(s->persistent_seq) + - sizeof(s->ip_updates) + sizeof(s->instant_sc) + sizeof(s->preempted) + - sizeof(s->use_plan) + sizeof(s->commit_sleep) + - sizeof(s->convert_sleep) + sizeof(s->same_schema) + sizeof(s->dbnum) + - sizeof(s->flg) + sizeof(s->rebuild_index) + - sizeof(s->index_to_rebuild) + sizeof(s->original_master_node) + - dests_field_packed_size(s) + sizeof(s->spname_len) + s->spname_len + - sizeof(s->lua_func_flags) + sizeof(s->newtable) + - sizeof(s->usedbtablevers) + sizeof(s->qdb_file_ver) + - _partition_packed_size(&s->partition); + if (s->version == 8) { + s->packed_len = + sizeof(s->kind) + sizeof(s->rqid) + sizeof(s->uuid) + + sizeof(s->tablename_len) + s->tablename_len + sizeof(s->fname_len) + + s->fname_len + sizeof(s->aname_len) + s->aname_len + + sizeof(s->avgitemsz) + sizeof(s->newdtastripe) + sizeof(s->blobstripe) + + sizeof(s->live) + sizeof(s->newcsc2_len) + s->newcsc2_len + + sizeof(s->scanmode) + sizeof(s->delay_commit) + + sizeof(s->force_rebuild) + sizeof(s->force_dta_rebuild) + + sizeof(s->force_blob_rebuild) + sizeof(s->force) + sizeof(s->headers) + + sizeof(s->header_change) + sizeof(s->compress) + + sizeof(s->compress_blobs) + sizeof(s->persistent_seq) + + sizeof(s->ip_updates) + sizeof(s->instant_sc) + sizeof(s->preempted) + + sizeof(s->use_plan) + sizeof(s->commit_sleep) + + sizeof(s->convert_sleep) + sizeof(s->same_schema) + sizeof(s->dbnum) + + sizeof(s->flg) + sizeof(s->rebuild_index) + + sizeof(s->index_to_rebuild) + sizeof(s->original_master_node) + + dests_field_packed_size(s) + sizeof(s->spname_len) + s->spname_len + + sizeof(s->lua_func_flags) + sizeof(s->newtable) + + sizeof(s->usedbtablevers) + sizeof(s->qdb_file_ver) + + _partition_packed_size(&s->partition); + } else { + s->packed_len = + sizeof(s->rqid) + sizeof(s->uuid) + sizeof(int/*type*/) + + sizeof(s->tablename_len) + s->tablename_len + sizeof(s->fname_len) + + s->fname_len + sizeof(s->aname_len) + s->aname_len + + sizeof(s->avgitemsz) + sizeof(int /*fastinit*/) + sizeof(s->newdtastripe) + + sizeof(s->blobstripe) + sizeof(s->live) + sizeof(int /*addonly*/) + + sizeof(int /*fulluprecs*/) + sizeof(int /*partialuprecs*/) + + sizeof(int /*alteronly*/) + sizeof(int /*is_trigger*/) + sizeof(s->newcsc2_len) + + s->newcsc2_len + sizeof(s->scanmode) + sizeof(s->delay_commit) + + sizeof(s->force_rebuild) + sizeof(s->force_dta_rebuild) + + sizeof(s->force_blob_rebuild) + sizeof(s->force) + sizeof(s->headers) + + sizeof(s->header_change) + sizeof(s->compress) + + sizeof(s->compress_blobs) + sizeof(s->ip_updates) + + sizeof(s->instant_sc) + sizeof(s->preempted) + sizeof(s->use_plan) + + sizeof(s->commit_sleep) + sizeof(s->convert_sleep) + + sizeof(s->same_schema) + sizeof(s->dbnum) + sizeof(s->flg) + + sizeof(s->rebuild_index) + sizeof(s->index_to_rebuild) + + sizeof(int /*drop_table*/) + sizeof(s->original_master_node) + + dests_field_packed_size(s) + sizeof(s->spname_len) + s->spname_len + + sizeof(int /*addsp*/) + sizeof(int /*delsp*/) + sizeof(int /*defaultsp*/) + + sizeof(int /*is_sfunc*/) + sizeof(int /*is_afunc*/) + sizeof(int /*rename*/) + + sizeof(s->newtable) + sizeof(s->usedbtablevers); + } return s->packed_len; } @@ -190,7 +218,221 @@ static void *buf_put_dests(struct schema_change_type *s, void *p_buf, return p_buf; } -void *buf_put_schemachange(struct schema_change_type *s, void *p_buf, void *p_buf_end) + +static int sc_get_7format_type(struct schema_change_type *s) +{ + int type = DBTYPE_TAGGED_TABLE; + + if (s->kind == SC_LEGACY_MORESTRIPE) + type = UNUSED_2 /*DBTYPE_MORESTRIPE*/; + else if (s->kind == SC_LEGACY_QUEUE) + type = DBTYPE_QUEUE; + else if (s->kind == SC_ADD_QDB_FILE || s->kind == SC_DEL_QDB_FILE) + type = DBTYPE_QUEUEDB; + + return type; +} +static int sc_7format_is_fastinit(struct schema_change_type *s) +{ + return s->kind == SC_DROPTABLE || s->kind == SC_TRUNCATETABLE; +} +static int sc_7format_is_addonly(struct schema_change_type *s) +{ + return s->kind == SC_ADDTABLE || s->kind == SC_ADD_TRIGGER; +} +static int sc_7format_is_fulluprecs(struct schema_change_type *s) +{ + return s->kind == SC_FULLUPRECS; +} +static int sc_7format_is_partialuprecs(struct schema_change_type *s) +{ + return s->kind == SC_PARTIALUPRECS; +} +static int sc_7format_is_alteronly(struct schema_change_type *s) +{ + if (s->kind == SC_ALTERTABLE) + return 1 /*SC_ALTER_ONLY*/; + else if (s->kind == SC_ALTERTABLE_PENDING) + return 2 /*SC_ALTER_PENDING*/; + return 0; +} +static int sc_7format_is_trigger(struct schema_change_type *s) +{ + return s->kind == SC_ADD_TRIGGER || s->kind == SC_DEL_TRIGGER; +} +static int sc_7format_is_droptable(struct schema_change_type *s) +{ + return s->kind == SC_DROPTABLE || s->kind == SC_DEL_TRIGGER; +} +static int sc_7format_is_addsp(struct schema_change_type *s) +{ + return s->kind == SC_ADDSP; +} +static int sc_7format_is_delsp(struct schema_change_type *s) +{ + return s->kind == SC_DELSP; +} +static int sc_7format_is_defaultsp(struct schema_change_type *s) +{ + return s->kind == SC_DEFAULTSP; +} +static int sc_7format_is_sfunc(struct schema_change_type *s) +{ + return s->kind == SC_ADD_SFUNC || s->kind == SC_DEL_SFUNC; +} +static int sc_7format_is_afunc(struct schema_change_type *s) +{ + return s->kind == SC_ADD_AFUNC || s->kind == SC_DEL_AFUNC; +} +static int sc_7format_is_rename(struct schema_change_type *s) +{ + return s->kind == SC_RENAMETABLE; +} + +static void *buf_put_schemachange_v1(struct schema_change_type *s, void *p_buf, void *p_buf_end) +{ + if (p_buf >= p_buf_end) return NULL; + + p_buf = buf_put(&s->rqid, sizeof(s->rqid), p_buf, p_buf_end); + + p_buf = buf_no_net_put(&s->uuid, sizeof(s->uuid), p_buf, p_buf_end); + + int type = sc_get_7format_type(s); + p_buf = buf_put(&type, sizeof(type), p_buf, p_buf_end); + + p_buf = + buf_put(&s->tablename_len, sizeof(s->tablename_len), p_buf, p_buf_end); + + p_buf = buf_no_net_put(s->tablename, s->tablename_len, p_buf, p_buf_end); + + p_buf = buf_put(&s->fname_len, sizeof(s->fname_len), p_buf, p_buf_end); + + p_buf = buf_no_net_put(s->fname, s->fname_len, p_buf, p_buf_end); + + p_buf = buf_put(&s->aname_len, sizeof(s->aname_len), p_buf, p_buf_end); + + p_buf = buf_no_net_put(s->aname, s->aname_len, p_buf, p_buf_end); + + p_buf = buf_put(&s->avgitemsz, sizeof(s->avgitemsz), p_buf, p_buf_end); + + int fastinit = sc_7format_is_fastinit(s); + p_buf = buf_put(&fastinit, sizeof(fastinit), p_buf, p_buf_end); + + p_buf = + buf_put(&s->newdtastripe, sizeof(s->newdtastripe), p_buf, p_buf_end); + + p_buf = buf_put(&s->blobstripe, sizeof(s->blobstripe), p_buf, p_buf_end); + + p_buf = buf_put(&s->live, sizeof(s->live), p_buf, p_buf_end); + + int addonly = sc_7format_is_addonly(s); + p_buf = buf_put(&addonly, sizeof(addonly), p_buf, p_buf_end); + + int fulluprecs = sc_7format_is_fulluprecs(s); + p_buf = buf_put(&fulluprecs, sizeof(fulluprecs), p_buf, p_buf_end); + + int partialuprecs = sc_7format_is_partialuprecs(s); + p_buf = + buf_put(&partialuprecs, sizeof(partialuprecs), p_buf, p_buf_end); + + int alteronly = sc_7format_is_alteronly(s); + p_buf = buf_put(&alteronly, sizeof(alteronly), p_buf, p_buf_end); + + int is_trigger = sc_7format_is_trigger(s); + p_buf = buf_put(&is_trigger, sizeof(is_trigger), p_buf, p_buf_end); + + p_buf = buf_put(&s->newcsc2_len, sizeof(s->newcsc2_len), p_buf, p_buf_end); + + if (s->newcsc2_len) { + p_buf = buf_no_net_put(s->newcsc2, s->newcsc2_len, p_buf, p_buf_end); + } + + p_buf = buf_put(&s->scanmode, sizeof(s->scanmode), p_buf, p_buf_end); + + p_buf = + buf_put(&s->delay_commit, sizeof(s->delay_commit), p_buf, p_buf_end); + + p_buf = + buf_put(&s->force_rebuild, sizeof(s->force_rebuild), p_buf, p_buf_end); + + p_buf = buf_put(&s->force_dta_rebuild, sizeof(s->force_dta_rebuild), p_buf, + p_buf_end); + + p_buf = buf_put(&s->force_blob_rebuild, sizeof(s->force_blob_rebuild), + p_buf, p_buf_end); + + p_buf = buf_put(&s->force, sizeof(s->force), p_buf, p_buf_end); + + p_buf = buf_put(&s->headers, sizeof(s->headers), p_buf, p_buf_end); + + p_buf = + buf_put(&s->header_change, sizeof(s->header_change), p_buf, p_buf_end); + + p_buf = buf_put(&s->compress, sizeof(s->compress), p_buf, p_buf_end); + + p_buf = buf_put(&s->compress_blobs, sizeof(s->compress_blobs), p_buf, + p_buf_end); + + p_buf = buf_put(&s->ip_updates, sizeof(s->ip_updates), p_buf, p_buf_end); + + p_buf = buf_put(&s->instant_sc, sizeof(s->instant_sc), p_buf, p_buf_end); + + p_buf = buf_put(&s->preempted, sizeof(s->preempted), p_buf, p_buf_end); + + p_buf = buf_put(&s->use_plan, sizeof(s->use_plan), p_buf, p_buf_end); + + p_buf = + buf_put(&s->commit_sleep, sizeof(s->commit_sleep), p_buf, p_buf_end); + + p_buf = + buf_put(&s->convert_sleep, sizeof(s->convert_sleep), p_buf, p_buf_end); + + p_buf = buf_put(&s->same_schema, sizeof(s->same_schema), p_buf, p_buf_end); + + p_buf = buf_put(&s->dbnum, sizeof(s->dbnum), p_buf, p_buf_end); + + p_buf = buf_put(&s->flg, sizeof(s->flg), p_buf, p_buf_end); + + p_buf = + buf_put(&s->rebuild_index, sizeof(s->rebuild_index), p_buf, p_buf_end); + + p_buf = buf_put(&s->index_to_rebuild, sizeof(s->index_to_rebuild), p_buf, + p_buf_end); + + p_buf = buf_put(&s->original_master_node, sizeof(s->original_master_node), + p_buf, p_buf_end); + + int drop_table = sc_7format_is_droptable(s); + p_buf = buf_put(&drop_table, sizeof(drop_table), p_buf, p_buf_end); + + p_buf = buf_put_dests(s, p_buf, p_buf_end); + + p_buf = buf_put(&s->spname_len, sizeof(s->spname_len), p_buf, p_buf_end); + p_buf = buf_no_net_put(s->spname, s->spname_len, p_buf, p_buf_end); + + int addsp = sc_7format_is_addsp(s); + p_buf = buf_put(&addsp, sizeof(addsp), p_buf, p_buf_end); + int delsp = sc_7format_is_delsp(s); + p_buf = buf_put(&delsp, sizeof(delsp), p_buf, p_buf_end); + int defaultsp = sc_7format_is_defaultsp(s); + p_buf = buf_put(&defaultsp, sizeof(defaultsp), p_buf, p_buf_end); + + int is_sfunc = sc_7format_is_sfunc(s); + p_buf = buf_put(&is_sfunc, sizeof(is_sfunc), p_buf, p_buf_end); + int is_afunc = sc_7format_is_afunc(s); + p_buf = buf_put(&is_afunc, sizeof(is_afunc), p_buf, p_buf_end); + + int rename = sc_7format_is_rename(s); + p_buf = buf_put(&rename, sizeof(rename), p_buf, p_buf_end); + + p_buf = buf_no_net_put(s->newtable, sizeof(s->newtable), p_buf, p_buf_end); + p_buf = buf_put(&s->usedbtablevers, sizeof(s->usedbtablevers), p_buf, + p_buf_end); + + return p_buf; +} + +static void *buf_put_schemachange_v2(struct schema_change_type *s, void *p_buf, void *p_buf_end) { if (p_buf >= p_buf_end) return NULL; @@ -324,6 +566,13 @@ void *buf_put_schemachange(struct schema_change_type *s, void *p_buf, void *p_bu return p_buf; } +void *buf_put_schemachange(struct schema_change_type *s, void *p_buf, void *p_buf_end) +{ + if (s->version == 7) + return buf_put_schemachange_v1(s, p_buf, p_buf_end); + return buf_put_schemachange_v2(s, p_buf, p_buf_end); +} + static const void *buf_get_dests(struct schema_change_type *s, const void *p_buf, void *p_buf_end) { @@ -368,8 +617,8 @@ static const void *buf_get_dests(struct schema_change_type *s, return p_buf; } -void *buf_get_schemachange_v1(struct schema_change_type *s, void *p_buf, - void *p_buf_end) +static void *buf_get_schemachange_v1(struct schema_change_type *s, void *p_buf, + void *p_buf_end) { int type = 0, fastinit = 0, addonly = 0, fulluprecs = 0, partialuprecs = 0, alteronly = 0, is_trigger = 0, drop_table = 0, @@ -510,12 +759,12 @@ void *buf_get_schemachange_v1(struct schema_change_type *s, void *p_buf, p_buf = (uint8_t *)buf_get(&s->index_to_rebuild, sizeof(s->index_to_rebuild), p_buf, p_buf_end); - p_buf = (uint8_t *)buf_get(&drop_table, sizeof(drop_table), p_buf, p_buf_end); /* s->drop_table */ - p_buf = (uint8_t *)buf_get(&s->original_master_node, sizeof(s->original_master_node), p_buf, p_buf_end); + p_buf = (uint8_t *)buf_get(&drop_table, sizeof(drop_table), p_buf, p_buf_end); /* s->drop_table */ + p_buf = (uint8_t *)buf_get_dests(s, p_buf, p_buf_end); p_buf = (uint8_t *)buf_get(&s->spname_len, sizeof(s->spname_len), p_buf, @@ -561,12 +810,23 @@ void *buf_get_schemachange_v1(struct schema_change_type *s, void *p_buf, s->kind = SC_DELSP; else if (defaultsp) s->kind = SC_DEFAULTSP; + else if (is_sfunc) { + if (addonly) + s->kind = SC_ADD_SFUNC; + else + s->kind = SC_DEL_SFUNC; + } else if (is_afunc) { + if (addonly) + s->kind = SC_ADD_AFUNC; + else + s->kind = SC_DEL_AFUNC; + } return p_buf; } -void *buf_get_schemachange_v2(struct schema_change_type *s, - void *p_buf, void *p_buf_end) +static void *buf_get_schemachange_v2(struct schema_change_type *s, + void *p_buf, void *p_buf_end) { if (p_buf >= p_buf_end) return NULL; @@ -749,6 +1009,15 @@ void *buf_get_schemachange_v2(struct schema_change_type *s, return p_buf; } +void *buf_get_schemachange(struct schema_change_type *s, void *p_buf, + void *p_buf_end) +{ + if (s->version == 7) + return buf_get_schemachange_v1(s, p_buf, p_buf_end); + return buf_get_schemachange_v2(s, p_buf, p_buf_end); +} + + /*********************************************************************************/ /* Packs a schema_change_type struct into an opaque binary buffer so that it can @@ -758,7 +1027,7 @@ void *buf_get_schemachange_v2(struct schema_change_type *s, * packed is set to a pointer to the packed data and is owned by callee if this * function succeeds */ int pack_schema_change_type(struct schema_change_type *s, void **packed, - size_t *packed_len) + size_t *packed_len) { /* compute the length of our buffer */ @@ -1230,6 +1499,8 @@ clone_schemachange_type(struct schema_change_type *sc) return NULL; } + newsc->version = sc->version; /* preserve format */ + p_buf = buf; p_buf = buf_get_schemachange(newsc, p_buf, p_buf_end); diff --git a/schemachange/schemachange.c b/schemachange/schemachange.c index dbf9bb7c01..ba40be36e1 100644 --- a/schemachange/schemachange.c +++ b/schemachange/schemachange.c @@ -393,6 +393,7 @@ int start_schema_change_tran(struct ireq *iq, tran_type *trans) return rc; } +extern int gbl_sc_7format; int start_schema_change(struct schema_change_type *s) { struct ireq *iq = NULL; @@ -403,6 +404,13 @@ int start_schema_change(struct schema_change_type *s) } init_fake_ireq(thedb, iq); if (s->already_locked) iq->sc_locked = 1; + + /* NOTE: if this comes from comdb2sc, it does not run + * init_schemachange! In these cases, version == 0. + * Fix it here. + */ + if (!s->version) + s->version = gbl_sc_7format ? 7 : 8; iq->sc = s; s->iq = iq; if (s->db == NULL) { diff --git a/schemachange/schemachange.h b/schemachange/schemachange.h index 1c69b085ec..ffde9955d5 100644 --- a/schemachange/schemachange.h +++ b/schemachange/schemachange.h @@ -289,6 +289,8 @@ struct schema_change_type { int (*publish)(tran_type *, struct schema_change_type *); void (*unpublish)(struct schema_change_type *); + + int version; }; typedef int (*ddl_t)(struct ireq *, struct schema_change_type *, tran_type *); @@ -410,10 +412,6 @@ void *buf_put_schemachange(struct schema_change_type *s, void *p_buf, void *p_buf_end); void *buf_get_schemachange(struct schema_change_type *s, void *p_buf, void *p_buf_end); -void *buf_get_schemachange_v1(struct schema_change_type *s, void *p_buf, - void *p_buf_end); -void *buf_get_schemachange_v2(struct schema_change_type *s, void *p_buf, - void *p_buf_end); /* This belong into sc_util.h */ int check_sc_ok(struct schema_change_type *s); diff --git a/tests/mixedcluster_sc.test/Makefile b/tests/mixedcluster_sc.test/Makefile new file mode 100644 index 0000000000..2d39e80074 --- /dev/null +++ b/tests/mixedcluster_sc.test/Makefile @@ -0,0 +1,8 @@ +ifeq ($(TESTSROOTDIR),) + include ../testcase.mk +else + include $(TESTSROOTDIR)/testcase.mk +endif +ifeq ($(TEST_TIMEOUT),) + export TEST_TIMEOUT=3m +endif diff --git a/tests/mixedcluster_sc.test/README b/tests/mixedcluster_sc.test/README new file mode 100644 index 0000000000..f4cdba1d4d --- /dev/null +++ b/tests/mixedcluster_sc.test/README @@ -0,0 +1,3 @@ +This is only a skeleton to test mixed cluster combinations, since we do not have yet a way to setup those. +It contains scripts we use to validate different scenarios for mixed clusters, so that we can run them +once a proper cluster is setup. diff --git a/tests/mixedcluster_sc.test/lrl.options b/tests/mixedcluster_sc.test/lrl.options new file mode 100644 index 0000000000..6112ed5b43 --- /dev/null +++ b/tests/mixedcluster_sc.test/lrl.options @@ -0,0 +1 @@ +sc_7format 1 diff --git a/tests/mixedcluster_sc.test/run.log.alpha b/tests/mixedcluster_sc.test/run.log.alpha new file mode 100644 index 0000000000..cb2af933b2 --- /dev/null +++ b/tests/mixedcluster_sc.test/run.log.alpha @@ -0,0 +1,22 @@ +(rows inserted=10) +(a=1) +(a=2) +(a=3) +(a=4) +(a=5) +(a=6) +(a=7) +(a=8) +(a=9) +(a=10) +(rows inserted=10) +(a=1) +(a=2) +(a=3) +(a=4) +(a=5) +(a=6) +(a=7) +(a=8) +(a=9) +(a=10) diff --git a/tests/mixedcluster_sc.test/runit b/tests/mixedcluster_sc.test/runit new file mode 100755 index 0000000000..351d0d3fb5 --- /dev/null +++ b/tests/mixedcluster_sc.test/runit @@ -0,0 +1,154 @@ +#!/usr/bin/env bash +bash -n "$0" | exit 1 + +set -x +# +# NOTE: run this on a 2 node cluster, one 7.0 and the other 8.0 +# +# args +# +dbname=$1 + +# PASS THE NODE DURING MANUAL TEST, OR SET CDB2_OPTIONS +node=$2 + +cmd="cdb2sql ${CDB2_OPTIONS} $dbname default" +if [[ -z $node ]]; then + cmdt="cdb2sql -tabs ${CDB2_OPTIONS} $dbname default" +else + cmdt="cdb2sql -tabs $dbname $node" +fi +master=`${cmdt} "select host from comdb2_cluster where is_master='Y'"` +replicant=`${cmdt} "select host from comdb2_cluster where is_master='N'"` +OUT="run.log" + +rm $OUT 2>/dev/null +touch $OUT + +if [[ -z $replicant ]] ; then + echo "Need at least 2 nodes for test" + exit 1 +fi + +echo "Master $master replicant $replicant" + +if [[ $node ]]; then + cmd="cdb2sql $dbname $replicant" +fi + +$cmd "drop table if exists t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE initially dropping table $replicant" + exit 1 +fi + +$cmd "create table t(a int)" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE creating table on $replicant" + exit 1 +fi + +$cmd "insert into t select * from generate_series(1, 10)" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE insert through $replicant" + exit 1 +fi + +$cmd "select * from t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE selecting from $replicant" + exit 1 +fi + +$cmd "truncate t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE truncating through $replicant" + exit 1 +fi + +$cmd "select * from t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE selecting from empty $replicant" + exit 1 +fi + +$cmd "truncate t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE truncating through $replicant" + exit 1 +fi + +$cmd "drop table t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE dropping table $replicant" + exit 1 +fi + +$cmd "exec procedure sys.cmd.send('downgrade')" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE downgrading $master" + exit 1 +fi + +sleep 5 + +$replicant=$master +if [[ $node ]]; then + cmd="cdb2sql $dbname $replicant" +fi + +$cmd "create table t(a int)" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE creating table on $replicant" + exit 1 +fi + +$cmd "insert into t select * from generate_series(1, 10)" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE insert through $replicant" + exit 1 +fi + +$cmd "select * from t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE selecting from $replicant" + exit 1 +fi + +$cmd "truncate t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE truncating through $replicant" + exit 1 +fi + +$cmd "select * from t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE selecting from empty $replicant" + exit 1 +fi + +$cmd "truncate t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE truncating through $replicant" + exit 1 +fi + +$cmd "drop table t" >> $OUT 2>&1 +if (( $? != 0 )) ; then + echo "FAILURE dropping table $replicant" + exit 1 +fi + +# we need to scrub dbname from alpha +sed "s/dorintdb/$dbname/g; s#\${CDB2_OPTIONS}#${CDB2_OPTIONS}#g" $OUT.alpha > $OUT.alpha.actual + + +difs=`diff $OUT $OUT.alpha.actual` +if [[ ! -z "${difs}" ]] ; then + echo "diff $OUT $OUT.alpha.actual" + echo ${difs} + echo "FAILURE" + exit 1 +fi + +echo "SUCCESS"