From 5c7b9a7466ad33f099513848ba6440355eef52aa Mon Sep 17 00:00:00 2001 From: "bryner%brianryner.com" Date: Mon, 24 Oct 2005 18:02:00 +0000 Subject: [PATCH] Keep an interface pointer to the nsISeekableStream in nsFastLoadFileReader/Writer/Updater to avoid repeated QI (bug 313575). r+sr=brendan. --- xpcom/io/nsFastLoadFile.cpp | 167 +++++++++++++++++------------------- xpcom/io/nsFastLoadFile.h | 15 ++++ 2 files changed, 93 insertions(+), 89 deletions(-) diff --git a/xpcom/io/nsFastLoadFile.cpp b/xpcom/io/nsFastLoadFile.cpp index 1f2030799e41..c75a8c28efcd 100644 --- a/xpcom/io/nsFastLoadFile.cpp +++ b/xpcom/io/nsFastLoadFile.cpp @@ -538,10 +538,9 @@ nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead) nsDocumentMapReadEntry* entry = mCurrentDocumentMapEntry; if (entry) { // Don't call our Seek wrapper, as it clears mCurrentDocumentMapEntry. - nsCOMPtr seekable(do_QueryInterface(mInputStream)); if (entry->mNeedToSeek) { - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - entry->mSaveOffset); + rv = mSeekableInput->Seek(nsISeekableStream::NS_SEEK_SET, + entry->mSaveOffset); if (NS_FAILED(rv)) return rv; @@ -559,8 +558,8 @@ nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead) if (entry->mNextSegmentOffset == 0) return NS_ERROR_UNEXPECTED; - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - entry->mNextSegmentOffset); + rv = mSeekableInput->Seek(nsISeekableStream::NS_SEEK_SET, + entry->mNextSegmentOffset); if (NS_FAILED(rv)) return rv; @@ -623,6 +622,16 @@ nsFastLoadFileReader::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, return rv; } +NS_IMETHODIMP +nsFastLoadFileReader::SetInputStream(nsIInputStream *aInputStream) +{ + nsresult rv = nsBinaryInputStream::SetInputStream(aInputStream); + mSeekableInput = do_QueryInterface(aInputStream); + NS_ASSERTION(!mInputStream || mSeekableInput, + "FastLoad requires a seekable input stream"); + return rv; +} + /** * XXX tuneme */ @@ -632,16 +641,15 @@ NS_IMETHODIMP nsFastLoadFileReader::ComputeChecksum(PRUint32 *aResult) { nsCOMPtr stream = mInputStream; + nsCOMPtr seekable = mSeekableInput; - nsCOMPtr seekable(do_QueryInterface(stream)); PRInt64 saveOffset; nsresult rv = seekable->Tell(&saveOffset); if (NS_FAILED(rv)) return rv; - nsCOMPtr bufferAccess(do_QueryInterface(stream)); - if (bufferAccess) { - rv = bufferAccess->GetUnbufferedStream(getter_AddRefs(stream)); + if (mBufferAccess) { + rv = mBufferAccess->GetUnbufferedStream(getter_AddRefs(stream)); if (NS_FAILED(rv)) return rv; @@ -932,22 +940,16 @@ nsFastLoadFileReader::ReadMuxedDocumentInfo(nsFastLoadMuxedDocumentInfo *aInfo) nsresult nsFastLoadFileReader::Open() { - nsCOMPtr seekable(do_QueryInterface(mInputStream)); - if (!seekable) - return NS_ERROR_UNEXPECTED; - nsresult rv; // Don't bother buffering the header, as we immediately seek to EOF. - nsCOMPtr - bufferAccess(do_QueryInterface(mInputStream)); - if (bufferAccess) - bufferAccess->DisableBuffering(); + if (mBufferAccess) + mBufferAccess->DisableBuffering(); rv = ReadHeader(&mHeader); - if (bufferAccess) - bufferAccess->EnableBuffering(); + if (mBufferAccess) + mBufferAccess->EnableBuffering(); if (NS_FAILED(rv)) return rv; @@ -956,12 +958,12 @@ nsFastLoadFileReader::Open() if (mHeader.mFooterOffset == 0) return NS_ERROR_UNEXPECTED; - rv = seekable->Seek(nsISeekableStream::NS_SEEK_END, 0); + rv = mSeekableInput->Seek(nsISeekableStream::NS_SEEK_END, 0); if (NS_FAILED(rv)) return rv; PRInt64 fileSize; - rv = seekable->Tell(&fileSize); + rv = mSeekableInput->Tell(&fileSize); if (NS_FAILED(rv)) return rv; @@ -971,8 +973,8 @@ nsFastLoadFileReader::Open() if ((PRUint32) fileSize64 != mHeader.mFileSize) return NS_ERROR_UNEXPECTED; - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - PRInt32(mHeader.mFooterOffset)); + rv = mSeekableInput->Seek(nsISeekableStream::NS_SEEK_SET, + PRInt32(mHeader.mFooterOffset)); if (NS_FAILED(rv)) return rv; @@ -980,8 +982,8 @@ nsFastLoadFileReader::Open() if (NS_FAILED(rv)) return rv; - return seekable->Seek(nsISeekableStream::NS_SEEK_SET, - sizeof(nsFastLoadHeader)); + return mSeekableInput->Seek(nsISeekableStream::NS_SEEK_SET, + sizeof(nsFastLoadHeader)); } NS_IMETHODIMP @@ -1063,11 +1065,10 @@ nsFastLoadFileReader::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject) // Check whether we've already deserialized the object for this OID. object = entry->mReadObject; if (!object) { - nsCOMPtr seekable(do_QueryInterface(mInputStream)); PRInt64 saveOffset; nsDocumentMapReadEntry* saveDocMapEntry = nsnull; - rv = seekable->Tell(&saveOffset); + rv = mSeekableInput->Tell(&saveOffset); if (NS_FAILED(rv)) return rv; @@ -1087,8 +1088,8 @@ nsFastLoadFileReader::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject) // or more multiplexed documents in the FastLoad file. saveDocMapEntry = mCurrentDocumentMapEntry; mCurrentDocumentMapEntry = nsnull; - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - entry->mCIDOffset); + rv = mSeekableInput->Seek(nsISeekableStream::NS_SEEK_SET, + entry->mCIDOffset); if (NS_FAILED(rv)) return rv; } @@ -1100,14 +1101,15 @@ nsFastLoadFileReader::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject) if (entry->mCIDOffset != saveOffset32) { // Save the "skip offset" in case we need to skip this object // definition when reading forward, later on. - rv = seekable->Tell(&entry->mSkipOffset); + rv = mSeekableInput->Tell(&entry->mSkipOffset); if (NS_FAILED(rv)) return rv; // Restore stream offset and mCurrentDocumentMapEntry in case // we're still reading forward through a part of the multiplex // to get object definitions eagerly. - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset); + rv = mSeekableInput->Seek(nsISeekableStream::NS_SEEK_SET, + saveOffset); if (NS_FAILED(rv)) return rv; mCurrentDocumentMapEntry = saveDocMapEntry; @@ -1122,10 +1124,8 @@ nsFastLoadFileReader::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject) // We must skip over the object definition. if (oid & MFL_OBJECT_DEF_TAG) { NS_ASSERTION(entry->mSkipOffset != 0, "impossible! see above"); - nsCOMPtr - seekable(do_QueryInterface(mInputStream)); - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - entry->mSkipOffset); + rv = mSeekableInput->Seek(nsISeekableStream::NS_SEEK_SET, + entry->mSkipOffset); if (NS_FAILED(rv)) return rv; } @@ -1181,22 +1181,19 @@ NS_IMETHODIMP nsFastLoadFileReader::Seek(PRInt32 aWhence, PRInt64 aOffset) { mCurrentDocumentMapEntry = nsnull; - nsCOMPtr seekable(do_QueryInterface(mInputStream)); - return seekable->Seek(aWhence, aOffset); + return mSeekableInput->Seek(aWhence, aOffset); } NS_IMETHODIMP nsFastLoadFileReader::Tell(PRInt64 *aResult) { - nsCOMPtr seekable(do_QueryInterface(mInputStream)); - return seekable->Tell(aResult); + return mSeekableInput->Tell(aResult); } NS_IMETHODIMP nsFastLoadFileReader::SetEOF() { - nsCOMPtr seekable(do_QueryInterface(mInputStream)); - return seekable->SetEOF(); + return mSeekableInput->SetEOF(); } NS_COM nsresult @@ -1436,13 +1433,10 @@ NS_IMETHODIMP nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI, nsISupports** aResult) { - // Avoid repeatedly QI'ing to nsISeekableStream as we tell and seek. - nsCOMPtr seekable(do_QueryInterface(mOutputStream)); - // Capture the current file offset (XXXbe maintain our own via Write?) nsresult rv; PRInt64 currentSegmentOffset; - rv = seekable->Tell(¤tSegmentOffset); + rv = mSeekableOutput->Tell(¤tSegmentOffset); if (NS_FAILED(rv)) return rv; @@ -1491,8 +1485,8 @@ nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI, TRACE_MUX(('w', "select prev %s offset %lu\n", prevDocMapEntry->mString, prevSegmentOffset)); - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - prevSegmentOffset + 4); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, + prevSegmentOffset + 4); if (NS_FAILED(rv)) return rv; @@ -1506,8 +1500,8 @@ nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI, // back to *this* entry's last "current" segment offset and write its // next segment offset at the first PRUint32 of the segment. if (!docMapEntry->mInitialSegmentOffset) { - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - currentSegmentOffset); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, + currentSegmentOffset); if (NS_FAILED(rv)) return rv; } @@ -1519,8 +1513,8 @@ nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI, if (!docMapEntry->mInitialSegmentOffset) { docMapEntry->mInitialSegmentOffset = currentSegmentOffset32; } else { - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - docMapEntry->mCurrentSegmentOffset); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, + docMapEntry->mCurrentSegmentOffset); if (NS_FAILED(rv)) return rv; @@ -1528,8 +1522,8 @@ nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI, if (NS_FAILED(rv)) return rv; - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - currentSegmentOffset); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, + currentSegmentOffset); if (NS_FAILED(rv)) return rv; } @@ -1918,14 +1912,10 @@ nsFastLoadFileWriter::Init() nsresult nsFastLoadFileWriter::Open() { - nsCOMPtr seekable(do_QueryInterface(mOutputStream)); - if (!seekable) - return NS_ERROR_UNEXPECTED; - nsresult rv; - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - sizeof(nsFastLoadHeader)); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, + sizeof(nsFastLoadHeader)); if (NS_FAILED(rv)) return rv; @@ -1941,10 +1931,8 @@ nsFastLoadFileWriter::Close() mHeader.mChecksum = 0; mHeader.mVersion = MFL_FILE_VERSION; - nsCOMPtr seekable(do_QueryInterface(mOutputStream)); - PRInt64 footerOffset; - rv = seekable->Tell(&footerOffset); + rv = mSeekableOutput->Tell(&footerOffset); LL_L2UI(mHeader.mFooterOffset, footerOffset); if (NS_FAILED(rv)) @@ -1955,8 +1943,8 @@ nsFastLoadFileWriter::Close() if (mCurrentDocumentMapEntry) { PRUint32 currentSegmentOffset = mCurrentDocumentMapEntry->mCurrentSegmentOffset; - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - currentSegmentOffset + 4); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, + currentSegmentOffset + 4); if (NS_FAILED(rv)) return rv; @@ -1965,8 +1953,8 @@ nsFastLoadFileWriter::Close() return rv; // Seek back to the current offset to write the footer. - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - mHeader.mFooterOffset); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, + mHeader.mFooterOffset); if (NS_FAILED(rv)) return rv; @@ -1977,12 +1965,12 @@ nsFastLoadFileWriter::Close() if (NS_FAILED(rv)) return rv; PRInt64 fileSize; - rv = seekable->Tell(&fileSize); + rv = mSeekableOutput->Tell(&fileSize); LL_L2UI(mHeader.mFileSize, fileSize); if (NS_FAILED(rv)) return rv; - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, 0); if (NS_FAILED(rv)) return rv; @@ -1996,10 +1984,8 @@ nsFastLoadFileWriter::Close() // Get the unbuffered output stream, which flushes the buffered header // so we can read and checksum it along with the rest of the file, and // which allows us to write the checksum directly. - nsCOMPtr - bufferAccess(do_QueryInterface(mOutputStream)); nsCOMPtr output; - rv = bufferAccess->GetUnbufferedStream(getter_AddRefs(output)); + rv = mBufferAccess->GetUnbufferedStream(getter_AddRefs(output)); if (NS_FAILED(rv) || !output) return NS_ERROR_UNEXPECTED; @@ -2011,14 +1997,15 @@ nsFastLoadFileWriter::Close() // Get the unbuffered input stream, to avoid copying overhead and to // keep our view of the file coherent with the writer -- we don't want // to hit a stale buffer in the reader's underlying stream. - bufferAccess = do_QueryInterface(input); + nsCOMPtr bufferAccess = + do_QueryInterface(input); rv = bufferAccess->GetUnbufferedStream(getter_AddRefs(input)); if (NS_FAILED(rv) || !input) return NS_ERROR_UNEXPECTED; // Seek the input stream to offset 0, in case it's a reader who has // already been used to consume some of the FastLoad file. - seekable = do_QueryInterface(input); + nsCOMPtr seekable = do_QueryInterface(input); rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); if (NS_FAILED(rv)) return rv; @@ -2280,22 +2267,27 @@ NS_IMETHODIMP nsFastLoadFileWriter::Seek(PRInt32 aWhence, PRInt64 aOffset) { mCurrentDocumentMapEntry = nsnull; - nsCOMPtr seekable(do_QueryInterface(mOutputStream)); - return seekable->Seek(aWhence, aOffset); + return mSeekableOutput->Seek(aWhence, aOffset); } NS_IMETHODIMP nsFastLoadFileWriter::Tell(PRInt64 *aResult) { - nsCOMPtr seekable(do_QueryInterface(mOutputStream)); - return seekable->Tell(aResult); + return mSeekableOutput->Tell(aResult); } NS_IMETHODIMP nsFastLoadFileWriter::SetEOF() { - nsCOMPtr seekable(do_QueryInterface(mOutputStream)); - return seekable->SetEOF(); + return mSeekableOutput->SetEOF(); +} + +NS_IMETHODIMP +nsFastLoadFileWriter::SetOutputStream(nsIOutputStream *aStream) +{ + nsresult rv = nsBinaryOutputStream::SetOutputStream(aStream); + mSeekableOutput = do_QueryInterface(mOutputStream); + return rv; } NS_COM nsresult @@ -2376,10 +2368,6 @@ nsFastLoadFileUpdater::CopyReadDocumentMapEntryToUpdater(PLDHashTable *aTable, nsresult nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader) { - nsCOMPtr seekable(do_QueryInterface(mOutputStream)); - if (!seekable) - return NS_ERROR_UNEXPECTED; - nsresult rv; rv = nsFastLoadFileWriter::Init(); if (NS_FAILED(rv)) @@ -2406,7 +2394,7 @@ nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader) // Prepare to save aReader state in case we need to seek back and read a // singleton object that might otherwise get written by this updater. nsDocumentMapReadEntry* saveDocMapEntry = nsnull; - nsCOMPtr inputSeekable; + nsISeekableStream* inputSeekable = nsnull; PRInt64 saveOffset = 0; for (i = 0, n = aReader->mFooter.mNumSharpObjects; i < n; i++) { @@ -2424,7 +2412,7 @@ nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader) nsISupports* obj = readEntry->mReadObject; if (!obj && MFL_GET_SINGLETON_FLAG(readEntry)) { if (!saveDocMapEntry) { - inputSeekable = do_QueryInterface(aReader->mInputStream); + inputSeekable = aReader->mSeekableInput; rv = inputSeekable->Tell(&saveOffset); if (NS_FAILED(rv)) return rv; @@ -2525,8 +2513,8 @@ nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader) // update the header to have a zero mFooterOffset, which will invalidate // the FastLoad file on next startup read attempt, should we crash before // completing this update. - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - offsetof(nsFastLoadHeader, mFooterOffset)); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, + offsetof(nsFastLoadHeader, mFooterOffset)); if (NS_FAILED(rv)) return rv; @@ -2534,8 +2522,8 @@ nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader) if (NS_FAILED(rv)) return rv; - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - aReader->mHeader.mFooterOffset); + rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, + aReader->mHeader.mFooterOffset); if (NS_FAILED(rv)) return rv; @@ -2545,6 +2533,7 @@ nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader) // that we override Close to break the resulting zero-length cycle. mFileIO = this; mInputStream = aReader->mInputStream; + mSeekableInput = aReader->mSeekableInput; return NS_OK; } diff --git a/xpcom/io/nsFastLoadFile.h b/xpcom/io/nsFastLoadFile.h index 9f6f061a473c..c1b41fc1573c 100644 --- a/xpcom/io/nsFastLoadFile.h +++ b/xpcom/io/nsFastLoadFile.h @@ -296,6 +296,9 @@ class nsFastLoadFileReader NS_IMETHODIMP ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, PRUint32 aCount, PRUint32 *aResult); + // Override SetInputStream so we can update mSeekableInput + NS_IMETHOD SetInputStream(nsIInputStream* aInputStream); + nsresult ReadHeader(nsFastLoadHeader *aHeader); /** @@ -384,6 +387,9 @@ class nsFastLoadFileReader NS_IMETHOD Close(); protected: + // Kept in sync with mInputStream to avoid repeated QI + nsCOMPtr mSeekableInput; + nsFastLoadHeader mHeader; nsFastLoadFooter mFooter; @@ -446,6 +452,9 @@ class nsFastLoadFileWriter PRBool aIsStrongRef); NS_IMETHOD WriteID(const nsID& aID); + // Override SetOutputStream so we can update mSeekableOutput + NS_IMETHOD SetOutputStream(nsIOutputStream* aOutputStream); + // nsIFastLoadFileControl methods NS_DECL_NSIFASTLOADFILECONTROL @@ -498,6 +507,9 @@ class nsFastLoadFileWriter void *aData); protected: + // Kept in sync with mOutputStream to avoid repeated QI + nsCOMPtr mSeekableOutput; + nsFastLoadHeader mHeader; PLDHashTable mIDMap; @@ -556,6 +568,9 @@ class nsFastLoadFileUpdater protected: nsCOMPtr mInputStream; + + // Kept in sync with mInputStream to avoid repeated QI + nsCOMPtr mSeekableInput; }; NS_COM nsresult