hechengjin 发表于 2016-7-22 15:39:56

imap连接原型


nsImapIncomingServer 维护imap连接队列 和任务队列
nsImapIncomingServer

nsCOMArray<nsIImapUrl> m_urlQueue;    任务队列
nsCOMArray<nsIImapProtocol> m_connectionCache;//imap连接线程队列


GetImapConnection(nsIImapUrl * aImapUrl,..)
{
        1.从缓存中取可用连接
        connection = m_connectionCache;
        2.没有可用连接,且连接数少于最大连接数,则创建新连接
        CreateProtocolInstance(nsIImapProtocol ** aImapConnection)
        3.如果找不到可用连接,则放到队列中
        m_urlQueue.AppendObject(aImapUrl);//GetImapConnectionAndLoadUrl
}

hechengjin 发表于 2016-7-25 13:43:43


5.关于任务执行(
a.内部保持一个任务队列,下一个要执行的命令就从这里取??
b.自身可以产生新任务,且可向上层发送
c.任务支持优先级
)

6.线程根据要执行的任务分类(
a.T1(类型1):邮件同步线程,如:同步邮件头512封,下载邮件体512封,再同步邮件头512封,再下载邮件体512封.... 直到所有邮件都下载完。
邮件夹有一定的优先级,且点击的优先下,处理好中断,且从最新的邮件开始下。
新邮件的下载也放这里,注意优先级会提升
b.T2(类型2): 处理本地相关操作任务,如:已读未读星标邮件上载 邮件复制、移动等。
对于批量操作用时较长时,要细分任务粒度,且相关交互操作优先级提升
c.T3(类型3): 定时任务执行线程:如:定期更新邮件夹目录,定期同步邮件变动。
d.T4(类型4):邮件体下载线程:针对点击的邮件优先处理,如果没下载完或这个邮件比较大,又切换到读其它的邮件,直接放弃该任务,直接进行下一个任务的下载。
e.处理好相关同步,如a和d,已下载中的邮件,不要重复下载
)

问题:
1.imap连接内部会产生新任务吗?
2.多个imap连接都产生同一个新任务如何处理?
ImapThreadMainLoop
ProcessCurrentURL
ProcessSelectedStateURL   
如:
同步某邮件夹的更新的任务(ProcessMailboxUpdate),发现新邮件需要接收
FetchMessage(idsToFetch, kFlags, fetchModifier);
则直接进行这项操作

----------------
加载任务后的处理流程
NS_IMETHODIMP nsImapProtocol::LoadImapUrl(nsIURI * aURL, nsISupports * aConsumer)
{
//1.本地能处理的任务直接处理返回
if (TryToRunUrlLocally(aURL, aConsumer))
      return NS_OK;
//2.设置运行的Url
SetupWithUrl(aURL.)
        {
        m_runningUrl = do_QueryInterface(aURL, &rv);
        }
        //3.获取url的执行动作
        m_runningUrl->GetImapAction(&imapAction);
        m_needNoop = (imapAction == nsIImapUrl::nsImapSelectFolder || imapAction == nsIImapUrl::nsImapDeleteAllMsgs);
}

线程函数中处理要运行的Url
ProcessSelectedStateURL(){
        case nsIImapUrl::nsImapSelectFolder:
                ProcessMailboxUpdate(true);
}

ProcessMailboxUpdate(..)
{
        needFolderSync
        FetchMessage("1:*", kFlags);
}
FetchMessage(...)
{
        SendData(protocolString);
        ParseIMAPandCheckForNewMail(protocolString);
}
ParseIMAPandCheckForNewMail(..){
        GetServerStateParser().ParseIMAPServerResponse(commandString, aIgnoreBadAndNOResponses);
}

nsImapServerResponseParser.cpp
ParseIMAPServerResponse(..){
response_data();
}
response_data()
{
mailbox_data();
numeric_mailbox_data();
}
numeric_mailbox_data()
{
msg_fetch();
}
msg_fetch()
{
}

//下面这些操作什么时候触发
case nsIImapUrl::nsImapSaveMessageToDisk:// nsImapService::SaveMessageToDisk
      case nsIImapUrl::nsImapMsgFetch://nsImapService::GetHeaders
      case nsIImapUrl::nsImapMsgFetchPeek:
      case nsIImapUrl::nsImapMsgDownloadForOffline://上层指定要下载的邮件触发nsImapService::DownloadMessagesForOffline(const nsACString &messageIds
      case nsIImapUrl::nsImapMsgPreview:

一个自动处理离线下载的管理器
nsAutoSyncState::DownloadMessagesForOffline(nsIArray *aMessagesList)
nsAutoSyncManager::TimerCallback
{
autoSyncStateObj->ProcessExistingHeaders(kNumberOfHeadersToProcess, &leftToProcess);
}
--------------
任务的产生(粒度)
线程的分类管理

hechengjin 发表于 2016-7-25 13:45:17

nsImapIncomingServer

nsCOMArray<nsIImapUrl> m_urlQueue;    任务队列
nsCOMArray<nsIImapProtocol> m_connectionCache;//imap连接线程队列


GetImapConnection(nsIImapUrl * aImapUrl,..)
{
        1.从缓存中取可用连接
        connection = m_connectionCache;
        2.没有可用连接,且连接数少于最大连接数,则创建新连接
        CreateProtocolInstance(nsIImapProtocol ** aImapConnection)
        3.如果找不到可用连接,则放到队列中
        m_urlQueue.AppendObject(aImapUrl);//GetImapConnectionAndLoadUrl
}


获取连接以后加载执行任务
rv = aProtocol->LoadImapUrl(mailnewsurl, aConsumer);


nsImapIncomingServer调用nsIImapService为了构建nsIImapUrl,然后再转回来调用nsImapIncomingServer,然后是nsImapProtocol

---------相关难点-----
多个imap线程连接之间,如何进行分开不重复执行相关任务,
imap线程内部永远不会自动产生新任务?
不需要时移除掉此连接 imapServer->RemoveConnection(this);

可自动获取上层的任务
rv = m_imapServerSink->LoadNextQueuedUrl(this, &anotherUrlRun);

LoadImapUrl的调用
nsImapIncomingServer下
GetImapConnectionAndLoadUrl   ---- nsImapMockChannel::ReadFromImapConnectionOnCacheEntryAvailableAsyncOpen
RetryUrl
LoadNextQueuedUrl


是否可共用连接的判断 :
in selected state can only run url with matching foldername//选择状态下只能是同一邮件夹下的相关任务可以共用


//头收完后,邮件体是如何触发收取的?
HeaderFetchCompleted()
nsImapMailFolder::ParseMsgHdrs(nsIImapProtocol *aProtocol, nsIImapHeaderXferInfo *aHdrXferInfo){
}


        !nsImapProtocol::LoadImapUrl(nsIURI * aURL, nsISupports * aConsumer) 行 2205        C++
>        !nsImapIncomingServer::LoadNextQueuedUrl(nsIImapProtocol * aProtocol, bool * aResult) 行 575        C++
        !`anonymous namespace'::SyncRunnable2<nsIImapMailFolderSink,unsigned int,nsIImapUrl *>::Run() 行 147        C++   ---界面点击触发,不点不触发?



        >        !nsImapProtocol::LoadImapUrl(nsIURI * aURL, nsISupports * aConsumer) 行 2205        C++
        !nsImapIncomingServer::LoadNextQueuedUrl(nsIImapProtocol * aProtocol, bool * aResult) 行 575        C++
        !`anonymous namespace'::SyncRunnable2<nsIImapMailFolderSink,unsigned int,nsIImapUrl *>::Run() 行 147        C++//nsImapMsgDownloadForOffline = 268435506,


        nsImapMsgDownloadForOffline邮件头下载完后,调用自动同步 HeaderFetchCompleted -> nsAutoSyncState
               !nsImapService::DownloadMessagesForOffline(const nsACString & messageIds, nsIMsgFolder * aFolder, nsIUrlListener * aUrlListener, nsIMsgWindow * aMsgWindow) 行 3255        C++
        !nsAutoSyncState::DownloadMessagesForOffline(nsIArray * aMessagesList) 行 651        C++
        !nsAutoSyncManager::DownloadMessagesForOffline(nsIAutoSyncState * aAutoSyncStateObj, unsigned int aSizeLimit) 行 982        C++
        !nsAutoSyncManager::OnDownloadQChanged(nsIAutoSyncState * aAutoSyncStateObj) 行 1206        C++
        !nsAutoSyncState::PlaceIntoDownloadQ(const nsTArray<unsigned int> & aMsgKeyList) 行 154        C++
>        !nsImapMailFolder::HeaderFetchCompleted(nsIImapProtocol * aProtocol) 行 5901        C++

页: [1]
查看完整版本: imap连接原型