In the past normal migration was possible only if the actual schema version differed from the version used in DB by 1. For example, if DB uses an old version 3 and you need to use it with the code written for version 5, the check_db_revision() will convert it to 4 and DB will still use incompatible schema version during Osmo-NITB running time. After next run it will be converted to version 5.
This patch replaces a set of 'else-if' checks by a 'switch' without 'break' statements between 'case' labels (waterfall). It makes you able to migrate from current version to the latest despite any difference between them.
Also fixed the sms_from_result_v3() to avoid large depth of function calls, because they can be changed in the future and lose compatibility with old table schemas.
Also fixed db_test and now it is successful.
Signed-off-by: Vadim Yanitskiy axilirator@gmail.com --- openbsc/src/libmsc/db.c | 65 ++++++++++++++++++++++++++++---------------- openbsc/tests/db/db_test.c | 1 + openbsc/tests/db/db_test.err | 3 ++ 3 files changed, 45 insertions(+), 24 deletions(-)
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 04aee79..ad5afca 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -225,23 +225,27 @@ static struct gsm_sms *sms_from_result_v3(dbi_result result) { struct gsm_sms *sms = sms_alloc(); long long unsigned int sender_id; - struct gsm_subscriber *sender; - const char *text, *daddr; + const char *text, *daddr, *extension; const unsigned char *user_data; - char buf[32]; + dbi_result sender_result;
if (!sms) return NULL;
- sms->id = dbi_result_get_ulonglong(result, "id"); - sender_id = dbi_result_get_ulonglong(result, "sender_id"); - snprintf(buf, sizeof(buf), "%llu", sender_id); - sender = db_get_subscriber(GSM_SUBSCRIBER_ID, buf); - OSMO_ASSERT(sender); - strncpy(sms->src.addr, sender->extension, sizeof(sms->src.addr)-1); - subscr_direct_free(sender); - sender = NULL; + sms->id = dbi_result_get_ulonglong(result, "id"); + + sender_result = dbi_conn_queryf(conn, + "SELECT * FROM Subscriber " + "WHERE id = %llu", sender_id); + + if (sender_result) { + if (dbi_result_next_row(sender_result)) { + extension = dbi_result_get_string(sender_result, "extension"); + strncpy(sms->src.addr, extension, sizeof(sms->src.addr) - 1); + } + dbi_result_free(sender_result); + }
sms->reply_path_req = dbi_result_get_ulonglong(result, "reply_path_req"); sms->status_rep_req = dbi_result_get_ulonglong(result, "status_rep_req"); @@ -477,16 +481,20 @@ static int check_db_revision(void) { dbi_result result; const char *rev_s; + int db_rev = 0;
+ /* Make a query */ result = dbi_conn_query(conn, - "SELECT value FROM Meta WHERE key='revision'"); + "SELECT value FROM Meta " + "WHERE key = 'revision'"); if (!result) return -EINVAL; - if (!dbi_result_next_row(result)) { dbi_result_free(result); return -EINVAL; } + + /* Fetch the DB schema revision */ rev_s = dbi_result_get_string(result, "value"); if (!rev_s) { dbi_result_free(result); @@ -494,28 +502,37 @@ static int check_db_revision(void) }
if (!strcmp(rev_s, SCHEMA_REVISION)) { - /* everything is fine */ - } else if (!strcmp(rev_s, "2")) { + /* Everything is fine */ + dbi_result_free(result); + return 0; + } + + db_rev = atoi(rev_s); + dbi_result_free(result); + + /* Incremental migration waterfall */ + switch (db_rev) { + case 2: if (update_db_revision_2()) goto error; - } else if (!strcmp(rev_s, "3")) { + case 3: if (update_db_revision_3()) goto error; - } else if (!strcmp(rev_s, "4")) { + case 4: if (update_db_revision_4()) - goto error; - } else { - LOGP(DDB, LOGL_FATAL, "Invalid database schema revision '%s'.\n", rev_s); - dbi_result_free(result); + goto error; + + /* The end of waterfall */ + break; + default: + LOGP(DDB, LOGL_FATAL, "Invalid database schema revision '%d'.\n", db_rev); return -EINVAL; }
- dbi_result_free(result); return 0;
error: - LOGP(DDB, LOGL_FATAL, "Failed to update database from schema revision '%s'.\n", rev_s); - dbi_result_free(result); + LOGP(DDB, LOGL_FATAL, "Failed to update database from schema revision '%d'.\n", db_rev); return -EINVAL; }
diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index a02d1f8..2fdd830 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -187,6 +187,7 @@ int main()
char *alice_imsi = "3243245432345"; alice = db_create_subscriber(alice_imsi); + db_subscriber_alloc_tmsi(alice); db_sync_subscriber(alice); alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice->imsi); COMPARE(alice, alice_db); diff --git a/openbsc/tests/db/db_test.err b/openbsc/tests/db/db_test.err index fa9a54c..d8a3e7f 100644 --- a/openbsc/tests/db/db_test.err +++ b/openbsc/tests/db/db_test.err @@ -1,2 +1,5 @@ Going to migrate from revision 3 +[0;mMigration complete. +[0;mGoing to migrate from revision 4 +[0;mMigration complete. [0;m \ No newline at end of file