[PATCH] osmo-msc[master]: Add a VTY command which deletes all expired SMS.

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Stefan Sperling gerrit-no-reply at lists.osmocom.org
Mon Jan 22 16:19:52 UTC 2018


Review at  https://gerrit.osmocom.org/5989

Add a VTY command which deletes all expired SMS.

We already delete SMS which have been sent successfully. However, there
are plans to accept SMS for any subscriber in order to fix the problem
described in https://osmocom.org/issues/2354 ("SMSC: Store&Forward not
working for subscribed but unregistered MS").

This means we may end up storing SMS which never get sent, e.g. because
the B subscriber doesn't actually exist. This could lead to a higher
degree of SMS database growth over time, and therefore we need a way
to keep database size under control.

As a first step, introduce a DB function which removes an expired SMS,
and add a VTY command which removes all expired SMS from the DB.

Later commits will build upon this to remove expired SMS automatically.

The SMS expiry time period is currently hard-coded to 2 weeks.
We could make this configurable in the future if desired.

Change-Id: Icd6093b7b5d8db84b19a0aa47c68182566113ee2
Related: OS#2354
---
M include/osmocom/msc/db.h
M include/osmocom/msc/sms_queue.h
M src/libmsc/db.c
M src/libmsc/sms_queue.c
M src/libmsc/vty_interface_layer3.c
5 files changed, 83 insertions(+), 7 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/89/5989/1

diff --git a/include/osmocom/msc/db.h b/include/osmocom/msc/db.h
index 13c5ed3..2105d38 100644
--- a/include/osmocom/msc/db.h
+++ b/include/osmocom/msc/db.h
@@ -50,6 +50,7 @@
 int db_sms_inc_deliver_attempts(struct gsm_sms *sms);
 int db_sms_delete_by_msisdn(const char *msisdn);
 int db_sms_delete_sent_message_by_id(unsigned long long sms_id);
+int db_sms_delete_expired_message_by_id(unsigned long long sms_id);
 
 /* Statistics counter storage */
 struct osmo_counter;
diff --git a/include/osmocom/msc/sms_queue.h b/include/osmocom/msc/sms_queue.h
index 2a8bd58..b5488fe 100644
--- a/include/osmocom/msc/sms_queue.h
+++ b/include/osmocom/msc/sms_queue.h
@@ -13,5 +13,6 @@
 int sms_queue_set_max_pending(struct gsm_sms_queue *, int max);
 int sms_queue_set_max_failure(struct gsm_sms_queue *, int fail);
 int sms_queue_clear(struct gsm_sms_queue *);
+int sms_queue_sms_is_pending(struct gsm_sms_queue *smsq, unsigned long long sms_id);
 
 #endif
diff --git a/src/libmsc/db.c b/src/libmsc/db.c
index 4bf9b1f..5f9865d 100644
--- a/src/libmsc/db.c
+++ b/src/libmsc/db.c
@@ -989,6 +989,41 @@
 	return 0;
 }
 
+int db_sms_delete_expired_message_by_id(unsigned long long sms_id)
+{
+	dbi_result result;
+	time_t created, validity_timestamp, now, min_created;
+
+	result = dbi_conn_queryf(conn, "SELECT created,valid_until FROM SMS WHERE id = %llu", sms_id);
+	if (!result)
+		return -1;
+	if (!next_row(result))
+		return -1;
+
+	created = dbi_result_get_datetime(result, "created");
+	validity_timestamp = dbi_result_get_datetime(result, "valid_until");
+	dbi_result_free(result);
+
+	now = time(NULL);
+	if (validity_timestamp > now)
+		return -1;
+
+	/* Our SMS expiry threshold is hard-coded to roughly 2 weeks at the moment. */
+	min_created = now - (time_t)(60 * 60 * 24 * 7 * 2);
+	if (min_created < 0) /* bogus system clock? */
+		return -1;
+	if (created >= min_created) /* not yet expired */
+		return -1;
+
+	result = dbi_conn_queryf(conn, "DELETE FROM SMS WHERE id = %llu", sms_id);
+	if (!result) {
+		LOGP(DDB, LOGL_ERROR, "Failed to delete SMS %llu.\n", sms_id);
+		return -1;
+	}
+	dbi_result_free(result);
+	return 0;
+}
+
 int db_store_counter(struct osmo_counter *ctr)
 {
 	dbi_result result;
diff --git a/src/libmsc/sms_queue.c b/src/libmsc/sms_queue.c
index 1372a2c..8cc9eb3 100644
--- a/src/libmsc/sms_queue.c
+++ b/src/libmsc/sms_queue.c
@@ -73,21 +73,21 @@
 static int sms_sms_cb(unsigned int, unsigned int, void *, void *);
 
 static struct gsm_sms_pending *sms_find_pending(struct gsm_sms_queue *smsq,
-						struct gsm_sms *sms)
+						unsigned long long sms_id)
 {
 	struct gsm_sms_pending *pending;
 
 	llist_for_each_entry(pending, &smsq->pending_sms, entry) {
-		if (pending->sms_id == sms->id)
+		if (pending->sms_id == sms_id)
 			return pending;
 	}
 
 	return NULL;
 }
 
-static int sms_is_in_pending(struct gsm_sms_queue *smsq, struct gsm_sms *sms)
+int sms_queue_sms_is_pending(struct gsm_sms_queue *smsq, unsigned long long sms_id)
 {
-	return sms_find_pending(smsq, sms) != NULL;
+	return sms_find_pending(smsq, sms_id) != NULL;
 }
 
 static struct gsm_sms_pending *sms_subscriber_find_pending(
@@ -287,7 +287,7 @@
 		}
 
 		/* no need to send a pending sms */
-		if (sms_is_in_pending(smsq, sms)) {
+		if (sms_queue_sms_is_pending(smsq, sms->id)) {
 			LOGP(DLSMS, LOGL_DEBUG,
 			     "SMSqueue with pending sms: %llu. Skipping\n", sms->id);
 			sms_free(sms);
@@ -338,7 +338,7 @@
 		goto no_pending_sms;
 
 	/* The sms should not be scheduled right now */
-	OSMO_ASSERT(!sms_is_in_pending(smsq, sms));
+	OSMO_ASSERT(!sms_queue_sms_is_pending(smsq, sms->id));
 
 	/* Remember that we deliver this SMS and send it */
 	pending = sms_pending_from(smsq, sms);
@@ -473,7 +473,7 @@
 	 * sms that are not in our control as we just have a channel
 	 * open anyway.
 	 */
-	pending = sms_find_pending(network->sms_queue, sig_sms->sms);
+	pending = sms_find_pending(network->sms_queue, sig_sms->sms->id);
 	if (!pending)
 		return 0;
 
diff --git a/src/libmsc/vty_interface_layer3.c b/src/libmsc/vty_interface_layer3.c
index c7ec586..df555fd 100644
--- a/src/libmsc/vty_interface_layer3.c
+++ b/src/libmsc/vty_interface_layer3.c
@@ -166,6 +166,44 @@
 	return CMD_SUCCESS;
 }
 
+
+DEFUN(sms_delete_expired,
+      sms_delete_expired_cmd,
+      "sms delete expired",
+      "SMS related commands\n" "SMS Database related commands\n"
+      "Delete all expired SMS")
+{
+	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+	struct gsm_sms *sms;
+	unsigned long long sms_id = 0;
+	long long num_deleted = 0;
+
+	while (1) {
+		sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
+		if (!sms)
+			break;
+
+		/* Skip SMS which are currently queued for sending. */
+		if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
+			continue;
+
+		/* Expiration check is performed by the DB layer. */
+		if (db_sms_delete_expired_message_by_id(sms->id) == 0)
+			num_deleted++;
+
+		sms_id = sms->id + 1;
+	}
+
+	if (num_deleted == 0) {
+		vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
+	return CMD_SUCCESS;
+}
+
+
 static int _send_sms_str(struct vlr_subscr *receiver,
 			 struct vlr_subscr *sender,
 			 char *str, uint8_t tp_pid)
@@ -903,6 +941,7 @@
 	install_element_ve(&show_subscr_cache_cmd);
 
 	install_element_ve(&sms_send_pend_cmd);
+	install_element_ve(&sms_delete_expired_cmd);
 
 	install_element_ve(&subscriber_create_cmd);
 	install_element_ve(&subscriber_send_sms_cmd);

-- 
To view, visit https://gerrit.osmocom.org/5989
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Icd6093b7b5d8db84b19a0aa47c68182566113ee2
Gerrit-PatchSet: 1
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Owner: Stefan Sperling <ssperling at sysmocom.de>



More information about the gerrit-log mailing list