cpw.nader.asynclogging-3: 4c2f2ae2: Did away with the is_removable_fn stuff ...

morshed.nader at gmail.com morshed.nader at gmail.com
Wed Jan 19 01:50:41 EST 2011


----------------------------------------------------------------------
Revision: 4c2f2ae22de0a0f80742a4af887eca3253e3575a
Parent:   98aaf314a845a1d550deeeb8c1a91f3f6fdf8075
Author:   morshed.nader at gmail.com
Date:     01/19/11 01:47:02
Branch:   im.pidgin.cpw.nader.asynclogging-3
URL: http://d.pidgin.im/viewmtn/revision/info/4c2f2ae22de0a0f80742a4af887eca3253e3575a

Changelog: 

Did away with the is_removable_fn stuff (And all the async/finish functions) and just made purple_log_is_removable check if the logger has a remove function
Reorganized the code so definitions in log.c reflected their order in log.h
Definition cleanup and filling in of missing functions

Changes against parent 98aaf314a845a1d550deeeb8c1a91f3f6fdf8075

  patched  finch/gntlog.c
  patched  libpurple/log.c
  patched  libpurple/log.h
  patched  pidgin/gtklog.c
  patched  pidgin/gtkutils.c

-------------- next part --------------
============================================================
--- libpurple/log.c	209ddae54b08b76a01b9bf97aedcb32cb64b24e3
+++ libpurple/log.c	742a6ed2fbf33ccb9ddb314db2a0033a06120120
@@ -145,9 +145,10 @@ static void thread_write_callback_data_f
 static void thread_callback_data_free(gpointer);
 static void thread_write_callback_data_free(gpointer);
 
-static GHashTable *log_get_log_sets_common(GCancellable *, GError **);
-static void log_get_log_sets_common_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
-static void log_get_log_sets_common_async(gint, GCancellable *, GAsyncReadyCallback, gpointer);
+static void write_update_size_cache(PurpleLog *, gssize);
+static void write_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
+static void purple_log_real_write_async(PurpleLog *, PurpleMessageFlags, const gchar *, time_t, const gchar *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
+static gssize purple_log_real_write_finish(PurpleLog *, GAsyncResult *, GError **);
 
 static void log_read_res_free(gpointer);
 static void read_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
@@ -158,36 +159,30 @@ static gssize purple_log_real_size_finis
 static void purple_log_real_size_async(PurpleLog *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
 static gssize purple_log_real_size_finish(PurpleLog *, GAsyncResult *, GError **);
 
-static void write_update_size_cache(PurpleLog *, gssize);
-static void write_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
-static void purple_log_real_write_async(PurpleLog *, PurpleMessageFlags, const gchar *, time_t, const gchar *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
-static gssize purple_log_real_write_finish(PurpleLog *, GAsyncResult *, GError **);
+static void get_logs_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
+static void purple_log_real_get_logs_async(PurpleLog *, PurpleLogChatType, const gchar *, PurpleAccount *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
+static GList *purple_log_real_get_logs_finish(PurpleLog *, GAsyncResult *, GError **);
 
+static void list_syslog_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
+static void purple_log_real_list_syslog_async(PurpleLog *, PurpleAccount *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
+static GList *purple_log_real_list_syslog_finish(PurpleLog *, GAsyncResult *, GError **);
+
 static void total_size_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
 static void purple_log_real_total_size_async(PurpleLog *, PurpleLogChatType, const gchar *, PurpleAccount *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
 static gssize purple_log_real_total_size_finish(PurpleLog *, GAsyncResult *, GError **);
 
-static void is_removable_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
-static void purple_log_real_is_removable_async(PurpleLog *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
-static gboolean purple_log_real_is_removable_finish(PurpleLog *, GAsyncResult *, GError **);
+static void get_log_sets_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
+static void purple_log_real_get_log_sets_async(PurpleLog *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
+static GHashTable *purple_log_real_get_log_sets_finish(PurpleLog *, GAsyncResult *, GError **);
 
+static GHashTable *log_get_log_sets_common(GCancellable *, GError **);
+static void log_get_log_sets_common_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
+static void log_get_log_sets_common_async(gint, GCancellable *, GAsyncReadyCallback, gpointer);
 
 static void remove_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
 static void purple_log_real_remove_async(PurpleLog *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
 static gboolean purple_log_real_remove_finish(PurpleLog *, GAsyncResult *, GError **);
 
-static void get_logs_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
-static void purple_log_real_get_logs_async(PurpleLog *, PurpleLogChatType, const gchar *, PurpleAccount *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
-static GList *purple_log_real_get_logs_finish(PurpleLog *, GAsyncResult *, GError **);
-
-static void get_log_sets_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
-static void purple_log_real_get_log_sets_async(PurpleLog *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
-static GHashTable *purple_log_real_get_log_sets_finish(PurpleLog *, GAsyncResult *, GError **);
-
-static void list_syslog_thread(GSimpleAsyncResult *, GObject *, GCancellable *);
-static void purple_log_real_list_syslog_async(PurpleLog *, PurpleAccount *, gint, GCancellable *, GAsyncReadyCallback, gpointer);
-static GList *purple_log_real_list_syslog_finish(PurpleLog *, GAsyncResult *, GError **);
-
 static void log_list_cb(GObject *, GAsyncResult *, gpointer);
 static void log_system_list_cb(GObject *, GAsyncResult *, gpointer);
 static void log_total_size_cb(GObject *, GAsyncResult *, gpointer);
@@ -284,8 +279,6 @@ purple_log_class_init(PurpleLogClass *cl
 	class->get_log_sets_finish = purple_log_real_get_log_sets_finish;
 	class->remove_async = purple_log_real_remove_async;
 	class->remove_finish = purple_log_real_remove_finish;
-	class->is_removable_async = purple_log_real_is_removable_async;
-	class->is_removable_finish = purple_log_real_is_removable_finish;
 
 	properties[PROP_LOG_CHAT_TYPE] =
 		g_param_spec_enum("chat-type",
@@ -604,14 +597,10 @@ thread_write_callback_data_free(gpointer
 	g_free(callback_data);
 }
 
-
-/**************************************************************************
- * PUBLIC LOGGING FUNCTIONS ***********************************************
- **************************************************************************/
-
 PurpleLog *
-purple_log_new(GType log_type, PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account,
-	PurpleConversation *conv, time_t time, const struct tm *tm)
+purple_log_new(GType log_type, PurpleLogChatType chat_type, const gchar *name,
+	PurpleAccount *account, PurpleConversation *conv, time_t time,
+	const struct tm *tm)
 {
 	PurpleLog *log;
 
@@ -991,6 +980,348 @@ purple_log_get_size_finish(PurpleLog *lo
 	return PURPLE_LOG_GET_CLASS(log)->size_finish(log, res, error);
 }
 
+GList *
+purple_log_get_logs(PurpleLog *log, PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error)
+{
+	PurpleLogClass *class;
+
+	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
+	g_return_val_if_fail(name != NULL, NULL);
+	g_return_val_if_fail(account != NULL, NULL); // PURPLE_IS_ACCOUNT(account)
+
+	class = PURPLE_LOG_GET_CLASS(log);
+
+	if (class->list_fn == NULL) {
+		g_set_error_literal(error,
+			G_IO_ERROR,
+			G_IO_ERROR_NOT_SUPPORTED,
+			_("Operation not supported"));
+
+		return NULL;
+	}
+
+	return class->list_fn(log, chat_type, name, account, cancellable, error);
+}
+
+static void
+get_logs_thread(GSimpleAsyncResult *simple, GObject *object, GCancellable *cancellable)
+{
+	_thread_callback_data *callback_data =
+		g_simple_async_result_get_op_res_gpointer(simple);
+	PurpleAccount *account = callback_data->account;
+	PurpleLog *log = PURPLE_LOG(object);
+	PurpleLogChatType chat_type = callback_data->chat_type;
+	GError *error = NULL;
+	GList *logs;
+	gchar *name = callback_data->name;
+
+	logs = purple_log_get_logs(log, chat_type, name, account, cancellable, &error);
+
+	if (logs == NULL && error != NULL)
+		g_simple_async_result_set_from_error(simple, error);
+	else
+		g_simple_async_result_set_op_res_gpointer(simple, logs, NULL);
+
+	g_clear_error(&error);
+}
+
+static void
+purple_log_real_get_logs_async(PurpleLog *log, PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+{
+	_thread_callback_data *callback_data;
+	GSimpleAsyncResult *simple;
+
+	callback_data = g_new0(_thread_callback_data, 1);
+	callback_data->chat_type = chat_type;
+	callback_data->name = g_strdup(name);
+	callback_data->account = account; // g_object_ref
+
+	simple = g_simple_async_result_new(G_OBJECT(log), cb, userdata,
+		purple_log_real_get_logs_async);
+
+	g_simple_async_result_set_op_res_gpointer(simple, callback_data, thread_callback_data_free);
+	g_simple_async_result_run_in_thread(simple, get_logs_thread, io_priority, cancellable);
+	g_object_unref(simple);
+}
+
+void
+purple_log_get_logs_async(PurpleLog *log, PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+{
+	g_return_if_fail(PURPLE_IS_LOG(log));
+	g_return_if_fail(name != NULL);
+	g_return_if_fail(account != NULL); // PURPLE_IS_ACCOUNT(account)
+
+	PURPLE_LOG_GET_CLASS(log)->list_async(log, chat_type, name, account, io_priority, cancellable, cb, userdata);
+}
+
+static GList *
+purple_log_real_get_logs_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+{
+	return g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res));
+}
+
+GList *
+purple_log_get_logs_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+{
+	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
+	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), NULL);
+
+	if (G_IS_SIMPLE_ASYNC_RESULT(res)) {
+		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
+
+		if (g_simple_async_result_propagate_error(simple, error))
+			return NULL;
+	}
+
+	return PURPLE_LOG_GET_CLASS(log)->list_finish(log, res, error);
+}
+
+GList *
+purple_logs_get_logs(PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error)
+{
+	GArray *array;
+	GList *logs = NULL;
+	guint i;
+
+	g_return_val_if_fail(name != NULL, NULL);
+	g_return_val_if_fail(account != NULL, NULL); // PURPLE_IS_ACCOUNT(account)
+
+	array = purple_log_logger_get_all();
+
+	for (i = 0; i < array->len; i++) {
+		PurpleLog *log;
+		GError *err = NULL;
+		GList *list;
+		GType log_type = g_array_index(array, GType, i);
+
+		log = g_object_new(log_type, NULL);
+		list = purple_log_get_logs(log, chat_type, name, account, cancellable, &err);
+
+		if (list == NULL && err != NULL) {
+			g_propagate_error(error, err);
+			g_list_foreach(logs, (GFunc) g_object_unref, NULL);
+			g_list_free(logs);
+			g_object_unref(log);
+
+			return NULL;
+		}
+
+		logs = g_list_concat(list, logs);
+		g_object_unref(log);
+	}
+
+	return g_list_sort(logs, purple_log_compare);
+}
+
+void
+purple_logs_get_logs_async(PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+{
+	_get_logs_callback_data *callback_data;
+	GArray *array;
+	guint i;
+
+	g_return_if_fail(name != NULL);
+	g_return_if_fail(account != NULL); // PURPLE_IS_ACCOUNT(account)
+
+	array = purple_log_logger_get_all();
+
+	callback_data = g_new0(_get_logs_callback_data, 1);
+	callback_data->cb = cb;
+	callback_data->userdata = userdata;
+	callback_data->counter = array->len;
+	callback_data->logs = NULL;
+
+	for (i = 0; i < array->len; i++) {
+		PurpleLog *log;
+		GType log_type = g_array_index(array, GType, i);
+
+		log = g_object_new(log_type, NULL);
+		purple_log_get_logs_async(log, chat_type, name, account, io_priority, cancellable, log_list_cb, callback_data);
+		g_object_unref(log);
+	}
+}
+
+GList *
+purple_logs_get_logs_finish(GAsyncResult *res, GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(res), NULL);
+
+	simple = G_SIMPLE_ASYNC_RESULT(res);
+
+	if (g_simple_async_result_propagate_error(simple, error))
+		return NULL;
+
+	return g_simple_async_result_get_op_res_gpointer(simple);
+}
+
+GList *
+purple_log_get_system_logs(PurpleLog *log, PurpleAccount *account, GCancellable *cancellable, GError **error)
+{
+	PurpleLogClass *class;
+
+	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
+	g_return_val_if_fail(account != NULL, NULL); // PURPLE_IS_ACCOUNT(account)
+
+	class = PURPLE_LOG_GET_CLASS(log);
+
+	if (class->list_syslog_fn == NULL) {
+		g_set_error_literal(error,
+			G_IO_ERROR,
+			G_IO_ERROR_NOT_SUPPORTED,
+			_("Operation not supported"));
+
+		return NULL;
+	}
+
+	return class->list_syslog_fn(log, account, cancellable, error);
+}
+
+GList *
+purple_logs_get_system_logs(PurpleAccount *account, GCancellable *cancellable, GError **error)
+{
+	GArray *array;
+	GList *logs = NULL;
+	guint i;
+
+	g_return_val_if_fail(account != NULL, NULL); // PURPLE_IS_ACCOUNT(account)
+
+	array = purple_log_logger_get_all();
+
+	for (i = 0; i < array->len; i++) {
+		PurpleLog *log;
+		GList *list;
+		GType log_type = g_array_index(array, GType, i);
+
+		log = g_object_new(log_type, NULL);
+		list = purple_log_get_system_logs(log, account, cancellable, error);
+
+		if (list == NULL) {
+			g_object_unref(log);
+			g_list_foreach(logs, (GFunc) g_object_unref, NULL);
+			g_list_free(logs);
+
+			return NULL;
+		}
+
+		logs = g_list_concat(list, logs);
+		g_object_unref(log);
+	}
+
+	return g_list_sort(logs, purple_log_compare);
+}
+
+static void
+list_syslog_thread(GSimpleAsyncResult *simple, GObject *object, GCancellable *cancellable)
+{
+	_thread_callback_data *callback_data =
+		g_simple_async_result_get_op_res_gpointer(simple);
+	PurpleAccount *account = callback_data->account;
+	GError *error = NULL;
+	GList *list;
+
+	list = purple_log_get_system_logs(PURPLE_LOG(object), account, cancellable, &error);
+
+	if (list == NULL && error != NULL)
+		g_simple_async_result_set_from_error(simple, error);
+	else
+		g_simple_async_result_set_op_res_gpointer(simple, list, NULL);
+
+	g_clear_error(&error);
+}
+
+static void
+purple_log_real_list_syslog_async(PurpleLog *log, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+{
+	_thread_callback_data *callback_data;
+	GSimpleAsyncResult *simple;
+
+	callback_data = g_new0(_thread_callback_data, 1);
+	callback_data->account = account; // g_object_ref
+
+	simple = g_simple_async_result_new(G_OBJECT(log), cb, userdata,
+		purple_log_real_list_syslog_async);
+
+	g_simple_async_result_set_op_res_gpointer(simple, callback_data, thread_callback_data_free);
+	g_simple_async_result_run_in_thread(simple, list_syslog_thread, io_priority, cancellable);
+	g_object_unref(simple);
+}
+
+void
+purple_log_get_system_logs_async(PurpleLog *log, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+{
+	g_return_if_fail(PURPLE_IS_LOG(log));
+	g_return_if_fail(account != NULL); // PURPLE_IS_ACCOUNT(account)
+
+	PURPLE_LOG_GET_CLASS(log)->list_syslog_async(log, account, io_priority, cancellable, cb, userdata);
+}
+
+void
+purple_logs_get_system_logs_async(PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+{
+	_get_logs_callback_data *callback_data;
+	GArray *array;
+	guint i;
+
+	g_return_if_fail(account != NULL); // PURPLE_IS_ACCOUNT(account)
+
+	array = purple_log_logger_get_all();
+
+	callback_data = g_new0(_get_logs_callback_data, 1);
+	callback_data->userdata = userdata;
+	callback_data->cb = cb;
+	callback_data->counter = array->len;
+	callback_data->logs = NULL;
+
+	for (i = 0; i < array->len; i++) {
+		PurpleLog *log;
+		GType log_type = g_array_index(array, GType, i);
+
+		log = g_object_new(log_type, NULL);
+		purple_log_get_system_logs_async(log, account, io_priority, cancellable, log_system_list_cb, callback_data);
+
+		g_object_unref(log);
+	}
+}
+
+static GList *
+purple_log_real_list_syslog_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+{
+	return g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res));
+}
+
+GList *
+purple_log_get_system_logs_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+{
+	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
+	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), NULL);
+
+	if (G_IS_SIMPLE_ASYNC_RESULT(res)) {
+		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
+
+		if (g_simple_async_result_propagate_error(simple, error))
+			return NULL;
+	}
+
+	return PURPLE_LOG_GET_CLASS(log)->list_syslog_finish(log, res, error);
+}
+
+GList *
+purple_logs_get_system_logs_finish(GAsyncResult *res, GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(res), NULL);
+
+	simple = G_SIMPLE_ASYNC_RESULT(res);
+
+	if (g_simple_async_result_propagate_error(simple, error))
+		return NULL;
+
+	return g_simple_async_result_get_op_res_gpointer(simple);
+}
+
 static guint
 _purple_logsize_user_hash(_purple_logsize_user *lu)
 {
@@ -1050,57 +1381,6 @@ purple_log_get_total_size(PurpleLog *log
 	}
 }
 
-gssize
-purple_logs_get_total_size(PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error)
-{
-	_purple_logsize_user *lu;
-	gpointer ptrsize;
-	gboolean result;
-	gssize total = 0;
-
-	g_return_val_if_fail(name != NULL, -1);
-	g_return_val_if_fail(account != NULL, -1); // PURPLE_IS_ACCOUNT(account)
-
-	lu = g_new(_purple_logsize_user, 1);
-	lu->name = g_strdup(purple_normalize(account, name));
-	lu->account = account; //g_object_ref?
-
-	G_LOCK(logsize_users);
-	result = g_hash_table_lookup_extended(logsize_users, lu, NULL, &ptrsize);
-	G_UNLOCK(logsize_users);
-
-	if (result) {
-		total = GPOINTER_TO_INT(ptrsize);
-
-		g_free(lu->name);
-		g_free(lu);
-	} else {
-		GArray *array = purple_log_logger_get_all();
-		guint i;
-
-		for (i = 0; i < array->len; i++) {
-			PurpleLog *log;
-			GType log_type = g_array_index(array, GType, i);
-			gssize size;
-
-			log = g_object_new(log_type, NULL);
-			size = purple_log_get_total_size(log, chat_type, name, account, cancellable, error);
-			g_object_unref(log);
-
-			if (size < 0)
-				return -1;
-
-			total += size;
-		}
-
-		G_LOCK(logsize_users);
-		g_hash_table_replace(logsize_users, lu, GINT_TO_POINTER(total));
-		G_UNLOCK(logsize_users);
-	}
-
-	return total;
-}
-
 static void
 total_size_thread(GSimpleAsyncResult *simple, GObject *object, GCancellable *cancellable)
 {
@@ -1185,6 +1465,91 @@ purple_log_real_total_size_async(PurpleL
 	g_object_unref(simple);
 }
 
+void
+purple_log_get_total_size_async(PurpleLog *log, PurpleLogChatType chat_type,
+	const gchar *name, PurpleAccount *account, gint io_priority,
+	GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+{
+	g_return_if_fail(name != NULL);
+	g_return_if_fail(account != NULL); // PURPLE_IS_ACCOUNT(account)
+
+	PURPLE_LOG_GET_CLASS(log)->total_size_async(log, chat_type, name, account,
+		io_priority, cancellable, cb, userdata);
+}
+
+static gssize
+purple_log_real_total_size_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+{
+	return g_simple_async_result_get_op_res_gssize(G_SIMPLE_ASYNC_RESULT(res));
+}
+
+gssize
+purple_log_get_total_size_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+{
+	g_return_val_if_fail(PURPLE_IS_LOG(log), -1);
+	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), -1);
+
+	if (G_IS_SIMPLE_ASYNC_RESULT(res)) {
+		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
+
+		if (g_simple_async_result_propagate_error(simple, error))
+			return -1;
+	}
+
+	return PURPLE_LOG_GET_CLASS(log)->total_size_finish(log, res, error);
+}
+
+gssize
+purple_logs_get_total_size(PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error)
+{
+	_purple_logsize_user *lu;
+	gpointer ptrsize;
+	gboolean result;
+	gssize total = 0;
+
+	g_return_val_if_fail(name != NULL, -1);
+	g_return_val_if_fail(account != NULL, -1); // PURPLE_IS_ACCOUNT(account)
+
+	lu = g_new(_purple_logsize_user, 1);
+	lu->name = g_strdup(purple_normalize(account, name));
+	lu->account = account; //g_object_ref?
+
+	G_LOCK(logsize_users);
+	result = g_hash_table_lookup_extended(logsize_users, lu, NULL, &ptrsize);
+	G_UNLOCK(logsize_users);
+
+	if (result) {
+		total = GPOINTER_TO_INT(ptrsize);
+
+		g_free(lu->name);
+		g_free(lu);
+	} else {
+		GArray *array = purple_log_logger_get_all();
+		guint i;
+
+		for (i = 0; i < array->len; i++) {
+			PurpleLog *log;
+			GType log_type = g_array_index(array, GType, i);
+			gssize size;
+
+			log = g_object_new(log_type, NULL);
+			size = purple_log_get_total_size(log, chat_type, name, account, cancellable, error);
+			g_object_unref(log);
+
+			if (size < 0)
+				return -1;
+
+			total += size;
+		}
+
+		G_LOCK(logsize_users);
+		g_hash_table_replace(logsize_users, lu, GINT_TO_POINTER(total));
+		G_UNLOCK(logsize_users);
+	}
+
+	return total;
+}
+
 // TODO: Would it make sense to allow the caller to pass in a list of logs, if
 // TODO: it just got them from purple_logs_get_logs_async()?  Pidgin asks
 // TODO: for the total size, which means that for some loggers, we end up
@@ -1197,7 +1562,9 @@ void
 // TODO: 	if (!log->logger->total_size && log->logger->size)
 // TODO: 		Call the size function.
 void
-purple_logs_get_total_size_async(PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+purple_logs_get_total_size_async(PurpleLogChatType chat_type, const gchar *name,
+	PurpleAccount *account, gint io_priority, GCancellable *cancellable,
+	GAsyncReadyCallback cb, gpointer userdata)
 {
 	_purple_log_total_size_callback_data *callback_data;
 	_purple_logsize_user *lu;
@@ -1255,47 +1622,225 @@ purple_logs_get_total_size_async(PurpleL
 		GType log_type = g_array_index(array, GType, i);
 
 		log = g_object_new(log_type, NULL);
-		PURPLE_LOG_GET_CLASS(log)->total_size_async(log, chat_type, name,
-			account, io_priority, cancellable, log_total_size_cb, callback_data);
+		purple_log_get_total_size_async(log, chat_type, name, account,
+			io_priority, cancellable, log_total_size_cb, callback_data);
 		g_object_unref(log);
 	}
 }
 
-static gssize
-purple_log_real_total_size_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+gssize
+purple_logs_get_total_size_finish(GAsyncResult *res, GError **error)
 {
-	return g_simple_async_result_get_op_res_gssize(G_SIMPLE_ASYNC_RESULT(res));
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(res), -1);
+
+	simple = G_SIMPLE_ASYNC_RESULT(res);
+
+	if (g_simple_async_result_propagate_error(simple, error))
+		return -1;
+
+	return g_simple_async_result_get_op_res_gssize(simple);
 }
 
-gssize
-purple_log_get_total_size_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+static gboolean
+steal_log_sets(gpointer key, gpointer value, gpointer sets)
 {
-	g_return_val_if_fail(PURPLE_IS_LOG(log), -1);
-	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), -1);
+	_purple_log_add_log_set_to_hash(sets, key);
+	return TRUE;
+}
 
+GHashTable *
+purple_log_get_log_sets(PurpleLog *log, GCancellable *cancellable, GError **error)
+{
+	PurpleLogClass *class;
+
+	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
+
+	class = PURPLE_LOG_GET_CLASS(log);
+
+	if (class->get_log_sets_fn == NULL) {
+		g_set_error_literal(error,
+			G_IO_ERROR,
+			G_IO_ERROR_NOT_SUPPORTED,
+			_("Operation not supported"));
+
+		return NULL;
+	}
+
+	return class->get_log_sets_fn(log, cancellable, error);
+}
+
+static void
+get_log_sets_thread(GSimpleAsyncResult *simple, GObject *object, GCancellable *cancellable)
+{
+	PurpleLog *log = PURPLE_LOG(object);
+	PurpleLogClass *class = PURPLE_LOG_GET_CLASS(log);
+	GError *error = NULL;
+	GHashTable *sets;
+
+	if (class->get_log_sets_fn == NULL) {
+		g_simple_async_result_set_error(simple, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+			_("Operation not supported"));
+
+		return;
+	}
+
+	sets = class->get_log_sets_fn(log, cancellable, &error);
+
+	if (sets == NULL)
+		g_simple_async_result_set_from_error(simple, error);
+	else
+		g_simple_async_result_set_op_res_gpointer(simple, sets, (GDestroyNotify) g_hash_table_unref);
+
+	g_clear_error(&error);
+}
+
+static void
+purple_log_real_get_log_sets_async(PurpleLog *log, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+{
+	GSimpleAsyncResult *simple;
+
+	simple = g_simple_async_result_new(G_OBJECT(log), cb, userdata,
+		purple_log_real_get_log_sets_async);
+
+	g_simple_async_result_run_in_thread(simple, get_log_sets_thread, io_priority, cancellable);
+	g_object_unref(simple);
+}
+
+void
+purple_log_get_log_sets_async(PurpleLog *log, gint io_priority,
+	GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
+{
+	g_return_if_fail(PURPLE_IS_LOG(log));
+
+	PURPLE_LOG_GET_CLASS(log)->get_log_sets_async(log,
+		io_priority, cancellable, cb, userdata);
+}
+
+static GHashTable * 
+purple_log_real_get_log_sets_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+{
+	return g_hash_table_ref(g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res)));
+}
+
+GHashTable *
+purple_log_get_log_sets_finish(PurpleLog *log, GAsyncResult *res, GError **error)
+{
+	g_return_val_if_fail(log == NULL || PURPLE_IS_LOG(log), NULL);
+	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), NULL);
+
 	if (G_IS_SIMPLE_ASYNC_RESULT(res)) {
 		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
 
 		if (g_simple_async_result_propagate_error(simple, error))
-			return -1;
+			return NULL;
 	}
 
-	return PURPLE_LOG_GET_CLASS(log)->total_size_finish(log, res, error);
+	if (log == NULL)
+		/* Result of purple_log_common */
+		return g_hash_table_ref(g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res)));
+	else
+		return PURPLE_LOG_GET_CLASS(log)->get_log_sets_finish(log, res, error);
 }
 
-gssize
-purple_logs_get_total_size_finish(GAsyncResult *res, GError **error)
+GHashTable *
+purple_logs_get_log_sets(GCancellable *cancellable, GError **error)
 {
+	GArray *array;
+	GHashTable *sets, *one_set;
+	GError *err = NULL;
+	guint i;
+
+	sets = g_hash_table_new_full(_purple_log_set_hash, _purple_log_set_equal,
+		(GDestroyNotify) purple_log_set_free, NULL);
+
+	array = purple_log_logger_get_all();
+
+	for (i = 0; i < array->len; i++) {
+		PurpleLog *log;
+		GType log_type = g_array_index(array, GType, i);
+
+		log = g_object_new(log_type, NULL);
+		one_set = purple_log_get_log_sets(log, cancellable, &err);
+
+		if (one_set == NULL) {
+			g_object_unref(log);
+
+			if (err->code == G_IO_ERROR_NOT_SUPPORTED) {
+				g_clear_error(&err);
+				continue;
+			} else {
+				g_propagate_error(error, err);
+				g_hash_table_destroy(sets);
+				return NULL;
+			}
+		}
+
+		g_hash_table_foreach_steal(one_set, steal_log_sets, sets);
+		g_hash_table_destroy(one_set);
+		g_object_unref(log);
+	}
+
+	one_set = log_get_log_sets_common(cancellable, error);
+
+	if (one_set == NULL) {
+		g_hash_table_destroy(sets);
+		return NULL;
+	}
+
+	g_hash_table_foreach_steal(one_set, steal_log_sets, sets);
+	g_hash_table_destroy(one_set);
+
+	/* Return the GHashTable of unique PurpleLogSets. */
+	return sets;
+}
+
+void
+purple_logs_get_log_sets_async(gint io_priority, GCancellable *cancellable,
+	GAsyncReadyCallback cb, gpointer userdata)
+{
+	_purple_log_sets_callback_data *callback_data;
+	GArray *array;
+	guint i;
+
+	callback_data = g_new0(_purple_log_sets_callback_data, 1);
+	callback_data->cb = cb;
+	callback_data->userdata = userdata;
+	callback_data->sets = g_hash_table_new_full(_purple_log_set_hash, _purple_log_set_equal,
+		(GDestroyNotify) purple_log_set_free, NULL);
+
+	/* +1 is need special for log_get_log_sets_common_async call */
+	array = purple_log_logger_get_all();
+	callback_data->counter = array->len + 1;
+
+	/* Get the log sets from all the loggers. */
+	for (i = 0; i < array->len; i++) {
+		PurpleLog *log;
+		GType log_type = g_array_index(array, GType, i);
+
+		log = g_object_new(log_type, NULL);
+
+		purple_log_get_log_sets_async(log, io_priority, cancellable,
+			log_hash_cb, callback_data);
+	}
+
+	log_get_log_sets_common_async(io_priority, cancellable, log_hash_cb, callback_data);
+}
+
+GHashTable *
+purple_logs_get_log_sets_finish(GAsyncResult *res, GError **error)
+{
 	GSimpleAsyncResult *simple;
 
-	g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(res), -1);
+	g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(res), NULL);
 
 	simple = G_SIMPLE_ASYNC_RESULT(res);
 
 	if (g_simple_async_result_propagate_error(simple, error))
-		return -1;
+		return NULL;
 
-	return g_simple_async_result_get_op_res_gssize(simple);
+	return g_hash_table_ref(g_simple_async_result_get_op_res_gpointer(simple));
 }
 
 gssize
@@ -1305,7 +1850,7 @@ purple_log_get_activity_score(PurpleLogC
 	gpointer ptrscore;
 	time_t now;
 	gboolean result;
-	gint score;
+	gssize score;
 
 	g_return_val_if_fail(name != NULL, -1);
 	g_return_val_if_fail(account != NULL, -1); // PURPLE_IS_ACCOUNT(account)
@@ -1359,7 +1904,7 @@ purple_log_get_activity_score(PurpleLogC
 			}
 		}
 
-		score = (gint) ceil(score_double);
+		score = (gssize) ceil(score_double);
 
 		G_LOCK(logsize_users_decayed);
 		g_hash_table_replace(logsize_users_decayed, lu, GINT_TO_POINTER(score));
@@ -1410,7 +1955,7 @@ purple_log_get_activity_score_async(Purp
 	g_object_unref(simple);
 }
 
-gint
+gssize
 purple_log_get_activity_score_finish(GAsyncResult *res, GError **error)
 {
 	GSimpleAsyncResult *simple;
@@ -1426,92 +1971,17 @@ gboolean
 }
 
 gboolean
-purple_log_is_removable(PurpleLog *log, GCancellable *cancellable, GError **error)
+purple_log_is_removable(PurpleLog *log)
 {
-	PurpleLogClass *class;
-
 	g_return_val_if_fail(PURPLE_IS_LOG(log), FALSE);
 
-	class = PURPLE_LOG_GET_CLASS(log);
-
-	if (class->remove_fn == NULL && class->remove_async == NULL) {
-		g_set_error_literal(error,
-			G_IO_ERROR,
-			G_IO_ERROR_NOT_SUPPORTED,
-			_("Operation not supported"));
-
+	if (PURPLE_LOG_GET_CLASS(log)->remove_fn == NULL)
 		return FALSE;
-	}
 
-	if (class->is_removable_fn != NULL)
-		return class->is_removable_fn(log, cancellable, error);
-
 	return TRUE;
 }
 
-static void
-is_removable_thread(GSimpleAsyncResult *simple, GObject *object, GCancellable *cancellable)
-{
-	PurpleLog *log = PURPLE_LOG(object);
-	GError *error = NULL;
-	gboolean result;
-
-	result = purple_log_is_removable(log, cancellable, &error);
-
-	if (!result)
-		g_simple_async_result_set_from_error(simple, error);
-	else
-		g_simple_async_result_set_op_res_gboolean(simple, result);
-
-	g_clear_error(&error);
-}
-
-static void
-purple_log_real_is_removable_async(PurpleLog *log, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	GSimpleAsyncResult *simple;
-
-	g_return_if_fail(PURPLE_IS_LOG(log));
-
-	simple = g_simple_async_result_new(G_OBJECT(log), cb, userdata,
-		purple_log_real_is_removable_async);
-
-	g_simple_async_result_run_in_thread(simple, is_removable_thread, io_priority, cancellable);
-	g_object_unref(simple);
-}
-
-void
-purple_log_is_removable_async(PurpleLog *log, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	g_return_if_fail(PURPLE_IS_LOG(log));
-
-	PURPLE_LOG_GET_CLASS(log)->is_removable_async(log, io_priority,
-		cancellable, cb, userdata);
-}
-
-static gboolean
-purple_log_real_is_removable_finish(PurpleLog *log, GAsyncResult *res, GError **error)
-{
-	return g_simple_async_result_get_op_res_gboolean(G_SIMPLE_ASYNC_RESULT(res));
-}
-
 gboolean
-purple_log_is_removable_finish(PurpleLog *log, GAsyncResult *res, GError **error)
-{
-	g_return_val_if_fail(PURPLE_IS_LOG(log), FALSE);
-	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), FALSE);
-
-	if (G_IS_SIMPLE_ASYNC_RESULT(res)) {
-		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
-
-		if (g_simple_async_result_propagate_error(simple, error))
-			return FALSE;
-	}
-
-	return PURPLE_LOG_GET_CLASS(log)->is_removable_finish(log, res, error);
-}
-
-gboolean
 purple_log_remove(PurpleLog *log, GCancellable *cancellable, GError **error)
 {
 	PurpleLogClass *class;
@@ -1779,184 +2249,6 @@ purple_log_compare(gconstpointer y, gcon
 	return purple_log_get_time(b) - purple_log_get_time(a);
 }
 
-GList *
-purple_log_get_logs(PurpleLog *log, PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error)
-{
-	PurpleLogClass *class;
-
-	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
-	g_return_val_if_fail(name != NULL, NULL);
-	g_return_val_if_fail(account != NULL, NULL); // PURPLE_IS_ACCOUNT(account)
-
-	class = PURPLE_LOG_GET_CLASS(log);
-
-	if (class->list_fn == NULL) {
-		g_set_error_literal(error,
-			G_IO_ERROR,
-			G_IO_ERROR_NOT_SUPPORTED,
-			_("Operation not supported"));
-
-		return NULL;
-	}
-
-	return class->list_fn(log, chat_type, name, account, cancellable, error);
-}
-
-static void
-get_logs_thread(GSimpleAsyncResult *simple, GObject *object, GCancellable *cancellable)
-{
-	_thread_callback_data *callback_data =
-		g_simple_async_result_get_op_res_gpointer(simple);
-	PurpleAccount *account = callback_data->account;
-	PurpleLog *log = PURPLE_LOG(object);
-	PurpleLogChatType chat_type = callback_data->chat_type;
-	GError *error = NULL;
-	GList *logs;
-	gchar *name = callback_data->name;
-
-	logs = purple_log_get_logs(log, chat_type, name, account, cancellable, &error);
-
-	if (logs == NULL && error != NULL)
-		g_simple_async_result_set_from_error(simple, error);
-	else
-		g_simple_async_result_set_op_res_gpointer(simple, logs, NULL);
-
-	g_clear_error(&error);
-}
-
-static void
-purple_log_real_get_logs_async(PurpleLog *log, PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	_thread_callback_data *callback_data;
-	GSimpleAsyncResult *simple;
-
-	callback_data = g_new0(_thread_callback_data, 1);
-	callback_data->chat_type = chat_type;
-	callback_data->name = g_strdup(name);
-	callback_data->account = account; // g_object_ref
-
-	simple = g_simple_async_result_new(G_OBJECT(log), cb, userdata,
-		purple_log_real_get_logs_async);
-
-	g_simple_async_result_set_op_res_gpointer(simple, callback_data, thread_callback_data_free);
-	g_simple_async_result_run_in_thread(simple, get_logs_thread, io_priority, cancellable);
-	g_object_unref(simple);
-}
-
-void
-purple_log_get_logs_async(PurpleLog *log, PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	g_return_if_fail(PURPLE_IS_LOG(log));
-	g_return_if_fail(name != NULL);
-	g_return_if_fail(account != NULL); // PURPLE_IS_ACCOUNT(account)
-
-	PURPLE_LOG_GET_CLASS(log)->list_async(log, chat_type, name, account, io_priority, cancellable, cb, userdata);
-}
-
-static GList *
-purple_log_real_get_logs_finish(PurpleLog *log, GAsyncResult *res, GError **error)
-{
-	return g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res));
-}
-
-GList *
-purple_log_get_logs_finish(PurpleLog *log, GAsyncResult *res, GError **error)
-{
-	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
-	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), NULL);
-
-	if (G_IS_SIMPLE_ASYNC_RESULT(res)) {
-		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
-
-		if (g_simple_async_result_propagate_error(simple, error))
-			return NULL;
-	}
-
-	return PURPLE_LOG_GET_CLASS(log)->list_finish(log, res, error);
-}
-
-GList *
-purple_logs_get_logs(PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error)
-{
-	GArray *array;
-	GList *logs = NULL;
-	guint i;
-
-	g_return_val_if_fail(name != NULL, NULL);
-	g_return_val_if_fail(account != NULL, NULL); // PURPLE_IS_ACCOUNT(account)
-
-	array = purple_log_logger_get_all();
-
-	for (i = 0; i < array->len; i++) {
-		PurpleLog *log;
-		GError *err = NULL;
-		GList *list;
-		GType log_type = g_array_index(array, GType, i);
-
-		log = g_object_new(log_type, NULL);
-		list = purple_log_get_logs(log, chat_type, name, account, cancellable, &err);
-
-		if (list == NULL && err != NULL) {
-			g_propagate_error(error, err);
-			g_list_foreach(logs, (GFunc) g_object_unref, NULL);
-			g_list_free(logs);
-
-			g_clear_error(&err);
-			g_object_unref(log);
-
-			return NULL;
-		}
-
-		logs = g_list_concat(list, logs);
-		g_object_unref(log);
-	}
-
-	return g_list_sort(logs, purple_log_compare);
-}
-
-void
-purple_logs_get_logs_async(PurpleLogChatType chat_type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	_get_logs_callback_data *callback_data;
-	GArray *array;
-	guint i;
-
-	g_return_if_fail(name != NULL);
-	g_return_if_fail(account != NULL); // PURPLE_IS_ACCOUNT(account)
-
-	array = purple_log_logger_get_all();
-
-	callback_data = g_new0(_get_logs_callback_data, 1);
-	callback_data->cb = cb;
-	callback_data->userdata = userdata;
-	callback_data->counter = array->len;
-	callback_data->logs = NULL;
-
-	for (i = 0; i < array->len; i++) {
-		PurpleLog *log;
-		GType log_type = g_array_index(array, GType, i);
-
-		log = g_object_new(log_type, NULL);
-		purple_log_get_logs_async(log, chat_type, name, account, io_priority, cancellable, log_list_cb, callback_data);
-		g_object_unref(log);
-	}
-}
-
-GList *
-purple_logs_get_logs_finish(GAsyncResult *res, GError **error)
-{
-	GSimpleAsyncResult *simple;
-
-	g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(res), NULL);
-
-	simple = G_SIMPLE_ASYNC_RESULT(res);
-
-	if (g_simple_async_result_propagate_error(simple, error))
-		return NULL;
-
-	return g_simple_async_result_get_op_res_gpointer(simple);
-}
-
 gint
 purple_log_set_compare(gconstpointer y, gconstpointer z)
 {
@@ -2016,207 +2308,7 @@ _purple_log_add_log_set_to_hash(GHashTab
 		purple_log_set_free(set);
 }
 
-static gboolean
-steal_log_sets(gpointer key, gpointer value, gpointer sets)
-{
-	_purple_log_add_log_set_to_hash(sets, key);
-	return TRUE;
-}
-
-GHashTable *
-purple_log_get_log_sets(PurpleLog *log, GCancellable *cancellable, GError **error)
-{
-	PurpleLogClass *class;
-
-	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
-
-	class = PURPLE_LOG_GET_CLASS(log);
-
-	if (class->get_log_sets_fn == NULL) {
-		g_set_error_literal(error,
-			G_IO_ERROR,
-			G_IO_ERROR_NOT_SUPPORTED,
-			_("Operation not supported"));
-
-		return NULL;
-	}
-
-	return class->get_log_sets_fn(log, cancellable, error);
-}
-
-GHashTable *
-purple_logs_get_log_sets(GCancellable *cancellable, GError **error)
-{
-	GArray *array;
-	GHashTable *sets, *one_set;
-	GError *err = NULL;
-	guint i;
-
-	sets = g_hash_table_new_full(_purple_log_set_hash, _purple_log_set_equal,
-		(GDestroyNotify) purple_log_set_free, NULL);
-
-	array = purple_log_logger_get_all();
-
-	for (i = 0; i < array->len; i++) {
-		PurpleLog *log;
-		GType log_type = g_array_index(array, GType, i);
-
-		log = g_object_new(log_type, NULL);
-		one_set = purple_log_get_log_sets(log, cancellable, &err);
-
-		if (one_set == NULL) {
-			g_object_unref(log);
-
-			if (err->code == G_IO_ERROR_NOT_SUPPORTED) {
-				g_clear_error(&err);
-				continue;
-			} else {
-				g_propagate_error(error, err);
-				g_hash_table_destroy(sets);
-				return NULL;
-			}
-		}
-
-		g_hash_table_foreach_steal(one_set, steal_log_sets, sets);
-		g_hash_table_destroy(one_set);
-		g_object_unref(log);
-	}
-
-	one_set = log_get_log_sets_common(cancellable, error);
-
-	if (one_set == NULL) {
-		g_hash_table_destroy(sets);
-		return NULL;
-	}
-
-	g_hash_table_foreach_steal(one_set, steal_log_sets, sets);
-	g_hash_table_destroy(one_set);
-
-	/* Return the GHashTable of unique PurpleLogSets. */
-	return sets;
-}
-
-static void
-get_log_sets_thread(GSimpleAsyncResult *simple, GObject *object, GCancellable *cancellable)
-{
-	PurpleLog *log = PURPLE_LOG(object);
-	PurpleLogClass *class = PURPLE_LOG_GET_CLASS(log);
-	GError *error = NULL;
-	GHashTable *sets;
-
-	if (class->get_log_sets_fn == NULL) {
-		g_simple_async_result_set_error(simple, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-			_("Operation not supported"));
-
-		return;
-	}
-
-	sets = class->get_log_sets_fn(log, cancellable, &error);
-
-	if (sets == NULL)
-		g_simple_async_result_set_from_error(simple, error);
-	else
-		g_simple_async_result_set_op_res_gpointer(simple, sets, (GDestroyNotify) g_hash_table_unref);
-
-	g_clear_error(&error);
-}
-
-static void
-purple_log_real_get_log_sets_async(PurpleLog *log, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	GSimpleAsyncResult *simple;
-
-	simple = g_simple_async_result_new(G_OBJECT(log), cb, userdata,
-		purple_log_real_get_log_sets_async);
-
-	g_simple_async_result_run_in_thread(simple, get_log_sets_thread, io_priority, cancellable);
-	g_object_unref(simple);
-}
-
 void
-purple_log_get_log_sets_async(PurpleLog *log, gint io_priority,
-	GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	g_return_if_fail(PURPLE_IS_LOG(log));
-
-	PURPLE_LOG_GET_CLASS(log)->get_log_sets_async(log,
-		io_priority, cancellable, cb, userdata);
-}
-
-void
-purple_logs_get_log_sets_async(gint io_priority, GCancellable *cancellable,
-	GAsyncReadyCallback cb, gpointer userdata)
-{
-	_purple_log_sets_callback_data *callback_data;
-	GArray *array;
-	guint i;
-
-	callback_data = g_new0(_purple_log_sets_callback_data, 1);
-	callback_data->cb = cb;
-	callback_data->userdata = userdata;
-	callback_data->sets = g_hash_table_new_full(_purple_log_set_hash, _purple_log_set_equal,
-		(GDestroyNotify) purple_log_set_free, NULL);
-
-	/* +1 is need special for log_get_log_sets_common_async call */
-	array = purple_log_logger_get_all();
-	callback_data->counter = array->len + 1;
-
-	/* Get the log sets from all the loggers. */
-	for (i = 0; i < array->len; i++) {
-		PurpleLog *log;
-		GType log_type = g_array_index(array, GType, i);
-
-		log = g_object_new(log_type, NULL);
-
-		purple_log_get_log_sets_async(log, io_priority, cancellable,
-			log_hash_cb, callback_data);
-	}
-
-	log_get_log_sets_common_async(io_priority, cancellable, log_hash_cb, callback_data);
-}
-
-static GHashTable * 
-purple_log_real_get_log_sets_finish(PurpleLog *log, GAsyncResult *res, GError **error)
-{
-	return g_hash_table_ref(g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res)));
-}
-
-GHashTable *
-purple_logs_get_log_sets_finish(GAsyncResult *res, GError **error)
-{
-	GSimpleAsyncResult *simple;
-
-	g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(res), NULL);
-
-	simple = G_SIMPLE_ASYNC_RESULT(res);
-
-	if (g_simple_async_result_propagate_error(simple, error))
-		return NULL;
-
-	return g_hash_table_ref(g_simple_async_result_get_op_res_gpointer(simple));
-}
-
-GHashTable *
-purple_log_get_log_sets_finish(PurpleLog *log, GAsyncResult *res, GError **error)
-{
-	g_return_val_if_fail(log == NULL || PURPLE_IS_LOG(log), NULL);
-	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), NULL);
-
-	if (G_IS_SIMPLE_ASYNC_RESULT(res)) {
-		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
-
-		if (g_simple_async_result_propagate_error(simple, error))
-			return NULL;
-	}
-
-	if (log == NULL)
-		/* Result of purple_log_common */
-		return g_hash_table_ref(g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res)));
-	else
-		return PURPLE_LOG_GET_CLASS(log)->get_log_sets_finish(log, res, error);
-}
-
-void
 purple_log_set_free(PurpleLogSet *set)
 {
 	g_return_if_fail(set != NULL);
@@ -2229,177 +2321,7 @@ purple_log_set_free(PurpleLogSet *set)
 	g_slice_free(PurpleLogSet, set);
 }
 
-GList *
-purple_log_get_system_logs(PurpleLog *log, PurpleAccount *account, GCancellable *cancellable, GError **error)
-{
-	PurpleLogClass *class;
-
-	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
-	g_return_val_if_fail(account != NULL, NULL); // PURPLE_IS_ACCOUNT(account)
-
-	class = PURPLE_LOG_GET_CLASS(log);
-
-	if (class->list_syslog_fn == NULL) {
-		g_set_error_literal(error,
-			G_IO_ERROR,
-			G_IO_ERROR_NOT_SUPPORTED,
-			_("Operation not supported"));
-
-		return NULL;
-	}
-
-	return class->list_syslog_fn(log, account, cancellable, error);
-}
-
-GList *
-purple_logs_get_system_logs(PurpleAccount *account, GCancellable *cancellable, GError **error)
-{
-	GArray *array;
-	GList *logs = NULL;
-	guint i;
-
-	g_return_val_if_fail(account != NULL, NULL); // PURPLE_IS_ACCOUNT(account)
-
-	array = purple_log_logger_get_all();
-
-	for (i = 0; i < array->len; i++) {
-		PurpleLog *log;
-		GList *list;
-		GType log_type = g_array_index(array, GType, i);
-
-		log = g_object_new(log_type, NULL);
-		list = purple_log_get_system_logs(log, account, cancellable, error);
-
-		if (list == NULL) {
-			g_object_unref(log);
-			g_list_foreach(logs, (GFunc) g_object_unref, NULL);
-			g_list_free(logs);
-
-			return NULL;
-		}
-
-		logs = g_list_concat(list, logs);
-		g_object_unref(log);
-	}
-
-	return g_list_sort(logs, purple_log_compare);
-}
-
-static void
-list_syslog_thread(GSimpleAsyncResult *simple, GObject *object, GCancellable *cancellable)
-{
-	_thread_callback_data *callback_data =
-		g_simple_async_result_get_op_res_gpointer(simple);
-	PurpleAccount *account = callback_data->account;
-	GError *error = NULL;
-	GList *list;
-
-	list = purple_log_get_system_logs(PURPLE_LOG(object), account, cancellable, &error);
-
-	if (list == NULL && error != NULL)
-		g_simple_async_result_set_from_error(simple, error);
-	else
-		g_simple_async_result_set_op_res_gpointer(simple, list, NULL);
-
-	g_clear_error(&error);
-}
-
-static void
-purple_log_real_list_syslog_async(PurpleLog *log, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	_thread_callback_data *callback_data;
-	GSimpleAsyncResult *simple;
-
-	callback_data = g_new0(_thread_callback_data, 1);
-	callback_data->account = account; // g_object_ref
-
-	simple = g_simple_async_result_new(G_OBJECT(log), cb, userdata,
-		purple_log_real_list_syslog_async);
-
-	g_simple_async_result_set_op_res_gpointer(simple, callback_data, thread_callback_data_free);
-	g_simple_async_result_run_in_thread(simple, list_syslog_thread, io_priority, cancellable);
-	g_object_unref(simple);
-}
-
 void
-purple_log_get_system_logs_async(PurpleLog *log, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	g_return_if_fail(PURPLE_IS_LOG(log));
-	g_return_if_fail(account != NULL); // PURPLE_IS_ACCOUNT(account)
-
-	PURPLE_LOG_GET_CLASS(log)->list_syslog_async(log, account, io_priority, cancellable, cb, userdata);
-}
-
-void
-purple_logs_get_system_logs_async(PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	_get_logs_callback_data *callback_data;
-	GArray *array;
-	guint i;
-
-	g_return_if_fail(account != NULL); // PURPLE_IS_ACCOUNT(account)
-
-	array = purple_log_logger_get_all();
-
-	callback_data = g_new0(_get_logs_callback_data, 1);
-	callback_data->userdata = userdata;
-	callback_data->cb = cb;
-	callback_data->counter = array->len;
-	callback_data->logs = NULL;
-
-	for (i = 0; i < array->len; i++) {
-		PurpleLog *log;
-		GType log_type = g_array_index(array, GType, i);
-
-		log = g_object_new(log_type, NULL);
-		purple_log_get_system_logs_async(log, account, io_priority, cancellable, log_system_list_cb, callback_data);
-
-		g_object_unref(log);
-	}
-}
-
-static GList *
-purple_log_real_list_syslog_finish(PurpleLog *log, GAsyncResult *res, GError **error)
-{
-	return g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res));
-}
-
-GList *
-purple_log_get_system_logs_finish(PurpleLog *log, GAsyncResult *res, GError **error)
-{
-	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
-	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), NULL);
-
-	if (G_IS_SIMPLE_ASYNC_RESULT(res)) {
-		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
-
-		if (g_simple_async_result_propagate_error(simple, error))
-			return NULL;
-	}
-
-	return PURPLE_LOG_GET_CLASS(log)->list_syslog_finish(log, res, error);
-}
-
-GList *
-purple_logs_get_system_logs_finish(GAsyncResult *res, GError **error)
-{
-	GSimpleAsyncResult *simple;
-
-	g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(res), NULL);
-
-	simple = G_SIMPLE_ASYNC_RESULT(res);
-
-	if (g_simple_async_result_propagate_error(simple, error))
-		return NULL;
-
-	return g_simple_async_result_get_op_res_gpointer(simple);
-}
-
-/****************************************************************************
- * LOG SUBSYSTEM ************************************************************
- ****************************************************************************/
-
-void
 purple_log_system_init(void)
 {
 	void *handle = purple_log_system_get_handle();
============================================================
--- pidgin/gtkutils.c	ff602bdc85f89effd93943f96bddfb0967960141
+++ pidgin/gtkutils.c	9c3293d754b731ef71c34c01a0cbb7edb876787d
@@ -2062,13 +2062,15 @@ add_completion_list_cb(GObject *object, 
 	GHashTable *sets;
 	GError *error = NULL;
 
-	sets = purple_log_get_log_sets_finish(PURPLE_LOG(object), res, &error);
+	sets = purple_logs_get_log_sets_finish(res, &error);
 
 	if (sets == NULL) {
 		if (error->code != G_IO_ERROR_CANCELLED)
 			purple_debug_error("gtkutils", "Unable to get hash table: %s\n", error->message);
-	} else
+	} else {
 		g_hash_table_foreach(sets, (GHFunc) get_log_set_name, userdata);
+		g_hash_table_unref(sets);
+	}
 
 	g_clear_error(&error);
 }
============================================================
--- libpurple/log.h	3931c44fa1c5609b9c81fabfb6bc9cb0c92807ba
+++ libpurple/log.h	874709ef8d9a5c0380a6ddd2173e4120af2a41f7
@@ -258,19 +258,6 @@ struct _PurpleLogClass {
 	/** Finishes an asynchronously remove operation */
 	gboolean (* remove_finish) (PurpleLog *log, GAsyncResult *res, GError **error);
 
-	/** Tests whether a log is removable */
-	gboolean (* is_removable_fn) (PurpleLog *log, GCancellable *cancellable,
-		GError **error);
-
-	/** Asynchronously tests whether a log is removable */
-	void (* is_removable_async) (PurpleLog *log, gint io_priority,
-		GCancellable *cancellable, GAsyncReadyCallback callback,
-		gpointer user_data);
-
-	/** Finishes an asynchronous test of whether a log is removable */
-	gboolean (* is_removable_finish) (PurpleLog *log, GAsyncResult *res,
-		GError **error);
-
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
 	void (*_purple_reserved3)(void);
@@ -446,23 +433,18 @@ gchar *purple_log_read_finish(PurpleLog 
 gchar *purple_log_read_finish(PurpleLog *log, GAsyncResult *res, PurpleLogReadFlags *flags, GError **error);
 
 /**
- * Returns a list of all available logs
+ * Returns the size of a log
  *
- * @param type         The type of the log
- * @param name         The name of the log
- * @param account      The account
+ * @param log          The log
  *
- * @return             A sorted list of #PurpleLog<!-- -->s
+ * @return             The size of the log, in bytes
  */
-GList *purple_log_get_logs(PurpleLog *log, PurpleLogChatType type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error);
-GList *purple_logs_get_logs(PurpleLogChatType type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error);
+gssize purple_log_get_size(PurpleLog *log, GCancellable *cancellable, GError **error);
 
 /**
- * Asynchronously gets a list of all available logs
+ * Asychronously gets the size of a log
  *
- * @param type         The type of the log
- * @param name         The name of the log
- * @param account      The account
+ * @param log          The log
  * @param io_priority  The io priority of the request
  * @param cancellable  (allow-none): #GCancellable object
  * @param cb           (allow-none): A #GAsyncReadyCallback to call when the request is satisfied
@@ -470,50 +452,38 @@ GList *purple_logs_get_logs(PurpleLogCha
  *
  * @since 2.8.0
  */
-void purple_log_get_logs_async(PurpleLog *log, PurpleLogChatType type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
-void purple_logs_get_logs_async(PurpleLogChatType type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
+void purple_log_get_size_async(PurpleLog *log, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
 
 /**
- * Finishes asynchronously getting a list of all available logs
+ * Finishes asynchronously getting the size of a log
  *
- * Note: Make sure to examine that error is not NULL as it is completely possible
- * for the list to be empty and the function to return NULL without an error
- *
+ * @param log          The #PurpleLog to size
  * @param res          A #GAsyncResult
  * @param error        (out) (allow-none): a #GError location to store the error
  *
- * @return             pointer to log list or %NULL on error
+ * @return             size of file or -1 on error
  *
  * @since 2.8.0
  */
-GList *purple_log_get_logs_finish(PurpleLog *log, GAsyncResult *res, GError **error);
-GList *purple_logs_get_logs_finish(GAsyncResult *res, GError **error);
+gssize purple_log_get_size_finish(PurpleLog *log, GAsyncResult *res, GError **error);
 
 /**
- * Returns a GHashTable of #PurpleLogSet<!-- -->s.
+ * Returns a list of all available logs
  *
- * A "log set" here means the information necessary to gather the
- * #PurpleLog<!-- -->s for a given buddy/chat. This information would be passed
- * to purple_log_get_log to get a list of #PurpleLog<!-- -->s.
+ * @param type         The type of the log
+ * @param name         The name of the log
+ * @param account      The account
  *
- * The primary use of this function is to get a list of everyone the
- * user has ever talked to (assuming he or she uses logging).
- *
- * The GHashTable that's returned will free all log sets in it when
- * destroyed. If a #PurpleLogSet is removed from the GHashTable, it
- * must be freed with purple_log_set_free().
- *
- * @return             A GHashTable of all available unique #PurpleLogSet<!-- -->s
+ * @return             A sorted list of #PurpleLog<!-- -->s
  */
-GHashTable *purple_log_get_log_sets(PurpleLog *, GCancellable *cancellable, GError **error);
-GHashTable *purple_logs_get_log_sets(GCancellable *cancellable, GError **error);
+GList *purple_log_get_logs(PurpleLog *log, PurpleLogChatType type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error);
 
 /**
- * Asychronously gets a #GHashTable of #PurpleLogSet<!-- -->s.
+ * Asynchronously gets a list of all available logs
  *
- * For more details, see purple_log_get_log_sets() which is
- * the synchronous version of this call.
- *
+ * @param type         The type of the log
+ * @param name         The name of the log
+ * @param account      The account
  * @param io_priority  The io priority of the request
  * @param cancellable  (allow-none): #GCancellable object
  * @param cb           (allow-none): A #GAsyncReadyCallback to call when the request is satisfied
@@ -521,22 +491,31 @@ GHashTable *purple_logs_get_log_sets(GCa
  *
  * @since 2.8.0
  */
-void purple_logs_get_log_sets_async(gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
-void purple_log_get_log_sets_async(PurpleLog *log, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
+void purple_log_get_logs_async(PurpleLog *log, PurpleLogChatType type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
 
 /**
- * Finishes asynchronously getting a hash table of log sets
+ * Finishes asynchronously getting a list of all available logs
  *
+ * Note: Make sure to examine that error is not NULL as it is completely possible
+ * for the list to be empty and the function to return NULL without an error
+ *
  * @param res          A #GAsyncResult
  * @param error        (out) (allow-none): a #GError location to store the error
  *
- * @return             pointer to hash table of log sets or %NULL on error
+ * @return             pointer to log list or %NULL on error
  *
  * @since 2.8.0
  */
-GHashTable *purple_logs_get_log_sets_finish(GAsyncResult *res, GError **error);
-GHashTable *purple_log_get_log_sets_finish(PurpleLog *log, GAsyncResult *res, GError **error);
+GList *purple_log_get_logs_finish(PurpleLog *log, GAsyncResult *res, GError **error);
 
+
+//
+GList *purple_logs_get_logs(PurpleLogChatType type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error);
+//
+void purple_logs_get_logs_async(PurpleLogChatType type, const gchar *name, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
+//
+GList *purple_logs_get_logs_finish(GAsyncResult *res, GError **error);
+
 /**
  * Returns a list of all available system logs
  *
@@ -545,7 +524,6 @@ GList *purple_log_get_system_logs(Purple
  * @return             A sorted list of #PurpleLog<!-- -->s
  */
 GList *purple_log_get_system_logs(PurpleLog *log, PurpleAccount *account, GCancellable *cancellable, GError **error);
-GList *purple_logs_get_system_logs(PurpleAccount *account, GCancellable *cancellable, GError **error);
 
 /**
  * Asychronously gets a list of all available system logs
@@ -559,7 +537,6 @@ void purple_log_get_system_logs_async(Pu
  * @since 2.8.0
  */
 void purple_log_get_system_logs_async(PurpleLog *log, PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
-void purple_logs_get_system_logs_async(PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
 
 /**
  * Finishes asychronously getting a list of all available system logs
@@ -575,21 +552,31 @@ GList *purple_log_get_system_logs_finish
  * @since 2.8.0
  */
 GList *purple_log_get_system_logs_finish(PurpleLog *log, GAsyncResult *res, GError **error);
+
+//
+GList *purple_logs_get_system_logs(PurpleAccount *account, GCancellable *cancellable, GError **error);
+//
+void purple_logs_get_system_logs_async(PurpleAccount *account, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
+//
 GList *purple_logs_get_system_logs_finish(GAsyncResult *res, GError **error);
 
 /**
- * Returns the size of a log
+ * Returns the size, in bytes, of all available logs in this conversation
  *
- * @param log          The log
+ * @param type         The type of the log
+ * @param name         The name of the log
+ * @param account      The account
  *
- * @return             The size of the log, in bytes
+ * @return             The size in bytes
  */
-gint purple_log_get_size(PurpleLog *log, GCancellable *cancellable, GError **error);
+gssize purple_log_get_total_size(PurpleLog *log, PurpleLogChatType type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error);
 
 /**
- * Asychronously gets the size of a log
+ * Asychronously gets the size, in bytes, of all available logs in this conversation
  *
- * @param log          The log
+ * @param type         The type of the log
+ * @param name         The name of the log
+ * @param account      The account
  * @param io_priority  The io priority of the request
  * @param cancellable  (allow-none): #GCancellable object
  * @param cb           (allow-none): A #GAsyncReadyCallback to call when the request is satisfied
@@ -597,12 +584,10 @@ gint purple_log_get_size(PurpleLog *log,
  *
  * @since 2.8.0
  */
-void purple_log_get_size_async(PurpleLog *log, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
-
+void purple_log_get_total_size_async(PurpleLog *log, PurpleLogChatType type, const gchar *name, PurpleAccount *account,  gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
 /**
- * Finishes asynchronously getting the size of a log
+ * Finishes asynchronously getting the total size of a conversation
  *
- * @param log          The #PurpleLog to size
  * @param res          A #GAsyncResult
  * @param error        (out) (allow-none): a #GError location to store the error
  *
@@ -610,26 +595,40 @@ void purple_log_get_size_async(PurpleLog
  *
  * @since 2.8.0
  */
-gssize purple_log_get_size_finish(PurpleLog *log, GAsyncResult *res, GError **error);
+gssize purple_log_get_total_size_finish(PurpleLog *log, GAsyncResult *res, GError **error);
 
+
+//
+gssize purple_logs_get_total_size(PurpleLogChatType type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error);
+//
+void purple_logs_get_total_size_async(PurpleLogChatType type, const gchar *name, PurpleAccount *account,  gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
+//
+gssize purple_logs_get_total_size_finish(GAsyncResult *res, GError **error);
+
 /**
- * Returns the size, in bytes, of all available logs in this conversation
+ * Returns a GHashTable of #PurpleLogSet<!-- -->s.
  *
- * @param type         The type of the log
- * @param name         The name of the log
- * @param account      The account
+ * A "log set" here means the information necessary to gather the
+ * #PurpleLog<!-- -->s for a given buddy/chat. This information would be passed
+ * to purple_log_get_log to get a list of #PurpleLog<!-- -->s.
  *
- * @return             The size in bytes
+ * The primary use of this function is to get a list of everyone the
+ * user has ever talked to (assuming he or she uses logging).
+ *
+ * The GHashTable that's returned will free all log sets in it when
+ * destroyed. If a #PurpleLogSet is removed from the GHashTable, it
+ * must be freed with purple_log_set_free().
+ *
+ * @return             A GHashTable of all available unique #PurpleLogSet<!-- -->s
  */
-gssize purple_log_get_total_size(PurpleLog *log, PurpleLogChatType type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error);
-gssize purple_logs_get_total_size(PurpleLogChatType type, const gchar *name, PurpleAccount *account, GCancellable *cancellable, GError **error);
+GHashTable *purple_log_get_log_sets(PurpleLog *, GCancellable *cancellable, GError **error);
 
 /**
- * Asychronously gets the size, in bytes, of all available logs in this conversation
+ * Asychronously gets a #GHashTable of #PurpleLogSet<!-- -->s.
  *
- * @param type         The type of the log
- * @param name         The name of the log
- * @param account      The account
+ * For more details, see purple_log_get_log_sets() which is
+ * the synchronous version of this call.
+ *
  * @param io_priority  The io priority of the request
  * @param cancellable  (allow-none): #GCancellable object
  * @param cb           (allow-none): A #GAsyncReadyCallback to call when the request is satisfied
@@ -637,21 +636,26 @@ gssize purple_logs_get_total_size(Purple
  *
  * @since 2.8.0
  */
-void purple_logs_get_total_size_async(PurpleLogChatType type, const gchar *name, PurpleAccount *account,  gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
+void purple_log_get_log_sets_async(PurpleLog *log, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
 
 /**
- * Finishes asynchronously getting the total size of a conversation
+ * Finishes asynchronously getting a hash table of log sets
  *
  * @param res          A #GAsyncResult
  * @param error        (out) (allow-none): a #GError location to store the error
  *
- * @return             size of file or -1 on error
+ * @return             pointer to hash table of log sets or %NULL on error
  *
  * @since 2.8.0
  */
-gssize purple_log_get_total_size_finish(PurpleLog *log, GAsyncResult *res, GError **error);
+GHashTable *purple_logs_get_log_sets_finish(GAsyncResult *res, GError **error);
 
-gssize purple_logs_get_total_size_finish(GAsyncResult *res, GError **error);
+//
+GHashTable *purple_logs_get_log_sets(GCancellable *cancellable, GError **error);
+//
+void purple_logs_get_log_sets_async(gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
+//
+GHashTable *purple_log_get_log_sets_finish(PurpleLog *log, GAsyncResult *res, GError **error);
 
 /**
  * Returns the activity score of a log, based on total size in bytes,
@@ -692,7 +696,7 @@ void purple_log_get_activity_score_async
  *
  * @since 2.8.0
  */
-gint purple_log_get_activity_score_finish(GAsyncResult *res, GError **error);
+gssize purple_log_get_activity_score_finish(GAsyncResult *res, GError **error);
 
 /**
  * Tests whether a log is removable
@@ -705,12 +709,8 @@ gint purple_log_get_activity_score_finis
  *
  * @return             %TRUE if the log is removable, %FALSE otherwise
  */
-gboolean purple_log_is_removable(PurpleLog *log, GCancellable *cancellable, GError **error);
+gboolean purple_log_is_removable(PurpleLog *log);
 
-void purple_log_is_removable_async(PurpleLog *log, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
-
-gboolean purple_log_is_removable_finish(PurpleLog *log, GAsyncResult *res, GError **error);
-
 /**
  * Removes a log
  *
============================================================
--- pidgin/gtklog.c	805610db9515885d1af9aa535a671ceb2ad57bf2
+++ pidgin/gtklog.c	106c14ab8e3ca1756309a8b1451cb049b5cd422c
@@ -611,7 +611,7 @@ log_show_popup_menu(GdkEventButton *even
 	menu = gtk_menu_new();
 	menuitem = gtk_menu_item_new_with_label(_("Delete Log..."));
 
-	if (!purple_log_is_removable(data->log_data->log, NULL, NULL))
+	if (!purple_log_is_removable(data->log_data->log))
 		gtk_widget_set_sensitive(menuitem, FALSE);
 
 	g_signal_connect(menuitem, "activate", G_CALLBACK(log_delete_log_cb), data);
============================================================
--- finch/gntlog.c	972cbcc824bc3541f3f5e4fc7290df9697a85ef4
+++ finch/gntlog.c	eef3990672d63ac8f411c1c37e82711ae400e712
@@ -707,11 +707,12 @@ finch_log_sets_cb(GObject *object, GAsyn
 			}
 		}
 
-		g_list_foreach(list, (GFunc) purple_log_set_free, NULL);
 		g_list_free(list);
 		g_hash_table_unref(table);
-	} else
+	} else {
 		finch_log_data_free(finch_log_data);
+		g_hash_table_unref(sets);
+	}
 
 	g_clear_error(&error);
 }


More information about the Commits mailing list