Closed
Bug 495304
Opened 15 years ago
Closed 15 years ago
gloda mimemsg fails if asked to stream same set of messages twice, synchronously
Categories
(MailNews Core :: MIME, defect)
MailNews Core
MIME
Tracking
(Not tracked)
RESOLVED
FIXED
Thunderbird 3.0b3
People
(Reporter: davida, Assigned: Bienvenu)
References
(Blocks 1 open bug)
Details
Attachments
(2 files)
7.26 KB,
patch
|
asuth
:
review+
standard8
:
superreview+
|
Details | Diff | Splinter Review |
4.86 KB,
patch
|
asuth
:
review+
standard8
:
superreview+
|
Details | Diff | Splinter Review |
Andrew's noticed that the JS mime streaming code sometimes fails inexplicably. I guess I should be happy that I now have STRs. Specifically, with the recent thread-summary view, if one deletes the message _before_ a collapsed thread by e.g. hitting the delete key (or archive will work), then the thread summary code is (correctly) called, but that code will cause the JS mime emitter to stream all of the messages in the thread pretty much simultaneously. At least on my mac, it's very easy to get it to fail to stream at least one if not all messages in a thread. The UX symptoms are that the snippets and tags aren't displayed in the thread summary. The high-level code problem is that the MsgHdrToMimeMessage() call ends up being called with a "blank" MimeMessage object as argument. NOTE: selecting a thread by clicking on the collapsed thread in the threadpane _never_ seems to cause this problem. Only selection that happens as a result of getting rid of whatever the existing selection currently is causes the failure. I'll let asuth comment about his suspicions as to where in the mime handling the problem is.
Flags: blocking-thunderbird3+
Reporter | ||
Comment 1•15 years ago
|
||
Additional note: this happens w/ local folders as well, so it's not IMAP specific.
Updated•15 years ago
|
Assignee | ||
Comment 2•15 years ago
|
||
this makes summarizeSelection return a boolean indicating if the commandUpdater did summarize the selection - if so, nsMsgDBView::SelectionChanged knows it doesn't have to load the selected message.
Assignee: nobody → bienvenu
Attachment #380506 -
Flags: superreview?(bugzilla)
Attachment #380506 -
Flags: review?(bugmail)
Assignee | ||
Comment 3•15 years ago
|
||
at this point, all the failures I'm seeing have to do with compaction of local folders changing the message key and causing getMessageCollectionForHeaders to exclude the headers we pass to it.
Comment 4•15 years ago
|
||
Comment on attachment 380506 [details] [diff] [review] don't load collapsed message - checked in. This also lets summarizeSelection otherwise co-opt the message display process. Muah hah ha!
Attachment #380506 -
Flags: review?(bugmail) → review+
Reporter | ||
Comment 5•15 years ago
|
||
Hmm, even w/ this, I'm not having reliable summary update in the scenario described in comment #0 on imap folders. It's _better_, no doubt, but not yet 100%. That said, that's testing w/ a patched up version of the folder sumary code, so it might all be my code breakage.
Assignee | ||
Comment 6•15 years ago
|
||
Hmm, it's hard for me to tell because of the compact folder issue which messages actually have snippets. This will fix the marking read of the first message when you land on a collapsed thread, however.
Reporter | ||
Comment 7•15 years ago
|
||
The last patch (https://bugzilla.mozilla.org/attachment.cgi?id=380861) on bug 454829 should make tracking this bug down easier.
Updated•15 years ago
|
Attachment #380506 -
Flags: superreview?(bugzilla) → superreview+
Assignee | ||
Updated•15 years ago
|
Attachment #380506 -
Attachment description: don't load collapsed message → don't load collapsed message - checked in.
Assignee | ||
Comment 8•15 years ago
|
||
I'm running with that patch - I'm seeing that we're streaming all the messages, but, I suspect never getting called back from gloda. So I'll add back my dump statements and see where things are going awry.
Assignee | ||
Comment 9•15 years ago
|
||
we're getting ondataavailable calls from the mailbox message code - I suspect we're losing things somewhere between there and the js mime emitter...
Assignee | ||
Comment 10•15 years ago
|
||
I believe the problem is that we're trying to stream the set of collapsed messages twice, in the case of deleting a message and landing on a collapsed thread. I think that confuses the jsmime emitter because it uses the url spec as an array index...
Assignee | ||
Comment 11•15 years ago
|
||
so yeah, we're generating two selection changed notifications, which means two calls to summarizeSelection, in the case of deleting a message and landing on a collapsed thread.
Assignee | ||
Comment 12•15 years ago
|
||
I've updated the summary - the issue is that mimemsg deletes the msg in RESULT_RENDEVOUZ and streaming the same set of messages twice doesn't work well because of it. But we don't want to be streaming the same set of messages twice anyway so I should fix that.
Summary: mime streaming fails if hit just the right way → gloda mimemsg fails if asked to stream same set of messages twice, synchronously
Comment 13•15 years ago
|
||
Does "fix that" = do not stream the message twice? It's fairly likely the mimemsg.js/jsmimeemitter.js logic will strike again. Actions that make sense to me, from worst to best: - Just throw an exception. This is likely to at least produce some error message before breaking code in ways it is unlikely to be prepared for. - Don't use the sketchy and poorly spelled RESULT_RENDEVOUZ. Unfortunately, I saw no good way to stash our MimeMsg on a per-URI basis when I originally wrote that. The downside to this is it's very redundant. - If we are trying to stream something we are already streaming, just add the extra callback to a list of callbacks rather than kicking off a new stream, so that everyone can benefit from the result. This would be sort-of like a caching mechanism, in the event that various extensions all hook off message display change and all want the message. (We could also potentially implement a weak-ref based caching mechanism, but that seems like overkill when we would instead want to just provide a more extension-friendly mechanism so the case never arises.)
Assignee | ||
Comment 14•15 years ago
|
||
I don't think the summarizeSelection code should do all that work twice, even if it did work. So perhaps we should try to fix both issues. The other thing is that the other code that gets snippets (e.g., the new mail alert) sticks the snippet in the msg hdr in the .msf file, as the "preview" property so that we don't have to recalculate it all the time. I'm wondering if we should do the same thing for these snippets. If I click on a thread with a couple megabyte messages, we're going to stream the whole message in order to get the first 200 bytes using MsgHdrToMimeMessage. Or stick the preview text in the sqlite db...
Comment 15•15 years ago
|
||
Right, I agree that summarizeSelection should stop doing things twice. But we should also deal with the deficiency in the mimemsg API/implementation. Using the preview property sounds like the right solution for the 200 character case. If people start getting concerned about disk space, maybe compaction could strip those properties. One complicating factor is that the connotent implementation supports pluggable whittlers, so there is the issue of staleness. For example, the gp-bugzilla plugin will get rid of the bugzilla e-mail cruft to show only the user's comments, and if it is installed after some things are stashed as properties, stale values will result. I think the benefit of potentially not pegging the user's system far exceeds the wacky behavior on that front or additional implementation complexity of dealing with it, though. Gloda already stashes the full body text (with quoting removal) of the message in the SQLite db, as it must do to use the FTS3 engine. The issues are that not all messages are gloda indexed, we only want to access that on the async thread, and the gloda queries try and build up the full object model which results in multiple rounds of queries.
Assignee | ||
Comment 16•15 years ago
|
||
(In reply to comment #15) > Right, I agree that summarizeSelection should stop doing things twice. But we > should also deal with the deficiency in the mimemsg API/implementation. I'm working on the latter now - my head was getting woozy from trying to figure out how to do the former. I also tried to figure out how to avoid having selectionChanged getting called twice, but there are so many edge cases with selection. > > Using the preview property sounds like the right solution for the 200 character case. I can add that while I'm in here. > If people start getting concerned about disk space, maybe compaction > could strip those properties. That's a thought. Or maybe we want some sort of disk pressure scheme similar to the memory pressure scheme that gecko uses.
Comment 17•15 years ago
|
||
(In reply to comment #16) > (In reply to comment #15) > > Right, I agree that summarizeSelection should stop doing things twice. But we > > should also deal with the deficiency in the mimemsg API/implementation. > > I'm working on the latter now - my head was getting woozy from trying to figure > out how to do the former. I also tried to figure out how to avoid having > selectionChanged getting called twice, but there are so many edge cases with > selection. Yes, selection is a nightmare. However, I have enough abstractions in bug 474701 that in theory it may just be easier to deal with the problem there. It is trivial for it to only re-notify the summarizer when the selection actually changes. For example: // sorta-pseudo-code to go in the summarizeSelect() notification from the dbview: if (gFolderDisplay.selectedIndices().toString() != summarizedIndices.toString()) { goSummarize(); summarizedIndices = gFolderDisplay.selectedIndices(); } However, if someone could explain/point me at an explanation of why the double events are generated in the first place, that would make that even easier. I think I've seen it around but do now know where it went.
Assignee | ||
Comment 18•15 years ago
|
||
(In reply to comment #17) > is trivial for it to only re-notify the summarizer when the selection actually > changes. For example: > > // sorta-pseudo-code to go in the summarizeSelect() notification from the > dbview: > if (gFolderDisplay.selectedIndices().toString() != > summarizedIndices.toString()) { > goSummarize(); > summarizedIndices = gFolderDisplay.selectedIndices(); > } If I delete a collapsed thread, we'll generate a the exact same selected indices again, as everything moves up a row to replace the deleted thread row. So it has to be a little more complicated :-) > > However, if someone could explain/point me at an explanation of why the double > events are generated in the first place, that would make that even easier. I > think I've seen it around but do now know where it went. We're both setting the selected index on the treeSelection, which generates a selectionChanged notification from inside the tree code, and for good measure, we're explicitly calling selectionChanged. The latter is perhaps because we want to generate a synthetic selectionChanged event, to force a resummarize. For example, if I expand a selected & collapsed thread, we want to have selectionChanged called, even though the selected index hasn't changed (not that that's what's going on in this case, but there are a number of places where selectionChanged calls have been sprinkled like pixie dust, including one that says "don't worry [be happy!] it's cheap if we end up calling it twice" :-)
Assignee | ||
Comment 19•15 years ago
|
||
turns the callback and callbackThis into arrays, and activeListeners into an object/associative array, and handles duplicate stream requests by adding callback to existing stream listener, and send the notifications to all the listener. Apologies if I've done something silly!
Attachment #381419 -
Flags: superreview?(bugzilla)
Attachment #381419 -
Flags: review?(bugmail)
Comment 20•15 years ago
|
||
Comment on attachment 381419 [details] [diff] [review] proposed fix >diff --git a/mailnews/db/gloda/modules/mimemsg.js b/mailnews/db/gloda/modules/mimemsg.js > onStopRequest: function (aRequest, aContext, aStatusCode) { ... >+ for (let i = 0; i < this._callbacksThis.length; i++) >+ if (this._callbacksThis[i]) >+ this._callbacks[i].call(this._callbacksThis[i], this._msgHdr, message); >+ else >+ this._callbacks[i].call(null, this._msgHdr, message); nit: indentation but also, since this._callbackThis[i] will be null, you can just reduce it to the first case and lose the if and the else clause, so it just becomes: this._callbacks[i].call(this._callbacksThis[i], this._msgHdr, message); > function MsgHdrToMimeMessage(aMsgHdr, aCallbackThis, aCallback) { > shutdownCleanupObserver.ensureInitialized(); > > let msgURI = aMsgHdr.folder.getUriForMsg(aMsgHdr); > let msgService = gMessenger.messageServiceFromURI(msgURI); > >+ // if we're already streaming this msg, just add the callback >+ // to the listener. >+ let listenerForURI = activeStreamListeners[msgURI]; >+ if (listenerForURI != undefined) { >+ listenerForURI._callbacks.push(aCallback); >+ listenerForURI._callbacksThis.push(aCallbackThis); >+ return; >+ } Because of the wacky variable-argument idiom, this can go wrong. I'm not opposed to bailing on it, but otherwise change those to: listenerForURI._callbacks.push(aCallback ? aCallback : aCallbackThis); listenerForURI._callbacksThis.push(aCallback ? aCallbackThis : null); r=asuth with suggested changes made.
Attachment #381419 -
Flags: review?(bugmail) → review+
Assignee | ||
Comment 21•15 years ago
|
||
fix checked in, with suggested changes made.
Status: NEW → RESOLVED
Closed: 15 years ago
Resolution: --- → FIXED
Comment 22•15 years ago
|
||
Comment on attachment 381419 [details] [diff] [review] proposed fix sr=Standard8, although it appears you've already checked this in ;-)
Attachment #381419 -
Flags: superreview?(bugzilla) → superreview+
Updated•15 years ago
|
Target Milestone: --- → Thunderbird 3.0b3
Assignee | ||
Comment 23•15 years ago
|
||
ack, sorry...guess I was so excited to fix a gloda bug that I jumped the gun ;-)
Comment 24•15 years ago
|
||
Don't worry, there's more than enough to go around... ;)
You need to log in
before you can comment on or make changes to this bug.
Description
•