Back to index

lightning-sunbird  0.9+nobinonly
nsFastLoadFile.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla FastLoad code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Brendan Eich <brendan@mozilla.org> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #ifndef nsFastLoadFile_h___
00040 #define nsFastLoadFile_h___
00041 
00046 #include "prtypes.h"
00047 #include "pldhash.h"
00048 
00049 #include "nsBinaryStream.h"
00050 #include "nsCOMPtr.h"
00051 #include "nsDebug.h"
00052 #include "nsID.h"
00053 #include "nsMemory.h"
00054 #include "nsVoidArray.h"
00055 
00056 #include "nsIFastLoadFileControl.h"
00057 #include "nsIFastLoadService.h"
00058 #include "nsISeekableStream.h"
00059 #include "nsISupportsArray.h"
00060 
00080 typedef PRUint32 NSFastLoadID;          // nsFastLoadFooter::mIDMap index
00081 typedef PRUint32 NSFastLoadOID;         // nsFastLoadFooter::mObjectMap index
00082 
00095 #define MFL_ID_XOR_KEY  0x9E3779B9      // key XOR'd with ID when serialized
00096 #define MFL_OID_XOR_KEY 0x6A09E667      // key XOR'd with OID when serialized
00097 
00111 #define MFL_OBJECT_TAG_BITS     3
00112 #define MFL_OBJECT_TAG_MASK     PR_BITMASK(MFL_OBJECT_TAG_BITS)
00113 
00114 #define MFL_OBJECT_DEF_TAG      1U      // object definition follows this OID
00115 #define MFL_WEAK_REF_TAG        2U      // OID weakly refers to a prior object
00116                                         // NB: do not confuse with nsWeakPtr!
00117 #define MFL_QUERY_INTERFACE_TAG 4U      // QI object to the ID follows this OID
00118                                         // NB: an NSFastLoadID, not an nsIID!
00119 
00125 #define MFL_DULL_OBJECT_OID     MFL_OBJECT_DEF_TAG
00126 
00130 #define MFL_OID_TO_SHARP_INDEX(oid)     (((oid) >> MFL_OBJECT_TAG_BITS) - 1)
00131 #define MFL_SHARP_INDEX_TO_OID(index)   (((index) + 1) << MFL_OBJECT_TAG_BITS)
00132 
00139 #define MFL_FILE_MAGIC          "XPCOM\nMozFASL\r\n\032"
00140 #define MFL_FILE_MAGIC_SIZE     16
00141 
00142 #define MFL_FILE_VERSION_0      0
00143 #define MFL_FILE_VERSION_1      1000
00144 #define MFL_FILE_VERSION        5       // rev'ed to defend against unversioned
00145                                         // XPCOM JS component fastload files
00146 
00182 PR_EXTERN(PRUint32)
00183 NS_AccumulateFastLoadChecksum(PRUint32 *aChecksum,
00184                               const PRUint8* aBuffer,
00185                               PRUint32 aLength,
00186                               PRBool aLastBuffer);
00187 
00188 PR_EXTERN(PRUint32)
00189 NS_AddFastLoadChecksums(PRUint32 sum1, PRUint32 sum2, PRUint32 sum2ByteCount);
00190 
00194 struct nsFastLoadHeader {
00195     char        mMagic[MFL_FILE_MAGIC_SIZE];
00196     PRUint32    mChecksum;
00197     PRUint32    mVersion;
00198     PRUint32    mFooterOffset;
00199     PRUint32    mFileSize;
00200 };
00201 
00206 struct nsFastLoadFooterPrefix {
00207     PRUint32    mNumIDs;
00208     PRUint32    mNumSharpObjects;
00209     PRUint32    mNumMuxedDocuments;
00210     PRUint32    mNumDependencies;
00211 };
00212 
00213 struct nsFastLoadSharpObjectInfo {
00214     PRUint32    mCIDOffset;     // offset of object's NSFastLoadID and data
00215     PRUint16    mStrongRefCnt;
00216     PRUint16    mWeakRefCnt;    // high bit is singleton flag, see below
00217 };
00218 
00219 #define MFL_SINGLETON_FLAG          0x8000
00220 #define MFL_WEAK_REFCNT_MASK        0x7fff
00221 
00222 #define MFL_GET_SINGLETON_FLAG(ip)  ((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG)
00223 #define MFL_GET_WEAK_REFCNT(ip)     ((ip)->mWeakRefCnt & MFL_WEAK_REFCNT_MASK)
00224 
00225 #define MFL_SET_SINGLETON_FLAG(ip)                                            \
00226     ((ip)->mWeakRefCnt |= MFL_SINGLETON_FLAG)
00227 #define MFL_SET_WEAK_REFCNT(ip,rc)                                            \
00228     ((ip)->mWeakRefCnt = (((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG) | (rc)))
00229 
00230 #define MFL_BUMP_WEAK_REFCNT(ip)    (++(ip)->mWeakRefCnt)
00231 #define MFL_DROP_WEAK_REFCNT(ip)    (--(ip)->mWeakRefCnt)
00232 
00233 struct nsFastLoadMuxedDocumentInfo {
00234     const char* mURISpec;
00235     PRUint32    mInitialSegmentOffset;
00236 };
00237 
00238 // forward declarations of opaque types defined in nsFastLoadFile.cpp
00239 struct nsDocumentMapReadEntry;
00240 struct nsDocumentMapWriteEntry;
00241 
00242 // So nsFastLoadFileUpdater can verify that its nsIObjectInputStream parameter
00243 // is an nsFastLoadFileReader.
00244 #define NS_FASTLOADFILEREADER_IID \
00245     {0x7d37d1bb,0xcef3,0x4c5f,{0x97,0x68,0x0f,0x89,0x7f,0x1a,0xe1,0x40}}
00246 
00247 struct nsIFastLoadFileReader : public nsISupports {
00248     NS_DEFINE_STATIC_IID_ACCESSOR(NS_FASTLOADFILEREADER_IID)
00249 };
00250 
00257 class nsFastLoadFileReader
00258     : public nsBinaryInputStream,
00259       public nsIFastLoadReadControl,
00260       public nsISeekableStream,
00261       public nsIFastLoadFileReader
00262 {
00263   public:
00264     nsFastLoadFileReader(nsIInputStream *aStream)
00265       : mCurrentDocumentMapEntry(nsnull) {
00266         SetInputStream(aStream);
00267         MOZ_COUNT_CTOR(nsFastLoadFileReader);
00268     }
00269 
00270     virtual ~nsFastLoadFileReader() {
00271         MOZ_COUNT_DTOR(nsFastLoadFileReader);
00272     }
00273 
00274   private:
00275     // nsISupports methods
00276     NS_DECL_ISUPPORTS_INHERITED
00277 
00278     // overridden nsIObjectInputStream methods
00279     NS_IMETHOD ReadObject(PRBool aIsStrongRef, nsISupports* *_retval);
00280     NS_IMETHOD ReadID(nsID *aResult);
00281 
00282     // nsIFastLoadFileControl methods
00283     NS_DECL_NSIFASTLOADFILECONTROL
00284 
00285     // nsIFastLoadReadControl methods
00286     NS_DECL_NSIFASTLOADREADCONTROL
00287 
00288     // nsISeekableStream methods
00289     NS_DECL_NSISEEKABLESTREAM
00290 
00291     // Override Read so we can demultiplex a document interleaved with others.
00292     NS_IMETHOD Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead);
00293 
00294     // Override ReadSegments too, as nsBinaryInputStream::ReadSegments does
00295     // not call through our overridden Read method -- it calls directly into
00296     // the underlying input stream.
00297     NS_IMETHODIMP ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
00298                                PRUint32 aCount, PRUint32 *aResult);
00299 
00300     // Override SetInputStream so we can update mSeekableInput
00301     NS_IMETHOD SetInputStream(nsIInputStream* aInputStream);
00302 
00303     nsresult ReadHeader(nsFastLoadHeader *aHeader);
00304 
00308     struct nsObjectMapEntry : public nsFastLoadSharpObjectInfo {
00309         nsCOMPtr<nsISupports>   mReadObject;
00310         PRInt64                 mSkipOffset;
00311         PRUint16                mSaveStrongRefCnt;      // saved for an Update
00312         PRUint16                mSaveWeakRefCnt;        // after a Read
00313     };
00314 
00318     struct nsFastLoadFooter : public nsFastLoadFooterPrefix {
00319         nsFastLoadFooter()
00320           : mIDMap(nsnull),
00321             mObjectMap(nsnull) {
00322             mDocumentMap.ops = mURIMap.ops = nsnull;
00323         }
00324 
00325         ~nsFastLoadFooter() {
00326             delete[] mIDMap;
00327             delete[] mObjectMap;
00328             if (mDocumentMap.ops)
00329                 PL_DHashTableFinish(&mDocumentMap);
00330             if (mURIMap.ops)
00331                 PL_DHashTableFinish(&mURIMap);
00332         }
00333 
00334         // These can't be static within GetID and GetSharpObjectEntry or the
00335         // toolchains on HP-UX 10.20's, RH 7.0, and Mac OS X all barf at link
00336         // time ("common symbols not allowed with MY_DHLIB output format", to
00337         // quote the OS X rev of gcc).
00338         static nsID gDummyID;
00339         static nsObjectMapEntry gDummySharpObjectEntry;
00340 
00341         const nsID& GetID(NSFastLoadID aFastId) const {
00342             PRUint32 index = aFastId - 1;
00343             NS_ASSERTION(index < mNumIDs, "aFastId out of range");
00344             if (index >= mNumIDs)
00345                 return gDummyID;
00346             return mIDMap[index];
00347         }
00348 
00349         nsObjectMapEntry&
00350         GetSharpObjectEntry(NSFastLoadOID aOID) const {
00351             PRUint32 index = MFL_OID_TO_SHARP_INDEX(aOID);
00352             NS_ASSERTION(index < mNumSharpObjects, "aOID out of range");
00353             if (index >= mNumSharpObjects)
00354                 return gDummySharpObjectEntry;
00355             return mObjectMap[index];
00356         }
00357 
00358         // Map from dense, zero-based, uint32 NSFastLoadID to 16-byte nsID.
00359         nsID* mIDMap;
00360 
00361         // Map from dense, zero-based MFL_OID_TO_SHARP_INDEX(oid) to sharp
00362         // object offset and refcnt information.
00363         nsObjectMapEntry* mObjectMap;
00364 
00365         // Map from URI spec string to nsDocumentMapReadEntry, which helps us
00366         // demultiplex a document's objects from among the interleaved object
00367         // stream segments in the FastLoad file.
00368         PLDHashTable mDocumentMap;
00369 
00370         // Fast mapping from URI object pointer to mDocumentMap entry, valid
00371         // only while the muxed document is loading.
00372         PLDHashTable mURIMap;
00373 
00374         // List of source filename dependencies that should trigger regeneration
00375         // of the FastLoad file.
00376         nsCOMPtr<nsISupportsArray> mDependencies;
00377     };
00378 
00379     nsresult ReadFooter(nsFastLoadFooter *aFooter);
00380     nsresult ReadFooterPrefix(nsFastLoadFooterPrefix *aFooterPrefix);
00381     nsresult ReadSlowID(nsID *aID);
00382     nsresult ReadFastID(NSFastLoadID *aID);
00383     nsresult ReadSharpObjectInfo(nsFastLoadSharpObjectInfo *aInfo);
00384     nsresult ReadMuxedDocumentInfo(nsFastLoadMuxedDocumentInfo *aInfo);
00385     nsresult DeserializeObject(nsISupports* *aObject);
00386 
00387     nsresult   Open();
00388     NS_IMETHOD Close();
00389 
00390   protected:
00391     // Kept in sync with mInputStream to avoid repeated QI
00392     nsCOMPtr<nsISeekableStream> mSeekableInput;
00393 
00394     nsFastLoadHeader mHeader;
00395     nsFastLoadFooter mFooter;
00396 
00397     nsDocumentMapReadEntry* mCurrentDocumentMapEntry;
00398 
00399     friend class nsFastLoadFileUpdater;
00400 };
00401 
00402 NS_COM nsresult
00403 NS_NewFastLoadFileReader(nsIObjectInputStream* *aResult,
00404                          nsIInputStream* aSrcStream);
00405 
00412 class nsFastLoadFileWriter
00413     : public nsBinaryOutputStream,
00414       public nsIFastLoadWriteControl,
00415       public nsISeekableStream
00416 {
00417   public:
00418     nsFastLoadFileWriter(nsIOutputStream *aStream, nsIFastLoadFileIO* aFileIO)
00419       : mCurrentDocumentMapEntry(nsnull),
00420         mFileIO(aFileIO)
00421     {
00422         SetOutputStream(aStream);
00423         mHeader.mChecksum = 0;
00424         mIDMap.ops = mObjectMap.ops = mDocumentMap.ops = mURIMap.ops = nsnull;
00425         mDependencyMap.ops = nsnull;
00426         MOZ_COUNT_CTOR(nsFastLoadFileWriter);
00427     }
00428 
00429     virtual ~nsFastLoadFileWriter()
00430     {
00431         if (mIDMap.ops)
00432             PL_DHashTableFinish(&mIDMap);
00433         if (mObjectMap.ops)
00434             PL_DHashTableFinish(&mObjectMap);
00435         if (mDocumentMap.ops)
00436             PL_DHashTableFinish(&mDocumentMap);
00437         if (mURIMap.ops)
00438             PL_DHashTableFinish(&mURIMap);
00439         if (mDependencyMap.ops)
00440             PL_DHashTableFinish(&mDependencyMap);
00441         MOZ_COUNT_DTOR(nsFastLoadFileWriter);
00442     }
00443 
00444   private:
00445     // nsISupports methods
00446     NS_DECL_ISUPPORTS_INHERITED
00447 
00448     // overridden nsIObjectOutputStream methods
00449     NS_IMETHOD WriteObject(nsISupports* aObject, PRBool aIsStrongRef);
00450     NS_IMETHOD WriteSingleRefObject(nsISupports* aObject);
00451     NS_IMETHOD WriteCompoundObject(nsISupports* aObject,
00452                                    const nsIID& aIID,
00453                                    PRBool aIsStrongRef);
00454     NS_IMETHOD WriteID(const nsID& aID);
00455 
00456     // Override SetOutputStream so we can update mSeekableOutput
00457     NS_IMETHOD SetOutputStream(nsIOutputStream* aOutputStream);
00458 
00459     // nsIFastLoadFileControl methods
00460     NS_DECL_NSIFASTLOADFILECONTROL
00461 
00462     // nsIFastLoadWriteControl methods
00463     NS_DECL_NSIFASTLOADWRITECONTROL
00464 
00465     // nsISeekableStream methods
00466     NS_DECL_NSISEEKABLESTREAM
00467 
00468     nsresult MapID(const nsID& aSlowID, NSFastLoadID *aResult);
00469 
00470     nsresult WriteHeader(nsFastLoadHeader *aHeader);
00471     nsresult WriteFooter();
00472     nsresult WriteFooterPrefix(const nsFastLoadFooterPrefix& aFooterPrefix);
00473     nsresult WriteSlowID(const nsID& aID);
00474     nsresult WriteFastID(NSFastLoadID aID);
00475     nsresult WriteSharpObjectInfo(const nsFastLoadSharpObjectInfo& aInfo);
00476     nsresult WriteMuxedDocumentInfo(const nsFastLoadMuxedDocumentInfo& aInfo);
00477 
00478     nsresult   Init();
00479     nsresult   Open();
00480     NS_IMETHOD Close();
00481 
00482     nsresult WriteObjectCommon(nsISupports* aObject,
00483                                PRBool aIsStrongRef,
00484                                PRUint32 aQITag);
00485 
00486     static PLDHashOperator PR_CALLBACK
00487     IDMapEnumerate(PLDHashTable *aTable,
00488                    PLDHashEntryHdr *aHdr,
00489                    PRUint32 aNumber,
00490                    void *aData);
00491 
00492     static PLDHashOperator PR_CALLBACK
00493     ObjectMapEnumerate(PLDHashTable *aTable,
00494                        PLDHashEntryHdr *aHdr,
00495                        PRUint32 aNumber,
00496                        void *aData);
00497 
00498     static PLDHashOperator PR_CALLBACK
00499     DocumentMapEnumerate(PLDHashTable *aTable,
00500                          PLDHashEntryHdr *aHdr,
00501                          PRUint32 aNumber,
00502                          void *aData);
00503 
00504     static PLDHashOperator PR_CALLBACK
00505     DependencyMapEnumerate(PLDHashTable *aTable,
00506                            PLDHashEntryHdr *aHdr,
00507                            PRUint32 aNumber,
00508                            void *aData);
00509 
00510   protected:
00511     // Kept in sync with mOutputStream to avoid repeated QI
00512     nsCOMPtr<nsISeekableStream> mSeekableOutput;
00513 
00514     nsFastLoadHeader mHeader;
00515 
00516     PLDHashTable mIDMap;
00517     PLDHashTable mObjectMap;
00518     PLDHashTable mDocumentMap;
00519     PLDHashTable mURIMap;
00520     PLDHashTable mDependencyMap;
00521 
00522     nsDocumentMapWriteEntry* mCurrentDocumentMapEntry;
00523     nsCOMPtr<nsIFastLoadFileIO> mFileIO;
00524 };
00525 
00526 NS_COM nsresult
00527 NS_NewFastLoadFileWriter(nsIObjectOutputStream* *aResult,
00528                          nsIOutputStream* aDestStream,
00529                          nsIFastLoadFileIO* aFileIO);
00530 
00538 class nsFastLoadFileUpdater
00539     : public nsFastLoadFileWriter,
00540              nsIFastLoadFileIO
00541 {
00542   public:
00543     nsFastLoadFileUpdater(nsIOutputStream* aOutputStream)
00544       : nsFastLoadFileWriter(aOutputStream, nsnull) {
00545         MOZ_COUNT_CTOR(nsFastLoadFileUpdater);
00546     }
00547 
00548     virtual ~nsFastLoadFileUpdater() {
00549         MOZ_COUNT_DTOR(nsFastLoadFileUpdater);
00550     }
00551 
00552   private:
00553     // nsISupports methods
00554     NS_DECL_ISUPPORTS_INHERITED
00555 
00556     // nsIFastLoadFileIO methods
00557     NS_DECL_NSIFASTLOADFILEIO
00558 
00559     nsresult   Open(nsFastLoadFileReader* aReader);
00560     NS_IMETHOD Close();
00561 
00562     static PLDHashOperator PR_CALLBACK
00563     CopyReadDocumentMapEntryToUpdater(PLDHashTable *aTable,
00564                                       PLDHashEntryHdr *aHdr,
00565                                       PRUint32 aNumber,
00566                                       void *aData);
00567 
00568     friend class nsFastLoadFileReader;
00569 
00570   protected:
00571     nsCOMPtr<nsIInputStream> mInputStream;
00572 
00573     // Kept in sync with mInputStream to avoid repeated QI
00574     nsCOMPtr<nsISeekableStream> mSeekableInput;
00575 };
00576 
00577 NS_COM nsresult
00578 NS_NewFastLoadFileUpdater(nsIObjectOutputStream* *aResult,
00579                           nsIOutputStream* aOutputStream,
00580                           nsIObjectInputStream* aReaderAsStream);
00581 
00582 #endif // nsFastLoadFile_h___