Mercurial > pidgin
comparison src/log.c @ 11177:3924db2b1ca8
[gaim-migrate @ 13285]
Performance optimizing the log set and screenname autocompletion code.
committer: Tailor Script <tailor@pidgin.im>
| author | Richard Laager <rlaager@wiktel.com> |
|---|---|
| date | Mon, 01 Aug 2005 04:08:27 +0000 |
| parents | 59a1ff5a4bae |
| children | bb0d7b719af2 |
comparison
equal
deleted
inserted
replaced
| 11176:6932df31225f | 11177:3924db2b1ca8 |
|---|---|
| 41 char *name; | 41 char *name; |
| 42 GaimAccount *account; | 42 GaimAccount *account; |
| 43 }; | 43 }; |
| 44 static GHashTable *logsize_users = NULL; | 44 static GHashTable *logsize_users = NULL; |
| 45 | 45 |
| 46 static GList *log_get_log_sets_common(); | 46 static void log_get_log_sets_common(GHashTable *sets); |
| 47 | 47 |
| 48 /************************************************************************** | 48 /************************************************************************** |
| 49 * PUBLIC LOGGING FUNCTIONS *********************************************** | 49 * PUBLIC LOGGING FUNCTIONS *********************************************** |
| 50 **************************************************************************/ | 50 **************************************************************************/ |
| 51 | 51 |
| 240 GList*(*list)(GaimLogType type, const char*, GaimAccount*), | 240 GList*(*list)(GaimLogType type, const char*, GaimAccount*), |
| 241 char*(*read)(GaimLog*, GaimLogReadFlags*), | 241 char*(*read)(GaimLog*, GaimLogReadFlags*), |
| 242 int(*size)(GaimLog*), | 242 int(*size)(GaimLog*), |
| 243 int(*total_size)(GaimLogType type, const char *name, GaimAccount *account), | 243 int(*total_size)(GaimLogType type, const char *name, GaimAccount *account), |
| 244 GList*(*list_syslog)(GaimAccount *account), | 244 GList*(*list_syslog)(GaimAccount *account), |
| 245 GList*(*get_log_sets)(void)) | 245 void(*get_log_sets)(GaimLogSetCallback cb, GHashTable *sets)) |
| 246 { | 246 { |
| 247 GaimLogLogger *logger = g_new0(GaimLogLogger, 1); | 247 GaimLogLogger *logger = g_new0(GaimLogLogger, 1); |
| 248 | 248 |
| 249 logger->create = create; | 249 logger->create = create; |
| 250 logger->write = write; | 250 logger->write = write; |
| 331 gint gaim_log_set_compare(gconstpointer y, gconstpointer z) | 331 gint gaim_log_set_compare(gconstpointer y, gconstpointer z) |
| 332 { | 332 { |
| 333 const GaimLogSet *a = y; | 333 const GaimLogSet *a = y; |
| 334 const GaimLogSet *b = z; | 334 const GaimLogSet *b = z; |
| 335 gint ret = 0; | 335 gint ret = 0; |
| 336 char *tmp; | |
| 337 | 336 |
| 338 /* This logic seems weird at first... | 337 /* This logic seems weird at first... |
| 339 * If either account is NULL, we pretend the accounts are | 338 * If either account is NULL, we pretend the accounts are |
| 340 * equal. This allows us to detect duplicates that will | 339 * equal. This allows us to detect duplicates that will |
| 341 * exist if one logger knows the account and another | 340 * exist if one logger knows the account and another |
| 342 * doesn't. */ | 341 * doesn't. */ |
| 343 if (a->account != NULL && b->account != NULL) { | 342 if (a->account != NULL && b->account != NULL) { |
| 344 ret = gaim_utf8_strcasecmp(gaim_account_get_username(a->account), gaim_account_get_username(b->account)); | 343 ret = strcmp(gaim_account_get_username(a->account), gaim_account_get_username(b->account)); |
| 345 if (ret != 0) | 344 if (ret != 0) |
| 346 return ret; | 345 return ret; |
| 347 } | 346 } |
| 348 | 347 |
| 349 tmp = g_strdup(gaim_normalize(a->account, a->name)); | 348 ret = strcmp(a->normalized_name, b->normalized_name); |
| 350 ret = gaim_utf8_strcasecmp(tmp, gaim_normalize(b->account, b->name)); | |
| 351 g_free(tmp); | |
| 352 if (ret != 0) | 349 if (ret != 0) |
| 353 return ret; | 350 return ret; |
| 354 | 351 |
| 355 return (gint)b->type - (gint)a->type; | 352 return (gint)b->type - (gint)a->type; |
| 356 } | 353 } |
| 371 * make sense for those data types, but I wish the comparison | 368 * make sense for those data types, but I wish the comparison |
| 372 * functions were compatible. */ | 369 * functions were compatible. */ |
| 373 return !gaim_log_set_compare(a, b); | 370 return !gaim_log_set_compare(a, b); |
| 374 } | 371 } |
| 375 | 372 |
| 376 void log_set_build_list(gpointer key, gpointer value, gpointer user_data) | 373 void log_add_log_set_to_hash(GHashTable *sets, GaimLogSet *set) |
| 377 { | 374 { |
| 378 *((GList **)user_data) = g_list_append(*((GList **)user_data), key); | 375 GaimLogSet *existing_set = g_hash_table_lookup(sets, set); |
| 379 } | 376 |
| 380 | 377 if (existing_set == NULL) |
| 381 GList *gaim_log_get_log_sets() | 378 g_hash_table_insert(sets, set, set); |
| 379 else if (existing_set->account == NULL && set->account != NULL) | |
| 380 g_hash_table_replace(sets, set, set); | |
| 381 else | |
| 382 gaim_log_set_free(set); | |
| 383 } | |
| 384 | |
| 385 GHashTable *gaim_log_get_log_sets(void) | |
| 382 { | 386 { |
| 383 GSList *n; | 387 GSList *n; |
| 384 GList *sets = NULL; | 388 GHashTable *sets = g_hash_table_new_full(log_set_hash, log_set_equal, |
| 385 GList *set; | 389 (GDestroyNotify)gaim_log_set_free, NULL); |
| 386 GHashTable *sets_ht = g_hash_table_new(log_set_hash, log_set_equal); | |
| 387 | 390 |
| 388 /* Get the log sets from all the loggers. */ | 391 /* Get the log sets from all the loggers. */ |
| 389 for (n = loggers; n; n = n->next) { | 392 for (n = loggers; n; n = n->next) { |
| 390 GaimLogLogger *logger = n->data; | 393 GaimLogLogger *logger = n->data; |
| 391 | 394 |
| 392 if (!logger->get_log_sets) | 395 if (!logger->get_log_sets) |
| 393 continue; | 396 continue; |
| 394 | 397 |
| 395 sets = g_list_concat(sets, logger->get_log_sets()); | 398 logger->get_log_sets(log_add_log_set_to_hash, sets); |
| 396 } | 399 } |
| 397 | 400 |
| 398 /* Get the log sets for loggers that use the common logger functions. */ | 401 log_get_log_sets_common(sets); |
| 399 sets = g_list_concat(sets, log_get_log_sets_common()); | 402 |
| 400 | 403 /* Return the GHashTable of unique GaimLogSets. */ |
| 401 for (set = sets; set != NULL ; set = set->next) { | 404 return sets; |
| 402 GaimLogSet *existing_set = g_hash_table_lookup(sets_ht, set->data); | 405 } |
| 403 | 406 |
| 404 if (existing_set == NULL) { | 407 void gaim_log_set_free(GaimLogSet *set) |
| 405 g_hash_table_insert(sets_ht, set->data, set->data); | 408 { |
| 406 } else if (existing_set->account == NULL && ((GaimLogSet *)set->data)->account != NULL) { | 409 g_return_if_fail(set != NULL); |
| 407 /* The existing entry in the hash table has no account. | 410 |
| 408 * This one does. We'll delete the old one and keep this one. */ | 411 g_free(set->name); |
| 409 g_hash_table_replace(sets_ht, set->data, set->data); | 412 if (set->normalized_name != set->name) |
| 410 g_free(existing_set->name); | 413 g_free(set->normalized_name); |
| 411 g_free(existing_set); | 414 g_free(set); |
| 412 } else { | |
| 413 g_free(((GaimLogSet *)set->data)->name); | |
| 414 g_free(set->data); | |
| 415 } | |
| 416 } | |
| 417 g_list_free(sets); | |
| 418 | |
| 419 /* At this point, we've built a GHashTable of unique GaimLogSets. | |
| 420 * So, we build a list of those keys and destroy the GHashTable. */ | |
| 421 sets = NULL; | |
| 422 g_hash_table_foreach(sets_ht, log_set_build_list, &sets); | |
| 423 g_hash_table_destroy(sets_ht); | |
| 424 | |
| 425 return g_list_sort(sets, gaim_log_set_compare); | |
| 426 } | 415 } |
| 427 | 416 |
| 428 GList *gaim_log_get_system_logs(GaimAccount *account) | 417 GList *gaim_log_get_system_logs(GaimAccount *account) |
| 429 { | 418 { |
| 430 GList *logs = NULL; | 419 GList *logs = NULL; |
| 554 return st.st_size; | 543 return st.st_size; |
| 555 } | 544 } |
| 556 | 545 |
| 557 /* This will build log sets for all loggers that use the common logger | 546 /* This will build log sets for all loggers that use the common logger |
| 558 * functions because they use the same directory structure. */ | 547 * functions because they use the same directory structure. */ |
| 559 static GList *log_get_log_sets_common() | 548 static void log_get_log_sets_common(GHashTable *sets) |
| 560 { | 549 { |
| 561 gchar *log_path = g_build_filename(gaim_user_dir(), "logs", NULL); | 550 gchar *log_path = g_build_filename(gaim_user_dir(), "logs", NULL); |
| 562 GDir *log_dir = g_dir_open(log_path, 0, NULL); | 551 GDir *log_dir = g_dir_open(log_path, 0, NULL); |
| 563 const gchar *protocol; | 552 const gchar *protocol; |
| 564 GList *sets = NULL; | |
| 565 | 553 |
| 566 if (log_dir == NULL) { | 554 if (log_dir == NULL) { |
| 567 g_free(log_path); | 555 g_free(log_path); |
| 568 return NULL; | 556 return; |
| 569 } | 557 } |
| 570 | 558 |
| 571 while ((protocol = g_dir_read_name(log_dir)) != NULL) { | 559 while ((protocol = g_dir_read_name(log_dir)) != NULL) { |
| 572 gchar *protocol_path = g_build_filename(log_path, protocol, NULL); | 560 gchar *protocol_path = g_build_filename(log_path, protocol, NULL); |
| 573 GDir *protocol_dir; | 561 GDir *protocol_dir; |
| 632 /* Get the (possibly new) length of name. */ | 620 /* Get the (possibly new) length of name. */ |
| 633 len = strlen(name); | 621 len = strlen(name); |
| 634 | 622 |
| 635 set->account = account; | 623 set->account = account; |
| 636 set->name = name; | 624 set->name = name; |
| 625 set->normalized_name = g_strdup(gaim_normalize(account, name)); | |
| 637 | 626 |
| 638 /* Chat for .chat or .system at the end of the name to determine the type. */ | 627 /* Chat for .chat or .system at the end of the name to determine the type. */ |
| 639 set->type = GAIM_LOG_IM; | 628 set->type = GAIM_LOG_IM; |
| 640 if (len > 7) { | 629 if (len > 7) { |
| 641 gchar *tmp = &name[len - 7]; | 630 gchar *tmp = &name[len - 7]; |
| 651 *tmp = '\0'; | 640 *tmp = '\0'; |
| 652 } | 641 } |
| 653 } | 642 } |
| 654 | 643 |
| 655 /* Determine if this (account, name) combination exists as a buddy. */ | 644 /* Determine if this (account, name) combination exists as a buddy. */ |
| 656 if (gaim_find_buddy(account, name) != NULL) | 645 set->buddy = (gaim_find_buddy(account, name) != NULL); |
| 657 set->buddy = TRUE; | 646 |
| 658 else | 647 log_add_log_set_to_hash(sets, set); |
| 659 set->buddy = FALSE; | |
| 660 | |
| 661 sets = g_list_append(sets, set); | |
| 662 } | 648 } |
| 663 g_free(username_path); | 649 g_free(username_path); |
| 664 g_dir_close(username_dir); | 650 g_dir_close(username_dir); |
| 665 } | 651 } |
| 666 g_free(protocol_path); | 652 g_free(protocol_path); |
| 667 g_dir_close(protocol_dir); | 653 g_dir_close(protocol_dir); |
| 668 } | 654 } |
| 669 g_free(log_path); | 655 g_free(log_path); |
| 670 g_dir_close(log_dir); | 656 g_dir_close(log_dir); |
| 671 | |
| 672 return sets; | |
| 673 } | 657 } |
| 674 | 658 |
| 675 #if 0 /* Maybe some other time. */ | 659 #if 0 /* Maybe some other time. */ |
| 676 /**************** | 660 /**************** |
| 677 ** XML LOGGER ** | 661 ** XML LOGGER ** |
| 1220 { | 1204 { |
| 1221 struct old_logger_data *data = log->logger_data; | 1205 struct old_logger_data *data = log->logger_data; |
| 1222 return data ? data->length : 0; | 1206 return data ? data->length : 0; |
| 1223 } | 1207 } |
| 1224 | 1208 |
| 1225 static GList *old_logger_get_log_sets() | 1209 static void old_logger_get_log_sets(GaimLogSetCallback cb, GHashTable *sets) |
| 1226 { | 1210 { |
| 1227 char *log_path = g_build_filename(gaim_user_dir(), "logs", NULL); | 1211 char *log_path = g_build_filename(gaim_user_dir(), "logs", NULL); |
| 1228 GDir *log_dir = g_dir_open(log_path, 0, NULL); | 1212 GDir *log_dir = g_dir_open(log_path, 0, NULL); |
| 1229 gchar *name; | 1213 gchar *name; |
| 1230 GList *sets = NULL; | |
| 1231 GaimBlistNode *gnode, *cnode, *bnode; | 1214 GaimBlistNode *gnode, *cnode, *bnode; |
| 1232 | 1215 |
| 1233 g_free(log_path); | 1216 g_free(log_path); |
| 1234 if (log_dir == NULL) | 1217 if (log_dir == NULL) |
| 1235 return NULL; | 1218 return; |
| 1236 | 1219 |
| 1237 /* Don't worry about the cast, name will be filled with a dynamically allocated data shortly. */ | 1220 /* Don't worry about the cast, name will be filled with a dynamically allocated data shortly. */ |
| 1238 while ((name = (gchar *)g_dir_read_name(log_dir)) != NULL) { | 1221 while ((name = (gchar *)g_dir_read_name(log_dir)) != NULL) { |
| 1239 size_t len; | 1222 size_t len; |
| 1240 gchar *ext; | 1223 gchar *ext; |
| 1270 set->type = GAIM_LOG_CHAT; | 1253 set->type = GAIM_LOG_CHAT; |
| 1271 *tmp = '\0'; | 1254 *tmp = '\0'; |
| 1272 } | 1255 } |
| 1273 } | 1256 } |
| 1274 | 1257 |
| 1275 set->name = name; | 1258 set->name = set->normalized_name = name; |
| 1276 | 1259 |
| 1277 /* Search the buddy list to find the account and to determine if this is a buddy. */ | 1260 /* Search the buddy list to find the account and to determine if this is a buddy. */ |
| 1278 for (gnode = gaim_get_blist()->root; !found && gnode != NULL; gnode = gnode->next) | 1261 for (gnode = gaim_get_blist()->root; !found && gnode != NULL; gnode = gnode->next) |
| 1279 { | 1262 { |
| 1280 if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) | 1263 if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) |
| 1296 } | 1279 } |
| 1297 } | 1280 } |
| 1298 } | 1281 } |
| 1299 } | 1282 } |
| 1300 | 1283 |
| 1301 sets = g_list_append(sets, set); | 1284 cb(sets, set); |
| 1302 } | 1285 } |
| 1303 g_dir_close(log_dir); | 1286 g_dir_close(log_dir); |
| 1304 | |
| 1305 return sets; | |
| 1306 } | 1287 } |
| 1307 | 1288 |
| 1308 static void old_logger_finalize(GaimLog *log) | 1289 static void old_logger_finalize(GaimLog *log) |
| 1309 { | 1290 { |
| 1310 struct old_logger_data *data = log->logger_data; | 1291 struct old_logger_data *data = log->logger_data; |
