Changeset 1048

Show
Ignore:
Timestamp:
10/23/06 14:59:59
Author:
pvanhoof
Message:

Memory reduction and bugfix

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ChangeLog

    r1046 r1048  
     12006-10-23  Philip Van Hoof <pvanhoof@gnome.org> 
     2 
     3        * libtinymail-camel/camel-lite: Drastic reduction of memory 
     4        consumption on initial download of both IMAP and NNTP folders. 
     5        * libtinymail-gnome-desktop: Default status of the device is now 
     6        offline in stead of online (for example in case network manager 
     7        installation was invalid or not found) 
     8 
    192006-10-20  Sankarshan Mukhopadhyay <sankarshan.mukhopadhyay@gmail.com> 
    210 
  • trunk/libtinymail-camel/camel-lite/camel/camel-folder-summary.c

    r1043 r1048  
    114114static void camel_folder_summary_finalize   (CamelObject *obj); 
    115115 
     116 
     117static void camel_folder_summary_mmap_add(CamelFolderSummary *s, CamelMessageInfo *info); 
     118static void camel_folder_summary_unload_mmap (CamelFolderSummary *s); 
     119 
    116120static CamelObjectClass *camel_folder_summary_parent; 
    117121 
     
    162166} 
    163167 
    164 static void 
    165 camel_folder_summary_finalize (CamelObject *obj) 
    166 
    167         struct _CamelFolderSummaryPrivate *p; 
    168         CamelFolderSummary *s = (CamelFolderSummary *)obj; 
    169  
    170         p = _PRIVATE(obj); 
    171  
     168static gboolean always_true (gpointer key, gpointer value, gpointer gp) 
     169
     170        return TRUE; 
     171
     172 
     173static void  
     174camel_folder_summary_unload_mmap (CamelFolderSummary *s) 
     175
    172176        camel_folder_summary_clear(s); 
    173177        if (s->file) 
     
    176180 
    177181        g_ptr_array_foreach (s->messages, foreach_msginfo, (gpointer)s->message_info_size); 
     182        if (s->messages->len > 0) 
     183                g_ptr_array_remove_range (s->messages, 0, s->messages->len-1); 
     184        g_hash_table_foreach_remove (s->messages_uid, always_true, NULL); 
     185 
     186} 
     187 
     188static void 
     189camel_folder_summary_finalize (CamelObject *obj) 
     190{ 
     191        struct _CamelFolderSummaryPrivate *p; 
     192        CamelFolderSummary *s = (CamelFolderSummary *)obj; 
     193 
     194        p = _PRIVATE(obj); 
     195 
     196        camel_folder_summary_clear(s); 
     197        if (s->file) 
     198                g_mapped_file_free (s->file); 
     199        s->file = NULL; 
     200 
     201        g_ptr_array_foreach (s->messages, foreach_msginfo, (gpointer)s->message_info_size); 
    178202        g_ptr_array_free(s->messages, TRUE); 
    179203        g_hash_table_destroy(s->messages_uid); 
     204        s->messages_uid = NULL; 
    180205 
    181206        g_hash_table_foreach(p->filter_charset, free_o_name, 0); 
     
    592617                } 
    593618 
    594                 camel_folder_summary_add(s, mi); 
     619                camel_folder_summary_mmap_add(s, mi); 
    595620        } 
    596621 
     
    808833 
    809834 
     835 
     836void  
     837camel_folder_summary_dump_mmap (CamelFolderSummary *s) 
     838{ 
     839        camel_folder_summary_save (s); 
     840        camel_folder_summary_unload_mmap (s); 
     841        camel_folder_summary_load(s); 
     842 
     843        return; 
     844} 
     845 
    810846/** 
    811847 * camel_folder_summary_add: 
     
    846882} 
    847883 
     884static void 
     885camel_folder_summary_mmap_add(CamelFolderSummary *s, CamelMessageInfo *info) 
     886{ 
     887        CAMEL_SUMMARY_LOCK(s, summary_lock); 
     888 
     889/* unnecessary for pooled vectors */ 
     890#ifdef DOESTRV 
     891        /* this is vitally important, and also if this is ever modified, then 
     892           the hash table needs to be resynced */ 
     893        info->strings = e_strv_pack(info->strings); 
     894#endif 
     895 
     896        g_ptr_array_add(s->messages, info); 
     897        g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); 
     898        s->flags |= CAMEL_SUMMARY_DIRTY; 
     899 
     900        CAMEL_SUMMARY_UNLOCK(s, summary_lock); 
     901} 
    848902 
    849903/** 
     
    10911145camel_folder_summary_touch(CamelFolderSummary *s) 
    10921146{ 
    1093         CAMEL_SUMMARY_LOCK(s, summary_lock); 
     1147        //CAMEL_SUMMARY_LOCK(s, summary_lock); 
    10941148        s->flags |= CAMEL_SUMMARY_DIRTY; 
    1095         CAMEL_SUMMARY_UNLOCK(s, summary_lock); 
     1149        //CAMEL_SUMMARY_UNLOCK(s, summary_lock); 
    10961150} 
    10971151 
  • trunk/libtinymail-camel/camel-lite/camel/camel-folder-summary.h

    r1043 r1048  
    309309CamelFolderSummary      *camel_folder_summary_new       (struct _CamelFolder *folder); 
    310310 
     311void camel_folder_summary_dump_mmap (CamelFolderSummary *s); 
     312 
    311313unsigned char* 
    312314decode_uint32 (unsigned char *start, guint32 *dest, gboolean is_string); 
  • trunk/libtinymail-camel/camel-lite/camel/camel-folder.c

    r1025 r1048  
    21172117        GPtrArray *olduids; 
    21182118        char *olduid; 
    2119          
     2119 
    21202120        g_assert(info != NULL); 
    21212121         
  • trunk/libtinymail-camel/camel-lite/camel/providers/Makefile.am

    r1025 r1048  
    11## Process this file with automake to produce Makefile.in 
    22 
     3 
     4SUBDIRS = pop3 smtp imap local   
     5 
    36if ENABLE_NNTP 
    4 NNTP_DIR=nntp 
     7SUBDIRS += nntp  
    58endif 
    69 
    710if ENABLE_IMAPP 
    8 IMAPP_DIR=imapp 
     11SUBDIRS += imapp  
    912endif 
     13 
    1014 
    1115if OS_WIN32 
    1216else 
    13 SENDMAIL_DIR=sendmail 
     17SUBDIRS += sendmail  
    1418endif 
    1519 
    16 SUBDIRS = pop3 $(SENDMAIL_DIR) smtp imap $(NNTP_DIR) local $(IMAPP_DIR)  
    1720 
    18  
  • trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c

    r1043 r1048  
    23382338                     CamelException *ex) 
    23392339{ 
    2340         CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); 
    2341         CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); 
    2342         GPtrArray *fetch_data = NULL, *messages = NULL, *needheaders; 
    2343         guint32 flags, uidval; 
    2344         int i, seq, first, size, got; 
    2345         CamelImapResponseType type; 
    2346         const char *header_spec; 
    2347         CamelImapMessageInfo *mi, *info; 
    2348         CamelStream *stream; 
    2349         char *uid, *resp; 
    2350         GData *data; 
    2351          
    2352         if (store->server_level >= IMAP_LEVEL_IMAP4REV1) 
    2353                 header_spec = "HEADER.FIELDS (" CAMEL_MESSAGE_INFO_HEADERS MAILING_LIST_HEADERS ")"; 
    2354         else 
    2355                 header_spec = "0"; 
    2356          
    2357         /* Used as a way to fetch all Headers instead of the selective headers. 
    2358            Support for fetching custom headers could be done in a better way, 
    2359            using CamelURL and EPlugins. */ 
    2360          
    2361         if( g_getenv ("EVO_IMAP_FETCH_ALL_HEADERS") ) 
    2362                 header_spec = "HEADER"; 
    2363          
     2340   CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); 
     2341   CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); 
     2342   GPtrArray *fetch_data = NULL, *messages = NULL, *needheaders; 
     2343   guint32 flags, uidval; 
     2344   int i, seq, first, size, got; 
     2345   CamelImapResponseType type; 
     2346   const char *header_spec; 
     2347   CamelImapMessageInfo *mi, *info; 
     2348   CamelStream *stream; 
     2349   char *uid, *resp; 
     2350   GData *data; 
     2351   gboolean more = TRUE; 
     2352   unsigned int nextn = 1; 
     2353 
     2354   if (store->server_level >= IMAP_LEVEL_IMAP4REV1) 
     2355        header_spec = "HEADER.FIELDS (" CAMEL_MESSAGE_INFO_HEADERS MAILING_LIST_HEADERS ")"; 
     2356   else 
     2357        header_spec = "0"; 
     2358 
     2359   /* Used as a way to fetch all Headers instead of the selective headers. 
     2360      Support for fetching custom headers could be done in a better way, 
     2361      using CamelURL and EPlugins. */ 
     2362 
     2363   if( g_getenv ("EVO_IMAP_FETCH_ALL_HEADERS") ) 
     2364        header_spec = "HEADER"; 
     2365 
     2366   while (more) 
     2367   { 
     2368        gint count = 0; 
     2369        more = FALSE; 
     2370 
    23642371        /* Figure out if any of the new messages are already cached (which 
    23652372         * may be the case if we're re-syncing after disconnected operation). 
     
    23752382        } else 
    23762383                uidval = 0; 
    2377          
     2384 
    23782385        size = (exists - seq) * (IMAP_PRETEND_SIZEOF_FLAGS + IMAP_PRETEND_SIZEOF_SIZE + IMAP_PRETEND_SIZEOF_HEADERS); 
    23792386        got = 0; 
    23802387        if (!camel_imap_command_start (store, folder, ex, 
    2381                                        "UID FETCH %d:* (FLAGS RFC822.SIZE INTERNALDATE BODY.PEEK[%s])", 
    2382                                        uidval + 1, header_spec)) 
     2388                                       "UID FETCH %d:%d (FLAGS RFC822.SIZE INTERNALDATE BODY.PEEK[%s])", 
     2389                                       uidval + 1, uidval + 1 + nextn, header_spec)) 
    23832390                return; 
     2391 
     2392        /* 1, 7, 19, 43, 91, .. until 1000 (the smaller, the more dumps,  
     2393        the slower. But too large consumes a lot memory, and also takes longer  
     2394        to fetch from the service before we can dump) */ 
     2395 
     2396        if (nextn < 1000) 
     2397                nextn += (nextn+5); 
     2398        else 
     2399                nextn = 1000; 
     2400 
    23842401        camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name); 
    2385          
     2402 
    23862403        /* Parse the responses. We can't add a message to the summary 
    23872404         * until we've gotten its headers, and there's no guarantee 
    23882405         * the server will send the responses in a useful order... 
    23892406         */ 
     2407 
    23902408        fetch_data = g_ptr_array_new (); 
    23912409        messages = g_ptr_array_new (); 
    23922410        while ((type = camel_imap_command_response (store, &resp, ex)) == 
    2393                CAMEL_IMAP_RESPONSE_UNTAGGED) { 
     2411                        CAMEL_IMAP_RESPONSE_UNTAGGED)  
     2412        { 
     2413                more = TRUE; 
    23942414                data = parse_fetch_response (imap_folder, resp); 
    23952415                g_free (resp); 
     2416 
    23962417                if (!data) 
    23972418                        continue; 
     
    24022423                        continue; 
    24032424                } 
    2404                  
     2425 
    24052426                if (g_datalist_get_data (&data, "FLAGS")) 
    24062427                        got += IMAP_PRETEND_SIZEOF_FLAGS; 
     
    24172438                        g_datalist_set_data (&data, "BODY_PART_STREAM", NULL); 
    24182439                } 
    2419                  
    2420                 camel_operation_progress (NULL, got * 100 / size); 
     2440 
     2441                if (size > 0) 
     2442                        camel_operation_progress (NULL, got * 100 / size); 
    24212443                g_ptr_array_add (fetch_data, data); 
    24222444        } 
    24232445        camel_operation_end (NULL); 
    2424          
     2446 
    24252447        if (type == CAMEL_IMAP_RESPONSE_ERROR) 
    24262448                goto lose; 
    2427          
     2449 
    24282450        /* Free the final tagged response */ 
    24292451        g_free (resp); 
    2430          
     2452 
    24312453        /* Figure out which headers we still need to fetch. */ 
    24322454        needheaders = g_ptr_array_new (); 
    24332455        size = got = 0; 
    2434         for (i = 0; i < fetch_data->len; i++) { 
     2456        for (i = 0; i < fetch_data->len; i++)  
     2457        { 
    24352458                data = fetch_data->pdata[i]; 
    24362459                if (g_datalist_get_data (&data, "BODY_PART_LEN")) 
    24372460                        continue; 
    2438                  
     2461 
    24392462                uid = g_datalist_get_data (&data, "UID"); 
    24402463                if (uid) { 
     
    24432466                } 
    24442467        } 
    2445          
     2468 
    24462469        /* And fetch them */ 
    2447         if (needheaders->len) { 
     2470        if (needheaders->len)  
     2471        { 
    24482472                char *uidset; 
    24492473                int uid = 0; 
    2450                  
     2474 
    24512475                qsort (needheaders->pdata, needheaders->len, 
    2452                        sizeof (void *), uid_compar); 
    2453                  
     2476                       sizeof (void *), uid_compar); 
     2477 
    24542478                camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name); 
    2455                  
    24562479                while (uid < needheaders->len) { 
    24572480                        uidset = imap_uid_array_to_set (folder->summary, needheaders, uid, UID_SET_LIMIT, &uid); 
     
    24652488                        } 
    24662489                        g_free (uidset); 
    2467                          
     2490 
    24682491                        while ((type = camel_imap_command_response (store, &resp, ex)) 
    24692492                               == CAMEL_IMAP_RESPONSE_UNTAGGED) { 
     
    24772500                                        add_message_from_data (folder, messages, first, data); 
    24782501                                        got += IMAP_PRETEND_SIZEOF_HEADERS; 
    2479                                         camel_operation_progress (NULL, got * 100 / size); 
     2502                                        if (size > 0) 
     2503                                                camel_operation_progress (NULL, got * 100 / size); 
    24802504                                } 
    24812505                                g_datalist_clear (&data); 
     
    24882512                        } 
    24892513                } 
    2490                  
    24912514                g_ptr_array_free (needheaders, TRUE); 
    24922515                camel_operation_end (NULL); 
    24932516        } 
    2494          
     2517 
    24952518        /* Now finish up summary entries (fix UIDs, set flags and size) */ 
    24962519        for (i = 0; i < fetch_data->len; i++) { 
    24972520                data = fetch_data->pdata[i]; 
    2498                  
     2521 
    24992522                seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); 
    25002523                if (seq >= first + messages->len) { 
     
    25022525                        continue; 
    25032526                } 
    2504                  
     2527 
    25052528                mi = messages->pdata[seq - first]; 
    25062529                if (mi == NULL) { 
    25072530                        CamelMessageInfo *pmi = NULL; 
    25082531                        int j; 
    2509                          
     2532 
    25102533                        /* This is a kludge around a bug in Exchange 
    25112534                         * 5.5 that sometimes claims multiple messages 
     
    25242547                                        break; 
    25252548                        } 
    2526                          
     2549 
    25272550                        if (pmi == NULL) { 
    25282551                                /* Server response is *really* fucked up, 
     
    25332556                        mi = (CamelImapMessageInfo *)camel_message_info_clone(pmi); 
    25342557                } 
    2535                  
     2558 
    25362559                uid = g_datalist_get_data (&data, "UID"); 
    2537  
    2538                 /* This strdup() might not get freed since the mmap() patch! */ 
    2539                 if (uid) 
     2560                if (uid) { 
    25402561                        mi->info.uid = g_strdup (uid); 
     2562                        mi->info.uid_needs_free = TRUE; 
     2563                } 
    25412564 
    25422565                flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS")); 
     
    25492572                        flags_to_label(folder, mi); 
    25502573                } 
    2551                  
     2574 
    25522575#ifdef NON_TINYMAIL_FEATURES 
    25532576                size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE")); 
     
    25552578                        mi->info.size = size; 
    25562579#endif 
     2580 
    25572581                g_datalist_clear (&data); 
    25582582        } 
    25592583        g_ptr_array_free (fetch_data, TRUE); 
    2560          
     2584 
    25612585        /* And add the entries to the summary, etc. */ 
    2562         for (i = 0; i < messages->len; i++) { 
     2586        for (i = 0; i < messages->len; i++)  
     2587        { 
     2588 
    25632589                mi = messages->pdata[i]; 
    25642590                if (!mi) { 
    2565                         g_warning ("No information for message %d", i + first); 
     2591                        /* g_warning ("No information for message %d", i + first); 
    25662592                        camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, 
    25672593                                              _("Incomplete server response: no information provided for message %d"), 
    2568                                               i + first); 
    2569                         break; 
    2570                 } 
     2594                                              i + first); */ 
     2595                        continue; 
     2596                } 
     2597 
    25712598                uid = (char *)camel_message_info_uid(mi); 
    25722599                if (uid[0] == 0) { 
     
    25772604                        break; 
    25782605                } 
     2606 
    25792607                info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, uid); 
    25802608                if (info) { 
     
    25922620                        break; 
    25932621                } 
    2594                  
     2622 
    25952623                camel_folder_summary_add (folder->summary, (CamelMessageInfo *)mi); 
    25962624                camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi)); 
    2597                  
     2625 
    25982626                if ((mi->info.flags & CAMEL_IMAP_MESSAGE_RECENT)) 
    25992627                        camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi)); 
    26002628        } 
     2629 
     2630        /* Dumping each nextn'th header (this is needed for the nextn calc to  
     2631           be correct), it *must* write the summary cache to disk! */ 
     2632 
     2633        camel_folder_summary_dump_mmap (folder->summary); 
    26012634 
    26022635        for ( ; i < messages->len; i++) { 
     
    26042637                        camel_message_info_free(&mi->info); 
    26052638        } 
    2606          
    26072639        g_ptr_array_free (messages, TRUE); 
    2608          
    2609         return
    2610          
     2640 
     2641        goto endbmore
     2642 
    26112643 lose: 
    26122644        if (fetch_data) { 
     
    26242656                g_ptr_array_free (messages, TRUE); 
    26252657        } 
     2658 
     2659        endbmore: 
     2660        count = 0; 
     2661   } /* more */ 
    26262662} 
    26272663 
  • trunk/libtinymail-camel/camel-lite/camel/providers/nntp/camel-nntp-summary.c

    r1042 r1048  
    220220        char *line, *tab; 
    221221        int len, ret; 
    222         unsigned int n, count, total, size
     222        unsigned int n, count, total, size, acnt=0
    223223        struct _xover_header *xover; 
    224224 
     
    282282                        mi = (CamelMessageInfoBase *)camel_folder_summary_uid(s, cns->priv->uid); 
    283283                        if (mi == NULL) { 
     284 
     285                                if (acnt > 1000) { 
     286                                        camel_folder_summary_dump_mmap (s); 
     287                                        acnt = 0; 
     288                                } 
     289                                acnt++; 
    284290                                mi = (CamelMessageInfoBase *)camel_folder_summary_add_from_header(s, headers); 
    285291                                if (mi) { 
     
    315321        int ret = -1; 
    316322        char *line, *msgid; 
    317         unsigned int i, n, count, total
     323        unsigned int i, n, count, total, acnt=0
    318324        CamelMessageInfo *mi; 
    319325        CamelMimeParser *mp; 
     
    349355                        line[1] = 0; 
    350356                        cns->priv->uid = g_strdup_printf("%u,%s\n", n, msgid); 
     357 
    351358                        mi = camel_folder_summary_uid(s, cns->priv->uid); 
    352359                        if (mi == NULL) { 
    353360                                if (camel_mime_parser_init_with_stream(mp, (CamelStream *)store->stream) == -1) 
    354361                                        goto error; 
     362                                if (acnt > 1000) { 
     363                                        camel_folder_summary_dump_mmap (s); 
     364                                        acnt = 0; 
     365                                } 
     366                                acnt++; 
    355367                                mi = camel_folder_summary_add_from_parser(s, mp); 
    356368                                while (camel_mime_parser_step(mp, NULL, NULL) != CAMEL_MIME_PARSER_STATE_EOF) 
  • trunk/libtinymail-gnome-desktop/tny-gnome-device-priv.h

    r879 r1048  
    2828     
    2929#ifdef GNOME 
     30        gboolean invnm; 
    3031        guint callback_id; 
    3132        libnm_glib_ctx *nm_ctx; 
  • trunk/libtinymail-gnome-desktop/tny-gnome-device.c

    r900 r1048  
    5858        priv->fset = FALSE; 
    5959        priv->forced = FALSE; 
    60      
     60 
    6161#ifdef GNOME 
    6262        nm_callback (priv->nm_ctx, self); 
     
    7575        nm_callback (priv->nm_ctx, self); 
    7676#endif 
    77      
     77 
    7878        return; 
    7979} 
     
    8989 
    9090#ifdef GNOME 
    91     nm_callback (priv->nm_ctx, self); 
    92 #endif 
    93      
     91       nm_callback (priv->nm_ctx, self); 
     92#endif 
     93 
    9494        return; 
    9595} 
     
    118118 
    119119#ifdef GNOME 
    120         if (!priv->fset
     120        if (!priv->fset && !priv->invnm
    121121        { 
    122122                libnm_glib_state state = libnm_glib_get_network_state (priv->nm_ctx); 
     
    124124                switch (state) 
    125125                { 
    126                         case LIBNM_NO_NETWORK_CONNECTION: 
    127                         retval = FALSE; 
     126                        case LIBNM_ACTIVE_NETWORK_CONNECTION: 
     127                        retval = TRUE; 
    128128                        break; 
    129129 
     
    131131                        case LIBNM_NO_NETWORKMANAGER: 
    132132                        case LIBNM_INVALID_CONTEXT: 
    133                         g_print (_("Invalid network manager installation. Going to assume Online status\n")); 
    134                         case LIBNM_ACTIVE_NETWORK_CONNECTION: 
     133                        g_print (_("Invalid network manager installation. Going to assume Offline status\n")); 
     134                        priv->invnm = TRUE; 
     135                        case LIBNM_NO_NETWORK_CONNECTION: 
    135136                        default: 
    136                         retval = TRUE; 
     137                        retval = FALSE; 
    137138                        break; 
    138139                } 
    139140        } 
    140141#endif 
    141      
     142 
    142143        return retval; 
    143144} 
     
    150151        TnyGnomeDevicePriv *priv = TNY_GNOME_DEVICE_GET_PRIVATE (self); 
    151152 
     153        priv->invnm = FALSE; 
    152154        priv->fset = FALSE; 
    153155        priv->forced = FALSE; 
     
    157159        priv->callback_id = libnm_glib_register_callback  
    158160                (priv->nm_ctx, nm_callback, self, NULL); 
    159  
    160 #endif 
    161      
     161#endif 
     162 
    162163        return; 
    163164}