From 36eea822d262b7a97d4c3a73ed86779fe33699c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grisez?= Date: Wed, 22 Jul 2015 23:26:59 +0200 Subject: [PATCH] Add a cache for unread messagaes count in LinphoneChatRoom That fix a performance issue when typing a message. The sqlite database was accessed each time a character was typed in order to mark all preceeding messages as read. That was done even if all message was marked as read. This patch add cache for unread messages count. Then, the count is only carried out at the first call of linphone_chat_room_get_unread_messages_count(). This function is used in linphone_chat_room_mark_as_read() to prevent database from being accessed if all messages are already marked as read. --- coreapi/chat.c | 7 +++++++ coreapi/message_storage.c | 21 +++++++++++++++++++++ coreapi/private.h | 1 + 3 files changed, 29 insertions(+) diff --git a/coreapi/chat.c b/coreapi/chat.c index abbbbf745..0140bdbe1 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -400,6 +400,7 @@ static LinphoneChatRoom * _linphone_core_create_chat_room(LinphoneCore *lc, Linp cr->lc = lc; cr->peer = linphone_address_as_string(addr); cr->peer_url = addr; + cr->unread_count = -1; lc->chatrooms = ms_list_append(lc->chatrooms, (void *)cr); return cr; } @@ -619,6 +620,8 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM msg->dir=LinphoneChatMessageOutgoing; msg->from=linphone_address_new(identity); msg->storage_id=linphone_chat_message_store(msg); + + if(cr->unread_count >= 0 && !msg->is_read) cr->unread_count++; // add to transient list cr->transient_messages = ms_list_append(cr->transient_messages, linphone_chat_message_ref(msg)); @@ -772,6 +775,10 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag linphone_address_destroy(addr); msg->storage_id=linphone_chat_message_store(msg); + + if(cr->unread_count < 0) cr->unread_count = 1; + else cr->unread_count++; + linphone_chat_room_message_received(cr,lc,msg); linphone_chat_message_unref(msg); } diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c index 22da7b8d0..a5985f4d3 100644 --- a/coreapi/message_storage.c +++ b/coreapi/message_storage.c @@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_PATH_SIZE 1024 #include "sqlite3.h" +#include static ORTP_INLINE LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, unsigned int storage_id){ MSList* transients = cr->transient_messages; @@ -286,6 +287,9 @@ void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ char *buf; if (lc->db==NULL) return ; + + // optimization: do not modify the database if no message is marked as unread + if(linphone_chat_room_get_unread_messages_count(cr) == 0) return; peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); buf=sqlite3_mprintf("UPDATE history SET read=%i WHERE remoteContact = %Q;", @@ -293,6 +297,8 @@ void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ linphone_sql_request(lc->db,buf); sqlite3_free(buf); ms_free(peer); + + cr->unread_count = 0; } void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { @@ -315,6 +321,9 @@ static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t un int returnValue; if (lc->db==NULL) return 0; + + // optimization: do not read database if the count is already available in memory + if(unread_only && cr->unread_count >= 0) return cr->unread_count; peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?"AND read = 0":""); @@ -327,6 +336,11 @@ static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t un sqlite3_finalize(selectStatement); sqlite3_free(buf); ms_free(peer); + + /* no need to test the sign of cr->unread_count here + * because it has been tested above */ + if(unread_only) cr->unread_count = numrows; + return numrows; } @@ -347,6 +361,11 @@ void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage buf=sqlite3_mprintf("DELETE FROM history WHERE id = %i;", msg->storage_id); linphone_sql_request(lc->db,buf); sqlite3_free(buf); + + if(cr->unread_count >= 0 && !msg->is_read) { + assert(cr->unread_count > 0); + cr->unread_count--; + } } void linphone_chat_room_delete_history(LinphoneChatRoom *cr){ @@ -361,6 +380,8 @@ void linphone_chat_room_delete_history(LinphoneChatRoom *cr){ linphone_sql_request(lc->db,buf); sqlite3_free(buf); ms_free(peer); + + if(cr->unread_count > 0) cr->unread_count = 0; } MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){ diff --git a/coreapi/private.h b/coreapi/private.h index 5366b9699..b48111c67 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -556,6 +556,7 @@ struct _LinphoneChatRoom{ LinphoneAddress *peer_url; MSList *messages_hist; MSList *transient_messages; + int unread_count; LinphoneIsComposingState remote_is_composing; LinphoneIsComposingState is_composing; belle_sip_source_t *remote_composing_refresh_timer;