[PATCH] Fix store file race

Alexander Malysh <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <[email protected]>
Hi all,

please find attached patch that fixes store file race condition by status request. Additionally this patch removes
status from each of store and add it to bb_store to abstract and simplified status handling in store.

Comment and objections please.

Thanks,
Alex
bb_store.patch (application/octet-stream, 18.6 KB)
diff --git a/gw/bb_store.c b/gw/bb_store.c
index 320af7d..fde39d3 100644
--- a/gw/bb_store.c
+++ b/gw/bb_store.c
@@ -64,6 +64,7 @@
 
 #include "gwlib/gwlib.h"
 #include "msg.h"
+#include "bearerbox.h"
 #include "bb_store.h"
 
 
@@ -73,10 +74,10 @@ int (*store_save_ack)(Msg *msg, ack_status_t status);
 int (*store_load)(void(*receive_msg)(Msg*));
 int (*store_dump)(void);
 void (*store_shutdown)(void);
-Octstr* (*store_status)(int status_type);
 Octstr* (*store_msg_pack)(Msg *msg);
 Msg* (*store_msg_unpack)(Octstr *os);
- 
+void (*store_for_each_message)(void(*callback_fn)(Msg* msg, void *data), void *data);
+
 
 int store_init(Cfg *cfg, const Octstr *type, const Octstr *fname, long dump_freq,
                void *pack_func, void *unpack_func)
@@ -101,3 +102,94 @@ int store_init(Cfg *cfg, const Octstr *type, const Octstr *fname, long dump_freq
 
     return ret;
 }
+
+struct status {
+    const char *format;
+    Octstr *status;
+};
+
+static void status_cb(Msg *msg, void *d)
+{
+    struct status *data = d;
+    struct tm tm;
+    char id[UUID_STR_LEN + 1];
+
+    if (msg == NULL)
+        return;
+
+    /* transform the time value */
+#if LOG_TIMESTAMP_LOCALTIME
+    tm = gw_localtime(msg->sms.time);
+#else
+    tm = gw_gmtime(msg->sms.time);
+#endif
+
+    uuid_unparse(msg->sms.id, id);
+
+    octstr_format_append(data->status, data->format,
+        id,
+        (msg->sms.sms_type == mo ? "MO" :
+        msg->sms.sms_type == mt_push ? "MT-PUSH" :
+        msg->sms.sms_type == mt_reply ? "MT-REPLY" :
+        msg->sms.sms_type == report_mo ? "DLR-MO" :
+        msg->sms.sms_type == report_mt ? "DLR-MT" : ""),
+        tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+        tm.tm_hour, tm.tm_min, tm.tm_sec,
+        (msg->sms.sender ? octstr_get_cstr(msg->sms.sender) : ""),
+        (msg->sms.receiver ? octstr_get_cstr(msg->sms.receiver) : ""),
+        (msg->sms.smsc_id ? octstr_get_cstr(msg->sms.smsc_id) : ""),
+        (msg->sms.boxc_id ? octstr_get_cstr(msg->sms.boxc_id) : ""),
+        msg->sms.mclass, msg->sms.coding, msg->sms.mwi, msg->sms.compress,
+        msg->sms.dlr_mask,
+        (msg->sms.udhdata ? msg->sms.udhdata : octstr_imm("")),
+        (msg->sms.msgdata ? msg->sms.msgdata : octstr_imm("")));
+}
+
+Octstr *store_status(int status_type)
+{
+    Octstr *ret = octstr_create("");
+    const char *format;
+    struct status data;
+
+    /* check if we are active */
+    if (store_for_each_message == NULL)
+        return ret;
+
+    /* set the type based header */
+    if (status_type == BBSTATUS_HTML) {
+        octstr_append_cstr(ret, "<table border=1>\n"
+            "<tr><td>SMS ID</td><td>Type</td><td>Time</td><td>Sender</td><td>Receiver</td>"
+            "<td>SMSC ID</td><td>BOX ID</td><td>Flags</td>"
+            "<td>UDH</td><td>Message</td>"
+            "</tr>\n");
+
+        format = "<tr><td>%s</td><td>%s</td>"
+                "<td>%04d-%02d-%02d %02d:%02d:%02d</td>"
+                "<td>%s</td><td>%s</td><td>%s</td>"
+                "<td>%s</td><td>%ld:%ld:%ld:%ld:%ld</td><td>%E</td><td>%E</td></tr>\n";
+    } else if (status_type == BBSTATUS_XML) {
+        format = "\t<message>\n\t<id>%s</id>\n\t<type>%s</type>\n\t"
+                "<time>%04d-%02d-%02d %02d:%02d:%02d</time>\n\t"
+                "<sender>%s</sender>\n\t"
+                "<receiver>%s</receiver>\n\t<smsc-id>%s</smsc-id>\n\t"
+                "<box-id>%s</box-id>\n\t"
+                "<flags>%ld:%ld:%ld:%ld:%ld</flags>\n\t"
+                "<udh-data>%E</udh-data>\n\t<msg-data>%E</msg-data>\n\t"
+                "</message>\n";
+    } else {
+        octstr_append_cstr(ret, "[SMS ID] [Type] [Time] [Sender] [Receiver] [SMSC ID] [BOX ID] [Flags] [UDH] [Message]\n");
+        format = "[%s] [%s] [%04d-%02d-%02d %02d:%02d:%02d] [%s] [%s] [%s] [%s] [%ld:%ld:%ld:%ld:%ld] [%E] [%E]\n";
+    }
+
+    data.format = format;
+    data.status = ret;
+
+    store_for_each_message(status_cb, &data);
+
+    /* set the type based footer */
+    if (status_type == BBSTATUS_HTML) {
+        octstr_append_cstr(ret,"</table>");
+    }
+
+    return ret;
+}
diff --git a/gw/bb_store.h b/gw/bb_store.h
index 86c5ea7..e85928e 100644
--- a/gw/bb_store.h
+++ b/gw/bb_store.h
@@ -105,7 +105,10 @@ int store_init(Cfg *cfg, const Octstr *type, const Octstr *fname, long dump_freq
 extern void (*store_shutdown)(void);
 
 /* return all containing messages in the current store */
-extern Octstr* (*store_status)(int status_type);
+Octstr* store_status(int status_type);
+
+extern void (*store_for_each_message)(void(*callback_fn)(Msg*, void*), void *data);
+
 
 /**
  * Init functions for different store types.
diff --git a/gw/bb_store_file.c b/gw/bb_store_file.c
index ed5f67d..44eb459 100644
--- a/gw/bb_store_file.c
+++ b/gw/bb_store_file.c
@@ -258,106 +258,29 @@ static void store_dumper(void *arg)
 
 /*------------------------------------------------------*/
 
-static Octstr *store_file_status(int status_type)
+static void store_file_for_each_message(void(*callback_fn)(Msg* msg, void *data), void *data)
 {
-    char *frmt;
-    Octstr *ret, *key;
-    unsigned long l;
-    struct tm tm;
-    Msg *msg;
     List *keys;
-    char id[UUID_STR_LEN + 1];
-
-    ret = octstr_create("");
+    long l;
+    Msg *msg;
+    Octstr *key;
 
-    /* set the type based header */
-    if (status_type == BBSTATUS_HTML) {
-        octstr_append_cstr(ret, "<table border=1>\n"
-            "<tr><td>SMS ID</td><td>Type</td><td>Time</td><td>Sender</td><td>Receiver</td>"
-            "<td>SMSC ID</td><td>BOX ID</td><td>UDH</td><td>Message</td>"
-            "</tr>\n");
-    } else if (status_type == BBSTATUS_TEXT) {
-        octstr_append_cstr(ret, "[SMS ID] [Type] [Time] [Sender] [Receiver] [SMSC ID] [BOX ID] [UDH] [Message]\n");
-    }
-   
     /* if there is no store-file, then don't loop in sms_store */
     if (filename == NULL)
-        goto finish;
+        return;
 
+    mutex_lock(file_mutex);
     keys = dict_keys(sms_dict);
-
     for (l = 0; l < gwlist_len(keys); l++) {
         key = gwlist_get(keys, l);
         msg = dict_get(sms_dict, key);
         if (msg == NULL)
             continue;
-
-        if (msg_type(msg) == sms) {
-
-            if (status_type == BBSTATUS_HTML) {
-                frmt = "<tr><td>%s</td><td>%s</td>"
-                       "<td>%04d-%02d-%02d %02d:%02d:%02d</td>"
-                       "<td>%s</td><td>%s</td><td>%s</td>"
-                       "<td>%s</td><td>%s</td><td>%s</td></tr>\n";
-            } else if (status_type == BBSTATUS_XML) {
-                frmt = "<message>\n\t<id>%s</id>\n\t<type>%s</type>\n\t"
-                       "<time>%04d-%02d-%02d %02d:%02d:%02d</time>\n\t"
-                       "<sender>%s</sender>\n\t"
-                       "<receiver>%s</receiver>\n\t<smsc-id>%s</smsc-id>\n\t"
-                       "<box-id>%s</box-id>\n\t"
-                       "<udh-data>%s</udh-data>\n\t<msg-data>%s</msg-data>\n\t"
-                       "</message>\n";
-            } else {
-                frmt = "[%s] [%s] [%04d-%02d-%02d %02d:%02d:%02d] [%s] [%s] [%s] [%s] [%s] [%s]\n";
-            }
-
-            /* transform the time value */
-#if LOG_TIMESTAMP_LOCALTIME
-            tm = gw_localtime(msg->sms.time);
-#else
-            tm = gw_gmtime(msg->sms.time);
-#endif
-            if (msg->sms.udhdata)
-                octstr_binary_to_hex(msg->sms.udhdata, 1);
-            if (msg->sms.msgdata &&
-                (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2 ||
-                (msg->sms.coding == DC_UNDEF && msg->sms.udhdata)))
-                octstr_binary_to_hex(msg->sms.msgdata, 1);
-
-            uuid_unparse(msg->sms.id, id);
-
-            octstr_format_append(ret, frmt, id,
-                (msg->sms.sms_type == mo ? "MO" :
-                 msg->sms.sms_type == mt_push ? "MT-PUSH" :
-                 msg->sms.sms_type == mt_reply ? "MT-REPLY" :
-                 msg->sms.sms_type == report_mo ? "DLR-MO" :
-                 msg->sms.sms_type == report_mt ? "DLR-MT" : ""),
-                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-                 tm.tm_hour, tm.tm_min, tm.tm_sec,
-                (msg->sms.sender ? octstr_get_cstr(msg->sms.sender) : ""),
-                (msg->sms.receiver ? octstr_get_cstr(msg->sms.receiver) : ""),
-                (msg->sms.smsc_id ? octstr_get_cstr(msg->sms.smsc_id) : ""),
-                (msg->sms.boxc_id ? octstr_get_cstr(msg->sms.boxc_id) : ""),
-                (msg->sms.udhdata ? octstr_get_cstr(msg->sms.udhdata) : ""),
-                (msg->sms.msgdata ? octstr_get_cstr(msg->sms.msgdata) : ""));
-
-            if (msg->sms.udhdata)
-                octstr_hex_to_binary(msg->sms.udhdata);
-            if (msg->sms.msgdata &&
-                (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2 ||
-                (msg->sms.coding == DC_UNDEF && msg->sms.udhdata)))
-                octstr_hex_to_binary(msg->sms.msgdata);
-        }
-    }
-    gwlist_destroy(keys, octstr_destroy_item);
-
-finish:
-    /* set the type based footer */
-    if (status_type == BBSTATUS_HTML) {
-        octstr_append_cstr(ret,"</table>");
+        callback_fn(msg, data);
     }
+    mutex_unlock(file_mutex);
 
-    return ret;
+    gwlist_destroy(keys, octstr_destroy_item);
 }
 
 
@@ -598,7 +521,7 @@ int store_file_init(const Octstr *fname, long dump_freq)
     store_load = store_file_load;
     store_dump = store_file_dump;
     store_shutdown = store_file_shutdown;
-    store_status = store_file_status;
+    store_for_each_message = store_file_for_each_message;
 
     if (fname == NULL)
         return 0; /* we are done */
diff --git a/gw/bb_store_redis.c b/gw/bb_store_redis.c
index fc94b2a..e87bb1a 100644
--- a/gw/bb_store_redis.c
+++ b/gw/bb_store_redis.c
@@ -158,7 +158,7 @@ static void store_redis_delete(Octstr *id)
 }
 
 
-struct store_db_fields *store_db_fields_create(CfgGroup *grp)
+static struct store_db_fields *store_db_fields_create(CfgGroup *grp)
 {
     struct store_db_fields *ret;
 
@@ -175,7 +175,7 @@ struct store_db_fields *store_db_fields_create(CfgGroup *grp)
 }
 
 
-void store_db_fields_destroy(struct store_db_fields *fields)
+static void store_db_fields_destroy(struct store_db_fields *fields)
 {
     /* sanity check */
     if (fields == NULL)
@@ -246,100 +246,38 @@ static int store_redis_getall(int ignore_err, void(*cb)(Octstr*, void*), void *d
 
 
 struct status {
-    const char *format;
-    Octstr *status;
+    void(*callback_fn)(Msg* msg, void *data);
+    void *data;
 };
 
+
 static void status_cb(Octstr *msg_s, void *d)
 {
     struct status *data = d;
-    struct tm tm;
-    char id[UUID_STR_LEN + 1];
     Msg *msg;
 
     msg = store_msg_unpack(msg_s);
-
     if (msg == NULL)
         return;
-    /* transform the time value */
-#if LOG_TIMESTAMP_LOCALTIME
-    tm = gw_localtime(msg->sms.time);
-#else
-    tm = gw_gmtime(msg->sms.time);
-#endif
-    if (msg->sms.udhdata)
-        octstr_binary_to_hex(msg->sms.udhdata, 1);
-    if (msg->sms.msgdata &&
-        (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2 ||
-        (msg->sms.coding == DC_UNDEF && msg->sms.udhdata)))
-        octstr_binary_to_hex(msg->sms.msgdata, 1);
-
-    uuid_unparse(msg->sms.id, id);
-
-    octstr_format_append(data->status, data->format,
-        id,
-        (msg->sms.sms_type == mo ? "MO" :
-        msg->sms.sms_type == mt_push ? "MT-PUSH" :
-        msg->sms.sms_type == mt_reply ? "MT-REPLY" :
-        msg->sms.sms_type == report_mo ? "DLR-MO" :
-        msg->sms.sms_type == report_mt ? "DLR-MT" : ""),
-        tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-        tm.tm_hour, tm.tm_min, tm.tm_sec,
-        (msg->sms.sender ? octstr_get_cstr(msg->sms.sender) : ""),
-        (msg->sms.receiver ? octstr_get_cstr(msg->sms.receiver) : ""),
-        (msg->sms.smsc_id ? octstr_get_cstr(msg->sms.smsc_id) : ""),
-        (msg->sms.boxc_id ? octstr_get_cstr(msg->sms.boxc_id) : ""),
-        (msg->sms.udhdata ? octstr_get_cstr(msg->sms.udhdata) : ""),
-        (msg->sms.msgdata ? octstr_get_cstr(msg->sms.msgdata) : ""));
+
+    data->callback_fn(msg, data->data);
 
     msg_destroy(msg);
 }
 
-static Octstr *store_redis_status(int status_type)
+
+static void store_redis_for_each_message(void(*callback_fn)(Msg* msg, void *data), void *data)
 {
-    Octstr *ret = octstr_create("");
-    const char *format;
-    struct status data;
+    struct status d;
 
-    /* check if we are active */
     if (pool == NULL)
-        return ret;
-
-    /* set the type based header */
-    if (status_type == BBSTATUS_HTML) {
-        octstr_append_cstr(ret, "<table border=1>\n"
-            "<tr><td>SMS ID</td><td>Type</td><td>Time</td><td>Sender</td><td>Receiver</td>"
-            "<td>SMSC ID</td><td>BOX ID</td><td>UDH</td><td>Message</td>"
-            "</tr>\n");
-
-        format = "<tr><td>%s</td><td>%s</td>"
-                "<td>%04d-%02d-%02d %02d:%02d:%02d</td>"
-                "<td>%s</td><td>%s</td><td>%s</td>"
-                "<td>%s</td><td>%s</td><td>%s</td></tr>\n";
-    } else if (status_type == BBSTATUS_XML) {
-        format = "<message>\n\t<id>%s</id>\n\t<type>%s</type>\n\t"
-                "<time>%04d-%02d-%02d %02d:%02d:%02d</time>\n\t"
-                "<sender>%s</sender>\n\t"
-                "<receiver>%s</receiver>\n\t<smsc-id>%s</smsc-id>\n\t"
-                "<box-id>%s</box-id>\n\t"
-                "<udh-data>%s</udh-data>\n\t<msg-data>%s</msg-data>\n\t"
-                "</message>\n";
-    } else {
-        octstr_append_cstr(ret, "[SMS ID] [Type] [Time] [Sender] [Receiver] [SMSC ID] [BOX ID] [UDH] [Message]\n");
-        format = "[%s] [%s] [%04d-%02d-%02d %02d:%02d:%02d] [%s] [%s] [%s] [%s] [%s] [%s]\n";
-    }
+        return;
 
-    data.format = format;
-    data.status = ret;
-    /* ignore error because files may disappear */
-    store_redis_getall(1, status_cb, &data);
+    d.callback_fn = callback_fn;
+    d.data = data;
 
-    /* set the type based footer */
-    if (status_type == BBSTATUS_HTML) {
-        octstr_append_cstr(ret,"</table>");
-    }
-
-    return ret;
+    /* ignore error because files may disappear */
+    store_redis_getall(1, status_cb, &d);
 }
 
 
@@ -477,7 +415,7 @@ int store_redis_init(Cfg *cfg)
     store_load = store_redis_load;
     store_dump = store_redis_dump;
     store_shutdown = store_redis_shutdown;
-    store_status = store_redis_status;
+    store_for_each_message = store_redis_for_each_message;
 
     /*
      * Check for all mandatory directives that specify the field names
diff --git a/gw/bb_store_spool.c b/gw/bb_store_spool.c
index 35d05ce..7994097 100644
--- a/gw/bb_store_spool.c
+++ b/gw/bb_store_spool.c
@@ -134,16 +134,14 @@ static int for_each_file(const Octstr *dir_s, int ignore_err, void(*cb)(const Oc
 
 
 struct status {
-    const char *format;
-    Octstr *status;
+    void(*callback_fn)(Msg* msg, void *data);
+    void *data;
 };
 
 
 static void status_cb(const Octstr *filename, void *d)
 {
     struct status *data = d;
-    struct tm tm;
-    char id[UUID_STR_LEN + 1];
     Octstr *msg_s;
     Msg *msg;
 
@@ -153,86 +151,24 @@ static void status_cb(const Octstr *filename, void *d)
     if (msg == NULL)
         return;
 
-    /* transform the time value */
-#if LOG_TIMESTAMP_LOCALTIME
-    tm = gw_localtime(msg->sms.time);
-#else
-    tm = gw_gmtime(msg->sms.time);
-#endif
-    if (msg->sms.udhdata)
-        octstr_binary_to_hex(msg->sms.udhdata, 1);
-    if (msg->sms.msgdata &&
-        (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2 ||
-        (msg->sms.coding == DC_UNDEF && msg->sms.udhdata)))
-        octstr_binary_to_hex(msg->sms.msgdata, 1);
-
-    uuid_unparse(msg->sms.id, id);
-
-    octstr_format_append(data->status, data->format,
-        id,
-        (msg->sms.sms_type == mo ? "MO" :
-        msg->sms.sms_type == mt_push ? "MT-PUSH" :
-        msg->sms.sms_type == mt_reply ? "MT-REPLY" :
-        msg->sms.sms_type == report_mo ? "DLR-MO" :
-        msg->sms.sms_type == report_mt ? "DLR-MT" : ""),
-        tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-        tm.tm_hour, tm.tm_min, tm.tm_sec,
-        (msg->sms.sender ? octstr_get_cstr(msg->sms.sender) : ""),
-        (msg->sms.receiver ? octstr_get_cstr(msg->sms.receiver) : ""),
-        (msg->sms.smsc_id ? octstr_get_cstr(msg->sms.smsc_id) : ""),
-        (msg->sms.boxc_id ? octstr_get_cstr(msg->sms.boxc_id) : ""),
-        (msg->sms.udhdata ? octstr_get_cstr(msg->sms.udhdata) : ""),
-        (msg->sms.msgdata ? octstr_get_cstr(msg->sms.msgdata) : ""));
+    data->callback_fn(msg, data->data);
 
     msg_destroy(msg);
 }
 
 
-static Octstr *store_spool_status(int status_type)
+static void store_spool_for_each_message(void(*callback_fn)(Msg* msg, void *data), void *data)
 {
-    Octstr *ret = octstr_create("");
-    const char *format;
-    struct status data;
+    struct status d;
 
-    /* check if we are active */
     if (spool == NULL)
-        return ret;
-
-    /* set the type based header */
-    if (status_type == BBSTATUS_HTML) {
-        octstr_append_cstr(ret, "<table border=1>\n"
-            "<tr><td>SMS ID</td><td>Type</td><td>Time</td><td>Sender</td><td>Receiver</td>"
-            "<td>SMSC ID</td><td>BOX ID</td><td>UDH</td><td>Message</td>"
-            "</tr>\n");
-
-        format = "<tr><td>%s</td><td>%s</td>"
-                "<td>%04d-%02d-%02d %02d:%02d:%02d</td>"
-                "<td>%s</td><td>%s</td><td>%s</td>"
-                "<td>%s</td><td>%s</td><td>%s</td></tr>\n";
-    } else if (status_type == BBSTATUS_XML) {
-        format = "<message>\n\t<id>%s</id>\n\t<type>%s</type>\n\t"
-                "<time>%04d-%02d-%02d %02d:%02d:%02d</time>\n\t"
-                "<sender>%s</sender>\n\t"
-                "<receiver>%s</receiver>\n\t<smsc-id>%s</smsc-id>\n\t"
-                "<box-id>%s</box-id>\n\t"
-                "<udh-data>%s</udh-data>\n\t<msg-data>%s</msg-data>\n\t"
-                "</message>\n";
-    } else {
-        octstr_append_cstr(ret, "[SMS ID] [Type] [Time] [Sender] [Receiver] [SMSC ID] [BOX ID] [UDH] [Message]\n");
-        format = "[%s] [%s] [%04d-%02d-%02d %02d:%02d:%02d] [%s] [%s] [%s] [%s] [%s] [%s]\n";
-    }
-
-    data.format = format;
-    data.status = ret;
-    /* ignore error because files may disappear */
-    for_each_file(spool, 1, status_cb, &data);
+        return;
 
-    /* set the type based footer */
-    if (status_type == BBSTATUS_HTML) {
-        octstr_append_cstr(ret,"</table>");
-    }
+    d.callback_fn = callback_fn;
+    d.data = data;
 
-    return ret;
+    /* ignore error because files may disappear */
+    for_each_file(spool, 1, status_cb, &d);
 }
 
 
@@ -409,7 +345,7 @@ int store_spool_init(const Octstr *store_dir)
     store_load = store_spool_load;
     store_dump = store_spool_dump;
     store_shutdown = store_spool_shutdown;
-    store_status = store_spool_status;
+    store_for_each_message = store_spool_for_each_message;
 
     if (store_dir == NULL)
         return 0;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.