<p>Vadim Yanitskiy has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/13632">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">WIP: store SM-TP-UDL in the database<br><br>Change-Id: I747a795ca486f3fcfa7583c5ab8aa2aee07a8ec2<br>---<br>M src/libmsc/db.c<br>1 file changed, 133 insertions(+), 3 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/32/13632/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/libmsc/db.c b/src/libmsc/db.c</span><br><span>index d9717d9..a9d6f0b 100644</span><br><span>--- a/src/libmsc/db.c</span><br><span>+++ b/src/libmsc/db.c</span><br><span>@@ -48,7 +48,7 @@</span><br><span> static dbi_conn conn;</span><br><span> static dbi_inst inst;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define SCHEMA_REVISION "5"</span><br><span style="color: hsl(120, 100%, 40%);">+#define SCHEMA_REVISION "6"</span><br><span> </span><br><span> enum {</span><br><span>   SCHEMA_META,</span><br><span>@@ -133,6 +133,7 @@</span><br><span>           "dest_addr TEXT NOT NULL, "</span><br><span>                "dest_ton INTEGER NOT NULL, "</span><br><span>              "dest_npi INTEGER NOT NULL, "</span><br><span style="color: hsl(120, 100%, 40%);">+               "user_data_len INTEGER NOT NULL, " /* TP-UDL */</span><br><span>            "user_data BLOB, "    /* TP-UD */</span><br><span>          /* additional data, interpreted from SMS */</span><br><span>          "header BLOB, "               /* UD Header */</span><br><span>@@ -227,20 +228,32 @@</span><br><span> </span><br><span> static void parse_tp_ud_from_result(struct gsm_sms *sms, dbi_result result)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int user_data_len, tp_udl;</span><br><span>  const unsigned char *user_data;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int user_data_len;</span><br><span>  unsigned int text_len;</span><br><span>       const char *text;</span><br><span> </span><br><span>        /* Retrieve TP-UDL (User-Data-Length) in octets (regardless of DCS) */</span><br><span>       user_data_len = dbi_result_get_field_length(result, "user_data");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Retrieve the original TP-UDL (User-Data-Length) value.</span><br><span style="color: hsl(120, 100%, 40%);">+      * Depending on DCS, may indicate the amount of octets or septets.</span><br><span style="color: hsl(120, 100%, 40%);">+     * Backwards compatibility: this field is available since v6.</span><br><span style="color: hsl(120, 100%, 40%);">+  * For older versions this call will return 0 (zero). */</span><br><span style="color: hsl(120, 100%, 40%);">+      tp_udl = dbi_result_get_ulonglong(result, "user_data_len");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tp_udl == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (user_data_len > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              sms->user_data_len = tp_udl;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Prevent TP-UD buffer overflow */</span><br><span>  if (user_data_len > sizeof(sms->user_data)) {</span><br><span>          LOGP(DDB, LOGL_ERROR,</span><br><span>                     "SMS TP-UD length %u is too big, truncating to %zu\n",</span><br><span>                     user_data_len, sizeof(sms->user_data));</span><br><span>              user_data_len = (uint8_t) sizeof(sms->user_data);</span><br><span>         }</span><br><span style="color: hsl(0, 100%, 40%);">-       sms->user_data_len = user_data_len;</span><br><span> </span><br><span>   /* Retrieve the TP-UD (User-Data) itself */</span><br><span>  user_data = dbi_result_get_binary(result, "user_data");</span><br><span>@@ -555,6 +568,119 @@</span><br><span>    return -EINVAL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Just like v4, but there is a new TP-UDL (User-Data-Length) field */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct gsm_sms *sms_from_result_v5(dbi_result result)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gsm_sms *sms;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      sms = sms_from_result_v4(result);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int update_db_revision_5(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct gsm_sms *sms;</span><br><span style="color: hsl(120, 100%, 40%);">+  dbi_result result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 5\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION");</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!result) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "Failed to begin transaction (upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Rename old SMS table to be able create a new one */</span><br><span style="color: hsl(120, 100%, 40%);">+        result = dbi_conn_query(conn, "ALTER TABLE SMS RENAME TO SMS_5");</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!result) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "Failed to rename the old SMS table (upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          goto rollback;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Create new SMS table with all the bells and whistles! */</span><br><span style="color: hsl(120, 100%, 40%);">+   result = dbi_conn_query(conn, create_stmts[SCHEMA_SMS]);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!result) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "Failed to create a new SMS table (upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            goto rollback;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Cycle through old messages and convert them to the new format */</span><br><span style="color: hsl(120, 100%, 40%);">+   result = dbi_conn_query(conn, "SELECT * FROM SMS_5");</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!result) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "Failed fetch messages from the old SMS table "</span><br><span style="color: hsl(120, 100%, 40%);">+                     "(upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             goto rollback;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     while (next_row(result)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            sms = sms_from_result_v5(result);</span><br><span style="color: hsl(120, 100%, 40%);">+             if (db_sms_store(sms) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 LOGP(DDB, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                      "Failed to store message to the new SMS table "</span><br><span style="color: hsl(120, 100%, 40%);">+                             "(upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                     dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+                      sms_free(sms);</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto rollback;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             sms_free(sms);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Remove the temporary table */</span><br><span style="color: hsl(120, 100%, 40%);">+      result = dbi_conn_query(conn, "DROP TABLE SMS_5");</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!result) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "Failed to drop the old SMS table (upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            goto rollback;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* We're done, bump DB Meta revision */</span><br><span style="color: hsl(120, 100%, 40%);">+   result = dbi_conn_query(conn,</span><br><span style="color: hsl(120, 100%, 40%);">+                         "UPDATE Meta "</span><br><span style="color: hsl(120, 100%, 40%);">+                              "SET value = '6' "</span><br><span style="color: hsl(120, 100%, 40%);">+                          "WHERE key = 'revision'");</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!result) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "Failed to update DB schema revision (upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         goto rollback;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+     dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    result = dbi_conn_query(conn, "COMMIT TRANSACTION");</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!result) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "Failed to commit the transaction (upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Shrink DB file size by actually wiping out SMS_4 table data */</span><br><span style="color: hsl(120, 100%, 40%);">+     result = dbi_conn_query(conn, "VACUUM");</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!result)</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGP(DDB, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "VACUUM failed. Ignoring it (upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+          dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+rollback:</span><br><span style="color: hsl(120, 100%, 40%);">+        result = dbi_conn_query(conn, "ROLLBACK TRANSACTION");</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!result)</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGP(DDB, LOGL_ERROR, "Rollback failed (upgrade from rev 5)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    else</span><br><span style="color: hsl(120, 100%, 40%);">+          dbi_result_free(result);</span><br><span style="color: hsl(120, 100%, 40%);">+      return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int check_db_revision(void)</span><br><span> {</span><br><span>      dbi_result result;</span><br><span>@@ -603,6 +729,10 @@</span><br><span>    case 4:</span><br><span>              if (update_db_revision_4())</span><br><span>                  goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* fall through */</span><br><span style="color: hsl(120, 100%, 40%);">+    case 5:</span><br><span style="color: hsl(120, 100%, 40%);">+               if (update_db_revision_5())</span><br><span style="color: hsl(120, 100%, 40%);">+                   goto error;</span><br><span> </span><br><span>      /* The end of waterfall */</span><br><span>   break;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13632">change 13632</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/13632"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-msc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I747a795ca486f3fcfa7583c5ab8aa2aee07a8ec2 </div>
<div style="display:none"> Gerrit-Change-Number: 13632 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Vadim Yanitskiy <axilirator@gmail.com> </div>