Changeset 2509

Show
Ignore:
Timestamp:
07/27/07 12:38:08
Author:
pvanhoof
Message:

Created a branch with improved connection management and going online support

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • devel/pvanhoof/sessionwork/libtinymail-camel/tny-camel-account.c

    r2484 r2509  
    697697        priv->session = session; 
    698698 
    699         _tny_session_camel_add_account_1 (session, self); 
     699        _tny_session_camel_register_account (session, self); 
    700700 
    701701        TNY_CAMEL_ACCOUNT_GET_CLASS (self)->prepare_func (self, FALSE, FALSE); 
     
    887887 
    888888        if (priv->session) 
    889                 _tny_session_camel_add_account_2 (priv->session, TNY_CAMEL_ACCOUNT (self)); 
     889                _tny_session_camel_activate_account (priv->session, TNY_CAMEL_ACCOUNT (self)); 
    890890 
    891891        g_static_rec_mutex_unlock (priv->service_lock); 
     
    13881388 
    13891389        if (priv->session) { 
    1390                 _tny_session_camel_forget_account (priv->session, (TnyCamelAccount*) object);     
     1390                _tny_session_camel_unregister_account (priv->session, (TnyCamelAccount*) object);     
    13911391                camel_object_unref (priv->session); 
    13921392        } 
  • devel/pvanhoof/sessionwork/libtinymail-camel/tny-camel-send-queue.c

    r2445 r2509  
    163163        TnySendQueue *self = (TnySendQueue *) data; 
    164164        TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self); 
    165         TnyCamelAccountPriv *apriv = NULL; 
     165        /* TnyCamelAccountPriv *apriv = NULL; */ 
    166166        TnyFolder *sentbox, *outbox; 
    167167        guint i = 0, length = 0; 
     
    173173        priv->creating_spin = FALSE; 
    174174 
    175       apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account); 
     175/*    apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account); 
    176176        if (apriv) 
    177                 tny_session_camel_join_connecting (apriv->session); 
     177                tny_session_camel_join_connecting (apriv->session); */ 
    178178 
    179179        list = tny_simple_list_new (); 
     
    386386{ 
    387387        TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self); 
    388         TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account); 
    389  
    390         if (!apriv->session->priv->conthread && priv->thread) 
     388 
     389        if (priv->thread) 
    391390                g_thread_join (priv->thread); 
    392391} 
  • devel/pvanhoof/sessionwork/libtinymail-camel/tny-camel-store-account-priv.h

    r2488 r2509  
    2121 */ 
    2222 
     23#include <tny-session-camel.h> 
    2324#include <tny-camel-store-account.h> 
     25 
    2426#include "tny-camel-queue-priv.h" 
     27#include "tny-session-camel-priv.h" 
    2528 
    2629typedef struct _TnyCamelStoreAccountPriv TnyCamelStoreAccountPriv; 
     
    4144 
    4245void _tny_camel_store_account_emit_conchg_signal (TnyCamelStoreAccount *self); 
     46void _tny_camel_store_account_queue_going_online (TnyCamelStoreAccount *self, TnySessionCamel *session, gboolean online, go_online_error_func err_func); 
    4347 
    4448#endif 
  • devel/pvanhoof/sessionwork/libtinymail-camel/tny-camel-store-account.c

    r2489 r2509  
    8484                TnyFolderStoreObserver *observer = TNY_FOLDER_STORE_OBSERVER (tny_iterator_get_current (iter)); 
    8585                tny_folder_store_observer_update (observer, change); 
    86                 g_object_unref (G_OBJECT (observer)); 
     86                g_object_unref (observer); 
    8787                tny_iterator_next (iter); 
    8888        } 
    89         g_object_unref (G_OBJECT (iter)); 
     89        g_object_unref (iter); 
    9090} 
    9191 
     
    9898        g_signal_emit (G_OBJECT (self),  
    9999                tny_account_signals [TNY_ACCOUNT_CONNECTION_STATUS_CHANGED],  
    100                 0, apriv->status); 
     100                       0, apriv->status); 
    101101 
    102102        return FALSE; 
     
    15251525} 
    15261526 
     1527 
     1528 
     1529typedef struct { 
     1530        TnySessionCamel *session; 
     1531        TnyCamelStoreAccount *self; 
     1532        gboolean online; 
     1533        go_online_error_func err_func; 
     1534} GoingOnlineInfo; 
     1535 
     1536static gpointer  
     1537tny_camel_store_account_queue_going_online_thread (gpointer thr_user_data) 
     1538{ 
     1539        GoingOnlineInfo *info = (GoingOnlineInfo*) thr_user_data; 
     1540        TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (info->self); 
     1541        GError *err = NULL; 
     1542 
     1543        /* So this happens in the queue thread. There's only one such thread 
     1544         * for each TnyCamelStoreAccount active at any given moment in time.  
     1545         * This means that operations on the queue, while this is happening, 
     1546         * must wait. */ 
     1547 
     1548        /* The info->err_func points to on_account_connect_failed in the  
     1549         * TnySessionCamel implementation. Go take a look! */ 
     1550 
     1551        apriv->is_connecting = TRUE; 
     1552 
     1553        /* This is one of those functions that our hero, Rob, is going to  
     1554         * refactor/rename to something that does make sense :-). Isn't that 
     1555         * true Rob? */ 
     1556 
     1557        _tny_camel_account_try_connect (TNY_CAMEL_ACCOUNT (info->self),  
     1558                        FALSE, &err); 
     1559 
     1560        if (err) { 
     1561                info->err_func (info->session, TNY_CAMEL_ACCOUNT (info->self), err); 
     1562                g_error_free (err); 
     1563        } else { 
     1564 
     1565                /* This one actually sets the account to online. Although Rob  
     1566                 * is probably going to improve all this. Right *poke*? */ 
     1567 
     1568                _tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->self),  
     1569                        info->online, &err); 
     1570 
     1571                if (err) { 
     1572                        info->err_func (info->session,  
     1573                                TNY_CAMEL_ACCOUNT (info->self), err); 
     1574                        g_error_free (err); 
     1575                } 
     1576        } 
     1577 
     1578        apriv->is_connecting = FALSE; 
     1579 
     1580        /* Thread reference */ 
     1581        camel_object_unref (info->session); 
     1582        g_object_unref (info->self); 
     1583 
     1584        return NULL; 
     1585} 
     1586 
     1587/* This is that protected implementation that will request to go online, on the 
     1588 * queue of this account @self. Each TnyCamelStoreAccount has two queues: One  
     1589 * queue is dedicated to getting messages. The other, the default queue, is 
     1590 * dedicated to any other operation. Including getting itself connected with an  
     1591 * actual server (that can be both a POP or an IMAP server, depending on the  
     1592 * url-string and/or proto setting of @self). */ 
     1593 
     1594void 
     1595_tny_camel_store_account_queue_going_online (TnyCamelStoreAccount *self, TnySessionCamel *session, gboolean online, go_online_error_func err_func) 
     1596{ 
     1597        GoingOnlineInfo *info = NULL; 
     1598        GError *err = NULL; 
     1599        TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self); 
     1600        TnyCamelStoreAccountPriv *priv = TNY_CAMEL_STORE_ACCOUNT_GET_PRIVATE (self); 
     1601 
     1602        /* Idle info for the callbacks */ 
     1603        info = g_slice_new0 (GoingOnlineInfo); 
     1604 
     1605        info->session = session; 
     1606        info->self = self; 
     1607        info->err_func = err_func; 
     1608        info->online = online; 
     1609 
     1610        /* thread reference */ 
     1611        g_object_ref (info->self); 
     1612        camel_object_ref (info->session); 
     1613 
     1614 
     1615        /* It's indeed a very typical queue operation */ 
     1616 
     1617        _tny_camel_queue_launch (priv->queue,  
     1618                tny_camel_store_account_queue_going_online_thread, info); 
     1619 
     1620        return; 
     1621} 
     1622 
    15271623static void 
    15281624tny_folder_store_init (gpointer g, gpointer iface_data) 
  • devel/pvanhoof/sessionwork/libtinymail-camel/tny-session-camel-priv.h

    r2453 r2509  
    1010        gboolean interactive, prev_constat; 
    1111        guint connchanged_signal; 
    12         GList *current_accounts; 
     12 
     13        GHashTable *current_accounts; 
     14        GStaticRecMutex *current_accounts_lock; 
     15 
    1316        gchar *camel_dir; 
    1417        gboolean in_auth_function, is_connecting; 
    15         gboolean async_connect; 
    1618        TnyLockable *ui_lock; 
    17         GMutex *conlock, *queue_lock; 
    18         GThread *conthread; 
     19        GMutex *queue_lock; 
     20 
    1921        gboolean stop_now, initialized; 
    20         gboolean is_inuse, background_thread_running
     22        gboolean is_inuse
    2123        GList *regged_queues; 
    2224}; 
    2325 
    24 void _tny_session_camel_add_account_1 (TnySessionCamel *self, TnyCamelAccount *account); 
    25 void _tny_session_camel_add_account_2 (TnySessionCamel *self, TnyCamelAccount *account); 
    26 void _tny_session_camel_forget_account (TnySessionCamel *self, TnyCamelAccount *account); 
     26typedef void (*go_online_error_func) (TnySessionCamel *self, TnyCamelAccount *account, GError *err); 
     27void _tny_session_camel_register_account (TnySessionCamel *self, TnyCamelAccount *account); 
     28void _tny_session_camel_activate_account (TnySessionCamel *self, TnyCamelAccount *account); 
     29void _tny_session_camel_unregister_account (TnySessionCamel *self, TnyCamelAccount *account); 
     30 
    2731void _tny_session_camel_reg_queue (TnySessionCamel *self, TnyCamelSendQueue *queue); 
    2832void _tny_session_camel_unreg_queue (TnySessionCamel *self, TnyCamelSendQueue *queue); 
  • devel/pvanhoof/sessionwork/libtinymail-camel/tny-session-camel.c

    r2453 r2509  
    360360} 
    361361 
    362 /** 
    363  * tny_session_camel_set_async_connecting: 
    364  * @self: a #TnySessionCamel object 
    365  * @enable: Whether or not to asynchronously connect 
    366  * 
    367  * Set connection strategy 
    368  **/ 
    369 void  
    370 tny_session_camel_set_async_connecting (TnySessionCamel *self, gboolean enable) 
    371 { 
    372         g_mutex_lock (self->priv->conlock); 
    373         self->priv->async_connect = enable; 
    374         g_mutex_unlock (self->priv->conlock); 
    375 } 
    376362 
    377363 
     
    386372        priv->stop_now = FALSE; 
    387373        priv->regged_queues = NULL; 
    388         priv->background_thread_running = FALSE; 
    389374        priv->is_inuse = FALSE; 
    390         priv->conlock = g_mutex_new (); 
    391375        priv->queue_lock = g_mutex_new (); 
    392         priv->conthread = NULL; 
    393         priv->current_accounts = NULL; 
     376 
     377        /* I know it would be better to have a hashtable that does reference 
     378         * counting. But then you'll get embraced references, which gobject 
     379         * can't really handle (unless doing it with a weak reference) */ 
     380 
     381        priv->current_accounts = g_hash_table_new_full (g_str_hash, g_direct_equal,  
     382                                        g_free, NULL); 
     383 
     384        priv->current_accounts_lock = g_new0 (GStaticRecMutex, 1); 
     385        g_static_rec_mutex_init (priv->current_accounts_lock); 
    394386        priv->prev_constat = FALSE; 
    395387        priv->device = NULL; 
     
    399391        priv->in_auth_function = FALSE; 
    400392        priv->is_connecting = FALSE; 
    401         priv->async_connect = TRUE; 
    402  
    403         return; 
    404 
    405  
    406 typedef struct 
    407 
    408         TnyDevice *device; 
    409         gboolean online, as_thread; 
    410         gpointer user_data; 
    411         TnySessionCamelPriv *priv; 
    412 } BackgroundConnectInfo; 
    413  
    414 static gboolean 
    415 background_connect_idle (gpointer data) 
    416 
    417         BackgroundConnectInfo *info = data; 
    418         TnySessionCamel *self = info->user_data; 
    419         TnySessionCamelPriv *priv = self->priv; 
    420  
    421         if (priv->account_store) 
    422         { 
    423                 g_signal_emit (priv->account_store,  
    424                         tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED], 0); 
    425                 g_signal_emit (priv->account_store, 
    426                         tny_account_store_signals [TNY_ACCOUNT_STORE_CONNECTING_FINISHED], 0); 
    427         } 
    428  
    429         return FALSE; 
    430 
    431  
    432  
    433  
    434 static void 
    435 background_connect_destroy (gpointer data) 
    436 
    437         BackgroundConnectInfo *info = data; 
    438  
    439         g_object_unref (G_OBJECT (info->device)); 
    440         g_slice_free (BackgroundConnectInfo, data); 
    441  
    442         return; 
    443 
    444  
    445  
    446  
    447 static void 
    448 foreach_account_set_connectivity (gpointer data, gpointer udata) 
    449 
    450         BackgroundConnectInfo *info = udata; 
    451         TnySessionCamel *self = info->user_data; 
    452          
    453         if (data && TNY_IS_CAMEL_ACCOUNT (data)) 
    454         { 
    455                 TnyCamelAccount *account = TNY_CAMEL_ACCOUNT (data); 
    456                  
    457                 GError *err = NULL; 
    458                 TnyCamelAccountPriv *apriv = NULL; 
    459  
    460                 /* We don't go online on transport accounts, yet */ 
    461                 if (TNY_IS_CAMEL_TRANSPORT_ACCOUNT (account)) 
    462                 { 
    463                         g_signal_emit (account,  
    464                                 tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, info->online); 
    465                         return; 
    466                 } 
    467  
    468                 apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account); 
    469  
    470                 apriv->is_connecting = TRUE; 
    471  
    472                 _tny_camel_account_try_connect (account, FALSE /* info->online */, &err); 
    473  
    474                 if (err == NULL) 
    475                         _tny_camel_account_set_online (account, info->online, &err); 
    476  
    477                 if (err != NULL)  
    478                 { 
    479                         if (self->priv->account_store) 
    480                         { 
    481                                 if (info->as_thread) 
    482                                         tny_lockable_lock (self->priv->ui_lock); 
    483  
    484                                 tny_session_camel_do_an_error (self, TNY_ACCOUNT (account), TNY_ALERT_TYPE_ERROR, FALSE, err); 
    485  
    486                                 if (info->as_thread) 
    487                                         tny_lockable_unlock (self->priv->ui_lock); 
    488                         } 
    489                         g_error_free (err); 
    490                 } 
    491  
    492                 apriv->is_connecting = FALSE; 
    493  
    494         } 
    495 
    496  
    497 typedef struct { 
    498         BackgroundConnectInfo *info; 
    499         TnyCamelAccount *account; 
    500 } AccGoOnlineInfo; 
    501  
    502 static gpointer 
    503 account_go_online (gpointer data) 
    504 
    505         AccGoOnlineInfo *ainfo = (AccGoOnlineInfo *) data; 
    506         TnySessionCamel *self = ainfo->info->user_data; 
    507         TnySessionCamelPriv *priv = self->priv; 
    508  
    509         priv->is_connecting = TRUE; 
    510  
    511         foreach_account_set_connectivity (ainfo->account, ainfo->info); 
    512  
    513         priv->is_connecting = FALSE; 
    514  
    515         camel_object_unref (ainfo->info->user_data); 
    516         g_object_unref (ainfo->account); 
    517  
    518         g_idle_add_full (G_PRIORITY_HIGH,  
    519                 background_connect_idle,  
    520                 ainfo->info, background_connect_destroy); 
    521  
    522         g_slice_free (AccGoOnlineInfo, ainfo); 
    523         /* ainfo->info is freed in the background_connect_destroy */ 
    524  
    525         priv->conthread = NULL; 
    526  
    527         g_thread_exit (NULL); 
    528         return NULL; 
    529 
    530  
    531  
     393 
     394        return; 
     395
     396 
     397 
     398/* Happens at tny_camel_account_set_session */ 
    532399void  
    533 _tny_session_camel_add_account_1 (TnySessionCamel *self, TnyCamelAccount *account) 
     400_tny_session_camel_register_account (TnySessionCamel *self, TnyCamelAccount *account) 
    534401{ 
    535402        TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account); 
     
    539406                g_free (apriv->cache_location); 
    540407        apriv->cache_location = g_strdup (priv->camel_dir); 
    541         priv->current_accounts = g_list_prepend (priv->current_accounts, account); 
    542 
     408 
     409        return; 
     410 
     411
     412 
     413static void 
     414on_account_connect_failed (TnySessionCamel *self, TnyCamelAccount *account, GError *err) 
     415
     416        tny_lockable_lock (self->priv->ui_lock); 
     417        tny_session_camel_do_an_error (self, TNY_ACCOUNT (account), TNY_ALERT_TYPE_ERROR, FALSE, err); 
     418        tny_lockable_unlock (self->priv->ui_lock); 
     419 
     420        return; 
     421
     422 
     423 
     424static void  
     425tny_session_queue_going_online_for_account (TnySessionCamel *self, TnyCamelAccount *account, gboolean online) 
     426
     427 
     428        /* So this is that wrapper that I talked about (see below). In case we  
     429         * are a store account, this means that we need to throw the request to 
     430         * go online to the account's queue. This is implemented in a protected 
     431         * method in TnyCamelStoreAccount. Go take a look! */ 
     432 
     433        if (TNY_IS_CAMEL_STORE_ACCOUNT (account))  
     434        { 
     435                TnySessionCamelPriv *priv = self->priv; 
     436 
     437                _tny_camel_store_account_queue_going_online ( 
     438                        TNY_CAMEL_STORE_ACCOUNT (account), self, online,  
     439                        on_account_connect_failed); 
     440        } 
     441 
     442        /* Else, if it's a transport account, we don't have any transport  
     443         * account implementations that actually need to go online at this  
     444         * moment yet. At the moment of transferring the first message, the 
     445         * current implementations will automatically connect themselves. */ 
     446 
     447        if (TNY_IS_CAMEL_TRANSPORT_ACCOUNT (account)) 
     448        { 
     449                g_signal_emit (account,  
     450                        tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, online); 
     451                return; 
     452        } 
     453
     454 
     455/* This happens when the password function of the account is set. It will after  
     456 * registering the account for future connection-changes, already set the online 
     457 * state of it to the current connectivity setting of the device */ 
    543458 
    544459void 
    545 _tny_session_camel_add_account_2 (TnySessionCamel *self, TnyCamelAccount *account) 
    546 
    547         TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account); 
    548         TnySessionCamelPriv *priv = self->priv; 
    549         gboolean doit = FALSE; 
    550  
    551         if (priv->initialized) 
    552         { 
    553                 g_mutex_lock (priv->conlock); 
    554                 doit = (priv->conthread == NULL); 
    555                 g_mutex_unlock (priv->conlock); 
    556         } 
    557  
    558         if (priv->initialized && !priv->background_thread_running && doit) 
    559         { 
    560                 if (priv->device && TNY_IS_DEVICE (priv->device)) 
    561                 { 
    562                         AccGoOnlineInfo *ainfo = g_slice_new (AccGoOnlineInfo); 
    563                         ainfo->info = g_slice_new (BackgroundConnectInfo); 
    564  
    565                         ainfo->info->online = tny_device_is_online (priv->device); 
    566                         ainfo->info->as_thread = TRUE; 
    567                         ainfo->info->priv = priv; 
    568  
    569                         ainfo->info->device = g_object_ref (priv->device); 
    570                         camel_object_ref (self); 
    571                         ainfo->info->user_data = self; 
    572                         ainfo->account = TNY_CAMEL_ACCOUNT (g_object_ref (account)); 
    573  
    574                         camel_session_set_online ((CamelSession *) self, TRUE);  
    575  
    576                         if (priv->account_store) 
    577                         { 
    578                                 g_signal_emit (priv->account_store, 
    579                                         tny_account_store_signals [TNY_ACCOUNT_STORE_CONNECTING_STARTED], 0); 
    580                         } 
    581  
    582                         g_mutex_lock (priv->conlock); 
    583                         if (priv->conthread) 
    584                                 g_thread_join (priv->conthread); 
    585                         priv->conthread = g_thread_create (account_go_online, ainfo, TRUE, NULL); 
    586                         g_mutex_unlock (priv->conlock); 
    587                 } 
    588         } 
    589 
     460_tny_session_camel_activate_account (TnySessionCamel *self, TnyCamelAccount *account) 
     461
     462        TnySessionCamelPriv *priv = self->priv; 
     463 
     464        g_static_rec_mutex_lock (priv->current_accounts_lock); 
     465 
     466        /* It would indeed be better to add a reference here. But then you'll 
     467         * get embraced references at some point. We'll get rid of the instance 
     468         * in the hashtable before the finalization of it, take a look at the 
     469         * unregister stuff below. */ 
     470 
     471        g_hash_table_insert (priv->current_accounts,  
     472                        g_strdup (tny_account_get_id (TNY_ACCOUNT (account))), 
     473                        account); 
     474        g_static_rec_mutex_unlock (priv->current_accounts_lock); 
     475 
     476        tny_session_queue_going_online_for_account (self, account,  
     477                tny_device_is_online (priv->device)); 
     478 
     479        return; 
     480
     481 
     482 
     483/* This happens when an account gets finalized. We more or less simply get rid 
     484 * of the instance in the hashtable. */ 
    590485 
    591486void  
    592 _tny_session_camel_forget_account (TnySessionCamel *self, TnyCamelAccount *account) 
     487_tny_session_camel_unregister_account (TnySessionCamel *self, TnyCamelAccount *account) 
    593488{ 
    594489        TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account); 
     
    599494        apriv->cache_location = NULL; 
    600495 
    601         priv->current_accounts = g_list_remove (priv->current_accounts, account); 
    602  
    603         return; 
    604 
    605  
    606  
    607  
    608  
    609 static gpointer  
    610 background_connect_thread (gpointer data) 
    611 
    612         BackgroundConnectInfo *info = data; 
    613         TnySessionCamel *self = info->user_data; 
    614         TnySessionCamelPriv *priv = self->priv; 
    615  
    616         if (priv->background_thread_running) { 
    617                 g_thread_exit (NULL); 
    618                 return NULL; 
    619         } 
    620  
    621         priv->background_thread_running = TRUE; 
    622  
    623         if (priv->stop_now)  
    624                 goto stop_now; 
    625  
    626         priv->is_connecting = TRUE; 
    627  
    628         if (priv->current_accounts && priv->prev_constat != info->online && priv->account_store)  
    629         { 
    630                 GList *copy = priv->current_accounts; 
    631                 while (copy) 
    632                 { 
    633                         if (priv->stop_now)  
    634                                 goto stop_now; 
    635                         foreach_account_set_connectivity (copy->data, info); 
    636                         if (priv->stop_now)  
    637                                 goto stop_now; 
    638                         copy = g_list_next (copy); 
    639                 } 
    640         } 
    641  
    642 stop_now: 
    643  
    644         priv->is_connecting = FALSE; 
    645  
    646         g_idle_add_full (G_PRIORITY_HIGH,  
    647                 background_connect_idle,  
    648                 info, background_connect_destroy); 
    649  
    650         priv->prev_constat = info->online; 
    651  
    652         priv->conthread = NULL; 
    653         priv->background_thread_running = FALSE; 
    654  
    655         priv->stop_now = FALSE; 
    656  
    657         g_thread_exit (NULL); 
    658         return NULL; 
    659 
    660  
    661 static gboolean 
    662 do_background_connect_thread (gpointer data) 
    663 
    664         BackgroundConnectInfo *info = data; 
    665         TnySessionCamel *self = info->user_data; 
    666         TnySessionCamelPriv *priv = self->priv; 
    667  
    668         /* g_mutex_lock (info->priv->conlock); */ 
    669         info->priv->conthread = g_thread_create (background_connect_thread, data, TRUE, NULL); 
    670         /* g_mutex_unlock (info->priv->conlock); */ 
    671  
    672         return FALSE; 
    673 
     496        g_static_rec_mutex_lock (priv->current_accounts_lock); 
     497        g_hash_table_remove (priv->current_accounts,  
     498                tny_account_get_id (TNY_ACCOUNT (account))); 
     499        g_static_rec_mutex_unlock (priv->current_accounts_lock); 
     500 
     501        return; 
     502
     503 
     504typedef struct { 
     505        TnySessionCamel *self; 
     506        gboolean online; 
     507} ConChangedForEachInfo; 
     508 
     509static void  
     510tny_session_camel_connection_changed_for_each (gpointer key, gpointer value, gpointer user_data) 
     511
     512        ConChangedForEachInfo *info = (ConChangedForEachInfo *) user_data; 
     513 
     514        /* For each registered account, we'll set its online state. Throwing it 
     515         * in its queue is implemented in the TnyCamelStoreAccount btw. For now, 
     516         * because it's shared with the account registration, this is a wrapper */ 
     517 
     518        tny_session_queue_going_online_for_account (info->self,  
     519                TNY_CAMEL_ACCOUNT (value), info->online); 
     520 
     521        return; 
     522
     523 
     524/* In case our TnyDevice's connection_changed event happened. We'll set all 
     525 * registered accounts to the proper online state here. Because these accounts 
     526 * all register their connecting on their own queue, it's not detectable when 
     527 * connecting got finished. They also all start doing their connecting stuff 
     528 * in parallel. Quite difficult to know when all are finished with that.  
     529 * 
     530 * In stead we provide components, like the TnyGtkFolderStoreTreeModel, that can 
     531 * cope with connection changes. For example: they'll load-in new folders as  
     532 * soon as it's known that the account went online. No more accounts-reloaded 
     533 * things as it's far more fine grained this way ... */ 
    674534 
    675535static void 
     
    678538        TnySessionCamel *self = user_data; 
    679539        TnySessionCamelPriv *priv = self->priv; 
    680         BackgroundConnectInfo *info; 
    681         gboolean inf; 
    682  
    683         inf = priv->in_auth_function; 
    684         if (inf) return; 
    685  
    686         info = g_slice_new (BackgroundConnectInfo); 
    687  
    688         info->device = g_object_ref (G_OBJECT (device)); 
     540        ConChangedForEachInfo *info = NULL; 
     541 
     542 
     543        /* Maybe we can remove this check after Rob is finished with throwing   
     544         * the questions in the GMainLoop. I'm leaving it here for now ... */ 
     545 
     546        if (priv->in_auth_function) 
     547                return; 
     548 
     549        info = g_slice_new (ConChangedForEachInfo); 
     550 
    689551        info->online = online; 
    690         info->user_data = user_data; 
    691         info->priv = priv; 
     552        info->self = self; 
     553 
     554 
     555        /* This Camel API exists, I haven't yet figured out what exactly it does 
     556         * or change in terms of behaviour. */ 
    692557 
    693558        camel_session_set_online ((CamelSession *) self, online);  
    694559 
     560 
     561        /* As said, we can issue this signal. We can't issue when connecting  
     562         * actually finished: that's because all accounts register getting  
     563         * connected on their own queues. So it'll all happen in parallel and 
     564         * a little bit less in control as when we would dedicate a thread to it, 
     565         * and in a serialized way get all accounts connected (the old way) */ 
     566 
    695567        if (priv->account_store) 
    696         { 
    697568                g_signal_emit (priv->account_store, 
    698569                        tny_account_store_signals [TNY_ACCOUNT_STORE_CONNECTING_STARTED], 0); 
    699         } 
    700  
    701  
    702         if (priv->async_connect)  
    703         { 
    704                 gboolean doit = FALSE; 
    705  
    706                 info->as_thread = TRUE; 
    707  
    708                 if (!priv->conthread) 
    709                         do_background_connect_thread (info); 
    710  
    711         } else { 
    712                 info->as_thread = FALSE; 
    713                 background_connect_thread (info); 
    714         } 
    715  
    716         return; 
    717 
    718  
    719 /** 
    720  * tny_session_camel_join_connecting 
    721  * @self: a #TnySessionCamel object 
    722  *  
    723  * Join the connection thread 
    724  **/  
    725 void  
    726 tny_session_camel_join_connecting (TnySessionCamel *self) 
    727 
    728         TnySessionCamelPriv *priv = self->priv; 
    729  
    730         g_mutex_lock (priv->conlock); 
    731         if (priv->conthread) 
    732                 g_thread_join (priv->conthread); 
    733         g_mutex_unlock (priv->conlock); 
    734 
     570 
     571        g_static_rec_mutex_lock (priv->current_accounts_lock); 
     572        /* So let's look above, at that for_each function ... */ 
     573        g_hash_table_foreach (priv->current_accounts,  
     574                tny_session_camel_connection_changed_for_each, info); 
     575        g_static_rec_mutex_unlock (priv->current_accounts_lock); 
     576 
     577        g_slice_free (ConChangedForEachInfo, info); 
     578 
     579        return; 
     580
     581 
    735582 
    736583/** 
     
    738585 * @self: the #TnySessionCamel instance 
    739586 * 
    740  * This method must be called one the initial accounts are created in your 
    741  * #TnyAccountStore implementation. 
     587 * This method must be called once the initial accounts are created in your 
     588 * #TnyAccountStore implementation and should indicate that the initialization 
     589 * of your initial accounts is completed. 
    742590 **/ 
    743591void  
     
    789637        } 
    790638 
     639        /* TNY TODO: proper reference counting here please */ 
    791640        priv->device = device; 
    792641 
     
    883732        TnySessionCamelPriv *priv = self->priv; 
    884733 
     734        g_static_rec_mutex_lock (priv->current_accounts_lock); 
     735        g_hash_table_destroy (priv->current_accounts); 
     736        g_static_rec_mutex_unlock (priv->current_accounts_lock); 
     737 
    885738        g_mutex_lock (priv->queue_lock); 
    886739        g_list_free (priv->regged_queues); 
     
    900753                g_free (priv->camel_dir); 
    901754 
    902         g_mutex_free (priv->conlock); 
    903755        g_mutex_free (priv->queue_lock); 
     756        g_static_rec_mutex_free (priv->current_accounts_lock); 
    904757 
    905758        g_slice_free (TnySessionCamelPriv, self->priv); 
  • devel/pvanhoof/sessionwork/libtinymail-camel/tny-session-camel.h

    r2444 r2509  
    5252void tny_session_camel_set_device (TnySessionCamel *self, TnyDevice *device); 
    5353void tny_session_camel_set_ui_locker (TnySessionCamel *self, TnyLockable *ui_lock); 
    54 void tny_session_camel_join_connecting (TnySessionCamel *self); 
    55 void tny_session_camel_set_async_connecting (TnySessionCamel *self, gboolean enable); 
    5654 
    5755void tny_session_camel_set_initialized (TnySessionCamel *self); 
  • devel/pvanhoof/sessionwork/libtinymail-gnome-desktop/tny-gnome-account-store.c

    r2444 r2509  
    154154        gchar *ptr = strrchr (key, '/'); ptr++; 
    155155 
    156  
    157156        if (!strcmp (ptr, "count")) 
    158         { 
    159157                kill_stored_accounts (priv); 
    160                 g_signal_emit (self,  
    161                         tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED], 0); 
    162         } 
    163158 
    164159        g_free (key); 
     
    490485} 
    491486 
    492 /** 
    493  * tny_gnome_account_store_add_store_account: 
    494  * @self: a #TnyGnomeAccountStore instance 
    495  * @account: a #TnyStoreAccount instance to add 
    496  *  
    497  * Add @account to @self 
    498  **/ 
    499 void 
    500 tny_gnome_account_store_add_store_account (TnyGnomeAccountStore *self, TnyStoreAccount *account) 
    501 { 
    502         tny_gnome_account_store_notify_remove (TNY_ACCOUNT_STORE (self)); 
    503         tny_gnome_account_store_add_account (TNY_ACCOUNT_STORE (self), TNY_ACCOUNT (account), "store"); 
    504         tny_gnome_account_store_notify_add (TNY_ACCOUNT_STORE (self)); 
    505  
    506         g_signal_emit (self, tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_INSERTED], 0, account); 
    507  
    508         return; 
    509 } 
    510  
    511 /** 
    512  * tny_gnome_account_store_add_transport_account: 
    513  * @self: a #TnyGnomeAccountStore instance 
    514  * @account: a #TnyTransportAccount instance to add 
    515  *  
    516  * Add @account to @self 
    517  **/ 
    518 void 
    519 tny_gnome_account_store_add_transport_account (TnyGnomeAccountStore *self, TnyTransportAccount *account) 
    520 { 
    521         tny_gnome_account_store_notify_remove (TNY_ACCOUNT_STORE (self)); 
    522         tny_gnome_account_store_add_account (TNY_ACCOUNT_STORE (self), TNY_ACCOUNT (account), "transport"); 
    523         tny_gnome_account_store_notify_add (TNY_ACCOUNT_STORE (self)); 
    524  
    525         g_signal_emit (self, tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_INSERTED], 0, account); 
    526  
    527         return; 
    528 } 
    529487 
    530488static TnyDevice* 
  • devel/pvanhoof/sessionwork/libtinymail-gnome-desktop/tny-gnome-account-store.h

    r1855 r2509  
    5353TnySessionCamel* tny_gnome_account_store_get_session (TnyGnomeAccountStore *self); 
    5454 
    55 void tny_gnome_account_store_add_store_account (TnyGnomeAccountStore *self, TnyStoreAccount *account); 
    56 void tny_gnome_account_store_add_transport_account (TnyGnomeAccountStore *self, TnyTransportAccount *account); 
    5755 
    5856G_END_DECLS 
  • devel/pvanhoof/sessionwork/libtinymail/tny-account-store.c

    r2444 r2509  
    375375        { 
    376376/** 
    377  * TnyAccountStore::account-changed 
    378  * @self: the object on which the signal is emitted 
    379  * @arg1: the #TnyAccount of the account that changed 
    380  * @user_data: user data set when the signal handler was connected 
    381  * 
    382  * API WARNING: This API might change 
    383  * 
    384  * Emitted when an account in the store changed 
    385  */ 
    386                 tny_account_store_signals[TNY_ACCOUNT_STORE_ACCOUNT_CHANGED] = 
    387                    g_signal_new ("account_changed", 
    388                         TNY_TYPE_ACCOUNT_STORE, 
    389                         G_SIGNAL_RUN_FIRST, 
    390                         G_STRUCT_OFFSET (TnyAccountStoreIface, account_changed), 
    391                         NULL, NULL, 
    392                         g_cclosure_marshal_VOID__POINTER, 
    393                         G_TYPE_NONE, 1, TNY_TYPE_ACCOUNT); 
    394  
    395 /** 
    396  * TnyAccountStore::account-inserted 
    397  * @self: the object on which the signal is emitted 
    398  * @arg1: the #TnyAccount of the account that got inserted 
    399  * @user_data: user data set when the signal handler was connected. 
    400  * 
    401  * API WARNING: This API might change 
    402  * 
    403  * Emitted when an account is added to the store 
    404  */ 
    405                 tny_account_store_signals[TNY_ACCOUNT_STORE_ACCOUNT_INSERTED] = 
    406                    g_signal_new ("account_inserted", 
    407                         TNY_TYPE_ACCOUNT_STORE, 
    408                         G_SIGNAL_RUN_FIRST, 
    409                         G_STRUCT_OFFSET (TnyAccountStoreIface, account_inserted), 
    410                         NULL, NULL, 
    411                         g_cclosure_marshal_VOID__POINTER, 
    412                         G_TYPE_NONE, 1, TNY_TYPE_ACCOUNT); 
    413  
    414 /** 
    415  * TnyAccountStore::account-removed 
    416  * @self: the object on which the signal is emitted 
    417  * @arg1: the #TnyAccount of the account that got removed 
    418  * @user_data: user data set when the signal handler was connected. 
    419  * 
    420  * API WARNING: This API might change 
    421  * 
    422  * Emitted when an account is removed from the store 
    423  */ 
    424                 tny_account_store_signals[TNY_ACCOUNT_STORE_ACCOUNT_REMOVED] = 
    425                    g_signal_new ("account_removed", 
    426                         TNY_TYPE_ACCOUNT_STORE, 
    427                         G_SIGNAL_RUN_FIRST, 
    428                         G_STRUCT_OFFSET (TnyAccountStoreIface, account_removed), 
    429                         NULL, NULL, 
    430                         g_cclosure_marshal_VOID__POINTER, 
    431                         G_TYPE_NONE, 1, TNY_TYPE_ACCOUNT); 
    432  
    433 /** 
    434  * TnyAccountStore::accounts-reloaded 
    435  * @self: the object on which the signal is emitted 
    436  * 
    437  * API WARNING: This API might change 
    438  * 
    439  * Emitted when the store reloads the accounts 
    440  */ 
    441                 tny_account_store_signals[TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED] = 
    442                    g_signal_new ("accounts_reloaded", 
    443                         TNY_TYPE_ACCOUNT_STORE, 
    444                         G_SIGNAL_RUN_FIRST, 
    445                         G_STRUCT_OFFSET (TnyAccountStoreIface, accounts_reloaded), 
    446                         NULL, NULL, 
    447                         g_cclosure_marshal_VOID__VOID, 
    448                         G_TYPE_NONE, 0); 
    449  
    450