add column 'last_lu_rat', show last RAN type
Change-Id: I5d73b1d928b61175d3198326706b7f49ba50e16f
diff --git a/src/db.c b/src/db.c
index 0a51178..892943a 100644
--- a/src/db.c
+++ b/src/db.c
@@ -28,7 +28,7 @@
#include "db_bootstrap.h"
/* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */
-#define CURRENT_SCHEMA_VERSION 2
+#define CURRENT_SCHEMA_VERSION 3
#define SEL_COLUMNS \
"id," \
@@ -44,7 +44,8 @@
"lmsi," \
"ms_purged_cs," \
"ms_purged_ps," \
- "last_lu_seen"
+ "last_lu_seen," \
+ "last_lu_rat"
static const char *stmt_sql[] = {
[DB_STMT_SEL_BY_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi = ?",
@@ -75,7 +76,8 @@
"INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, op, opc, ind_bitlen)"
" VALUES($subscriber_id, $algo_id_3g, $k, $op, $opc, $ind_bitlen)",
[DB_STMT_AUC_3G_DELETE] = "DELETE FROM auc_3g WHERE subscriber_id = $subscriber_id",
- [DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
+ [DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch'), last_lu_rat = $rat"
+ " WHERE id = $subscriber_id",
[DB_STMT_UPD_RAT_FLAG] = "INSERT OR REPLACE INTO subscriber_rat (subscriber_id, rat, allowed)"
" VALUES ($subscriber_id, $rat, $allowed)",
[DB_STMT_RAT_BY_ID] =
@@ -341,6 +343,40 @@
return SQLITE_DONE;
}
+static int db_upgrade_v3(struct db_context *dbc)
+{
+ sqlite3_stmt *stmt;
+ int rc;
+ const char *update_stmt_sql = "ALTER TABLE subscriber ADD COLUMN last_lu_rat TEXT default NULL";
+ const char *set_schema_version_sql = "PRAGMA user_version = 3";
+
+ rc = sqlite3_prepare_v2(dbc->db, update_stmt_sql, -1, &stmt, NULL);
+ if (rc != SQLITE_OK) {
+ LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", update_stmt_sql);
+ return rc;
+ }
+ rc = sqlite3_step(stmt);
+ db_remove_reset(stmt);
+ sqlite3_finalize(stmt);
+ if (rc != SQLITE_DONE) {
+ LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version %d\n", 1);
+ return rc;
+ }
+
+ rc = sqlite3_prepare_v2(dbc->db, set_schema_version_sql, -1, &stmt, NULL);
+ if (rc != SQLITE_OK) {
+ LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", set_schema_version_sql);
+ return rc;
+ }
+ rc = sqlite3_step(stmt);
+ if (rc != SQLITE_DONE)
+ LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 3\n");
+
+ db_remove_reset(stmt);
+ sqlite3_finalize(stmt);
+ return rc;
+}
+
static int db_get_user_version(struct db_context *dbc)
{
const char *user_version_sql = "PRAGMA user_version";
@@ -462,6 +498,15 @@
}
version = 2;
/* fall through */
+ case 2:
+ rc = db_upgrade_v3(dbc);
+ if (rc != SQLITE_DONE) {
+ LOGP(DDB, LOGL_ERROR, "Failed to upgrade HLR DB schema to version 3: (rc=%d) %s\n",
+ rc, sqlite3_errmsg(dbc->db));
+ goto out_free;
+ }
+ version = 2;
+ /* fall through */
/* case N: ... */
default:
break;
diff --git a/src/db.h b/src/db.h
index 6fd33ee..bb3a031 100644
--- a/src/db.h
+++ b/src/db.h
@@ -89,6 +89,7 @@
bool ms_purged_cs;
bool ms_purged_ps;
time_t last_lu_seen;
+ char last_lu_rat[128];
bool rat_types[OSMO_RAT_COUNT];
};
@@ -140,7 +141,8 @@
struct hlr_subscriber *subscr);
int db_subscr_nam(struct db_context *dbc, const char *imsi, bool nam_val, bool is_ps);
int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
- const char *vlr_or_sgsn_number, bool is_ps);
+ const char *vlr_or_sgsn_number, bool is_ps,
+ const enum osmo_rat_type rat_types[], size_t rat_types_len);
int db_subscr_purge(struct db_context *dbc, const char *by_imsi,
bool purge_val, bool is_ps);
diff --git a/src/db_hlr.c b/src/db_hlr.c
index f546e46..d1bb7b8 100644
--- a/src/db_hlr.c
+++ b/src/db_hlr.c
@@ -440,6 +440,7 @@
}
}
}
+ copy_sqlite3_text_to_buf(subscr->last_lu_rat, stmt, 14);
out:
db_remove_reset(stmt);
@@ -598,11 +599,14 @@
* -EIO on database errors.
*/
int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
- const char *vlr_or_sgsn_number, bool is_ps)
+ const char *vlr_or_sgsn_number, bool is_ps,
+ const enum osmo_rat_type rat_types[], size_t rat_types_len)
{
sqlite3_stmt *stmt;
int rc, ret = 0;
struct timespec localtime;
+ char rat_types_str[128] = "";
+ int i;
stmt = dbc->stmt[is_ps ? DB_STMT_UPD_SGSN_BY_ID
: DB_STMT_UPD_VLR_BY_ID];
@@ -656,6 +660,21 @@
goto out;
}
+ for (i = 0; i < rat_types_len; i++) {
+ char *pos = rat_types_str + strnlen(rat_types_str, sizeof(rat_types_str));
+ int len = pos - rat_types_str;
+ rc = snprintf(pos, len, "%s%s", pos == rat_types_str ? "" : ",", osmo_rat_type_name(rat_types[i]));
+ if (rc > len) {
+ osmo_strlcpy(rat_types_str + sizeof(rat_types_str) - 4, "...", 4);
+ break;
+ }
+ }
+
+ if (!db_bind_text(stmt, "$rat", rat_types_str)) {
+ ret = -EIO;
+ goto out;
+ }
+
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
LOGP(DAUC, LOGL_ERROR,
diff --git a/src/hlr.c b/src/hlr.c
index 098b934..1f5e63d 100644
--- a/src/hlr.c
+++ b/src/hlr.c
@@ -356,7 +356,8 @@
LOGP(DAUC, LOGL_DEBUG, "IMSI='%s': storing %s = %s\n",
subscr->imsi, luop->is_ps ? "SGSN number" : "VLR number",
osmo_quote_str((const char*)luop->peer, -1));
- if (db_subscr_lu(g_hlr->dbc, subscr->id, (const char *)luop->peer, luop->is_ps))
+ if (db_subscr_lu(g_hlr->dbc, subscr->id, (const char *)luop->peer, luop->is_ps,
+ gsup->rat_types, gsup->rat_types_len))
LOGP(DAUC, LOGL_ERROR, "IMSI='%s': Cannot update %s in the database\n",
subscr->imsi, luop->is_ps ? "SGSN number" : "VLR number");
diff --git a/src/hlr_vty_subscr.c b/src/hlr_vty_subscr.c
index 21296ff..983a71c 100644
--- a/src/hlr_vty_subscr.c
+++ b/src/hlr_vty_subscr.c
@@ -80,6 +80,8 @@
vty_out(vty, " PS purged%s", VTY_NEWLINE);
if (subscr->last_lu_seen)
vty_out(vty, " last LU seen: %s%s", get_datestr(&subscr->last_lu_seen), VTY_NEWLINE);
+ if (subscr->last_lu_rat[0])
+ vty_out(vty, " last LU RAT: %s%s", subscr->last_lu_rat, VTY_NEWLINE);
for (i = OSMO_RAT_UNKNOWN + 1; i < ARRAY_SIZE(subscr->rat_types); i++) {
vty_out(vty, " %s: %s%s", osmo_rat_type_name(i), subscr->rat_types[i] ? "allowed" : "forbidden",
VTY_NEWLINE);