@@ -13,7 +13,7 @@
#define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001
/* gprs_sgsn.h defines additional flags including and above bit 16 (0x10000) */
-#define tmsi_from_string(str) strtoul(str, NULL, 10)
+#define tmsi_from_string(str) strtoul(str + 2, NULL, 16)
#define GSM_SUBSCRIBER_NO_EXPIRATION 0x0
@@ -48,7 +48,7 @@
static char *db_dirname = NULL;
static dbi_conn conn;
-#define SCHEMA_REVISION "4"
+#define SCHEMA_REVISION "5"
enum {
SCHEMA_META,
@@ -84,7 +84,7 @@
"name TEXT, "
"extension TEXT UNIQUE, "
"authorized INTEGER NOT NULL DEFAULT 0, "
- "tmsi TEXT UNIQUE, "
+ "tmsi INTEGER UNIQUE, "
"lac INTEGER NOT NULL DEFAULT 0, "
"expire_lu TIMESTAMP DEFAULT NULL"
")",
@@ -213,6 +213,7 @@
}
dbi_result_free(result);
+ LOGP(DDB, LOGL_NOTICE, "Migration complete.\n");
return 0;
}
@@ -225,23 +226,27 @@
{
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");
@@ -358,6 +363,7 @@
else
dbi_result_free(result);
+ LOGP(DDB, LOGL_NOTICE, "Migration complete.\n");
return 0;
rollback:
@@ -365,6 +371,108 @@
if (!result)
LOGP(DDB, LOGL_ERROR,
"Rollback failed (upgrade from rev 3).\n");
+ else
+ dbi_result_free(result);
+ return -EINVAL;
+}
+
+static int update_db_revision_4(void)
+{
+ dbi_result result;
+
+ LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 4\n");
+
+ result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to begin transaction "
+ "(upgrade from rev 4)\n");
+ return -EINVAL;
+ }
+ dbi_result_free(result);
+
+ /* Rename old Subscriber table to be able create a new one */
+ result = dbi_conn_query(conn,
+ "ALTER TABLE Subscriber RENAME TO Subscriber_4");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to rename the old Subscriber table "
+ "(upgrade from rev 4).\n");
+ goto rollback;
+ }
+ dbi_result_free(result);
+
+ /* Create new Subscriber table */
+ result = dbi_conn_query(conn, create_stmts[SCHEMA_SUBSCRIBER]);
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to create a new Subscriber table "
+ "(upgrade from rev 4).\n");
+ goto rollback;
+ }
+ dbi_result_free(result);
+
+ /* Copy subscriber data into the new table */
+ result = dbi_conn_query(conn,
+ "INSERT INTO Subscriber "
+ "SELECT * FROM Subscriber_4");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to copy subscriber data into the new table "
+ "(upgrade from rev 4).\n");
+ goto rollback;
+ }
+ dbi_result_free(result);
+
+ /* Remove the temporary table */
+ result = dbi_conn_query(conn, "DROP TABLE Subscriber_4");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to drop the old Subscriber table "
+ "(upgrade from rev 4).\n");
+ goto rollback;
+ }
+ dbi_result_free(result);
+
+ /* We're done. Bump DB Meta revision to 5 */
+ result = dbi_conn_query(conn,
+ "UPDATE Meta "
+ "SET value = '5' "
+ "WHERE key = 'revision'");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to update DB schema revision "
+ "(upgrade from rev 4).\n");
+ goto rollback;
+ }
+ dbi_result_free(result);
+
+ result = dbi_conn_query(conn, "COMMIT TRANSACTION");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to commit the transaction "
+ "(upgrade from rev 4)\n");
+ return -EINVAL;
+ }
+
+ /* Shrink DB file size by actually wiping out Subscriber_4 table data */
+ result = dbi_conn_query(conn, "VACUUM");
+ if (!result)
+ LOGP(DDB, LOGL_ERROR,
+ "VACUUM failed. Ignoring it "
+ "(upgrade from rev 4).\n");
+ else
+ dbi_result_free(result);
+
+ LOGP(DDB, LOGL_NOTICE, "Migration complete.\n");
+ return 0;
+
+rollback:
+ result = dbi_conn_query(conn, "ROLLBACK TRANSACTION");
+ if (!result)
+ LOGP(DDB, LOGL_ERROR,
+ "Rollback failed "
+ "(upgrade from rev 4).\n");
else
dbi_result_free(result);
return -EINVAL;
@@ -412,6 +520,9 @@
goto error;
case 3:
if (update_db_revision_3())
+ goto error;
+ case 4:
+ if (update_db_revision_4())
goto error;
/* The end of waterfall */
@@ -823,10 +934,6 @@
if (string)
strncpy(subscr->imsi, string, sizeof(subscr->imsi)-1);
- string = dbi_result_get_string(result, "tmsi");
- if (string)
- subscr->tmsi = tmsi_from_string(string);
-
string = dbi_result_get_string(result, "name");
if (string)
strncpy(subscr->name, string, GSM_NAME_LENGTH);
@@ -836,6 +943,7 @@
strncpy(subscr->extension, string, GSM_EXTENSION_LENGTH);
subscr->lac = dbi_result_get_ulonglong(result, "lac");
+ subscr->tmsi = dbi_result_get_ulonglong(result, "tmsi");
if (!dbi_result_field_is_null(result, "expire_lu"))
subscr->expire_lu = dbi_result_get_datetime(result, "expire_lu");
@@ -908,9 +1016,10 @@
subscr->id = dbi_result_get_ulonglong(result, "id");
db_set_from_query(subscr, result);
- DEBUGP(DDB, "Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', LAC %hu, AUTH %u\n",
- subscr->id, subscr->imsi, subscr->name, subscr->tmsi, subscr->extension,
- subscr->lac, subscr->authorized);
+ DEBUGP(DDB, "Found Subscriber: ID %llu, IMSI %s, NAME '%s', "
+ "TMSI 0x%08x, EXTEN '%s', LAC %hu, AUTH %u\n",
+ subscr->id, subscr->imsi, subscr->name, subscr->tmsi,
+ subscr->extension, subscr->lac, subscr->authorized);
dbi_result_free(result);
get_equipment_by_subscr(subscr);
@@ -1240,7 +1349,7 @@
}
if (!dbi_result_next_row(result)) {
dbi_result_free(result);
- DEBUGP(DDB, "Allocated TMSI %u for IMSI %s.\n",
+ DEBUGP(DDB, "Allocated TMSI 0x%08x for IMSI %s.\n",
subscriber->tmsi, subscriber->imsi);
return db_sync_subscriber(subscriber);
}
@@ -189,7 +189,8 @@
else if (!strcmp(type, "imsi"))
return subscr_get_by_imsi(gsmnet->subscr_group, id);
else if (!strcmp(type, "tmsi"))
- return subscr_get_by_tmsi(gsmnet->subscr_group, atoi(id));
+ return subscr_get_by_tmsi(gsmnet->subscr_group,
+ tmsi_from_string(id));
else if (!strcmp(type, "id"))
return subscr_get_by_id(gsmnet->subscr_group, atoi(id));
@@ -187,6 +187,7 @@
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);
@@ -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
@@ -195,7 +195,7 @@
/* tmsi code */
mi_len = gsm48_generate_mid_from_tmsi(mi, tmsi);
gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len - 2);
- COMPARE((uint32_t)strtoul(mi_parsed, NULL, 10), ==, tmsi);
+ COMPARE((uint32_t)tmsi_from_string(mi_parsed), ==, tmsi);
/* imsi code */
mi_len = gsm48_generate_mid_from_imsi(mi, imsi_odd);