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(a)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
--
2.8.0