fix 90452 threading by subject slow when threads are very large, sr=mscott, a=bsmedberg

This commit is contained in:
bienvenu%nventure.com 2005-07-28 14:21:11 +00:00
Родитель d8d22d4dfd
Коммит 279b803590
1 изменённых файлов: 51 добавлений и 37 удалений

Просмотреть файл

@ -290,54 +290,68 @@ NS_IMETHODIMP nsMsgThread::AddChild(nsIMsgDBHdr *child, nsIMsgDBHdr *inReplyTo,
PRBool hdrMoved = PR_FALSE; PRBool hdrMoved = PR_FALSE;
nsCOMPtr <nsIMsgDBHdr> curHdr; nsCOMPtr <nsIMsgDBHdr> curHdr;
for (childIndex = 0; childIndex < numChildren; childIndex++)
// This is an ugly but simple fix for a difficult problem. Basically, when we add
// a message to a thread, we have to run through the thread to see if the new
// message is a parent of an existing message in the thread, and adjust things
// accordingly. If you thread by subject, and you have a large folder with
// messages w/ all the same subject, this code can take a really long time. So the
// pragmatic thing is to say that for threads with more than 1000 messages, it's
// simply not worth dealing with the case where the parent comes in after the
// child. Threads with more than 1000 messages are pretty unwieldy anyway.
// See Bug 90452
if (numChildren < 1000)
{ {
nsMsgKey msgKey; for (childIndex = 0; childIndex < numChildren; childIndex++)
ret = GetChildHdrAt(childIndex, getter_AddRefs(curHdr));
if (NS_SUCCEEDED(ret) && curHdr)
{ {
if (hdr->IsParentOf(curHdr)) nsMsgKey msgKey;
ret = GetChildHdrAt(childIndex, getter_AddRefs(curHdr));
if (NS_SUCCEEDED(ret) && curHdr)
{ {
nsMsgKey oldThreadParent; if (hdr->IsParentOf(curHdr))
mdb_pos outPos;
// move this hdr before the current header.
if (!hdrMoved)
{ {
m_mdbTable->MoveRow(m_mdbDB->GetEnv(), hdrRow, -1, childIndex, &outPos); nsMsgKey oldThreadParent;
hdrMoved = PR_TRUE; mdb_pos outPos;
curHdr->GetThreadParent(&oldThreadParent); // move this hdr before the current header.
curHdr->GetMessageKey(&msgKey); if (!hdrMoved)
nsCOMPtr <nsIMsgDBHdr> curParent;
m_mdbDB->GetMsgHdrForKey(oldThreadParent, getter_AddRefs(curParent));
if (curParent && hdr->IsAncestorOf(curParent))
{ {
nsMsgKey curParentKey; m_mdbTable->MoveRow(m_mdbDB->GetEnv(), hdrRow, -1, childIndex, &outPos);
curParent->GetMessageKey(&curParentKey); hdrMoved = PR_TRUE;
if (curParentKey == m_threadRootKey) curHdr->GetThreadParent(&oldThreadParent);
curHdr->GetMessageKey(&msgKey);
nsCOMPtr <nsIMsgDBHdr> curParent;
m_mdbDB->GetMsgHdrForKey(oldThreadParent, getter_AddRefs(curParent));
if (curParent && hdr->IsAncestorOf(curParent))
{ {
m_mdbTable->MoveRow(m_mdbDB->GetEnv(), hdrRow, -1, 0, &outPos); nsMsgKey curParentKey;
RerootThread(child, curParent, announcer); curParent->GetMessageKey(&curParentKey);
if (curParentKey == m_threadRootKey)
{
m_mdbTable->MoveRow(m_mdbDB->GetEnv(), hdrRow, -1, 0, &outPos);
RerootThread(child, curParent, announcer);
parentKeyNeedsSetting = PR_FALSE;
}
}
else if (msgKey == m_threadRootKey)
{
RerootThread(child, curHdr, announcer);
parentKeyNeedsSetting = PR_FALSE; parentKeyNeedsSetting = PR_FALSE;
} }
} }
else if (msgKey == m_threadRootKey) curHdr->SetThreadParent(newHdrKey);
{ if (msgKey == newHdrKey)
RerootThread(child, curHdr, announcer);
parentKeyNeedsSetting = PR_FALSE; parentKeyNeedsSetting = PR_FALSE;
}
}
curHdr->SetThreadParent(newHdrKey);
if (msgKey == newHdrKey)
parentKeyNeedsSetting = PR_FALSE;
// OK, this is a reparenting - need to send notification // OK, this is a reparenting - need to send notification
if (announcer) if (announcer)
announcer->NotifyParentChangedAll(msgKey, oldThreadParent, newHdrKey, nsnull); announcer->NotifyParentChangedAll(msgKey, oldThreadParent, newHdrKey, nsnull);
#ifdef DEBUG_bienvenu1 #ifdef DEBUG_bienvenu1
if (newHdrKey != m_threadKey) if (newHdrKey != m_threadKey)
printf("adding second level child\n"); printf("adding second level child\n");
#endif #endif
}
} }
} }
} }