Lately, I refreshed comm-central thunderbird code
and tested my local modification to enable buffering of writing
downloaded message to a local mail store.

(This is about when one uses POP3. Please bear this in mind.
Imap testing is further along.)

I noticed a couple of things:

(1) File API semantic change? : unexpected file pointer position.

First, this could be my mixup of refreshing the source tree
and merging the local modification to create a new set of hg patches,
but has there been a change to file-handling function code so that
a newly opened file's seek position (or file pointer to write or read
for the next operation in other words) be placed at the beginning (i.e.,
0 offset) even if the said file existed and has non-zero value and the
intention is to append?
I didn't write the original code, so am unsure, but the intention was to
append to the file. I don't think I touched that part of the code.

It seems to me that the file pointer was at the end of the file for
writing to Berkely style mbox-format Inbox (so we append to it)
previously before the refresh of source tree.
But after the refresh, I realized it is no longer positioned at the end,
but at 0-th offset, and so a call to |Seek()| before appending is now
indeed necessary.

I have been attempting to remove a call to |seek()| in a busy loop to
write to the Inbox: I don't think this |seek()| is needed.
[1]
The offending |Seek()| nullifies our attempt to write to Inbox with
buffering. This slows down I/O.

After a couple of months testing and debugging on and off, even
monitoring the checking of the file positions before and after |seek|,
I thought I can remove the offending |seek()| safely at least from my
limited testing.

Well what about other people's environment?
Screwing up one's mailbox is something that needs to be avoided at all cost.

Based on the suggestion of aceman, I was about to upload a proposed
patch for Beta to test that it is true that we can remove the |seek()|
and still be safe in other people's environment: the patch is meant to
check that the |seek()| has no effect, i.e., the file pointer position
does not change before and after the offending |seek()|. There are a few
preferences that can change the behavior of TB and so I wanted to make
sure. Once we know for sure that it is safe to remove |Seek()|, I intend
to upload the final patch to remove the |Seek()|.

Above slight change in the file pointer position after opening
mbox-style Inbox, I now need to insert a |Seek| once after we begin
writing to it. Just once.

All is well now.

But I am curious if anyone is aware of such file API change.
I tried to read through the changes to M-C tree for the last week, but
it was long and I could not figure out if the change is in the last week
or not. Thus I have to ask experts here.


(2)  This is more like C++ semantic issue and the way XPCOM is built.

(After I wrote down the following, I found out from system trace, that
maybe my change does not buffer the writing to temporary file still :-(.
I will follow up when the dust settles.)

With a user preference setting of "mailnews.downloadToTempFile" to true,
thunderbird mail client can be taught to download a POP3 message
first to a temporary file and close it, and then
read the content of this file and append it to mbox-style Inbox.

I think this is meant to deal with arcane very spartan anti-virus
software that would REMOVE/QUARANTINE a file when a virus or malware is
detected. If you receive a spam e-mail with malware, and your whole
Inbox is removed/quarantined, it is a disaster.

I think today's AV software is more benign and handle the situation more
elegantly (I don't know the details.)

Although "mailnews.downloadToTempFile" does not even exist by default,
and you need to manually set it to test the feature,
the code path to handle this feature DOES exist, and I
needed to test the path in my quest for better I/O error handling in
TB.[2][3][4][5].

When I enabled buffering of writing to a local file during
downloading as in [1], and the local file is temporary (by setting
mailnews.downloadToTempFile to true), I hit a snug.

There is a code in the "mailnews.downloadToTempFile is true"  path.
http://mxr.mozilla.org/comm-central/source/mailnews/local/src/nsPop3Sink.cpp#787


*   787       nsCOMPtr <nsIInputStream> inboxInputStream =
do_QueryInterface(m_outFileStream);
    788       rv = MsgReopenFileStream(m_tmpDownloadFile, inboxInputStream);

Before, as in the current release, m_outFileStream is not buffered.
And the code on line 787 produces non-null inboxInputStream.

However, once m_outFileStream is turned into a buffered output stream
using, say,

  m_outFileStream = NS_BufferOutputStream(m_outFileStream, 64 * 1024 );

the code on line 787 produces nullptr.

Is this to be expected?

Up until now, I thought of do_QueryInterface() as mere sugar-coating for
certain type-mutation or something. But I now know I am wrong.

I read a page about do_QueryInterface() but it does not
explain the principle very much.

Is the reason of failure something like as follows.
I am using a very general class hierarchy.


     A   base class
     |
 +---+---+
 B       C     B and C are derived from base class A
         |
       --+--+
            |
            D     D is derived further from Class D.

Let's say Class B and C are derived from Class A.
Class D is further derived from Class C.
Let us assume there are corresponding XPCOM class/object A', B', C', D'.

By using do_QueryInterface() on objects,
    we can follow the path of  direct "derives" relation
         B' <= do_QueryInterface (A') (or is it the other way round?)

    and maybe between B' and C' (? Not sure about this.)

    but we can NOT follow the direction of
      B' <= do_QueryInterface (D')
    That is
       X = do_QeuryInterface(Y) is possible only when X is the direct or
indirect  descendant of Y?

Thank you for clarification.

It is a pity that the original authors of nsPop3*.{cpp,h} code
did not define a derived class that would make it possible to execute
the following code successfully
  nsCOMPtr <this_derived_class> inboxInputStream =
do_QueryInterface(m_outFileStream);

and also prepare the file APIs that accept |this_derived_class| in the
position of |nsIInputFile|.

TIA

CI

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1116055
Bug 1116055 - Performance issue: Failure to use buffered write
(comm-central thunderbird)
[2] Bug 1121842 [META] RFC: C-C Thunderbird - Cleaning of incorrect
Close, unchecked Flush, Write etc. in nsPop3Sink.cpp and friends.
[3] Bug 1122698 C-C Thunderbird - Cleaning of incorrect Close, unchecked
Flush, Write etc. in nsPop3Sink.cpp and friends. (Step-1)       2015-04-08
[4] Bug 1134527 C-C Thunderbird - Cleaning of incorrect Close, unchecked
Flush, Write etc. in nsPop3Sink.cpp and friends. (Step-2)
[5] Bug 1134529 C-C Thunderbird - Cleaning of incorrect Close, unchecked
Flush, Write etc. in nsPop3Sink.cpp and friends. (Step-3)
[6]Bug 1159777 - Strange Failure of inboxInputStream =
do_QueryInterface(m_outFileStream) in nsPop3Sink.cpp

_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to