[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;