diff --git a/chrome/src/nsChromeProtocolHandler.cpp b/chrome/src/nsChromeProtocolHandler.cpp index 7df3fa80603..ac88986e8f1 100644 --- a/chrome/src/nsChromeProtocolHandler.cpp +++ b/chrome/src/nsChromeProtocolHandler.cpp @@ -52,7 +52,6 @@ #include "nsIChannel.h" #include "nsIChromeRegistry.h" #include "nsIComponentManager.h" -#include "nsIFastLoadService.h" #include "nsIFile.h" #include "nsIFileURL.h" #include "nsIFileChannel.h" diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index 8c08d5e0532..0d9daf33fc2 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -151,7 +151,6 @@ MOZ_URL_CLASSIFIER = @MOZ_URL_CLASSIFIER@ MOZ_ZIPWRITER = @MOZ_ZIPWRITER@ MOZ_MORK = @MOZ_MORK@ MOZ_MORKREADER = @MOZ_MORKREADER@ -MOZ_NO_FAST_LOAD = @MOZ_NO_FAST_LOAD@ MOZ_OGG = @MOZ_OGG@ MOZ_RAW = @MOZ_RAW@ MOZ_SYDNEYAUDIO = @MOZ_SYDNEYAUDIO@ diff --git a/configure.in b/configure.in index 9341a9e3521..ad5b398317a 100644 --- a/configure.in +++ b/configure.in @@ -4768,7 +4768,6 @@ MOZ_MORK= MOZ_MORKREADER=1 MOZ_AUTH_EXTENSION=1 MOZ_NO_ACTIVEX_SUPPORT=1 -MOZ_NO_FAST_LOAD= MOZ_OGG=1 MOZ_RAW= MOZ_SYDNEYAUDIO= @@ -5723,21 +5722,6 @@ if test "$NS_PRINTING"; then AC_DEFINE(NS_PRINT_PREVIEW) fi -dnl ======================================================== -dnl = Disable Fast Load -dnl ======================================================== -MOZ_ARG_DISABLE_BOOL(xpcom-fastload, -[ --disable-xpcom-fastload - Disable XPCOM fastload support], - MOZ_NO_FAST_LOAD=1, - MOZ_NO_FAST_LOAD=) - -AC_SUBST(MOZ_NO_FAST_LOAD) - -if test -n "$MOZ_NO_FAST_LOAD"; then - AC_DEFINE(MOZ_NO_FAST_LOAD) -fi - dnl ======================================================== dnl = Enable Raw Codecs dnl ======================================================== diff --git a/content/xul/document/src/nsXULPrototypeCache.cpp b/content/xul/document/src/nsXULPrototypeCache.cpp index 1bdfdccad4c..3302ffa545e 100644 --- a/content/xul/document/src/nsXULPrototypeCache.cpp +++ b/content/xul/document/src/nsXULPrototypeCache.cpp @@ -50,8 +50,6 @@ #include "nsIURI.h" #include "nsIChromeRegistry.h" -#include "nsIFastLoadService.h" -#include "nsIFastLoadFileControl.h" #include "nsIFile.h" #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" diff --git a/js/src/xpconnect/loader/mozJSComponentLoader.h b/js/src/xpconnect/loader/mozJSComponentLoader.h index b86e77b0c60..77d4ae5f485 100644 --- a/js/src/xpconnect/loader/mozJSComponentLoader.h +++ b/js/src/xpconnect/loader/mozJSComponentLoader.h @@ -46,7 +46,6 @@ #include "nsIXPConnect.h" #include "nsIFile.h" #include "nsAutoPtr.h" -#include "nsIFastLoadService.h" #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" #include "nsITimer.h" @@ -68,28 +67,6 @@ using namespace mozilla::scache; { 0xbb, 0xef, 0xf0, 0xcc, 0xb5, 0xfa, 0x64, 0xb6 }} #define MOZJSCOMPONENTLOADER_CONTRACTID "@mozilla.org/moz/jsloader;1" -// nsIFastLoadFileIO implementation for component fastload -class nsXPCFastLoadIO : public nsIFastLoadFileIO -{ - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIFASTLOADFILEIO - - nsXPCFastLoadIO(nsIFile *file) : mFile(file), mTruncateOutputFile(true) {} - - void SetInputStream(nsIInputStream *stream) { mInputStream = stream; } - void SetOutputStream(nsIOutputStream *stream) { mOutputStream = stream; } - - private: - ~nsXPCFastLoadIO() {} - - nsCOMPtr mFile; - nsCOMPtr mInputStream; - nsCOMPtr mOutputStream; - bool mTruncateOutputFile; -}; - - class mozJSComponentLoader : public mozilla::ModuleLoader, public xpcIJSModuleLoader, public nsIObserver diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index a63545dfa3c..90b217dff15 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -93,7 +93,6 @@ using mozilla::dom::ContentParent; #include "nsIContentHandler.h" #include "nsIDialogParamBlock.h" #include "nsIDOMWindow.h" -#include "nsIFastLoadService.h" // for PLATFORM_FASL_SUFFIX #include "mozilla/ModuleUtils.h" #include "nsIIOService2.h" #include "nsIObserverService.h" @@ -2289,6 +2288,12 @@ static void RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfi if (!file) return; +#if defined(XP_UNIX) || defined(XP_BEOS) +#define PLATFORM_FASL_SUFFIX ".mfasl" +#elif defined(XP_WIN) || defined(XP_OS2) +#define PLATFORM_FASL_SUFFIX ".mfl" +#endif + file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX)); file->Remove(PR_FALSE); diff --git a/xpcom/build/XPCOM.h b/xpcom/build/XPCOM.h index 15b28f333f9..a434ca5268e 100644 --- a/xpcom/build/XPCOM.h +++ b/xpcom/build/XPCOM.h @@ -74,8 +74,6 @@ #include "nsIException.h" #include "nsIExceptionService.h" #include "nsIFactory.h" -#include "nsIFastLoadFileControl.h" -#include "nsIFastLoadService.h" #include "nsIFile.h" #include "nsIHashable.h" #include "nsIINIParser.h" diff --git a/xpcom/build/XPCOMModule.inc b/xpcom/build/XPCOMModule.inc index f4330c871b2..5de259fca16 100644 --- a/xpcom/build/XPCOMModule.inc +++ b/xpcom/build/XPCOMModule.inc @@ -64,10 +64,6 @@ COMPONENT(STRINGINPUTSTREAM, nsStringInputStreamConstructor) COMPONENT(MULTIPLEXINPUTSTREAM, nsMultiplexInputStreamConstructor) -#ifndef MOZ_NO_FAST_LOAD - COMPONENT(FASTLOADSERVICE, nsFastLoadService::Create) -#endif - COMPONENT(VARIANT, nsVariantConstructor) COMPONENT(INTERFACEINFOMANAGER_SERVICE, nsXPTIInterfaceInfoManagerGetSingleton) diff --git a/xpcom/build/nsXPComInit.cpp b/xpcom/build/nsXPComInit.cpp index 7a8198a5aad..fa94943af20 100644 --- a/xpcom/build/nsXPComInit.cpp +++ b/xpcom/build/nsXPComInit.cpp @@ -107,8 +107,6 @@ #include "nsStringStream.h" extern nsresult nsStringInputStreamConstructor(nsISupports *, REFNSIID, void **); -#include "nsFastLoadService.h" - #include "nsAtomService.h" #include "nsAtomTable.h" #include "nsTraceRefcnt.h" diff --git a/xpcom/io/Makefile.in b/xpcom/io/Makefile.in index 442697828ab..94b364efcbb 100644 --- a/xpcom/io/Makefile.in +++ b/xpcom/io/Makefile.in @@ -85,13 +85,6 @@ CMMSRCS += \ $(NULL) endif -ifndef MOZ_NO_FAST_LOAD -CPPSRCS += \ - nsFastLoadFile.cpp \ - nsFastLoadService.cpp \ - $(NULL) -endif - ifeq ($(MOZ_WIDGET_TOOLKIT),os2) CPPSRCS += nsLocalFileOS2.cpp else @@ -107,7 +100,6 @@ EXPORTS = \ nsDirectoryService.h \ nsDirectoryServiceAtomList.h \ nsEscape.h \ - nsFastLoadService.h \ nsLinebreakConverter.h \ nsLocalFile.h \ nsMultiplexInputStream.h \ @@ -138,8 +130,6 @@ XPIDLSRCS = \ nsIBinaryInputStream.idl \ nsIBinaryOutputStream.idl \ nsIDirectoryEnumerator.idl \ - nsIFastLoadFileControl.idl \ - nsIFastLoadService.idl \ nsIInputStreamTee.idl \ nsILocalFileWin.idl \ nsILineInputStream.idl \ diff --git a/xpcom/io/nsFastLoadFile.cpp b/xpcom/io/nsFastLoadFile.cpp deleted file mode 100644 index 4f3882eff2b..00000000000 --- a/xpcom/io/nsFastLoadFile.cpp +++ /dev/null @@ -1,2489 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla FastLoad code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brendan Eich (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include -#include "prtypes.h" -#include "nsAlgorithm.h" -#include "nscore.h" -#include "nsDebug.h" -#include "nsEnumeratorUtils.h" -#include "nsMemory.h" -#include "nsXPIDLString.h" -#include "nsString.h" -#include "nsReadableUtils.h" - -#include "nsIComponentManager.h" -#include "nsIFile.h" -#include "nsILocalFile.h" -#include "nsISeekableStream.h" -#include "nsISerializable.h" -#include "nsIStreamBufferAccess.h" -#include "nsIClassInfo.h" - -#include "nsBinaryStream.h" -#include "nsFastLoadFile.h" -#ifdef XP_UNIX -#include -#endif - -#ifdef DEBUG_brendan -# define METERING -# define DEBUG_MUX -#endif - -#ifdef METERING -# define METER(x) x -#else -# define METER(x) /* nothing */ -#endif - -#ifdef DEBUG_MUX -# include -# include - -static void trace_mux(char mode, const char *format, ...) -{ - va_list ap; - static FILE *tfp; - if (!tfp) { - char tfn[16]; - sprintf(tfn, "/tmp/mux.%ctrace", mode); - tfp = fopen(tfn, "w"); - if (!tfp) - return; - setvbuf(tfp, NULL, _IOLBF, 0); - } - va_start(ap, format); - vfprintf(tfp, format, ap); - va_end(ap); -} - -# define TRACE_MUX(args) trace_mux args -#else -# define TRACE_MUX(args) /* nothing */ -#endif - -/* - * Fletcher's 16-bit checksum, using 32-bit two's-complement arithmetic. - */ -#define FOLD_ONES_COMPLEMENT_CARRY(X) ((X) = ((X) & 0xffff) + ((X) >> 16)) -#define ONES_COMPLEMENT_ACCUMULATE(X,Y) (X) += (Y); if ((X) & 0x80000000) \ - FOLD_ONES_COMPLEMENT_CARRY(X) -#define FLETCHER_ACCUMULATE(A,B,U) ONES_COMPLEMENT_ACCUMULATE(A, U); \ - ONES_COMPLEMENT_ACCUMULATE(B, A) - -PRUint32 -NS_AccumulateFastLoadChecksum(PRUint32 *aChecksum, - const PRUint8* aBuffer, - PRUint32 aLength, - PRBool aLastBuffer) -{ - PRUint32 C = *aChecksum; - PRUint32 A = C & 0xffff; - PRUint32 B = C >> 16; - - PRUint16 U = 0; - if (aLength >= 4) { - PRBool odd = PRWord(aBuffer) & 1; - switch (PRWord(aBuffer) & 3) { - case 3: - U = (aBuffer[0] << 8) | aBuffer[1]; - FLETCHER_ACCUMULATE(A, B, U); - U = aBuffer[2]; - aBuffer += 3; - aLength -= 3; - break; - - case 2: - U = (aBuffer[0] << 8) | aBuffer[1]; - FLETCHER_ACCUMULATE(A, B, U); - U = 0; - aBuffer += 2; - aLength -= 2; - break; - - case 1: - U = *aBuffer++; - aLength--; - break; - } - - PRUint32 W; - if (odd) { - while (aLength > 3) { - W = *reinterpret_cast(aBuffer); - U <<= 8; -#ifdef IS_BIG_ENDIAN - U |= W >> 24; - FLETCHER_ACCUMULATE(A, B, U); - U = PRUint16(W >> 8); - FLETCHER_ACCUMULATE(A, B, U); - U = W & 0xff; -#else - U |= W & 0xff; - FLETCHER_ACCUMULATE(A, B, U); - U = PRUint16(W >> 8); - U = NS_SWAP16(U); - FLETCHER_ACCUMULATE(A, B, U); - U = W >> 24; -#endif - aBuffer += 4; - aLength -= 4; - } - aBuffer--; // we're odd, we didn't checksum the last byte - aLength++; - } else { - while (aLength > 3) { - W = *reinterpret_cast(aBuffer); -#ifdef IS_BIG_ENDIAN - U = W >> 16; - FLETCHER_ACCUMULATE(A, B, U); - U = PRUint16(W); - FLETCHER_ACCUMULATE(A, B, U); -#else - U = NS_SWAP16(W); - FLETCHER_ACCUMULATE(A, B, U); - U = W >> 16; - U = NS_SWAP16(W); - FLETCHER_ACCUMULATE(A, B, U); -#endif - aBuffer += 4; - aLength -= 4; - } - } - } - - if (aLastBuffer) { - NS_ASSERTION(aLength <= 4, "aLength botch"); - switch (aLength) { - case 4: - U = (aBuffer[0] << 8) | aBuffer[1]; - FLETCHER_ACCUMULATE(A, B, U); - U = (aBuffer[2] << 8) | aBuffer[3]; - FLETCHER_ACCUMULATE(A, B, U); - break; - - case 3: - U = (aBuffer[0] << 8) | aBuffer[1]; - FLETCHER_ACCUMULATE(A, B, U); - U = aBuffer[2]; - FLETCHER_ACCUMULATE(A, B, U); - break; - - case 2: - U = (aBuffer[0] << 8) | aBuffer[1]; - FLETCHER_ACCUMULATE(A, B, U); - break; - - case 1: - U = aBuffer[0]; - FLETCHER_ACCUMULATE(A, B, U); - break; - } - - aLength = 0; - } - - while (A >> 16) - FOLD_ONES_COMPLEMENT_CARRY(A); - while (B >> 16) - FOLD_ONES_COMPLEMENT_CARRY(B); - - *aChecksum = (B << 16) | A; - return aLength; -} - -PRUint32 -NS_AddFastLoadChecksums(PRUint32 sum1, PRUint32 sum2, PRUint32 sum2ByteCount) -{ - PRUint32 A1 = sum1 & 0xffff; - PRUint32 B1 = sum1 >> 16; - - PRUint32 A2 = sum2 & 0xffff; - PRUint32 B2 = sum2 >> 16; - - PRUint32 A = A1 + A2; - while (A >> 16) - FOLD_ONES_COMPLEMENT_CARRY(A); - - PRUint32 B = B2; - for (PRUint32 n = (sum2ByteCount + 1) / 2; n != 0; n--) - ONES_COMPLEMENT_ACCUMULATE(B, B1); - while (B >> 16) - FOLD_ONES_COMPLEMENT_CARRY(B); - - return (B << 16) | A; -} - -#undef FOLD_ONES_COMPLEMENT_CARRY -#undef ONES_COMPLEMENT_ACCUMULATE -#undef FLETCHER_ACCUMULATE - -static const char magic[] = MFL_FILE_MAGIC; - -// -------------------------- nsFastLoadFileReader -------------------------- - -nsID nsFastLoadFileReader::nsFastLoadFooter::gDummyID; -nsFastLoadFileReader::nsObjectMapEntry - nsFastLoadFileReader::nsFastLoadFooter::gDummySharpObjectEntry; - -NS_IMPL_ISUPPORTS_INHERITED5(nsFastLoadFileReader, - nsBinaryInputStream, - nsIObjectInputStream, - nsIFastLoadFileControl, - nsIFastLoadReadControl, - nsISeekableStream, - nsIFastLoadFileReader) - -nsresult -nsFastLoadFileReader::ReadHeader(nsFastLoadHeader *aHeader) -{ - nsresult rv; - PRUint32 bytesRead; - - rv = Read(reinterpret_cast(aHeader), sizeof *aHeader, &bytesRead); - if (NS_FAILED(rv)) - return rv; - - if (bytesRead != sizeof *aHeader || - memcmp(aHeader->mMagic, magic, MFL_FILE_MAGIC_SIZE)) { - return NS_ERROR_UNEXPECTED; - } - - aHeader->mChecksum = NS_SWAP32(aHeader->mChecksum); - aHeader->mVersion = NS_SWAP32(aHeader->mVersion); - aHeader->mFooterOffset = NS_SWAP32(aHeader->mFooterOffset); - aHeader->mFileSize = NS_SWAP32(aHeader->mFileSize); - - return NS_OK; -} - -// nsIFastLoadFileControl methods: - -NS_IMETHODIMP -nsFastLoadFileReader::GetChecksum(PRUint32 *aChecksum) -{ - *aChecksum = mHeader.mChecksum; - return NS_OK; -} - -struct nsStringMapEntry : public PLDHashEntryHdr { - const char* mString; // key, must come first - nsISupports* mURI; // for SelectMuxedDocument return value -}; - -struct nsDocumentMapEntry : public nsStringMapEntry { - PRUint32 mInitialSegmentOffset; // offset of URI's first segment in file -}; - -struct nsDocumentMapReadEntry : public nsDocumentMapEntry { - PRUint32 mNextSegmentOffset; // offset of URI's next segment to read - PRUint32 mBytesLeft : 31, // bytes remaining in current segment - mNeedToSeek : 1; // flag to defer Seek from Select to - // Read, in case there is no Read before - // another entry is Selected (to improve - // input stream buffer utilization) - PRInt64 mSaveOffset; // in case demux schedule differs from - // mux schedule -}; - -static void -strmap_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr) -{ - nsStringMapEntry* entry = static_cast(aHdr); - - if (entry->mString) - nsMemory::Free((void*) entry->mString); - NS_IF_RELEASE(entry->mURI); - PL_DHashClearEntryStub(aTable, aHdr); -} - -static const PLDHashTableOps strmap_DHashTableOps = { - PL_DHashAllocTable, - PL_DHashFreeTable, - PL_DHashStringKey, - PL_DHashMatchStringKey, - PL_DHashMoveEntryStub, - strmap_ClearEntry, - PL_DHashFinalizeStub, - NULL -}; - -// An nsObjectMapEntry holds a strong reference to an XPCOM object, unless the -// mObject member, when cast to NSFastLoadOID, has its MFL_OBJECT_DEF_TAG bit -// set. NB: we rely on the fact that an nsISupports* is never an odd pointer. -struct nsObjectMapEntry : public PLDHashEntryHdr { - nsISupports* mObject; // key, must come first -}; - -// Fast mapping from URI object pointer back to spec-indexed document info. -struct nsURIMapReadEntry : public nsObjectMapEntry { - nsDocumentMapReadEntry* mDocMapEntry; -}; - -static void -objmap_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr) -{ - nsObjectMapEntry* entry = static_cast(aHdr); - - // Ignore tagged object ids stored as object pointer keys (the updater - // code does this). - if ((NS_PTR_TO_INT32(entry->mObject) & MFL_OBJECT_DEF_TAG) == 0) - NS_IF_RELEASE(entry->mObject); - PL_DHashClearEntryStub(aTable, aHdr); -} - -static const PLDHashTableOps objmap_DHashTableOps = { - PL_DHashAllocTable, - PL_DHashFreeTable, - PL_DHashVoidPtrKeyStub, - PL_DHashMatchEntryStub, - PL_DHashMoveEntryStub, - objmap_ClearEntry, - PL_DHashFinalizeStub, - NULL -}; - -NS_IMETHODIMP -nsFastLoadFileReader::HasMuxedDocument(const char* aURISpec, PRBool *aResult) -{ - nsDocumentMapReadEntry* docMapEntry = - static_cast - (PL_DHashTableOperate(&mFooter.mDocumentMap, aURISpec, - PL_DHASH_LOOKUP)); - - *aResult = PL_DHASH_ENTRY_IS_BUSY(docMapEntry); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::StartMuxedDocument(nsISupports* aURI, const char* aURISpec) -{ - nsDocumentMapReadEntry* docMapEntry = - static_cast - (PL_DHashTableOperate(&mFooter.mDocumentMap, aURISpec, - PL_DHASH_LOOKUP)); - - // If the spec isn't in the map, return NS_ERROR_NOT_AVAILABLE so the - // FastLoad service can try for a file update. - if (PL_DHASH_ENTRY_IS_FREE(docMapEntry)) - return NS_ERROR_NOT_AVAILABLE; - - nsCOMPtr key(do_QueryInterface(aURI)); - nsURIMapReadEntry* uriMapEntry = - static_cast - (PL_DHashTableOperate(&mFooter.mURIMap, key, - PL_DHASH_ADD)); - if (!uriMapEntry) - return NS_ERROR_OUT_OF_MEMORY; - - NS_ASSERTION(uriMapEntry->mDocMapEntry == nsnull, - "URI mapped to two different specs?"); - if (uriMapEntry->mDocMapEntry) - return NS_ERROR_UNEXPECTED; - - docMapEntry->mURI = aURI; - NS_ADDREF(docMapEntry->mURI); - uriMapEntry->mObject = key; - NS_ADDREF(uriMapEntry->mObject); - uriMapEntry->mDocMapEntry = docMapEntry; - TRACE_MUX(('r', "start %p (%p) %s\n", aURI, key.get(), aURISpec)); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI, - nsISupports** aResult) -{ - nsresult rv; - - // Find the given URI's entry and select it for more reading. - nsCOMPtr key(do_QueryInterface(aURI)); - nsURIMapReadEntry* uriMapEntry = - static_cast - (PL_DHashTableOperate(&mFooter.mURIMap, key, - PL_DHASH_LOOKUP)); - - // If the URI isn't in the map, return NS_ERROR_NOT_AVAILABLE so the - // FastLoad service can try selecting the file updater. - if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry)) - return NS_ERROR_NOT_AVAILABLE; - - // If we're interrupting another document's segment, save its offset so - // we can seek back when it's reselected. If prevDocMapEntry->mNeedToSeek - // is set, that means the stream is not positioned for prevDocMapEntry, to - // avoid buffer thrashing. See below in this function for more. - nsDocumentMapReadEntry* prevDocMapEntry = mCurrentDocumentMapEntry; - if (prevDocMapEntry && - prevDocMapEntry->mBytesLeft && - !prevDocMapEntry->mNeedToSeek) { - rv = Tell(&prevDocMapEntry->mSaveOffset); - if (NS_FAILED(rv)) - return rv; - } - - // It turns out we get a fair amount of redundant select calls, thanks to - // non-blocking hunks of data from the parser that are devoid of scripts. - // As more data gets FastLoaded, the number of these useless selects will - // decline. - nsDocumentMapReadEntry* docMapEntry = uriMapEntry->mDocMapEntry; - if (docMapEntry == prevDocMapEntry) { - TRACE_MUX(('r', "select prev %s same as current!\n", - docMapEntry->mString)); - } - - // Invariant: docMapEntry->mBytesLeft implies docMapEntry->mSaveOffset has - // been set non-zero by the Tell call above. - else if (docMapEntry->mBytesLeft) { - NS_ASSERTION(docMapEntry->mSaveOffset != 0, - "reselecting from multiplex at unsaved offset?"); - - // Defer Seek till Read, in case of "ping-pong" Selects without any - // intervening Reads, to avoid dumping the underlying mInputStream's - // input buffer for cases where alternate "pongs" fall in the same - // buffer. - docMapEntry->mNeedToSeek = PR_TRUE; - } - - *aResult = prevDocMapEntry ? prevDocMapEntry->mURI : nsnull; - NS_IF_ADDREF(*aResult); - - mCurrentDocumentMapEntry = docMapEntry; -#ifdef DEBUG_MUX - PRInt64 currentSegmentOffset; - Tell(¤tSegmentOffset); - trace_mux('r', "select %p (%p) offset %ld\n", - aURI, key.get(), (long) currentSegmentOffset); -#endif - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::EndMuxedDocument(nsISupports* aURI) -{ - nsCOMPtr key(do_QueryInterface(aURI)); - nsURIMapReadEntry* uriMapEntry = - static_cast - (PL_DHashTableOperate(&mFooter.mURIMap, key, - PL_DHASH_LOOKUP)); - - // If the URI isn't in the map, return NS_ERROR_NOT_AVAILABLE so the - // FastLoad service can try to end a select on its file updater. - if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry)) - return NS_ERROR_NOT_AVAILABLE; - - // Drop our ref to the URI object that was passed to StartMuxedDocument, - // we no longer need it, and we do not want to extend its lifetime. - if (uriMapEntry->mDocMapEntry) - NS_RELEASE(uriMapEntry->mDocMapEntry->mURI); - - // Shrink the table if half the entries are removed sentinels. - PRUint32 size = PL_DHASH_TABLE_SIZE(&mFooter.mURIMap); - if (mFooter.mURIMap.removedCount >= (size >> 2)) - PL_DHashTableOperate(&mFooter.mURIMap, key, PL_DHASH_REMOVE); - else - PL_DHashTableRawRemove(&mFooter.mURIMap, uriMapEntry); - - TRACE_MUX(('r', "end %p (%p)\n", aURI, key.get())); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead) -{ - nsDocumentMapReadEntry* entry = mCurrentDocumentMapEntry; - if (entry) { - // Don't call our Seek wrapper, as it clears mCurrentDocumentMapEntry. - if (entry->mNeedToSeek) { - SeekTo(entry->mSaveOffset); - entry->mNeedToSeek = PR_FALSE; - } - - // Loop to handle empty segments, which may be generated by the - // writer, given Start A; Start B; Select A; Select B; write B data; - // multiplexing schedules, which do tend to occur given non-blocking - // i/o with LIFO scheduling. XXXbe investigate LIFO issues - while (entry->mBytesLeft == 0) { - // Check for unexpected end of multiplexed stream. - NS_ASSERTION(entry->mNextSegmentOffset != 0, - "document demuxed from FastLoad file more than once?"); - if (entry->mNextSegmentOffset == 0) - return NS_ERROR_UNEXPECTED; - - SeekTo(entry->mNextSegmentOffset); - // Clear mCurrentDocumentMapEntry temporarily to avoid recursion. - mCurrentDocumentMapEntry = nsnull; - - nsresult rv = Read32(&entry->mNextSegmentOffset); - if (NS_SUCCEEDED(rv)) { - PRUint32 bytesLeft = 0; - rv = Read32(&bytesLeft); - entry->mBytesLeft = bytesLeft; - } - - mCurrentDocumentMapEntry = entry; - if (NS_FAILED(rv)) - return rv; - - NS_ASSERTION(entry->mBytesLeft >= 8, "demux segment length botch!"); - entry->mBytesLeft -= 8; - } - } - if (!mFileData) - return NS_BASE_STREAM_CLOSED; - - PRUint32 count = NS_MIN(mFileLen - mFilePos, aCount); - memcpy(aBuffer, mFileData+mFilePos, count); - *aBytesRead = count; - mFilePos += count; - if (entry) { - NS_ASSERTION(entry->mBytesLeft >= *aBytesRead, "demux Read underflow!"); - entry->mBytesLeft -= *aBytesRead; - -#ifdef NS_DEBUG - // Invariant: !entry->mBytesLeft implies entry->mSaveOffset == 0. - if (entry->mBytesLeft == 0) - entry->mSaveOffset = 0; -#endif - } - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, - PRUint32 aCount, PRUint32 *aResult) -{ - nsDocumentMapReadEntry* entry = mCurrentDocumentMapEntry; - - NS_ASSERTION(!entry || (!entry->mNeedToSeek && entry->mBytesLeft != 0), - "ReadSegments called from above nsFastLoadFileReader layer?!"); - - if (!mFileData) - return NS_BASE_STREAM_CLOSED; - - PRUint32 count = NS_MIN(mFileLen - mFilePos, aCount); - - // Errors returned from the writer get ignored. - aWriter(this, aClosure, (char*)(mFileData + mFilePos), 0, - count, aResult); - mFilePos += count; - if (entry) { - NS_ASSERTION(entry->mBytesLeft >= *aResult, - "demux ReadSegments underflow!"); - entry->mBytesLeft -= *aResult; - -#ifdef NS_DEBUG - // Invariant: !entry->mBytesLeft implies entry->mSaveOffset == 0. - if (entry->mBytesLeft == 0) - entry->mSaveOffset = 0; -#endif - } - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::ComputeChecksum(PRUint32 *aResult) -{ - PRUint32 checksum = 0; - // Skip first 2 fields. - PRUint32 pos = offsetof(nsFastLoadHeader, mVersion); - NS_AccumulateFastLoadChecksum(&checksum, - mFileData + pos, - mFileLen - pos, - PR_TRUE); - *aResult = checksum; - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::GetDependencies(nsISimpleEnumerator* *aDependencies) -{ - return NS_NewArrayEnumerator(aDependencies, mFooter.mDependencies); -} - -nsresult -nsFastLoadFileReader::ReadFooter(nsFastLoadFooter *aFooter) -{ - nsresult rv; - - rv = ReadFooterPrefix(aFooter); - if (NS_FAILED(rv)) - return rv; - - aFooter->mIDMap = new nsID[aFooter->mNumIDs]; - if (!aFooter->mIDMap) - return NS_ERROR_OUT_OF_MEMORY; - - PRUint32 i, n; - for (i = 0, n = aFooter->mNumIDs; i < n; i++) { - rv = ReadSlowID(&aFooter->mIDMap[i]); - if (NS_FAILED(rv)) - return rv; - } - - aFooter->mObjectMap = new nsObjectMapEntry[aFooter->mNumSharpObjects]; - if (!aFooter->mObjectMap) - return NS_ERROR_OUT_OF_MEMORY; - - for (i = 0, n = aFooter->mNumSharpObjects; i < n; i++) { - nsObjectMapEntry* entry = &aFooter->mObjectMap[i]; - - rv = ReadSharpObjectInfo(entry); - if (NS_FAILED(rv)) - return rv; - - entry->mReadObject = nsnull; - entry->mSkipOffset = 0; - entry->mSaveStrongRefCnt = entry->mStrongRefCnt; - entry->mSaveWeakRefCnt = entry->mWeakRefCnt; - } - - if (!PL_DHashTableInit(&aFooter->mDocumentMap, &strmap_DHashTableOps, - (void *)this, sizeof(nsDocumentMapReadEntry), - aFooter->mNumMuxedDocuments)) { - aFooter->mDocumentMap.ops = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - if (!PL_DHashTableInit(&aFooter->mURIMap, &objmap_DHashTableOps, - (void *)this, sizeof(nsURIMapReadEntry), - aFooter->mNumMuxedDocuments)) { - aFooter->mURIMap.ops = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - for (i = 0, n = aFooter->mNumMuxedDocuments; i < n; i++) { - nsFastLoadMuxedDocumentInfo info; - - rv = ReadMuxedDocumentInfo(&info); - if (NS_FAILED(rv)) - return rv; - - nsDocumentMapReadEntry* entry = - static_cast - (PL_DHashTableOperate(&aFooter->mDocumentMap, - info.mURISpec, - PL_DHASH_ADD)); - if (!entry) { - nsMemory::Free((void*) info.mURISpec); - return NS_ERROR_OUT_OF_MEMORY; - } - - NS_ASSERTION(!entry->mString, "duplicate URISpec in MuxedDocumentMap"); - entry->mString = info.mURISpec; - entry->mURI = nsnull; - entry->mInitialSegmentOffset = info.mInitialSegmentOffset; - entry->mNextSegmentOffset = info.mInitialSegmentOffset; - entry->mBytesLeft = 0; - entry->mNeedToSeek = PR_FALSE; - entry->mSaveOffset = 0; - } - - nsCOMPtr readDeps; - rv = NS_NewISupportsArray(getter_AddRefs(readDeps)); - if (NS_FAILED(rv)) - return rv; - - nsCAutoString filename; - for (i = 0, n = aFooter->mNumDependencies; i < n; i++) { - rv = ReadCString(filename); - if (NS_FAILED(rv)) - return rv; - - PRInt64 fastLoadMtime; - rv = Read64(reinterpret_cast(&fastLoadMtime)); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr file; - rv = NS_NewNativeLocalFile(filename, PR_TRUE, getter_AddRefs(file)); - if (NS_FAILED(rv)) - return rv; -#ifdef DEBUG - PRInt64 currentMtime; - rv = file->GetLastModifiedTime(¤tMtime); - if (NS_FAILED(rv)) - return rv; - - if (LL_NE(fastLoadMtime, currentMtime)) { - nsCAutoString path; - file->GetNativePath(path); - printf("%s mtime changed, invalidating FastLoad file\n", - path.get()); - return NS_ERROR_FAILURE; - } -#endif - - rv = readDeps->AppendElement(file); - if (NS_FAILED(rv)) - return rv; - } - - aFooter->mDependencies = readDeps; - return NS_OK; -} - -nsresult -nsFastLoadFileReader::ReadFooterPrefix(nsFastLoadFooterPrefix *aFooterPrefix) -{ - nsresult rv; - - rv = Read32(&aFooterPrefix->mNumIDs); - if (NS_FAILED(rv)) - return rv; - - rv = Read32(&aFooterPrefix->mNumSharpObjects); - if (NS_FAILED(rv)) - return rv; - - rv = Read32(&aFooterPrefix->mNumMuxedDocuments); - if (NS_FAILED(rv)) - return rv; - - rv = Read32(&aFooterPrefix->mNumDependencies); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - -nsresult -nsFastLoadFileReader::ReadSlowID(nsID *aID) -{ - nsresult rv; - - rv = Read32(&aID->m0); - if (NS_FAILED(rv)) - return rv; - - rv = Read16(&aID->m1); - if (NS_FAILED(rv)) - return rv; - - rv = Read16(&aID->m2); - if (NS_FAILED(rv)) - return rv; - - PRUint32 bytesRead; - rv = Read(reinterpret_cast(aID->m3), sizeof aID->m3, &bytesRead); - if (NS_FAILED(rv)) - return rv; - - if (bytesRead != sizeof aID->m3) - return NS_ERROR_FAILURE; - return NS_OK; -} - -nsresult -nsFastLoadFileReader::ReadFastID(NSFastLoadID *aID) -{ - nsresult rv = Read32(aID); - if (NS_SUCCEEDED(rv)) - *aID ^= MFL_ID_XOR_KEY; - return rv; -} - -nsresult -nsFastLoadFileReader::ReadSharpObjectInfo(nsFastLoadSharpObjectInfo *aInfo) -{ - nsresult rv; - - rv = Read32(&aInfo->mCIDOffset); - if (NS_FAILED(rv)) - return rv; - - NS_ASSERTION(aInfo->mCIDOffset != 0, - "fastload reader: mCIDOffset cannot be zero!"); - - rv = Read16(&aInfo->mStrongRefCnt); - if (NS_FAILED(rv)) - return rv; - - rv = Read16(&aInfo->mWeakRefCnt); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - -nsresult -nsFastLoadFileReader::ReadMuxedDocumentInfo(nsFastLoadMuxedDocumentInfo *aInfo) -{ - nsresult rv; - - nsCAutoString spec; - rv = ReadCString(spec); - if (NS_FAILED(rv)) - return rv; - - rv = Read32(&aInfo->mInitialSegmentOffset); - if (NS_FAILED(rv)) - return rv; - - aInfo->mURISpec = ToNewCString(spec); - return NS_OK; -} - -nsresult -nsFastLoadFileReader::Open() -{ - nsresult rv; - nsCOMPtr localFile = do_QueryInterface(mFile, &rv); - if (NS_FAILED(rv)) - return rv; - PRFileDesc *fd; // OS file-descriptor - rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd); - if (NS_FAILED(rv)) - return rv; - - PRInt64 size = PR_Available64(fd); - if (size >= PR_INT32_MAX) { - PR_Close(fd); - return NS_ERROR_FILE_TOO_BIG; - } - - mFileLen = (PRUint32) size; - if (mFileLen < sizeof(nsFastLoadHeader)) { - PR_Close(fd); - return NS_ERROR_FAILURE; - } - - mFileMap = PR_CreateFileMap(fd, mFileLen, PR_PROT_READONLY); - if (!mFileMap) { - PR_Close(fd); - return NS_ERROR_FAILURE; - } - - mFileData = (PRUint8*) PR_MemMap(mFileMap, 0, mFileLen); - // At this point the non-mmap file descriptor is no longer needed - PR_Close(fd); - - if (!mFileData) - return NS_ERROR_FAILURE; - -#if defined(XP_UNIX) - madvise((char *)mFileData, mFileLen, MADV_WILLNEED); -#endif - - rv = ReadHeader(&mHeader); - if (NS_FAILED(rv)) - return rv; - - PRUint32 checksum; - rv = ComputeChecksum(&checksum); - if (NS_FAILED(rv)) - return rv; - - if (checksum != mHeader.mChecksum) - return NS_ERROR_FAILURE; - - if (mHeader.mVersion != MFL_FILE_VERSION || - mHeader.mFooterOffset == 0 || - memcmp(mHeader.mMagic, magic, MFL_FILE_MAGIC_SIZE)) - return NS_ERROR_UNEXPECTED; - - SeekTo(mHeader.mFooterOffset); - - rv = ReadFooter(&mFooter); - if (NS_FAILED(rv)) - return rv; - - SeekTo(sizeof(nsFastLoadHeader)); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::Close() -{ - // Give up our strong "keepalive" references, in case not all objects that - // were deserialized were fully re-connected. - // - // This happens for sure when an nsFastLoadFileUpdater is created and wraps - // an nsFastLoadFileReader whose data was already deserialized by an earlier - // FastLoad episode. The reader is useful in the second such episode during - // a session not so much for reading objects as for its footer information, - // which primes the updater's tables so that after the update completes, the - // FastLoad file has a superset footer. - if (mFileData) { - PR_MemUnmap(mFileData, mFileLen); - mFileData = nsnull; - } - - if (mFileMap) { - PR_CloseFileMap(mFileMap); - mFileMap = nsnull; - } - - mFileLen = 0; - mFilePos = 0; - - if (!mFooter.mObjectMap) - return NS_OK; - - for (PRUint32 i = 0, n = mFooter.mNumSharpObjects; i < n; i++) { - nsObjectMapEntry* entry = &mFooter.mObjectMap[i]; - entry->mReadObject = nsnull; - } - mFooter.mNumSharpObjects = 0; - - return NS_OK; -} - -nsresult -nsFastLoadFileReader::DeserializeObject(nsISupports* *aObject) -{ - nsresult rv; - NSFastLoadID fastCID; - - rv = ReadFastID(&fastCID); - if (NS_FAILED(rv)) - return rv; - - const nsID& slowCID = mFooter.GetID(fastCID); - nsCOMPtr object(do_CreateInstance(slowCID, &rv)); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr serializable(do_QueryInterface(object)); - if (!serializable) - return NS_ERROR_FAILURE; - - rv = serializable->Read(this); - if (NS_FAILED(rv)) - return rv; - - *aObject = object; - NS_ADDREF(*aObject); - return NS_OK; -} - -nsresult -nsFastLoadFileReader::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject) -{ - nsresult rv; - NSFastLoadOID oid; - - rv = Read32(&oid); - if (NS_FAILED(rv)) - return rv; - oid ^= MFL_OID_XOR_KEY; - - nsCOMPtr object; - - if (oid == MFL_DULL_OBJECT_OID) { - // A very dull object, defined at point of single (strong) reference. - NS_ASSERTION(aIsStrongRef, "dull object read via weak ref!"); - - rv = DeserializeObject(getter_AddRefs(object)); - if (NS_FAILED(rv)) - return rv; - } else { - NS_ASSERTION((oid & MFL_WEAK_REF_TAG) == - (aIsStrongRef ? 0 : MFL_WEAK_REF_TAG), - "strong vs. weak ref deserialization mismatch!"); - - nsObjectMapEntry* entry = &mFooter.GetSharpObjectEntry(oid); - - // Check whether we've already deserialized the object for this OID. - object = entry->mReadObject; - if (!object) { - nsDocumentMapReadEntry* saveDocMapEntry = nsnull; - - PRUint32 saveOffset32 = mFilePos; - if (entry->mCIDOffset != saveOffset32) { - // We skipped deserialization of this object from its position - // earlier in the input stream, presumably due to the reference - // there being an nsFastLoadPtr, or (more likely) because the - // object was muxed in another document, and deserialization - // order does not match serialization order. So we must seek - // back and read it now. - NS_ASSERTION(entry->mCIDOffset < saveOffset32, - "out of order object?!"); - - // Ape our Seek wrapper by clearing mCurrentDocumentMapEntry. - // This allows for a skipped object to be referenced from two - // or more multiplexed documents in the FastLoad file. - saveDocMapEntry = mCurrentDocumentMapEntry; - mCurrentDocumentMapEntry = nsnull; - SeekTo(entry->mCIDOffset); - } - - rv = DeserializeObject(getter_AddRefs(object)); - if (NS_FAILED(rv)) - return rv; - - if (entry->mCIDOffset != saveOffset32) { - // Save the "skip offset" in case we need to skip this object - // definition when reading forward, later on. - entry->mSkipOffset = mFilePos; - // Restore stream offset and mCurrentDocumentMapEntry in case - // we're still reading forward through a part of the multiplex - // to get object definitions eagerly. - SeekTo(saveOffset32); - mCurrentDocumentMapEntry = saveDocMapEntry; - } - - // Save object until all refs have been deserialized. - entry->mReadObject = object; - } else { - // What if we are at a definition that's already been read? This - // case arises when a sharp object's def is serialized before its - // refs, while a non-defining ref is deserialized before the def. - // We must skip over the object definition. - if (oid & MFL_OBJECT_DEF_TAG) { - NS_ASSERTION(entry->mSkipOffset != 0, "impossible! see above"); - - // Since we are seeking within a muxed segment, we must adjust - // mBytesLeft, so that Seek called from Read will be triggered - // when mBytesLeft goes to zero. - PRUint32 currentOffset = mFilePos; - NS_ASSERTION(entry->mSkipOffset > (PRUint32)currentOffset, - "skipping backwards from object?!"); - NS_ASSERTION(mCurrentDocumentMapEntry->mBytesLeft >= - entry->mSkipOffset - (PRUint32)currentOffset, - "skipped object buffer underflow!"); - - mCurrentDocumentMapEntry->mBytesLeft -= - entry->mSkipOffset - (PRUint32)currentOffset; - - SeekTo(entry->mSkipOffset); - } - } - - if (aIsStrongRef) { - NS_ASSERTION(entry->mStrongRefCnt != 0, - "mStrongRefCnt underflow!"); - --entry->mStrongRefCnt; - } else { - NS_ASSERTION(MFL_GET_WEAK_REFCNT(entry) != 0, - "mWeakRefCnt underflow!"); - MFL_DROP_WEAK_REFCNT(entry); - } - - if (entry->mStrongRefCnt == 0 && MFL_GET_WEAK_REFCNT(entry) == 0) - entry->mReadObject = nsnull; - } - - if (oid & MFL_QUERY_INTERFACE_TAG) { - NSFastLoadID iid; - rv = ReadFastID(&iid); - if (NS_FAILED(rv)) - return rv; - - rv = object->QueryInterface(mFooter.GetID(iid), - reinterpret_cast(aObject)); - if (NS_FAILED(rv)) - return rv; - } else { - *aObject = object; - NS_ADDREF(*aObject); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::ReadID(nsID *aResult) -{ - nsresult rv; - NSFastLoadID fastID; - - rv = ReadFastID(&fastID); - if (NS_FAILED(rv)) - return rv; - - *aResult = mFooter.GetID(fastID); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::Seek(PRInt32 aWhence, PRInt64 aOffset) -{ - NS_ASSERTION(aWhence == nsISeekableStream::NS_SEEK_SET, "Only NS_SEEK_SET seeks are supported"); - mCurrentDocumentMapEntry = nsnull; - SeekTo(aOffset); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::Tell(PRInt64 *aResult) -{ - *aResult = mFilePos; - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileReader::SetEOF() -{ - NS_ERROR("Refusing to truncate a memory-mapped file"); - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_COM nsresult -NS_NewFastLoadFileReader(nsIObjectInputStream* *aResult, nsIFile *aFile) -{ - nsFastLoadFileReader* reader = new nsFastLoadFileReader(aFile); - if (!reader) - return NS_ERROR_OUT_OF_MEMORY; - - // Stabilize reader's refcnt. - nsCOMPtr stream(reader); - - nsresult rv = reader->Open(); - if (NS_FAILED(rv)) - return rv; - - *aResult = stream; - NS_ADDREF(*aResult); - return NS_OK; -} - -// -------------------------- nsFastLoadFileWriter -------------------------- - -NS_IMPL_ISUPPORTS_INHERITED4(nsFastLoadFileWriter, - nsBinaryOutputStream, - nsIObjectOutputStream, - nsIFastLoadFileControl, - nsIFastLoadWriteControl, - nsISeekableStream) - -struct nsIDMapEntry : public PLDHashEntryHdr { - NSFastLoadID mFastID; // 1 + nsFastLoadFooter::mIDMap index - nsID mSlowID; // key, used by PLDHashTableOps below -}; - -static PLDHashNumber -idmap_HashKey(PLDHashTable *aTable, const void *aKey) -{ - const nsID *idp = reinterpret_cast(aKey); - - return idp->m0; -} - -static PRBool -idmap_MatchEntry(PLDHashTable *aTable, - const PLDHashEntryHdr *aHdr, - const void *aKey) -{ - const nsIDMapEntry* entry = static_cast(aHdr); - const nsID *idp = reinterpret_cast(aKey); - - return memcmp(&entry->mSlowID, idp, sizeof(nsID)) == 0; -} - -static const PLDHashTableOps idmap_DHashTableOps = { - PL_DHashAllocTable, - PL_DHashFreeTable, - idmap_HashKey, - idmap_MatchEntry, - PL_DHashMoveEntryStub, - PL_DHashClearEntryStub, - PL_DHashFinalizeStub, - NULL -}; - -nsresult -nsFastLoadFileWriter::MapID(const nsID& aSlowID, NSFastLoadID *aResult) -{ - nsIDMapEntry* entry = - static_cast - (PL_DHashTableOperate(&mIDMap, &aSlowID, PL_DHASH_ADD)); - if (!entry) - return NS_ERROR_OUT_OF_MEMORY; - - if (entry->mFastID == 0) { - entry->mFastID = mIDMap.entryCount; - entry->mSlowID = aSlowID; - } - - *aResult = entry->mFastID; - return NS_OK; -} - -nsresult -nsFastLoadFileWriter::WriteHeader(nsFastLoadHeader *aHeader) -{ - nsresult rv; - PRUint32 bytesWritten; - - rv = Write(aHeader->mMagic, MFL_FILE_MAGIC_SIZE, &bytesWritten); - if (NS_FAILED(rv)) - return rv; - - if (bytesWritten != MFL_FILE_MAGIC_SIZE) - return NS_ERROR_FAILURE; - - rv = Write32(aHeader->mChecksum); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(aHeader->mVersion); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(aHeader->mFooterOffset); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(aHeader->mFileSize); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - -// nsIFastLoadFileControl methods: - -NS_IMETHODIMP -nsFastLoadFileWriter::GetChecksum(PRUint32 *aChecksum) -{ - if (mHeader.mChecksum == 0) - return NS_ERROR_NOT_AVAILABLE; - *aChecksum = mHeader.mChecksum; - return NS_OK; -} - -struct nsDocumentMapWriteEntry : public nsDocumentMapEntry { - PRUint32 mCurrentSegmentOffset; // last written segment's offset -}; - -// Fast mapping from URI object pointer back to spec-indexed document info. -// We also may need the slow mapping from mURISpec to nsDocumentMapWriteEntry, -// because the writer's mDocumentMap double hash table may grow "behind the -// back of" each mURIMap entry's mDocMapEntry member. -struct nsURIMapWriteEntry : public nsObjectMapEntry { - nsDocumentMapWriteEntry* mDocMapEntry; - PRUint32 mGeneration; - const char* mURISpec; -}; - -NS_IMETHODIMP -nsFastLoadFileWriter::HasMuxedDocument(const char* aURISpec, PRBool *aResult) -{ - nsDocumentMapWriteEntry* docMapEntry = - static_cast - (PL_DHashTableOperate(&mDocumentMap, aURISpec, - PL_DHASH_LOOKUP)); - - *aResult = PL_DHASH_ENTRY_IS_BUSY(docMapEntry); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileWriter::StartMuxedDocument(nsISupports* aURI, - const char* aURISpec) -{ - // Save mDocumentMap table generation and mCurrentDocumentMapEntry key in - // case the hash table grows during the PL_DHASH_ADD operation. - PRUint32 saveGeneration = mDocumentMap.generation; - const char* saveURISpec = mCurrentDocumentMapEntry - ? mCurrentDocumentMapEntry->mString - : nsnull; - - nsDocumentMapWriteEntry* docMapEntry = - static_cast - (PL_DHashTableOperate(&mDocumentMap, aURISpec, - PL_DHASH_ADD)); - if (!docMapEntry) - return NS_ERROR_OUT_OF_MEMORY; - - // If the generation number changed, refresh mCurrentDocumentMapEntry. - if (mCurrentDocumentMapEntry && mDocumentMap.generation != saveGeneration) { - mCurrentDocumentMapEntry = - static_cast - (PL_DHashTableOperate(&mDocumentMap, saveURISpec, - PL_DHASH_LOOKUP)); - NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(mCurrentDocumentMapEntry), - "mCurrentDocumentMapEntry lost during table growth?!"); - - // Refresh saveGeneration for use below when initializing uriMapEntry. - saveGeneration = mDocumentMap.generation; - } - - NS_WARN_IF_FALSE(docMapEntry->mString == nsnull, - "redundant multiplexed document?"); - if (docMapEntry->mString) - return NS_ERROR_UNEXPECTED; - - void* spec = nsMemory::Clone(aURISpec, strlen(aURISpec) + 1); - if (!spec) - return NS_ERROR_OUT_OF_MEMORY; - docMapEntry->mString = reinterpret_cast(spec); - docMapEntry->mURI = aURI; - NS_ADDREF(docMapEntry->mURI); - - nsCOMPtr key(do_QueryInterface(aURI)); - nsURIMapWriteEntry* uriMapEntry = - static_cast - (PL_DHashTableOperate(&mURIMap, key, PL_DHASH_ADD)); - if (!uriMapEntry) - return NS_ERROR_OUT_OF_MEMORY; - - NS_ASSERTION(uriMapEntry->mDocMapEntry == nsnull, - "URI mapped to two different specs?"); - if (uriMapEntry->mDocMapEntry) - return NS_ERROR_UNEXPECTED; - - uriMapEntry->mObject = key; - NS_ADDREF(uriMapEntry->mObject); - uriMapEntry->mDocMapEntry = docMapEntry; - uriMapEntry->mGeneration = saveGeneration; - uriMapEntry->mURISpec = reinterpret_cast(spec); - TRACE_MUX(('w', "start %p (%p) %s\n", aURI, key.get(), aURISpec)); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI, - nsISupports** aResult) -{ - // Capture the current file offset (XXXbe maintain our own via Write?) - nsresult rv; - PRInt64 currentSegmentOffset; - rv = mSeekableOutput->Tell(¤tSegmentOffset); - if (NS_FAILED(rv)) - return rv; - - PRUint32 currentSegmentOffset32 = currentSegmentOffset; - // Look for an existing entry keyed by aURI, added by StartMuxedDocument. - nsCOMPtr key(do_QueryInterface(aURI)); - nsURIMapWriteEntry* uriMapEntry = - static_cast - (PL_DHashTableOperate(&mURIMap, key, PL_DHASH_LOOKUP)); - NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(uriMapEntry), - "SelectMuxedDocument without prior StartMuxedDocument?"); - if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry)) - return NS_ERROR_UNEXPECTED; - - // Beware that uriMapEntry->mDocMapEntry may be stale, if an mDocumentMap - // addition caused that table to grow. We save the mDocumentMap generation - // in each uriMapEntry and compare it to the current generation, rehashing - // uriMapEntry->mURISpec if necessary. - - nsDocumentMapWriteEntry* docMapEntry = uriMapEntry->mDocMapEntry; - if (uriMapEntry->mGeneration != mDocumentMap.generation) { - docMapEntry = - static_cast - (PL_DHashTableOperate(&mDocumentMap, - uriMapEntry->mURISpec, - PL_DHASH_LOOKUP)); - NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(docMapEntry), "lost mDocMapEntry!?"); - uriMapEntry->mDocMapEntry = docMapEntry; - uriMapEntry->mGeneration = mDocumentMap.generation; - } - - // If there is a muxed document segment open, close it now by setting its - // length, stored in the second PRUint32 of the segment. - nsDocumentMapWriteEntry* prevDocMapEntry = mCurrentDocumentMapEntry; - if (prevDocMapEntry) { - if (prevDocMapEntry == docMapEntry) { - TRACE_MUX(('w', "select prev %s same as current!\n", - prevDocMapEntry->mString)); - *aResult = docMapEntry->mURI; - NS_ADDREF(*aResult); - return NS_OK; - } - - PRUint32 prevSegmentOffset = prevDocMapEntry->mCurrentSegmentOffset; - TRACE_MUX(('w', "select prev %s offset %lu\n", - prevDocMapEntry->mString, prevSegmentOffset)); - - rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, - prevSegmentOffset + 4); - if (NS_FAILED(rv)) - return rv; - - // The length counts all bytes in the segment, including the header - // that contains [nextSegmentOffset, length]. - rv = Write32(currentSegmentOffset32 - prevSegmentOffset); - if (NS_FAILED(rv)) - return rv; - - // Seek back to the current offset only if we are not going to seek - // 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 = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, - currentSegmentOffset); - if (NS_FAILED(rv)) - return rv; - } - } - - // If this entry was newly added, set its key and initial segment offset. - // Otherwise, seek back to write the next segment offset of the previous - // segment for this document in the multiplex. - if (!docMapEntry->mInitialSegmentOffset) { - docMapEntry->mInitialSegmentOffset = currentSegmentOffset32; - } else { - rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, - docMapEntry->mCurrentSegmentOffset); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(currentSegmentOffset32); - if (NS_FAILED(rv)) - return rv; - - rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, - currentSegmentOffset); - if (NS_FAILED(rv)) - return rv; - } - - // Update this document's current segment offset so we can later fix its - // next segment offset (unless it is last, in which case we leave the zero - // placeholder as a terminator). - docMapEntry->mCurrentSegmentOffset = currentSegmentOffset32; - - rv = Write32(0); // nextSegmentOffset placeholder - if (NS_FAILED(rv)) - return rv; - - rv = Write32(0); // length placeholder - if (NS_FAILED(rv)) - return rv; - - *aResult = prevDocMapEntry ? prevDocMapEntry->mURI : nsnull; - NS_IF_ADDREF(*aResult); - - mCurrentDocumentMapEntry = docMapEntry; - TRACE_MUX(('w', "select %p (%p) offset %lu\n", - aURI, key.get(), currentSegmentOffset)); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileWriter::EndMuxedDocument(nsISupports* aURI) -{ - nsCOMPtr key(do_QueryInterface(aURI)); - nsURIMapWriteEntry* uriMapEntry = - static_cast - (PL_DHashTableOperate(&mURIMap, key, PL_DHASH_LOOKUP)); - - // If the URI isn't in the map, nsFastLoadFileWriter::StartMuxedDocument - // must have been called with a redundant URI, *and* its caller must have - // ignored the NS_ERROR_UNEXPECTED it returned in that case. - if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry)) { - TRACE_MUX(('w', "bad end %p (%p)\n", aURI, key.get())); - return NS_ERROR_UNEXPECTED; - } - - // Drop our ref to the URI object that was passed to StartMuxedDocument, - // we no longer need it, and we do not want to extend its lifetime. - if (uriMapEntry->mDocMapEntry) - NS_RELEASE(uriMapEntry->mDocMapEntry->mURI); - - // Shrink the table if half the entries are removed sentinels. - PRUint32 size = PL_DHASH_TABLE_SIZE(&mURIMap); - if (mURIMap.removedCount >= (size >> 2)) - PL_DHashTableOperate(&mURIMap, key, PL_DHASH_REMOVE); - else - PL_DHashTableRawRemove(&mURIMap, uriMapEntry); - - TRACE_MUX(('w', "end %p (%p)\n", aURI, key.get())); - return NS_OK; -} - -struct nsDependencyMapEntry : public nsStringMapEntry { - PRInt64 mLastModified; -}; - -NS_IMETHODIMP -nsFastLoadFileWriter::AddDependency(nsIFile* aFile) -{ - nsCAutoString path; - nsresult rv = aFile->GetNativePath(path); - if (NS_FAILED(rv)) - return rv; - - nsDependencyMapEntry* entry = - static_cast - (PL_DHashTableOperate(&mDependencyMap, path.get(), - PL_DHASH_ADD)); - if (!entry) - return NS_ERROR_OUT_OF_MEMORY; - - if (!entry->mString) { - const char *tmp = ToNewCString(path); - if (!tmp) - return NS_ERROR_OUT_OF_MEMORY; - entry->mString = tmp; - - // If we can't get the last modified time from aFile, assume it does - // not exist, or is otherwise inaccessible to us (due to permissions), - // remove the dependency, and suppress the failure. - // - // Otherwise, we would end up aborting the fastload process due to a - // missing .js or .xul or other file on every startup. - - rv = aFile->GetLastModifiedTime(&entry->mLastModified); - if (NS_FAILED(rv)) { - PL_DHashTableOperate(&mDependencyMap, path.get(), PL_DHASH_REMOVE); - rv = NS_OK; - } - } - return rv; -} - -nsresult -nsFastLoadFileWriter::WriteFooterPrefix(const nsFastLoadFooterPrefix& aFooterPrefix) -{ - nsresult rv; - - rv = Write32(aFooterPrefix.mNumIDs); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(aFooterPrefix.mNumSharpObjects); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(aFooterPrefix.mNumMuxedDocuments); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(aFooterPrefix.mNumDependencies); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - -nsresult -nsFastLoadFileWriter::WriteSlowID(const nsID& aID) -{ - nsresult rv; - - rv = Write32(aID.m0); - if (NS_FAILED(rv)) - return rv; - - rv = Write16(aID.m1); - if (NS_FAILED(rv)) - return rv; - - rv = Write16(aID.m2); - if (NS_FAILED(rv)) - return rv; - - PRUint32 bytesWritten; - rv = Write(reinterpret_cast(aID.m3), sizeof aID.m3, - &bytesWritten); - if (NS_FAILED(rv)) - return rv; - - if (bytesWritten != sizeof aID.m3) - return NS_ERROR_FAILURE; - return NS_OK; -} - -nsresult -nsFastLoadFileWriter::WriteFastID(NSFastLoadID aID) -{ - return Write32(aID ^ MFL_ID_XOR_KEY); -} - -nsresult -nsFastLoadFileWriter::WriteSharpObjectInfo(const nsFastLoadSharpObjectInfo& aInfo) -{ - nsresult rv; - - NS_ASSERTION(aInfo.mCIDOffset != 0, - "fastload writer: mCIDOffset cannot be zero!"); - - rv = Write32(aInfo.mCIDOffset); - if (NS_FAILED(rv)) - return rv; - - rv = Write16(aInfo.mStrongRefCnt); - if (NS_FAILED(rv)) - return rv; - - rv = Write16(aInfo.mWeakRefCnt); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - -nsresult -nsFastLoadFileWriter::WriteMuxedDocumentInfo(const nsFastLoadMuxedDocumentInfo& aInfo) -{ - nsresult rv; - - rv = WriteStringZ(aInfo.mURISpec); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(aInfo.mInitialSegmentOffset); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - -PLDHashOperator -nsFastLoadFileWriter::IDMapEnumerate(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData) -{ - nsIDMapEntry* entry = static_cast(aHdr); - PRUint32 index = entry->mFastID - 1; - nsID* vector = reinterpret_cast(aData); - - NS_ASSERTION(index < aTable->entryCount, "bad nsIDMap index!"); - vector[index] = entry->mSlowID; - return PL_DHASH_NEXT; -} - -struct nsSharpObjectMapEntry : public nsObjectMapEntry { - NSFastLoadOID mOID; - nsFastLoadSharpObjectInfo mInfo; -}; - -PLDHashOperator -nsFastLoadFileWriter::ObjectMapEnumerate(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData) -{ - nsSharpObjectMapEntry* entry = static_cast(aHdr); - PRUint32 index = MFL_OID_TO_SHARP_INDEX(entry->mOID); - nsFastLoadSharpObjectInfo* vector = - reinterpret_cast(aData); - - NS_ASSERTION(index < aTable->entryCount, "bad nsObjectMap index!"); - vector[index] = entry->mInfo; - - NS_ASSERTION(entry->mInfo.mStrongRefCnt, "no strong ref in serialization!"); - - // Ignore tagged object ids stored as object pointer keys (the updater - // code does this). - if ((NS_PTR_TO_INT32(entry->mObject) & MFL_OBJECT_DEF_TAG) == 0) - NS_RELEASE(entry->mObject); - - return PL_DHASH_NEXT; -} - -PLDHashOperator -nsFastLoadFileWriter::DocumentMapEnumerate(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData) -{ - nsFastLoadFileWriter* writer = - reinterpret_cast(aTable->data); - nsDocumentMapWriteEntry* entry = - static_cast(aHdr); - nsresult* rvp = reinterpret_cast(aData); - - nsFastLoadMuxedDocumentInfo info; - info.mURISpec = entry->mString; - info.mInitialSegmentOffset = entry->mInitialSegmentOffset; - *rvp = writer->WriteMuxedDocumentInfo(info); - - return NS_FAILED(*rvp) ? PL_DHASH_STOP : PL_DHASH_NEXT; -} - -PLDHashOperator -nsFastLoadFileWriter::DependencyMapEnumerate(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData) -{ - nsFastLoadFileWriter* writer = - reinterpret_cast(aTable->data); - nsDependencyMapEntry* entry = static_cast(aHdr); - nsresult* rvp = reinterpret_cast(aData); - - *rvp = writer->WriteStringZ(entry->mString); - if (NS_SUCCEEDED(*rvp)) - *rvp = writer->Write64(entry->mLastModified); - - return NS_FAILED(*rvp) ? PL_DHASH_STOP :PL_DHASH_NEXT; -} - -nsresult -nsFastLoadFileWriter::WriteFooter() -{ - nsresult rv; - PRUint32 i, count; - - nsFastLoadFooterPrefix footerPrefix; - footerPrefix.mNumIDs = mIDMap.entryCount; - footerPrefix.mNumSharpObjects = mObjectMap.entryCount; - footerPrefix.mNumMuxedDocuments = mDocumentMap.entryCount; - footerPrefix.mNumDependencies = mDependencyMap.entryCount; - - rv = WriteFooterPrefix(footerPrefix); - if (NS_FAILED(rv)) - return rv; - - // Enumerate mIDMap into a vector indexed by mFastID and write it. - nsID* idvec = new nsID[footerPrefix.mNumIDs]; - if (!idvec) - return NS_ERROR_OUT_OF_MEMORY; - - count = PL_DHashTableEnumerate(&mIDMap, IDMapEnumerate, idvec); - NS_ASSERTION(count == footerPrefix.mNumIDs, "bad mIDMap enumeration!"); - for (i = 0; i < count; i++) { - rv = WriteSlowID(idvec[i]); - if (NS_FAILED(rv)) break; - } - - delete[] idvec; - if (NS_FAILED(rv)) - return rv; - - // Enumerate mObjectMap into a vector indexed by mOID and write it. - nsFastLoadSharpObjectInfo* objvec = - new nsFastLoadSharpObjectInfo[footerPrefix.mNumSharpObjects]; - if (!objvec) - return NS_ERROR_OUT_OF_MEMORY; -#ifdef NS_DEBUG - memset(objvec, 0, footerPrefix.mNumSharpObjects * - sizeof(nsFastLoadSharpObjectInfo)); -#endif - - count = PL_DHashTableEnumerate(&mObjectMap, ObjectMapEnumerate, objvec); - NS_ASSERTION(count == footerPrefix.mNumSharpObjects, - "bad mObjectMap enumeration!"); - for (i = 0; i < count; i++) { - rv = WriteSharpObjectInfo(objvec[i]); - if (NS_FAILED(rv)) break; - } - - delete[] objvec; - if (NS_FAILED(rv)) - return rv; - - // Enumerate mDocumentMap, writing nsFastLoadMuxedDocumentInfo records - count = PL_DHashTableEnumerate(&mDocumentMap, DocumentMapEnumerate, &rv); - if (NS_FAILED(rv)) - return rv; - - NS_ASSERTION(count == footerPrefix.mNumMuxedDocuments, - "bad mDocumentMap enumeration!"); - - // Write out make-like file dependencies. - count = PL_DHashTableEnumerate(&mDependencyMap, DependencyMapEnumerate, &rv); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - -nsresult -nsFastLoadFileWriter::Init() -{ - if (!PL_DHashTableInit(&mIDMap, &idmap_DHashTableOps, (void *)this, - sizeof(nsIDMapEntry), PL_DHASH_MIN_SIZE)) { - mIDMap.ops = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - if (!PL_DHashTableInit(&mObjectMap, &objmap_DHashTableOps, (void *)this, - sizeof(nsSharpObjectMapEntry), PL_DHASH_MIN_SIZE)) { - mObjectMap.ops = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - if (!PL_DHashTableInit(&mDocumentMap, &strmap_DHashTableOps, (void *)this, - sizeof(nsDocumentMapWriteEntry), - PL_DHASH_MIN_SIZE)) { - mDocumentMap.ops = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - if (!PL_DHashTableInit(&mURIMap, &objmap_DHashTableOps, (void *)this, - sizeof(nsURIMapWriteEntry), PL_DHASH_MIN_SIZE)) { - mURIMap.ops = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - if (!PL_DHashTableInit(&mDependencyMap, &strmap_DHashTableOps, (void *)this, - sizeof(nsDependencyMapEntry), PL_DHASH_MIN_SIZE)) { - mDependencyMap.ops = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - return NS_OK; -} - -nsresult -nsFastLoadFileWriter::Open() -{ - nsresult rv; - - if (!mSeekableOutput) - return NS_ERROR_FAILURE; - - rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, - sizeof(nsFastLoadHeader)); - if (NS_FAILED(rv)) - return rv; - - return Init(); -} - -#define MFL_CHECKSUM_BUFSIZE (6 * 8192) - -NS_IMETHODIMP -nsFastLoadFileWriter::Close() -{ - nsresult rv; - - memcpy(mHeader.mMagic, magic, MFL_FILE_MAGIC_SIZE); - mHeader.mChecksum = 0; - mHeader.mVersion = MFL_FILE_VERSION; - - PRInt64 footerOffset; - rv = mSeekableOutput->Tell(&footerOffset); - - LL_L2UI(mHeader.mFooterOffset, footerOffset); - if (NS_FAILED(rv)) - return rv; - - // If there is a muxed document segment open, close it now by setting its - // length, stored in the second PRUint32 of the segment. - if (mCurrentDocumentMapEntry) { - PRUint32 currentSegmentOffset = - mCurrentDocumentMapEntry->mCurrentSegmentOffset; - rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, - currentSegmentOffset + 4); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(mHeader.mFooterOffset - currentSegmentOffset); - if (NS_FAILED(rv)) - return rv; - - // Seek back to the current offset to write the footer. - rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, - mHeader.mFooterOffset); - if (NS_FAILED(rv)) - return rv; - - mCurrentDocumentMapEntry = nsnull; - } - - rv = WriteFooter(); - if (NS_FAILED(rv)) - return rv; - PRInt64 fileSize; - rv = mSeekableOutput->Tell(&fileSize); - LL_L2UI(mHeader.mFileSize, fileSize); - if (NS_FAILED(rv)) - return rv; - - rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, 0); - if (NS_FAILED(rv)) - return rv; - - rv = WriteHeader(&mHeader); - if (NS_FAILED(rv)) - return rv; - - // Now compute the checksum, using mFileIO to get an input stream on the - // underlying FastLoad file. - if (mFileIO) { - // 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 output; - rv = mBufferAccess->GetUnbufferedStream(getter_AddRefs(output)); - if (NS_FAILED(rv) || !output) - return NS_ERROR_UNEXPECTED; - - nsCOMPtr input; - rv = mFileIO->GetInputStream(getter_AddRefs(input)); - if (NS_FAILED(rv)) - return rv; - - // Seek the input stream to right after checksum/magic. - nsCOMPtr seekable = do_QueryInterface(input); - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - offsetof(nsFastLoadHeader, mVersion)); - if (NS_FAILED(rv)) - return rv; - - char buf[MFL_CHECKSUM_BUFSIZE]; - PRUint32 len, rem = 0; - PRUint32 checksum = 0; - - // Ok, we're finally ready to checksum the FastLoad file we just wrote! - while (NS_SUCCEEDED(rv = - input->Read(buf + rem, sizeof buf - rem, &len)) && - len) { - len += rem; - rem = NS_AccumulateFastLoadChecksum(&checksum, - reinterpret_cast - (buf), - len, - PR_FALSE); - if (rem) - memcpy(buf, buf + len - rem, rem); - } - if (NS_FAILED(rv)) - return rv; - - if (rem) { - NS_AccumulateFastLoadChecksum(&checksum, - reinterpret_cast(buf), - rem, - PR_TRUE); - } - - // Store the checksum in the FastLoad file header and remember it via - // mHeader.mChecksum, for GetChecksum. - seekable = do_QueryInterface(output); - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, - offsetof(nsFastLoadHeader, mChecksum)); - if (NS_FAILED(rv)) - return rv; - - mHeader.mChecksum = checksum; - checksum = NS_SWAP32(checksum); - PRUint32 bytesWritten; - rv = output->Write(reinterpret_cast(&checksum), - sizeof checksum, - &bytesWritten); - if (NS_FAILED(rv)) - return rv; - if (bytesWritten != sizeof checksum) - return NS_ERROR_FAILURE; - } - - return mOutputStream->Close(); -} - -// Pseudo-tag used as flag between WriteSingleRefObject and WriteObjectCommon. -#define MFL_SINGLE_REF_PSEUDO_TAG PR_BIT(MFL_OBJECT_TAG_BITS) - -nsresult -nsFastLoadFileWriter::WriteObjectCommon(nsISupports* aObject, - PRBool aIsStrongRef, - PRUint32 aTags) -{ - nsrefcnt rc; - nsresult rv; - - NS_ASSERTION((NS_PTR_TO_INT32(aObject) & MFL_OBJECT_DEF_TAG) == 0, - "odd nsISupports*, oh no!"); - - // Here be manual refcounting dragons! - rc = aObject->AddRef(); - NS_ASSERTION(rc != 0, "bad refcnt when writing aObject!"); - - NSFastLoadOID oid; - nsCOMPtr classInfo; - - if (rc == 2 && (aTags & MFL_SINGLE_REF_PSEUDO_TAG)) { - // Dull object: only one strong ref and no weak refs in serialization. - // Conservative: we don't trust the caller if there are more than two - // refs (one from the AddRef above, one from the data structure that's - // being serialized). - oid = MFL_DULL_OBJECT_OID; - aObject->Release(); - } else { - // Object is presumed to be multiply connected through some combo of - // strong and weak refs. Hold onto it via mObjectMap. - nsSharpObjectMapEntry* entry = - static_cast - (PL_DHashTableOperate(&mObjectMap, aObject, - PL_DHASH_ADD)); - if (!entry) { - aObject->Release(); - return NS_ERROR_OUT_OF_MEMORY; - } - - if (!entry->mObject) { - // First time we've seen this object address: add it to mObjectMap - // and serialize the object at the current stream offset. - PRInt64 thisOffset; - rv = Tell(&thisOffset); - if (NS_FAILED(rv)) { - aObject->Release(); - return rv; - } - - // NB: aObject was already held, and mObject is a raw nsISupports*. - entry->mObject = aObject; - - oid = (mObjectMap.entryCount << MFL_OBJECT_TAG_BITS); - entry->mOID = oid; - - // NB: the (32-bit, fast) CID and object data follow the OID. - entry->mInfo.mCIDOffset = thisOffset + sizeof(oid); - entry->mInfo.mStrongRefCnt = aIsStrongRef ? 1 : 0; - entry->mInfo.mWeakRefCnt = aIsStrongRef ? 0 : 1; - - // Record in oid the fact that we're defining this object in the - // stream, and get the object's class info here, so we can take - // note of singletons in order to avoid reserializing them when - // updating after reading. - oid |= MFL_OBJECT_DEF_TAG; - classInfo = do_QueryInterface(aObject); - if (!classInfo) { - NS_NOTREACHED("aObject must implement nsIClassInfo"); - return NS_ERROR_FAILURE; - } - - PRUint32 flags; - if (NS_SUCCEEDED(classInfo->GetFlags(&flags)) && - (flags & nsIClassInfo::SINGLETON)) { - MFL_SET_SINGLETON_FLAG(&entry->mInfo); - } - } else { - // Already serialized, recover oid and update the desired refcnt. - oid = entry->mOID; - if (aIsStrongRef) { - ++entry->mInfo.mStrongRefCnt; - NS_ASSERTION(entry->mInfo.mStrongRefCnt != 0, - "mStrongRefCnt overflow"); - } else { - MFL_BUMP_WEAK_REFCNT(&entry->mInfo); - NS_ASSERTION(MFL_GET_WEAK_REFCNT(&entry->mInfo) != 0, - "mWeakRefCnt overflow"); - } - - aObject->Release(); - } - } - - if (!aIsStrongRef) - oid |= MFL_WEAK_REF_TAG; - oid |= (aTags & MFL_QUERY_INTERFACE_TAG); - - rv = Write32(oid ^ MFL_OID_XOR_KEY); - if (NS_FAILED(rv)) - return rv; - - if (oid & MFL_OBJECT_DEF_TAG) { - nsCOMPtr serializable(do_QueryInterface(aObject)); - if (!serializable) { - NS_NOTREACHED("aObject must implement nsISerializable"); - return NS_ERROR_FAILURE; - } - - nsCID slowCID; - rv = classInfo->GetClassIDNoAlloc(&slowCID); - if (NS_FAILED(rv)) - return rv; - - NSFastLoadID fastCID; - rv = MapID(slowCID, &fastCID); - if (NS_FAILED(rv)) - return rv; - - rv = WriteFastID(fastCID); - if (NS_FAILED(rv)) - return rv; - - rv = serializable->Write(this); - if (NS_FAILED(rv)) - return rv; - } - - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileWriter::WriteObject(nsISupports* aObject, PRBool aIsStrongRef) -{ -#ifdef NS_DEBUG - nsCOMPtr rootObject(do_QueryInterface(aObject)); - - NS_ASSERTION(rootObject.get() == aObject, - "bad call to WriteObject -- call WriteCompoundObject!"); -#endif - - return WriteObjectCommon(aObject, aIsStrongRef, 0); -} - -NS_IMETHODIMP -nsFastLoadFileWriter::WriteSingleRefObject(nsISupports* aObject) -{ -#ifdef NS_DEBUG - nsCOMPtr rootObject(do_QueryInterface(aObject)); - - NS_ASSERTION(rootObject.get() == aObject, - "bad call to WriteSingleRefObject -- call WriteCompoundObject!"); -#endif - - return WriteObjectCommon(aObject, PR_TRUE, MFL_SINGLE_REF_PSEUDO_TAG); -} - -NS_IMETHODIMP -nsFastLoadFileWriter::WriteCompoundObject(nsISupports* aObject, - const nsIID& aIID, - PRBool aIsStrongRef) -{ - nsresult rv; - nsCOMPtr rootObject(do_QueryInterface(aObject)); - - // We could assert that |rootObject != aObject|, but that would prevent - // callers who don't know whether they're dealing with the primary - // nsISupports pointer (e.g., they don't know which implementation of - // nsIURI they have) from using this function. - -#ifdef NS_DEBUG - nsCOMPtr roundtrip; - rootObject->QueryInterface(aIID, getter_AddRefs(roundtrip)); - NS_ASSERTION(roundtrip.get() == aObject, - "bad aggregation or multiple inheritance detected by call to " - "WriteCompoundObject!"); -#endif - - rv = WriteObjectCommon(rootObject, aIsStrongRef, MFL_QUERY_INTERFACE_TAG); - if (NS_FAILED(rv)) - return rv; - - NSFastLoadID iid; - rv = MapID(aIID, &iid); - if (NS_FAILED(rv)) - return rv; - - return WriteFastID(iid); -} - -NS_IMETHODIMP -nsFastLoadFileWriter::WriteID(const nsID& aID) -{ - nsresult rv; - NSFastLoadID fastID; - - rv = MapID(aID, &fastID); - if (NS_FAILED(rv)) - return rv; - - return WriteFastID(fastID); -} - -NS_IMETHODIMP -nsFastLoadFileWriter::Seek(PRInt32 aWhence, PRInt64 aOffset) -{ - mCurrentDocumentMapEntry = nsnull; - return mSeekableOutput->Seek(aWhence, aOffset); -} - -NS_IMETHODIMP -nsFastLoadFileWriter::Tell(PRInt64 *aResult) -{ - return mSeekableOutput->Tell(aResult); -} - -NS_IMETHODIMP -nsFastLoadFileWriter::SetEOF() -{ - return mSeekableOutput->SetEOF(); -} - -NS_IMETHODIMP -nsFastLoadFileWriter::SetOutputStream(nsIOutputStream *aStream) -{ - nsresult rv = nsBinaryOutputStream::SetOutputStream(aStream); - mSeekableOutput = do_QueryInterface(mOutputStream); - return rv; -} - -NS_COM nsresult -NS_NewFastLoadFileWriter(nsIObjectOutputStream* *aResult, - nsIOutputStream* aDestStream, - nsIFastLoadFileIO* aFileIO) -{ - nsFastLoadFileWriter* writer = - new nsFastLoadFileWriter(aDestStream, aFileIO); - if (!writer) - return NS_ERROR_OUT_OF_MEMORY; - - // Stabilize writer's refcnt. - nsCOMPtr stream(writer); - - nsresult rv = writer->Open(); - if (NS_FAILED(rv)) - return rv; - - *aResult = stream; - NS_ADDREF(*aResult); - return NS_OK; -} - -// -------------------------- nsFastLoadFileUpdater -------------------------- - -NS_IMPL_ISUPPORTS_INHERITED0(nsFastLoadFileUpdater, - nsFastLoadFileWriter) - -PLDHashOperator -nsFastLoadFileUpdater::CopyReadDocumentMapEntryToUpdater(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData) -{ - nsDocumentMapReadEntry* readEntry = - static_cast(aHdr); - nsFastLoadFileUpdater* updater = - reinterpret_cast(aData); - - void* spec = nsMemory::Clone(readEntry->mString, - strlen(readEntry->mString) + 1); - if (!spec) - return PL_DHASH_STOP; - - nsDocumentMapWriteEntry* writeEntry = - static_cast - (PL_DHashTableOperate(&updater->mDocumentMap, spec, - PL_DHASH_ADD)); - if (!writeEntry) { - nsMemory::Free(spec); - return PL_DHASH_STOP; - } - - writeEntry->mString = reinterpret_cast(spec); - writeEntry->mURI = nsnull; - writeEntry->mInitialSegmentOffset = readEntry->mInitialSegmentOffset; - writeEntry->mCurrentSegmentOffset = 0; - return PL_DHASH_NEXT; -} - -nsresult -nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader) -{ - nsresult rv; - rv = nsFastLoadFileWriter::Init(); - if (NS_FAILED(rv)) - return rv; - - PRUint32 i, n; - - // Map from dense, zero-based, uint32 NSFastLoadID in reader to 16-byte - // nsID in updater. - nsID* readIDMap = aReader->mFooter.mIDMap; - for (i = 0, n = aReader->mFooter.mNumIDs; i < n; i++) { - NSFastLoadID fastID; - rv = MapID(readIDMap[i], &fastID); - NS_ASSERTION(fastID == i + 1, "huh?"); - if (NS_FAILED(rv)) - return rv; - } - - // Map from reader dense, zero-based MFL_OID_TO_SHARP_INDEX(oid) to sharp - // object offset and refcnt information in updater. - nsFastLoadFileReader::nsObjectMapEntry* readObjectMap = - aReader->mFooter.mObjectMap; - - // 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; - PRInt64 saveOffset = 0; - - for (i = 0, n = aReader->mFooter.mNumSharpObjects; i < n; i++) { - nsFastLoadFileReader::nsObjectMapEntry* readEntry = &readObjectMap[i]; - - NS_ASSERTION(readEntry->mCIDOffset != 0, - "fastload updater: mCIDOffset cannot be zero!"); - - // If the reader didn't read this object but it's a singleton, we must - // "deserialize" it now, to discover its one and only root nsISupports - // address. The object already exists in memory if it was created at - // startup without resort to the FastLoad file. The canonical example - // is the system principal object held by all XUL JS scripts. - - nsISupports* obj = readEntry->mReadObject; - if (!obj && MFL_GET_SINGLETON_FLAG(readEntry)) { - if (!saveDocMapEntry) { - rv = aReader->Tell(&saveOffset); - if (NS_FAILED(rv)) - return rv; - - saveDocMapEntry = aReader->mCurrentDocumentMapEntry; - aReader->mCurrentDocumentMapEntry = nsnull; - } - - rv = aReader->Seek(nsISeekableStream::NS_SEEK_SET, - readEntry->mCIDOffset); - if (NS_FAILED(rv)) - return rv; - - rv = aReader - ->DeserializeObject(getter_AddRefs(readEntry->mReadObject)); - if (NS_FAILED(rv)) - return rv; - obj = readEntry->mReadObject; - - // Don't forget to set mSkipOffset in case someone calls the reader - // to "deserialize" (yet again) the object we just read. - // - // Say the singleton is the system principal, and the FastLoad file - // contains data for navigator.xul including scripts and functions. - // If we update the FastLoad file to contain data for messenger.xul - // in a separate session started via mozilla -mail, *and during the - // same FastLoad episode in this session* race to open a navigator - // window, we will attempt to read all objects serialized in the - // navigator.xul portion of the FastLoad file. - // - // mSkipOffset must be set in such a case so the reader can skip - // the system principal's serialized data, because the updater for - // messenger.xul being opened here has already read it. - - rv = aReader->Tell(&readEntry->mSkipOffset); - if (NS_FAILED(rv)) - return rv; - } - - NSFastLoadOID oid = MFL_SHARP_INDEX_TO_OID(i); - void* key = obj - ? reinterpret_cast(obj) - : reinterpret_cast((oid | MFL_OBJECT_DEF_TAG)); - - nsSharpObjectMapEntry* writeEntry = - static_cast - (PL_DHashTableOperate(&mObjectMap, key, - PL_DHASH_ADD)); - if (!writeEntry) - return NS_ERROR_OUT_OF_MEMORY; - - // Hold the object if there is one, so that objmap_ClearEntry can - // release the reference. - NS_IF_ADDREF(obj); - writeEntry->mObject = reinterpret_cast(key); - writeEntry->mOID = oid; - writeEntry->mInfo.mCIDOffset = readEntry->mCIDOffset; - writeEntry->mInfo.mStrongRefCnt = readEntry->mSaveStrongRefCnt; - writeEntry->mInfo.mWeakRefCnt = readEntry->mSaveWeakRefCnt; - } - - // If we had to read any singletons, restore aReader's saved state. - if (saveDocMapEntry) { - rv = aReader->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset); - if (NS_FAILED(rv)) - return rv; - - aReader->mCurrentDocumentMapEntry = saveDocMapEntry; - } - - // Copy URI spec string and initial segment offset in FastLoad file from - // nsDocumentMapReadEntry in reader to nsDocumentMapWriteEntry in updater. - // If we didn't enumerate all entries, we ran out of memory. - n = PL_DHashTableEnumerate(&aReader->mFooter.mDocumentMap, - CopyReadDocumentMapEntryToUpdater, - this); - if (n != aReader->mFooter.mDocumentMap.entryCount) - return NS_ERROR_OUT_OF_MEMORY; - - // Copy source filename dependencies from reader to updater. - nsISupportsArray* readDeps = aReader->mFooter.mDependencies; - rv = readDeps->Count(&n); - if (NS_FAILED(rv)) - return rv; - - for (i = 0; i < n; i++) { - nsCOMPtr file; - rv = readDeps->GetElementAt(i, getter_AddRefs(file)); - if (NS_FAILED(rv)) - return rv; - - rv = AddDependency(file); - if (NS_FAILED(rv)) - return rv; - } - - // Seek to the reader's footer offset so we overwrite the footer. First, - // 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 = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, - offsetof(nsFastLoadHeader, mFooterOffset)); - if (NS_FAILED(rv)) - return rv; - - rv = Write32(0); - if (NS_FAILED(rv)) - return rv; - - rv = mSeekableOutput->Seek(nsISeekableStream::NS_SEEK_SET, - aReader->mHeader.mFooterOffset); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadFileUpdater::Close() -{ - // Call base-class Close implementation, which uses mFileIO. - nsresult rv = nsFastLoadFileWriter::Close(); - - // Break degenerate cycle from this->mFileIO to this. - mFileIO = nsnull; - return rv; -} - -NS_COM nsresult -NS_NewFastLoadFileUpdater(nsIObjectOutputStream* *aResult, - nsIFastLoadFileIO *aFileIO, - nsIObjectInputStream* aReaderAsStream) -{ - // Make sure that aReaderAsStream is an nsFastLoadFileReader. - nsCOMPtr reader(do_QueryInterface(aReaderAsStream)); - if (!reader) - return NS_ERROR_UNEXPECTED; - - nsCOMPtr output; - nsresult rv = aFileIO->GetOutputStream(getter_AddRefs(output)); - if (NS_FAILED(rv)) - return rv; - - nsFastLoadFileUpdater* updater = new nsFastLoadFileUpdater(output, aFileIO); - if (!updater) - return NS_ERROR_OUT_OF_MEMORY; - - // Stabilize updater's refcnt. - nsCOMPtr stream(updater); - - rv = updater->Open(static_cast(aReaderAsStream)); - if (NS_FAILED(rv)) - return rv; - - *aResult = stream; - NS_ADDREF(*aResult); - return NS_OK; -} diff --git a/xpcom/io/nsFastLoadFile.h b/xpcom/io/nsFastLoadFile.h deleted file mode 100644 index 2ec29aedb28..00000000000 --- a/xpcom/io/nsFastLoadFile.h +++ /dev/null @@ -1,582 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla FastLoad code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brendan Eich (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsFastLoadFile_h___ -#define nsFastLoadFile_h___ - -/** - * Mozilla FastLoad file format and helper types. - */ - -#include "prtypes.h" -#include "pldhash.h" -#include "nsAlgorithm.h" - -#include "nsBinaryStream.h" -#include "nsCOMPtr.h" -#include "nsDebug.h" -#include "nsID.h" -#include "nsMemory.h" - -#include "nsIFastLoadFileControl.h" -#include "nsIFastLoadService.h" -#include "nsISeekableStream.h" -#include "nsISupportsArray.h" - -/** - * FastLoad file Object ID (OID) is an identifier for multiply and cyclicly - * connected objects in the serialized graph of all reachable objects. - * - * Holy Mixed Metaphors: JS, after Common Lisp, uses #n= to define a "sharp - * variable" naming an object that's multiply or cyclicly connected, and #n# - * to stand for a connection to an already-defined object. We too call any - * object with multiple references "sharp", and (here it comes) any object - * with only one reference "dull". - * - * Note that only sharp objects require a mapping from OID to FastLoad file - * offset and other information. Dull objects can be serialized _in situ_ - * (where they are referenced) and deserialized when their (singular, shared) - * OID is scanned. - * - * We also compress 16-byte XPCOM IDs into 32-bit dense identifiers to save - * space. See nsFastLoadFooter, below, for the mapping data structure used to - * compute an nsID given an NSFastLoadID. - */ -typedef PRUint32 NSFastLoadID; // nsFastLoadFooter::mIDMap index -typedef PRUint32 NSFastLoadOID; // nsFastLoadFooter::mObjectMap index - -/** - * A Mozilla FastLoad file is an untagged (in general) stream of objects and - * primitive-type data. Small integers are fairly common, and could easily be - * confused for NSFastLoadIDs and NSFastLoadOIDs. To help catch bugs where - * reader and writer code fail to match, we XOR unlikely 32-bit numbers with - * NSFastLoad*IDs when storing and fetching. The following unlikely values are - * irrational numbers ((sqrt(5)-1)/2, sqrt(2)-1) represented in fixed point. - * - * The reader XORs, converts the ID to an index, and bounds-checks all array - * accesses that use the index. Array access code asserts that the index is in - * bounds, and returns a dummy array element if it isn't. - */ -#define MFL_ID_XOR_KEY 0x9E3779B9 // key XOR'd with ID when serialized -#define MFL_OID_XOR_KEY 0x6A09E667 // key XOR'd with OID when serialized - -/** - * An OID can be tagged to introduce the serialized definition of the object, - * or to stand for a strong or weak reference to that object. Thus the high - * 29 bits actually identify the object, and the low three bits tell whether - * the object is being defined or just referenced -- and via what inheritance - * chain or inner object, if necessary. - * - * The MFL_QUERY_INTERFACE_TAG bit helps us cope with aggregation and multiple - * inheritance: object identity follows the XPCOM rule, but a deserializer may - * need to query for an interface not on the primary inheritance chain ending - * in the nsISupports whose address uniquely identifies the XPCOM object being - * referenced or defined. - */ -#define MFL_OBJECT_TAG_BITS 3 -#define MFL_OBJECT_TAG_MASK PR_BITMASK(MFL_OBJECT_TAG_BITS) - -#define MFL_OBJECT_DEF_TAG 1U // object definition follows this OID -#define MFL_WEAK_REF_TAG 2U // OID weakly refers to a prior object - // NB: do not confuse with nsWeakPtr! -#define MFL_QUERY_INTERFACE_TAG 4U // QI object to the ID follows this OID - // NB: an NSFastLoadID, not an nsIID! - -/** - * The dull object identifier introduces the definition of all objects that - * have only one (necessarily strong) ref in the serialization. The definition - * appears at the point of reference. - */ -#define MFL_DULL_OBJECT_OID MFL_OBJECT_DEF_TAG - -/** - * Convert an OID to an index into nsFastLoadFooter::mObjectMap. - */ -#define MFL_OID_TO_SHARP_INDEX(oid) (((oid) >> MFL_OBJECT_TAG_BITS) - 1) -#define MFL_SHARP_INDEX_TO_OID(index) (((index) + 1) << MFL_OBJECT_TAG_BITS) - -/** - * Magic "number" at start of a FastLoad file. Inspired by the PNG "magic" - * string, which inspired XPCOM's typelib (.xpt) file magic. Guaranteed to be - * corrupted by FTP-as-ASCII and other likely errors, meaningful to clued-in - * humans, and ending in ^Z to terminate erroneous text input on Windows. - */ -#define MFL_FILE_MAGIC "XPCOM\nMozFASL\r\n\032" -#define MFL_FILE_MAGIC_SIZE 16 - -#define MFL_FILE_VERSION_0 0 -#define MFL_FILE_VERSION_1 1000 -#define MFL_FILE_VERSION 5 // rev'ed to defend against unversioned - // XPCOM JS component fastload files - -/** - * Compute Fletcher's 16-bit checksum over aLength bytes starting at aBuffer, - * with the initial accumulators seeded from *aChecksum, and final checksum - * returned in *aChecksum. The return value is the number of unchecked bytes, - * which may be non-zero if aBuffer is misaligned or aLength is odd. Callers - * should copy any remaining bytes to the front of the next buffer. - * - * If aLastBuffer is false, do not check any bytes remaining due to misaligned - * aBuffer or odd aLength, instead returning the remaining byte count. But if - * aLastBuffer is true, treat aBuffer as the last buffer in the file and check - * every byte, returning 0. Here's a read-loop checksumming sketch: - * - * char buf[BUFSIZE]; - * PRUint32 len, rem = 0; - * PRUint32 checksum = 0; - * - * while (NS_SUCCEEDED(rv = Read(buf + rem, sizeof buf - rem, &len)) && len) { - * len += rem; - * rem = NS_AccumulateFastLoadChecksum(&checksum, - * reinterpret_cast(buf), - * len, - * PR_FALSE); - * if (rem) - * memcpy(buf, buf + len - rem, rem); - * } - * - * if (rem) { - * NS_AccumulateFastLoadChecksum(&checksum, - * reinterpret_cast(buf), - * rem, - * PR_TRUE); - * } - * - * After this, if NS_SUCCEEDED(rv), checksum contains a valid FastLoad sum. - */ -NS_COM PRUint32 -NS_AccumulateFastLoadChecksum(PRUint32 *aChecksum, - const PRUint8* aBuffer, - PRUint32 aLength, - PRBool aLastBuffer); - -NS_COM PRUint32 -NS_AddFastLoadChecksums(PRUint32 sum1, PRUint32 sum2, PRUint32 sum2ByteCount); - -/** - * Header at the start of a FastLoad file. - */ -struct nsFastLoadHeader { - char mMagic[MFL_FILE_MAGIC_SIZE]; - PRUint32 mChecksum; - PRUint32 mVersion; - PRUint32 mFooterOffset; - PRUint32 mFileSize; -}; - -/** - * Footer prefix structure (footer header, ugh), after which come arrays of - * structures or strings counted by these members. - */ -struct nsFastLoadFooterPrefix { - PRUint32 mNumIDs; - PRUint32 mNumSharpObjects; - PRUint32 mNumMuxedDocuments; - PRUint32 mNumDependencies; -}; - -struct nsFastLoadSharpObjectInfo { - PRUint32 mCIDOffset; // offset of object's NSFastLoadID and data - PRUint16 mStrongRefCnt; - PRUint16 mWeakRefCnt; // high bit is singleton flag, see below -}; - -#define MFL_SINGLETON_FLAG 0x8000 -#define MFL_WEAK_REFCNT_MASK 0x7fff - -#define MFL_GET_SINGLETON_FLAG(ip) ((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG) -#define MFL_GET_WEAK_REFCNT(ip) ((ip)->mWeakRefCnt & MFL_WEAK_REFCNT_MASK) - -#define MFL_SET_SINGLETON_FLAG(ip) \ - ((ip)->mWeakRefCnt |= MFL_SINGLETON_FLAG) -#define MFL_SET_WEAK_REFCNT(ip,rc) \ - ((ip)->mWeakRefCnt = (((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG) | (rc))) - -#define MFL_BUMP_WEAK_REFCNT(ip) (++(ip)->mWeakRefCnt) -#define MFL_DROP_WEAK_REFCNT(ip) (--(ip)->mWeakRefCnt) - -struct nsFastLoadMuxedDocumentInfo { - const char* mURISpec; - PRUint32 mInitialSegmentOffset; -}; - -// forward declarations of opaque types defined in nsFastLoadFile.cpp -struct nsDocumentMapReadEntry; -struct nsDocumentMapWriteEntry; - -// So nsFastLoadFileUpdater can verify that its nsIObjectInputStream parameter -// is an nsFastLoadFileReader. -#define NS_FASTLOADFILEREADER_IID \ - {0x7d37d1bb,0xcef3,0x4c5f,{0x97,0x68,0x0f,0x89,0x7f,0x1a,0xe1,0x40}} - -struct nsIFastLoadFileReader : public nsISupports { - NS_DECLARE_STATIC_IID_ACCESSOR(NS_FASTLOADFILEREADER_IID) -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsIFastLoadFileReader, NS_FASTLOADFILEREADER_IID) - -/** - * Inherit from the concrete class nsBinaryInputStream, which inherits from - * abstract nsIObjectInputStream but does not implement its direct methods. - * Though the names are not as clear as I'd like, this seems to be the best - * way to share nsBinaryStream.cpp code. - */ -class nsFastLoadFileReader - : public nsBinaryInputStream, - public nsIFastLoadReadControl, - public nsISeekableStream, - public nsIFastLoadFileReader -{ - public: - nsFastLoadFileReader(nsIFile *aFile) - : mCurrentDocumentMapEntry(nsnull), mFile(aFile), - mFileLen(0), mFilePos(0), mFileMap(nsnull), mFileData(nsnull) - { - MOZ_COUNT_CTOR(nsFastLoadFileReader); - } - - virtual ~nsFastLoadFileReader() { - Close(); - MOZ_COUNT_DTOR(nsFastLoadFileReader); - } - - private: - // nsISupports methods - NS_DECL_ISUPPORTS_INHERITED - - // overridden nsIObjectInputStream methods - NS_IMETHOD ReadObject(PRBool aIsStrongRef, nsISupports* *_retval); - NS_IMETHOD ReadID(nsID *aResult); - - void SeekTo(PRInt64 aOffset) { - mFilePos = NS_MAX(0, NS_MIN(aOffset, mFileLen)); - NS_ASSERTION(aOffset == mFilePos, "Attempt to seek out of bounds"); - } - - // nsIFastLoadFileControl methods - NS_DECL_NSIFASTLOADFILECONTROL - - // nsIFastLoadReadControl methods - NS_DECL_NSIFASTLOADREADCONTROL - - // nsISeekableStream methods - NS_DECL_NSISEEKABLESTREAM - - // Override Read so we can demultiplex a document interleaved with others. - NS_IMETHOD Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead); - nsresult ReadHeader(nsFastLoadHeader *aHeader); - - /** - * In-memory representation of an indexed nsFastLoadSharpObjectInfo record. - */ - struct nsObjectMapEntry : public nsFastLoadSharpObjectInfo { - nsCOMPtr mReadObject; - PRInt64 mSkipOffset; - PRUint16 mSaveStrongRefCnt; // saved for an Update - PRUint16 mSaveWeakRefCnt; // after a Read - }; - - NS_IMETHODIMP ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, - PRUint32 aCount, PRUint32 *aResult); - - /** - * In-memory representation of the FastLoad file footer. - */ - struct nsFastLoadFooter : public nsFastLoadFooterPrefix { - nsFastLoadFooter() - : mIDMap(nsnull), - mObjectMap(nsnull) { - mDocumentMap.ops = mURIMap.ops = nsnull; - } - - ~nsFastLoadFooter() { - delete[] mIDMap; - delete[] mObjectMap; - if (mDocumentMap.ops) - PL_DHashTableFinish(&mDocumentMap); - if (mURIMap.ops) - PL_DHashTableFinish(&mURIMap); - } - - // These can't be static within GetID and GetSharpObjectEntry or the - // toolchains on HP-UX 10.20's, RH 7.0, and Mac OS X all barf at link - // time ("common symbols not allowed with MY_DHLIB output format", to - // quote the OS X rev of gcc). - static nsID gDummyID; - static nsObjectMapEntry gDummySharpObjectEntry; - - const nsID& GetID(NSFastLoadID aFastId) const { - PRUint32 index = aFastId - 1; - NS_ASSERTION(index < mNumIDs, "aFastId out of range"); - if (index >= mNumIDs) - return gDummyID; - return mIDMap[index]; - } - - nsObjectMapEntry& - GetSharpObjectEntry(NSFastLoadOID aOID) const { - PRUint32 index = MFL_OID_TO_SHARP_INDEX(aOID); - NS_ASSERTION(index < mNumSharpObjects, "aOID out of range"); - if (index >= mNumSharpObjects) - return gDummySharpObjectEntry; - return mObjectMap[index]; - } - - // Map from dense, zero-based, uint32 NSFastLoadID to 16-byte nsID. - nsID* mIDMap; - - // Map from dense, zero-based MFL_OID_TO_SHARP_INDEX(oid) to sharp - // object offset and refcnt information. - nsObjectMapEntry* mObjectMap; - - // Map from URI spec string to nsDocumentMapReadEntry, which helps us - // demultiplex a document's objects from among the interleaved object - // stream segments in the FastLoad file. - PLDHashTable mDocumentMap; - - // Fast mapping from URI object pointer to mDocumentMap entry, valid - // only while the muxed document is loading. - PLDHashTable mURIMap; - - // List of source filename dependencies that should trigger regeneration - // of the FastLoad file. - nsCOMPtr mDependencies; - }; - - nsresult ReadFooter(nsFastLoadFooter *aFooter); - nsresult ReadFooterPrefix(nsFastLoadFooterPrefix *aFooterPrefix); - nsresult ReadSlowID(nsID *aID); - nsresult ReadFastID(NSFastLoadID *aID); - nsresult ReadSharpObjectInfo(nsFastLoadSharpObjectInfo *aInfo); - nsresult ReadMuxedDocumentInfo(nsFastLoadMuxedDocumentInfo *aInfo); - nsresult DeserializeObject(nsISupports* *aObject); - - nsresult Open(); - NS_IMETHOD Close(); - - protected: - nsFastLoadHeader mHeader; - nsFastLoadFooter mFooter; - - nsDocumentMapReadEntry* mCurrentDocumentMapEntry; - - friend class nsFastLoadFileUpdater; - nsIFile *mFile; // .mfasl file - PRUint32 mFileLen; // length of file - PRUint32 mFilePos; // current position within file - PRFileMap *mFileMap;// nspr datastructure for mmap - PRUint8 *mFileData; // pointer to mmaped file -}; - -NS_COM nsresult -NS_NewFastLoadFileReader(nsIObjectInputStream* *aResult NS_OUTPARAM, - nsIFile* aFile); - -/** - * Inherit from the concrete class nsBinaryInputStream, which inherits from - * abstract nsIObjectInputStream but does not implement its direct methods. - * Though the names are not as clear as I'd like, this seems to be the best - * way to share nsBinaryStream.cpp code. - */ -class nsFastLoadFileWriter - : public nsBinaryOutputStream, - public nsIFastLoadWriteControl, - public nsISeekableStream -{ - public: - nsFastLoadFileWriter(nsIOutputStream *aStream, nsIFastLoadFileIO* aFileIO) - : mCurrentDocumentMapEntry(nsnull), - mFileIO(aFileIO) - { - SetOutputStream(aStream); - mHeader.mChecksum = 0; - mIDMap.ops = mObjectMap.ops = mDocumentMap.ops = mURIMap.ops = nsnull; - mDependencyMap.ops = nsnull; - MOZ_COUNT_CTOR(nsFastLoadFileWriter); - } - - virtual ~nsFastLoadFileWriter() - { - if (mIDMap.ops) - PL_DHashTableFinish(&mIDMap); - if (mObjectMap.ops) - PL_DHashTableFinish(&mObjectMap); - if (mDocumentMap.ops) - PL_DHashTableFinish(&mDocumentMap); - if (mURIMap.ops) - PL_DHashTableFinish(&mURIMap); - if (mDependencyMap.ops) - PL_DHashTableFinish(&mDependencyMap); - MOZ_COUNT_DTOR(nsFastLoadFileWriter); - } - - private: - // nsISupports methods - NS_DECL_ISUPPORTS_INHERITED - - // overridden nsIObjectOutputStream methods - NS_IMETHOD WriteObject(nsISupports* aObject, PRBool aIsStrongRef); - NS_IMETHOD WriteSingleRefObject(nsISupports* aObject); - NS_IMETHOD WriteCompoundObject(nsISupports* aObject, - const nsIID& aIID, - 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 - - // nsIFastLoadWriteControl methods - NS_DECL_NSIFASTLOADWRITECONTROL - - // nsISeekableStream methods - NS_DECL_NSISEEKABLESTREAM - - nsresult MapID(const nsID& aSlowID, NSFastLoadID *aResult); - - nsresult WriteHeader(nsFastLoadHeader *aHeader); - nsresult WriteFooter(); - nsresult WriteFooterPrefix(const nsFastLoadFooterPrefix& aFooterPrefix); - nsresult WriteSlowID(const nsID& aID); - nsresult WriteFastID(NSFastLoadID aID); - nsresult WriteSharpObjectInfo(const nsFastLoadSharpObjectInfo& aInfo); - nsresult WriteMuxedDocumentInfo(const nsFastLoadMuxedDocumentInfo& aInfo); - - nsresult Init(); - nsresult Open(); - NS_IMETHOD Close(); - - nsresult WriteObjectCommon(nsISupports* aObject, - PRBool aIsStrongRef, - PRUint32 aQITag); - - static PLDHashOperator - IDMapEnumerate(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData); - - static PLDHashOperator - ObjectMapEnumerate(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData); - - static PLDHashOperator - DocumentMapEnumerate(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData); - - static PLDHashOperator - DependencyMapEnumerate(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData); - - protected: - // Kept in sync with mOutputStream to avoid repeated QI - nsCOMPtr mSeekableOutput; - - nsFastLoadHeader mHeader; - - PLDHashTable mIDMap; - PLDHashTable mObjectMap; - PLDHashTable mDocumentMap; - PLDHashTable mURIMap; - PLDHashTable mDependencyMap; - - nsDocumentMapWriteEntry* mCurrentDocumentMapEntry; - nsCOMPtr mFileIO; -}; - -NS_COM nsresult -NS_NewFastLoadFileWriter(nsIObjectOutputStream* *aResult NS_OUTPARAM, - nsIOutputStream* aDestStream, - nsIFastLoadFileIO* aFileIO); - -/** - * Subclass of nsFastLoadFileWriter, friend of nsFastLoadFileReader which it - * wraps when a FastLoad file needs to be updated. The wrapped reader can be - * used to demulitplex data for documents already in the FastLoad file, while - * the updater writes new data over the old footer, then writes a new footer - * that maps all data on Close. - */ -class nsFastLoadFileUpdater - : public nsFastLoadFileWriter -{ - public: - nsFastLoadFileUpdater(nsIOutputStream* aOutputStream, nsIFastLoadFileIO *aFileIO) - : nsFastLoadFileWriter(aOutputStream, aFileIO) { - MOZ_COUNT_CTOR(nsFastLoadFileUpdater); - } - - virtual ~nsFastLoadFileUpdater() { - MOZ_COUNT_DTOR(nsFastLoadFileUpdater); - } - - private: - // nsISupports methods - NS_DECL_ISUPPORTS_INHERITED - - nsresult Open(nsFastLoadFileReader* aReader); - NS_IMETHOD Close(); - - static PLDHashOperator - CopyReadDocumentMapEntryToUpdater(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - PRUint32 aNumber, - void *aData); - - friend class nsFastLoadFileReader; - - protected: - nsCOMPtr mInputStream; - - // Kept in sync with mInputStream to avoid repeated QI - nsCOMPtr mSeekableInput; -}; - -NS_COM nsresult -NS_NewFastLoadFileUpdater(nsIObjectOutputStream* *aResult NS_OUTPARAM, - nsIFastLoadFileIO* aFileIO, - nsIObjectInputStream* aReaderAsStream); - -#endif // nsFastLoadFile_h___ diff --git a/xpcom/io/nsFastLoadService.cpp b/xpcom/io/nsFastLoadService.cpp deleted file mode 100644 index 276a97e2754..00000000000 --- a/xpcom/io/nsFastLoadService.cpp +++ /dev/null @@ -1,558 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla FastLoad code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brendan Eich (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "prtypes.h" -#include "prio.h" -#include "prtime.h" -#include "pldhash.h" - -#include "nsAppDirectoryServiceDefs.h" -#include "nsCOMPtr.h" -#include "nsFastLoadFile.h" -#include "nsFastLoadService.h" -#include "nsString.h" - -#include "nsIComponentManager.h" -#include "nsIEnumerator.h" -#include "nsIFastLoadFileControl.h" -#include "nsIFile.h" -#include "nsIObjectInputStream.h" -#include "nsIObjectOutputStream.h" -#include "nsISeekableStream.h" -#include "nsISupports.h" - -using namespace mozilla; - -NS_IMPL_THREADSAFE_ISUPPORTS1(nsFastLoadService, nsIFastLoadService) - -nsFastLoadService::nsFastLoadService() - : mLock("nsFastLoadService.mLock"), - mFastLoadPtrMap(nsnull), - mDirection(0) -{ -} - -nsFastLoadService::~nsFastLoadService() -{ - if (mInputStream) - mInputStream->Close(); - if (mOutputStream) - mOutputStream->Close(); - - if (mFastLoadPtrMap) - PL_DHashTableDestroy(mFastLoadPtrMap); -} - -nsresult -nsFastLoadService::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) -{ - *aResult = nsnull; - if (aOuter) - return NS_ERROR_NO_AGGREGATION; - - nsFastLoadService* fastLoadService = new nsFastLoadService(); - if (!fastLoadService) - return NS_ERROR_OUT_OF_MEMORY; - - NS_ADDREF(fastLoadService); - nsresult rv = fastLoadService->QueryInterface(aIID, aResult); - NS_RELEASE(fastLoadService); - return rv; -} - -nsresult -nsFastLoadService::NewFastLoadFile(const char* aBaseName, nsIFile* *aResult) -{ - nsresult rv; - - // Try "ProfDS" first, so that we can get the profile directory - // during startup. - nsCOMPtr profFile; - rv = NS_GetSpecialDirectory("ProfDS", - getter_AddRefs(profFile)); - if (NS_FAILED(rv)) { - // The directory service doesn't know about "ProfDS", so just ask - // for the regular profile directory key. Note, however, that this - // will fail if a profile hasn't yet been selected. - rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, - getter_AddRefs(profFile)); - if (NS_FAILED(rv)) { - return rv; - } - } - - // Try "ProfLDS" first, so that we can get the local profile directory - // during startup. - nsCOMPtr file; - rv = NS_GetSpecialDirectory("ProfLDS", getter_AddRefs(file)); - if (NS_FAILED(rv)) { - // The directory service doesn't know about "ProfLDS", so just ask - // for the regular local profile directory key. Note, however, that - // this will fail if a profile hasn't yet been selected. - rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR, - getter_AddRefs(file)); - } - if (NS_FAILED(rv)) - file = profFile; - - PRBool sameDir; - rv = file->Equals(profFile, &sameDir); - if (NS_FAILED(rv)) - return rv; - - nsCAutoString name(aBaseName); - name += PLATFORM_FASL_SUFFIX; - rv = file->AppendNative(name); - if (NS_FAILED(rv)) - return rv; - - if (!sameDir) { - // Cleanup any pre-existing fastload files that may live in the profile - // directory from previous versions of the code that didn't store them - // in the profile temp directory. - rv = profFile->AppendNative(name); - if (NS_SUCCEEDED(rv)) - profFile->Remove(PR_FALSE); // OK if this fails - } - - *aResult = file; - NS_ADDREF(*aResult); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::NewInputStream(nsIFile *aFile, nsIObjectInputStream* *aResult) -{ - MutexAutoLock lock(mLock); - - nsCOMPtr stream; - nsresult rv = NS_NewFastLoadFileReader(getter_AddRefs(stream), aFile); - if (NS_FAILED(rv)) - return rv; - - mFileIO->DisableTruncate(); - *aResult = stream; - NS_ADDREF(*aResult); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::NewOutputStream(nsIOutputStream* aDestStream, - nsIObjectOutputStream* *aResult) -{ - MutexAutoLock lock(mLock); - - return NS_NewFastLoadFileWriter(aResult, aDestStream, mFileIO); -} - -NS_IMETHODIMP -nsFastLoadService::GetInputStream(nsIObjectInputStream* *aResult) -{ - NS_IF_ADDREF(*aResult = mInputStream); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::SetInputStream(nsIObjectInputStream* aStream) -{ - MutexAutoLock lock(mLock); - mInputStream = aStream; - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::GetOutputStream(nsIObjectOutputStream* *aResult) -{ - NS_IF_ADDREF(*aResult = mOutputStream); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::SetOutputStream(nsIObjectOutputStream* aStream) -{ - MutexAutoLock lock(mLock); - mOutputStream = aStream; - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::GetFileIO(nsIFastLoadFileIO* *aResult) -{ - NS_IF_ADDREF(*aResult = mFileIO); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::SetFileIO(nsIFastLoadFileIO* aFileIO) -{ - MutexAutoLock lock(mLock); - mFileIO = aFileIO; - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::GetDirection(PRInt32 *aResult) -{ - *aResult = mDirection; - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::HasMuxedDocument(const char* aURISpec, PRBool *aResult) -{ - nsresult rv = NS_ERROR_NOT_AVAILABLE; - nsCOMPtr control; - - *aResult = PR_FALSE; - MutexAutoLock lock(mLock); - - if (mInputStream) { - control = do_QueryInterface(mInputStream); - if (control) - rv = control->HasMuxedDocument(aURISpec, aResult); - } - - if (! *aResult && mOutputStream) { - control = do_QueryInterface(mOutputStream); - if (control) - rv = control->HasMuxedDocument(aURISpec, aResult); - } - - return rv; -} - -NS_IMETHODIMP -nsFastLoadService::StartMuxedDocument(nsISupports* aURI, const char* aURISpec, - PRInt32 aDirectionFlags) -{ - nsresult rv = NS_ERROR_NOT_AVAILABLE; - nsCOMPtr control; - MutexAutoLock lock(mLock); - - // Try for an input stream first, in case aURISpec's data is multiplexed - // in the current FastLoad file. - if ((aDirectionFlags & NS_FASTLOAD_READ) && mInputStream) { - control = do_QueryInterface(mInputStream); - if (control) { - // If aURISpec is not in the multiplex, control->StartMuxedDocument - // will return NS_ERROR_NOT_AVAILABLE. - rv = control->StartMuxedDocument(aURI, aURISpec); - if (NS_SUCCEEDED(rv) || rv != NS_ERROR_NOT_AVAILABLE) - return rv; - - // Ok, aURISpec is not in the existing mux. If we have no output - // stream yet, wrap the reader with a FastLoad file updater. - if (!mOutputStream && mFileIO) { - // NB: mInputStream must be an nsFastLoadFileReader! - rv = NS_NewFastLoadFileUpdater(getter_AddRefs(mOutputStream), - mFileIO, mInputStream); - if (NS_FAILED(rv)) - return rv; - } - - if (aDirectionFlags == NS_FASTLOAD_READ) { - // Tell our caller to re-start multiplexing, rather than attempt - // to select and deserialize now. - return NS_ERROR_NOT_AVAILABLE; - } - } - } - - if ((aDirectionFlags & NS_FASTLOAD_WRITE) && mOutputStream) { - control = do_QueryInterface(mOutputStream); - if (control) - rv = control->StartMuxedDocument(aURI, aURISpec); - } - return rv; -} - -NS_IMETHODIMP -nsFastLoadService::SelectMuxedDocument(nsISupports* aURI, nsISupports** aResult) -{ - nsresult rv = NS_ERROR_NOT_AVAILABLE; - nsCOMPtr control; - MutexAutoLock lock(mLock); - - // Try to select the reader, if any; then only if the URI was not in the - // file already, select the writer/updater. - if (mInputStream) { - control = do_QueryInterface(mInputStream); - if (control) { - rv = control->SelectMuxedDocument(aURI, aResult); - if (NS_SUCCEEDED(rv)) - mDirection = NS_FASTLOAD_READ; - } - } - - if (rv == NS_ERROR_NOT_AVAILABLE && mOutputStream) { - control = do_QueryInterface(mOutputStream); - if (control) { - rv = control->SelectMuxedDocument(aURI, aResult); - if (NS_SUCCEEDED(rv)) - mDirection = NS_FASTLOAD_WRITE; - } - } - - return rv; -} - -NS_IMETHODIMP -nsFastLoadService::EndMuxedDocument(nsISupports* aURI) -{ - nsresult rv = NS_ERROR_NOT_AVAILABLE; - nsCOMPtr control; - MutexAutoLock lock(mLock); - - // Try to end the document identified by aURI in the reader, if any; then - // only if the URI was not in the file already, end the writer/updater. - if (mInputStream) { - control = do_QueryInterface(mInputStream); - if (control) - rv = control->EndMuxedDocument(aURI); - } - - if (rv == NS_ERROR_NOT_AVAILABLE && mOutputStream) { - control = do_QueryInterface(mOutputStream); - if (control) - rv = control->EndMuxedDocument(aURI); - } - - mDirection = 0; - return rv; -} - -NS_IMETHODIMP -nsFastLoadService::AddDependency(nsIFile* aFile) -{ - MutexAutoLock lock(mLock); - - nsCOMPtr control(do_QueryInterface(mOutputStream)); - if (!control) - return NS_ERROR_NOT_AVAILABLE; - - return control->AddDependency(aFile); -} - -NS_IMETHODIMP -nsFastLoadService::ComputeChecksum(nsIFile* aFile, - nsIFastLoadReadControl* aControl, - PRUint32 *aChecksum) -{ - nsCAutoString path; - nsresult rv = aFile->GetNativePath(path); - if (NS_FAILED(rv)) - return rv; - - nsCStringKey key(path); - PRUint32 checksum = NS_PTR_TO_INT32(mChecksumTable.Get(&key)); - if (checksum) { - *aChecksum = checksum; - return NS_OK; - } - - rv = aControl->ComputeChecksum(&checksum); - if (NS_FAILED(rv)) - return rv; - - mChecksumTable.Put(&key, NS_INT32_TO_PTR(checksum)); - *aChecksum = checksum; - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::CacheChecksum(nsIFile* aFile, nsIObjectOutputStream *aStream) -{ - nsCOMPtr control(do_QueryInterface(aStream)); - if (!control) - return NS_ERROR_FAILURE; - - PRUint32 checksum; - nsresult rv = control->GetChecksum(&checksum); - if (NS_FAILED(rv)) - return rv; - - nsCAutoString path; - rv = aFile->GetNativePath(path); - if (NS_FAILED(rv)) - return rv; - - nsCStringKey key(path); - mChecksumTable.Put(&key, NS_INT32_TO_PTR(checksum)); - return NS_OK; -} - -struct nsFastLoadPtrEntry : public PLDHashEntryHdr { - nsISupports** mPtrAddr; // key, must come first for PL_DHashGetStubOps - PRUint32 mOffset; -}; - -NS_IMETHODIMP -nsFastLoadService::GetFastLoadReferent(nsISupports* *aPtrAddr) -{ - NS_ASSERTION(*aPtrAddr == nsnull, - "aPtrAddr doesn't point to null nsFastLoadPtr::mRawAddr?"); - - MutexAutoLock lock(mLock); - if (!mFastLoadPtrMap || !mInputStream) - return NS_OK; - - nsFastLoadPtrEntry* entry = - static_cast - (PL_DHashTableOperate(mFastLoadPtrMap, aPtrAddr, - PL_DHASH_LOOKUP)); - if (PL_DHASH_ENTRY_IS_FREE(entry)) - return NS_OK; - - nsresult rv; - nsCOMPtr seekable(do_QueryInterface(mInputStream)); - - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, entry->mOffset); - if (NS_FAILED(rv)) - return rv; - - rv = mInputStream->ReadObject(PR_TRUE, aPtrAddr); - if (NS_FAILED(rv)) - return rv; - - // Shrink the table if half the entries are removed sentinels. - PRUint32 size = PL_DHASH_TABLE_SIZE(mFastLoadPtrMap); - if (mFastLoadPtrMap->removedCount >= (size >> 2)) - PL_DHashTableOperate(mFastLoadPtrMap, entry, PL_DHASH_REMOVE); - else - PL_DHashTableRawRemove(mFastLoadPtrMap, entry); - - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::ReadFastLoadPtr(nsIObjectInputStream* aInputStream, - nsISupports* *aPtrAddr) -{ - // nsFastLoadPtrs self-construct to null, so if we have a non-null value - // in our inout parameter, we must have been read already, alright! - if (*aPtrAddr) - return NS_OK; - - nsresult rv; - PRUint32 nextOffset; - MutexAutoLock lock(mLock); - - rv = aInputStream->Read32(&nextOffset); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr seekable(do_QueryInterface(aInputStream)); - if (!seekable) - return NS_ERROR_FAILURE; - - PRInt64 thisOffset; - rv = seekable->Tell(&thisOffset); - if (NS_FAILED(rv)) - return rv; - - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, nextOffset); - if (NS_FAILED(rv)) - return rv; - - if (!mFastLoadPtrMap) { - mFastLoadPtrMap = PL_NewDHashTable(PL_DHashGetStubOps(), this, - sizeof(nsFastLoadPtrEntry), - PL_DHASH_MIN_SIZE); - if (!mFastLoadPtrMap) - return NS_ERROR_OUT_OF_MEMORY; - } - - nsFastLoadPtrEntry* entry = - static_cast - (PL_DHashTableOperate(mFastLoadPtrMap, aPtrAddr, - PL_DHASH_ADD)); - NS_ASSERTION(entry->mPtrAddr == nsnull, "duplicate nsFastLoadPtr?!"); - - entry->mPtrAddr = aPtrAddr; - - LL_L2UI(entry->mOffset, thisOffset); - return NS_OK; -} - -NS_IMETHODIMP -nsFastLoadService::WriteFastLoadPtr(nsIObjectOutputStream* aOutputStream, - nsISupports* aObject) -{ - NS_ASSERTION(aObject != nsnull, "writing an unread nsFastLoadPtr?!"); - if (!aObject) - return NS_ERROR_UNEXPECTED; - - nsresult rv; - MutexAutoLock lock(mLock); // serialize writes to aOutputStream - - nsCOMPtr seekable(do_QueryInterface(aOutputStream)); - if (!seekable) - return NS_ERROR_FAILURE; - - PRInt64 saveOffset; - rv = seekable->Tell(&saveOffset); - if (NS_FAILED(rv)) - return rv; - - rv = aOutputStream->Write32(0); // nextOffset placeholder - if (NS_FAILED(rv)) - return rv; - - rv = aOutputStream->WriteObject(aObject, PR_TRUE); - if (NS_FAILED(rv)) - return rv; - - PRInt64 nextOffset; - rv = seekable->Tell(&nextOffset); - if (NS_FAILED(rv)) - return rv; - - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset); - if (NS_FAILED(rv)) - return rv; - - rv = aOutputStream->Write32(nextOffset); - if (NS_FAILED(rv)) - return rv; - - rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, nextOffset); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} diff --git a/xpcom/io/nsFastLoadService.h b/xpcom/io/nsFastLoadService.h deleted file mode 100644 index 4300e6fdd7c..00000000000 --- a/xpcom/io/nsFastLoadService.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla FastLoad code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brendan Eich (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "prtypes.h" -#include "pldhash.h" -#include "mozilla/Mutex.h" -#include "nsCOMPtr.h" -#include "nsHashtable.h" -#include "nsIFastLoadService.h" -#include "nsIObjectInputStream.h" -#include "nsIObjectOutputStream.h" - -class nsFastLoadFileReader; -class nsFastLoadFileWriter; - -class nsFastLoadService : public nsIFastLoadService -{ - public: - nsFastLoadService(); - private: - ~nsFastLoadService(); - - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIFASTLOADSERVICE - - static nsresult - Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); - - private: - mozilla::Mutex mLock; - PLDHashTable* mFastLoadPtrMap; - nsCOMPtr mInputStream; - nsCOMPtr mOutputStream; - nsCOMPtr mFileIO; - PRInt32 mDirection; - nsHashtable mChecksumTable; -}; diff --git a/xpcom/io/nsIFastLoadFileControl.idl b/xpcom/io/nsIFastLoadFileControl.idl deleted file mode 100644 index 91f8c755868..00000000000 --- a/xpcom/io/nsIFastLoadFileControl.idl +++ /dev/null @@ -1,123 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla FastLoad code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brendan Eich (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsISupports.idl" -#include "nsrootidl.idl" - -interface nsIFile; -interface nsISimpleEnumerator; - -/** - * The nsIFastLoadFileControl interface and its subinterfaces are mix-ins for - * classes implementing nsIObjectInputStream and nsIObjectOutputStream, so that - * those stream types can be used with nsIFastLoadService to access and compute - * FastLoad file checksums, update and check FastLoad file dependencies, and - * multiplex documents loaded via non-blocking i/o. - * - * If an nsIObjectInputStream class doesn't support nsIFastLoadReadControl, or - * an nsIObjectOutputStream class doesn't support nsIFastLoadWriteControl, that - * implementation may still be useful for object serialization, but it can't be - * used to read or write a Mozilla FastLoad file. - */ -[scriptable, uuid(e7c8c14f-c273-4e70-826f-b85864303dc6)] -interface nsIFastLoadFileControl : nsISupports -{ - /** - * Get the recorded checksum value from the FastLoad file header. - */ - readonly attribute PRUint32 checksum; - - /** - * Multiplexed document control methods. A FastLoad file may contain - * multiple interleaved documents identified by a URI specifier string, - * and indexed for fast multiplexor select by an opaque URI object key. - * You StartMuxedDocument when initiating a document load, then Select - * before every batch of calls to (de)serialize document data, and End - * when the load completes. - * - * Document multiplexing is necessary to support incremental FastLoad - * development in a non-blocking i/o architecture such as Mozilla, where - * some (but not all, at first, or for a while during development) of the - * results of parsing and compiling various inputs can be multiplexed to - * or from a FastLoad file. - * - * Note: Select returns the previously selected URI object in case the - * caller is synchronously selecting and writing data to the FastLoad - * file, so the caller can reselect the previous URI and return to code - * the continues to write FastLoad data for the previous URI, unaware of - * the nested select/write/reselect. - */ - void startMuxedDocument(in nsISupports aURI, in string aURISpec); - nsISupports selectMuxedDocument(in nsISupports aURI); - void endMuxedDocument(in nsISupports aURI); - - /** - * Return true if aURISpec identifies a muxed document in the FastLoad - * file, false otherwise. - */ - boolean hasMuxedDocument(in string aURISpec); -}; - -[scriptable, uuid(7604429c-6090-40fe-a87b-928221a1ca67)] -interface nsIFastLoadReadControl : nsIFastLoadFileControl -{ - /** - * Computes the correct checksum of the FastLoad file, independent of the - * header's checksum value. The header checksum field is treated as zero - * when computing the checksum. - */ - PRUint32 computeChecksum(); - - /** - * Get the collection of dependency nsIFile instances recorded during the - * FastLoad file write or read/update process, and checked during the read - * process to invalidate the FastLoad file if any dependencies are newer. - */ - readonly attribute nsISimpleEnumerator dependencies; -}; - -[scriptable, uuid(3dbdca8f-0631-4826-a29c-8aba1deea09d)] -interface nsIFastLoadWriteControl : nsIFastLoadFileControl -{ - /** - * Add a file dependency of the FastLoad file (e.g., a .jar file) to the - * set of dependencies that trigger regeneration if any dependency has a - * last-modified-time greater than the FastLoad file's mtime. - */ - void addDependency(in nsIFile aFile); -}; diff --git a/xpcom/io/nsIFastLoadService.idl b/xpcom/io/nsIFastLoadService.idl deleted file mode 100644 index b5b65ffdddc..00000000000 --- a/xpcom/io/nsIFastLoadService.idl +++ /dev/null @@ -1,171 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla FastLoad code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brendan Eich (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsISupports.idl" -#include "nsrootidl.idl" - -interface nsIFastLoadReadControl; -interface nsIFile; -interface nsIInputStream; -interface nsIOutputStream; -interface nsIObjectInputStream; -interface nsIObjectOutputStream; - -[scriptable, uuid(61cd17e0-b07a-4158-9817-36a206b100e9)] -interface nsIFastLoadFileIO : nsISupports -{ - readonly attribute nsIInputStream inputStream; - readonly attribute nsIOutputStream outputStream; - /** - * Causes outputStream to be created in non-truncating mode - */ - [noscript] void disableTruncate(); -}; - -[scriptable, uuid(c18df300-c2e4-4115-a61c-9110655f7dd8)] -interface nsIFastLoadService : nsISupports -{ - nsIFile newFastLoadFile(in string aBaseName); - - nsIObjectInputStream newInputStream(in nsIFile aFile); - nsIObjectOutputStream newOutputStream(in nsIOutputStream aDestStream); - - // Flag values for the direction attribute and the aDirectionFlags - // parameter to startMuxedDocument. - const PRInt32 NS_FASTLOAD_READ = 1; - const PRInt32 NS_FASTLOAD_WRITE = 2; - - attribute nsIObjectInputStream inputStream; - attribute nsIObjectOutputStream outputStream; - attribute nsIFastLoadFileIO fileIO; - readonly attribute PRInt32 direction; - - /** - * These methods associate a URI object with its spec, for faster select - * using the object pointer as a key, rather than the spec string. The - * selectMuxedDocument method returns the previously selected URI object, - * in case a caller needs to reselect the previous after muxing data for - * a given URI synchronously. For the non-blocking or "asynchronous" i/o - * case, the caller must select the source URI from the FastLoad multiplex - * before writing a new burst of data parsed from the slow-loaded source. - * - * Clients of inputStream and outputStream should try to demultiplex data - * from the input stream only if fastLoadService->StartMuxedDocument(uri, - * urispec, NS_FASTLOAD_READ) succeeds. If StartMuxedDocument fails with - * NS_ERROR_NOT_AVAILABLE, callers should slow-load the documents, muxing - * their data to the current output stream. - */ - void startMuxedDocument(in nsISupports aURI, - in string aURISpec, - in PRInt32 aDirectionFlags); - nsISupports selectMuxedDocument(in nsISupports aURI); - void endMuxedDocument(in nsISupports aURI); - - void addDependency(in nsIFile aFile); - - PRUint32 computeChecksum(in nsIFile aFile, - in nsIFastLoadReadControl aControl); - void cacheChecksum(in nsIFile aFile, - in nsIObjectOutputStream aStream); - - [noscript] void getFastLoadReferent(inout nsISupports aPtr); - - [noscript] void readFastLoadPtr(in nsIObjectInputStream aInputStream, - inout nsISupports aPtr); - - [noscript] void writeFastLoadPtr(in nsIObjectOutputStream aOutputStream, - in nsISupports aPtr); - - /** - * Return true if aURISpec identifies a muxed document in the FastLoad - * file, false otherwise. - */ - boolean hasMuxedDocument(in string aURISpec); -}; - -%{C++ -#define NS_FASTLOADSERVICE_CLASSNAME "Mozilla FastLoad Service" - -#define NS_FASTLOADSERVICE_CID \ - {0xc943093c,0xac94,0x4bee,{0x84,0x0b,0x8b,0x5a,0x6e,0x31,0x4f,0xa7}} - -#define NS_FASTLOADSERVICE_CONTRACTID \ - "@mozilla.org/fast-load-service;1" - -#ifndef nsCOMPtr_h___ -# include "nsCOMPtr.h" -#endif -#ifndef __gen_nsIFile_h__ -# include "nsIFile.h" -#endif -#ifndef nsIServiceManager_h___ -# include "nsIServiceManager.h" -#endif - -inline const nsGetServiceByContractID -do_GetFastLoadService() -{ - return nsGetServiceByContractID(NS_FASTLOADSERVICE_CONTRACTID); -} - -inline const nsGetServiceByContractIDWithError -do_GetFastLoadService(nsresult *aResultCode) -{ - return nsGetServiceByContractIDWithError(NS_FASTLOADSERVICE_CONTRACTID, - aResultCode); -} - -inline nsresult -NS_AddFastLoadDependency(nsIFile* aFile) -{ - nsCOMPtr fastLoadService(do_GetFastLoadService()); - if (fastLoadService) { - nsresult rv = fastLoadService->AddDependency(aFile); - if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE) - return rv; - } - return NS_OK; -} - -#if defined(XP_UNIX) || defined(XP_BEOS) -#define PLATFORM_FASL_SUFFIX ".mfasl" -#elif defined(XP_WIN) || defined(XP_OS2) -#define PLATFORM_FASL_SUFFIX ".mfl" -#endif - -%}