diff --git a/netwerk/base/public/nsIFileStreams.idl b/netwerk/base/public/nsIFileStreams.idl index abc36b46b86..c4ca7de9685 100644 --- a/netwerk/base/public/nsIFileStreams.idl +++ b/netwerk/base/public/nsIFileStreams.idl @@ -37,7 +37,7 @@ interface nsIFileOutputStream : nsIOutputStream }; [scriptable, uuid(e9de5df0-c7ec-11d3-8cda-0060b0fc14a3)] -interface nsIRandomAccessStore : nsISupports +interface nsISeekableStream : nsISupports { // correspond to PRSeekWhence values const long NS_SEEK_SET = 0; @@ -45,12 +45,26 @@ interface nsIRandomAccessStore : nsISupports const long NS_SEEK_END = 2; void seek(in long whence, in long offset); - long tell(); + unsigned long tell(); +}; + +[scriptable, uuid(616f5b48-da09-11d3-8cda-0060b0fc14a3)] +interface nsIBufferedInputStream : nsIInputStream +{ + void init(in nsIInputStream fillFromStream, + in unsigned long bufferSize); +}; + +[scriptable, uuid(6476378a-da09-11d3-8cda-0060b0fc14a3)] +interface nsIBufferedOutputStream : nsIOutputStream +{ + void init(in nsIOutputStream sinkToStream, + in unsigned long bufferSize); }; %{C++ -#include "prio.h" // for read/write modes, etc. +//////////////////////////////////////////////////////////////////////////////// #define NS_FILEINPUTSTREAM_CLASSNAME "File Input Stream" #define NS_FILEINPUTSTREAM_PROGID "component://netscape/network/file-input-stream" @@ -74,6 +88,31 @@ interface nsIRandomAccessStore : nsISupports {0x8c, 0xda, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \ } +//////////////////////////////////////////////////////////////////////////////// + +#define NS_BUFFEREDINPUTSTREAM_CLASSNAME "Buffered Input Stream" +#define NS_BUFFEREDINPUTSTREAM_PROGID "component://netscape/network/buffered-input-stream" + +#define NS_BUFFEREDINPUTSTREAM_CID \ +{ /* 9226888e-da08-11d3-8cda-0060b0fc14a3 */ \ + 0x9226888e, \ + 0xda08, \ + 0x11d3, \ + {0x8c, 0xda, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \ +} + +#define NS_BUFFEREDOUTPUTSTREAM_CLASSNAME "Buffered Output Stream" +#define NS_BUFFEREDOUTPUTSTREAM_PROGID "component://netscape/network/buffered-output-stream" + +#define NS_BUFFEREDOUTPUTSTREAM_CID \ +{ /* 9868b4ce-da08-11d3-8cda-0060b0fc14a3 */ \ + 0x9868b4ce, \ + 0xda08, \ + 0x11d3, \ + {0x8c, 0xda, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \ +} + +//////////////////////////////////////////////////////////////////////////////// // move to nsNetUtil.h later... #include "nsILoadGroup.h" @@ -84,6 +123,7 @@ interface nsIRandomAccessStore : nsISupports #include "nsILocalFile.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" +#include "prio.h" // for read/write modes, etc. inline nsresult NS_NewFileChannel(nsIFile* file, @@ -159,4 +199,46 @@ NS_NewFileOutputStream(nsIFile* file, PRInt32 flags, PRInt32 mode, return NS_OK; } +//////////////////////////////////////////////////////////////////////////////// + +inline nsresult +NS_NewBufferedInputStream(nsIInputStream* str, PRUint32 bufferSize, + nsIInputStream* *result) +{ + nsresult rv; + nsCOMPtr in; + static NS_DEFINE_CID(kBufferedInputStreamCID, NS_BUFFEREDINPUTSTREAM_CID); + rv = nsComponentManager::CreateInstance(kBufferedInputStreamCID, + nsnull, + NS_GET_IID(nsIBufferedInputStream), + getter_AddRefs(in)); + if (NS_FAILED(rv)) return rv; + rv = in->Init(str, bufferSize); + if (NS_FAILED(rv)) return rv; + + *result = in; + NS_ADDREF(*result); + return NS_OK; +} + +inline nsresult +NS_NewBufferedOutputStream(nsIOutputStream* str, PRUint32 bufferSize, + nsIOutputStream* *result) +{ + nsresult rv; + nsCOMPtr out; + static NS_DEFINE_CID(kBufferedOutputStreamCID, NS_BUFFEREDOUTPUTSTREAM_CID); + rv = nsComponentManager::CreateInstance(kBufferedOutputStreamCID, + nsnull, + NS_GET_IID(nsIBufferedOutputStream), + getter_AddRefs(out)); + if (NS_FAILED(rv)) return rv; + rv = out->Init(str, bufferSize); + if (NS_FAILED(rv)) return rv; + + *result = out; + NS_ADDREF(*result); + return NS_OK; +} + %} diff --git a/netwerk/base/src/Makefile.in b/netwerk/base/src/Makefile.in index d49afa89dde..f802adeaa82 100644 --- a/netwerk/base/src/Makefile.in +++ b/netwerk/base/src/Makefile.in @@ -32,6 +32,7 @@ LIBRARY_NAME = neckobase_s CPPSRCS = \ nsURLHelper.cpp \ nsFileStreams.cpp \ + nsBufferedStreams.cpp \ nsAsyncStreamListener.cpp \ nsSyncStreamListener.cpp \ nsIOService.cpp \ diff --git a/netwerk/base/src/nsBufferedStreams.cpp b/netwerk/base/src/nsBufferedStreams.cpp index 4e01fe12871..4cd35bdc457 100644 --- a/netwerk/base/src/nsBufferedStreams.cpp +++ b/netwerk/base/src/nsBufferedStreams.cpp @@ -21,6 +21,7 @@ */ #include "nsBufferedStreams.h" +#include "nsCRT.h" //////////////////////////////////////////////////////////////////////////////// // nsBufferedStream @@ -28,7 +29,9 @@ nsBufferedStream::nsBufferedStream() : mBuffer(nsnull), mBufferStartOffset(0), - mCursor(0) + mCursor(0), + mFillPoint(0), + mStream(nsnull) { NS_INIT_REFCNT(); } @@ -40,18 +43,19 @@ nsBufferedStream::~nsBufferedStream() NS_IMPL_ISUPPORTS2(nsBufferedStream, nsIBaseStream, - nsIRandomAccessStore); + nsISeekableStream); nsresult -nsBufferedStream::Init(PRUint32 BufferedSize, nsIBaseStream* stream) +nsBufferedStream::Init(nsIBaseStream* stream, PRUint32 bufferSize) { NS_ASSERTION(stream, "need to supply a stream"); NS_ASSERTION(mStream == nsnull, "already inited"); mStream = stream; - mBufferSize = BufferedSize; + NS_ADDREF(mStream); + mBufferSize = bufferSize; mBufferStartOffset = 0; mCursor = 0; - mBuffer = new char[BufferedSize]; + mBuffer = new char[bufferSize]; if (mBuffer == nsnull) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; @@ -60,8 +64,10 @@ nsBufferedStream::Init(PRUint32 BufferedSize, nsIBaseStream* stream) NS_IMETHODIMP nsBufferedStream::Close() { + nsresult rv = NS_OK; if (mStream) { - return mStream->Close(); + rv = mStream->Close(); + NS_RELEASE(mStream); mStream = nsnull; delete mBuffer; mBuffer = nsnull; @@ -69,7 +75,7 @@ nsBufferedStream::Close() mBufferStartOffset = 0; mCursor = 0; } - return NS_OK; + return rv; } NS_IMETHODIMP @@ -78,30 +84,72 @@ nsBufferedStream::Seek(PRInt32 whence, PRInt32 offset) if (mStream == nsnull) return NS_BASE_STREAM_CLOSED; - if (whence == nsIRandomAccessStore::NS_SEEK_CUR && - mCursor + offset < mBufferStartOffset + mBufferSize) { - mCursor += offset; + // If the underlying stream isn't a random access store, then fail early. + // We could possibly succeed for the case where the seek position denotes + // something that happens to be read into the buffer, but that would make + // the failure data-dependent. + nsresult rv; + nsCOMPtr ras = do_QueryInterface(mStream, &rv); + if (NS_FAILED(rv)) return rv; + + PRInt32 absPos; + switch (whence) { + case nsISeekableStream::NS_SEEK_SET: + absPos = offset; + break; + case nsISeekableStream::NS_SEEK_CUR: + absPos = mBufferStartOffset + mCursor + offset; + break; + case nsISeekableStream::NS_SEEK_END: + absPos = -1; + break; + default: + NS_NOTREACHED("bogus seek whence parameter"); + return NS_ERROR_UNEXPECTED; + } + + if ((PRInt32)mBufferStartOffset <= absPos + && absPos < (PRInt32)(mBufferStartOffset + mFillPoint)) { + mCursor = absPos - mBufferStartOffset; return NS_OK; } - // XXX more... - return NS_ERROR_NOT_IMPLEMENTED; + + rv = Flush(); + if (NS_FAILED(rv)) return rv; + + rv = ras->Seek(whence, offset); + if (NS_FAILED(rv)) return rv; + + if (absPos == -1) { + // then we had the SEEK_END case, above + rv = ras->Tell(&mBufferStartOffset); + if (NS_FAILED(rv)) return rv; + } + else { + mBufferStartOffset = absPos; + } + mCursor = 0; + mFillPoint = 0; + return Fill(); } NS_IMETHODIMP -nsBufferedStream::Tell(PRInt32 *result) +nsBufferedStream::Tell(PRUint32 *result) { if (mStream == nsnull) return NS_BASE_STREAM_CLOSED; - return NS_ERROR_NOT_IMPLEMENTED; + *result = mBufferStartOffset + mCursor; + return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsBufferedInputStream -NS_IMPL_ISUPPORTS_INHERITED1(nsBufferedInputStream, +NS_IMPL_ISUPPORTS_INHERITED2(nsBufferedInputStream, nsBufferedStream, - nsIInputStream); + nsIInputStream, + nsIBufferedInputStream); NS_METHOD nsBufferedInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) @@ -117,6 +165,12 @@ nsBufferedInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult return rv; } +NS_IMETHODIMP +nsBufferedInputStream::Init(nsIInputStream* stream, PRUint32 bufferSize) +{ + return nsBufferedStream::Init(stream, bufferSize); +} + NS_IMETHODIMP nsBufferedInputStream::Close() { @@ -126,21 +180,62 @@ nsBufferedInputStream::Close() NS_IMETHODIMP nsBufferedInputStream::Available(PRUint32 *result) { - return NS_ERROR_NOT_IMPLEMENTED; + *result = mFillPoint - mCursor; + return NS_OK; } NS_IMETHODIMP nsBufferedInputStream::Read(char * buf, PRUint32 count, PRUint32 *result) { - return NS_ERROR_NOT_IMPLEMENTED; + nsresult rv = NS_OK; + PRUint32 read = 0; + while (count > 0) { + PRUint32 amt = PR_MIN(count, mFillPoint - mCursor); + if (amt > 0) { + nsCRT::memcpy(buf, mBuffer + mCursor, amt); + read += amt; + count -= amt; + mCursor += amt; + } + else { + rv = Fill(); + if (NS_FAILED(rv)) break; + } + } + *result = read; + return (read > 0 || rv == NS_BASE_STREAM_CLOSED) ? NS_OK : rv; +} + +NS_IMETHODIMP +nsBufferedInputStream::Fill() +{ + nsresult rv; + PRUint32 rem = mFillPoint - mCursor; + if (rem > 0) { + // slide the remainder down to the start of the buffer + // |<------------->|<--rem-->|<--->| + // b c f s + nsCRT::memcpy(mBuffer, mBuffer + mCursor, rem); + mBufferStartOffset += mCursor; + mFillPoint = rem; + mCursor = 0; + } + + PRUint32 amt; + rv = Source()->Read(mBuffer + mFillPoint, mBufferSize - mFillPoint, &amt); + if (NS_FAILED(rv)) return rv; + + mFillPoint += amt; + return amt > 0 ? NS_OK : NS_BASE_STREAM_CLOSED; } //////////////////////////////////////////////////////////////////////////////// // nsBufferedOutputStream -NS_IMPL_ISUPPORTS_INHERITED1(nsBufferedOutputStream, +NS_IMPL_ISUPPORTS_INHERITED2(nsBufferedOutputStream, nsBufferedStream, - nsIOutputStream); + nsIOutputStream, + nsIBufferedOutputStream); NS_METHOD nsBufferedOutputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) @@ -156,22 +251,68 @@ nsBufferedOutputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResul return rv; } +NS_IMETHODIMP +nsBufferedOutputStream::Init(nsIOutputStream* stream, PRUint32 bufferSize) +{ + mFillPoint = bufferSize; // always fill to the end for buffered output streams + return nsBufferedStream::Init(stream, bufferSize); +} + NS_IMETHODIMP nsBufferedOutputStream::Close() { - return nsBufferedStream::Close(); + nsresult rv1, rv2; + rv1 = Flush(); + // If we fail to Flush all the data, then we close anyway and drop the + // remaining data in the buffer. We do this because it's what Unix does + // for fclose and close. However, we report the error from Flush anyway. + rv2 = nsBufferedStream::Close(); + if (NS_FAILED(rv1)) return rv1; + return rv2; } NS_IMETHODIMP nsBufferedOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *result) { - return NS_ERROR_NOT_IMPLEMENTED; + nsresult rv = NS_OK; + PRUint32 written = 0; + while (count > 0) { + PRUint32 amt = PR_MIN(count, mFillPoint - mCursor); + if (amt > 0) { + nsCRT::memcpy(mBuffer + mCursor, buf, amt); + written += amt; + count -= amt; + mCursor += amt; + } + else { + rv = Flush(); + if (NS_FAILED(rv)) break; + } + } + *result = written; + return (written > 0) ? NS_OK : rv; } NS_IMETHODIMP nsBufferedOutputStream::Flush(void) { - return NS_ERROR_NOT_IMPLEMENTED; + nsresult rv; + PRUint32 amt; + rv = Sink()->Write(mBuffer, mCursor, &amt); + if (NS_FAILED(rv)) return rv; + mBufferStartOffset += amt; + if (mCursor == amt) { + mCursor = 0; + return NS_OK; // flushed everything + } + + // slide the remainder down to the start of the buffer + // |<-------------->|<---|----->| + // b a c s + PRUint32 rem = mCursor - amt; + nsCRT::memcpy(mBuffer, mBuffer + amt, rem); + mCursor = rem; + return NS_ERROR_FAILURE; // didn't flush all } //////////////////////////////////////////////////////////////////////////////// diff --git a/netwerk/base/src/nsBufferedStreams.h b/netwerk/base/src/nsBufferedStreams.h index 6a165586ab0..3cc8ff4e402 100644 --- a/netwerk/base/src/nsBufferedStreams.h +++ b/netwerk/base/src/nsBufferedStreams.h @@ -31,36 +31,46 @@ //////////////////////////////////////////////////////////////////////////////// class nsBufferedStream : public nsIBaseStream, - public nsIRandomAccessStore + public nsISeekableStream { public: NS_DECL_ISUPPORTS NS_DECL_NSIBASESTREAM - NS_DECL_NSIRANDOMACCESSSTORE + NS_DECL_NSISEEKABLESTREAM nsBufferedStream(); virtual ~nsBufferedStream(); - nsresult Init(PRUint32 bufferSize, nsIBaseStream* stream); +protected: + nsresult Init(nsIBaseStream* stream, PRUint32 bufferSize); + NS_IMETHOD Fill() = 0; + NS_IMETHOD Flush() = 0; protected: PRUint32 mBufferSize; char* mBuffer; + // mBufferStartOffset is the offset relative to the start of mStream: PRUint32 mBufferStartOffset; + // mCursor is the read cursor for input streams, or write cursor for + // output streams, and is relative to mBufferStartOffset: PRUint32 mCursor; - nsCOMPtr mStream; + // mFillPoint is the amount available in the buffer for input streams, + // or the end of the buffer for output streams, and is relative to + // mBufferStartOffset: + PRUint32 mFillPoint; + nsIBaseStream* mStream; // cast to appropriate subclass }; //////////////////////////////////////////////////////////////////////////////// class nsBufferedInputStream : public nsBufferedStream, - public nsIInputStream + public nsIBufferedInputStream { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIBASESTREAM NS_DECL_NSIINPUTSTREAM - NS_DECL_NSIRANDOMACCESSSTORE + NS_DECL_NSIBUFFEREDINPUTSTREAM nsBufferedInputStream() : nsBufferedStream() {} virtual ~nsBufferedInputStream() {} @@ -69,20 +79,24 @@ public: Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); nsIInputStream* Source() { - return (nsIInputStream*)mStream.get(); + return (nsIInputStream*)mStream; } + +protected: + NS_IMETHOD Fill(); + NS_IMETHOD Flush() { return NS_OK; } // no-op for input streams }; //////////////////////////////////////////////////////////////////////////////// class nsBufferedOutputStream : public nsBufferedStream, - public nsIOutputStream + public nsIBufferedOutputStream { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIBASESTREAM NS_DECL_NSIOUTPUTSTREAM - NS_DECL_NSIRANDOMACCESSSTORE + NS_DECL_NSIBUFFEREDOUTPUTSTREAM nsBufferedOutputStream() : nsBufferedStream() {} virtual ~nsBufferedOutputStream() {} @@ -91,8 +105,11 @@ public: Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); nsIOutputStream* Sink() { - return (nsIOutputStream*)mStream.get(); + return (nsIOutputStream*)mStream; } + +protected: + NS_IMETHOD Fill() { return NS_OK; } // no-op for output streams }; //////////////////////////////////////////////////////////////////////////////// diff --git a/netwerk/base/src/nsFileStreams.cpp b/netwerk/base/src/nsFileStreams.cpp index e438fda0607..f611b11b597 100644 --- a/netwerk/base/src/nsFileStreams.cpp +++ b/netwerk/base/src/nsFileStreams.cpp @@ -40,7 +40,7 @@ nsFileStream::~nsFileStream() NS_IMPL_ISUPPORTS2(nsFileStream, nsIBaseStream, - nsIRandomAccessStore); + nsISeekableStream); NS_IMETHODIMP nsFileStream::Close() @@ -66,7 +66,7 @@ nsFileStream::Seek(PRInt32 whence, PRInt32 offset) } NS_IMETHODIMP -nsFileStream::Tell(PRInt32 *result) +nsFileStream::Tell(PRUint32 *result) { if (mFD == nsnull) return NS_BASE_STREAM_CLOSED; @@ -168,6 +168,8 @@ NS_IMETHODIMP nsFileOutputStream::Init(nsILocalFile* file, PRInt32 flags, PRInt32 mode) { NS_ASSERTION(mFD == nsnull, "already inited"); + if (mFD != nsnull) + return NS_ERROR_FAILURE; return file->OpenNSPRFileDesc(flags, mode, &mFD); } diff --git a/netwerk/base/src/nsFileStreams.h b/netwerk/base/src/nsFileStreams.h index 43b51458c2b..dabdbcf15b7 100644 --- a/netwerk/base/src/nsFileStreams.h +++ b/netwerk/base/src/nsFileStreams.h @@ -32,12 +32,12 @@ //////////////////////////////////////////////////////////////////////////////// class nsFileStream : public nsIBaseStream, - public nsIRandomAccessStore + public nsISeekableStream { public: NS_DECL_ISUPPORTS NS_DECL_NSIBASESTREAM - NS_DECL_NSIRANDOMACCESSSTORE + NS_DECL_NSISEEKABLESTREAM nsFileStream(); virtual ~nsFileStream(); diff --git a/netwerk/base/src/nsFileTransport.cpp b/netwerk/base/src/nsFileTransport.cpp index 015cff2ad11..111d07e61fd 100644 --- a/netwerk/base/src/nsFileTransport.cpp +++ b/netwerk/base/src/nsFileTransport.cpp @@ -46,6 +46,11 @@ #include "nsNetUtil.h" #include "nsInt64.h" +#define NS_INPUT_STREAM_BUFFER_SIZE (16 * 1024) +#define NS_OUTPUT_STREAM_BUFFER_SIZE (64 * 1024) + +//#define NO_BUFFERING 1 + static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID); static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); @@ -89,9 +94,12 @@ public: // just do the right thing.) PRInt64 size; rv = mFile->GetFileSize(&size); - if (NS_FAILED(rv)) return rv; - *contentLength = nsInt64(size); - if (! *contentLength) + if (NS_SUCCEEDED(rv)) { + *contentLength = nsInt64(size); + if (! *contentLength) + *contentLength = -1; + } + else *contentLength = -1; PRBool isDir; @@ -162,7 +170,20 @@ public: (const char*)mSpec, rv)); return rv; } - rv = NS_NewFileInputStream(mFile, aInputStream); + + nsCOMPtr fileIn; + rv = NS_NewFileInputStream(mFile, getter_AddRefs(fileIn)); + if (NS_FAILED(rv)) return rv; + +#ifdef NO_BUFFERING + *aInputStream = fileIn; + NS_ADDREF(*aInputStream); +#else + rv = NS_NewBufferedInputStream(fileIn, NS_OUTPUT_STREAM_BUFFER_SIZE, + aInputStream); +#endif + + // printf("opening %s for reading\n", (const char*)mSpec); PR_LOG(gFileTransportLog, PR_LOG_DEBUG, ("nsFileTransport: opening local file %s for input (%x)", (const char*)mSpec, rv)); @@ -177,10 +198,27 @@ public: if (isDir) { return NS_ERROR_FAILURE; } + + nsCOMPtr fileOut; rv = NS_NewFileOutputStream(mFile, PR_CREATE_FILE | PR_WRONLY, 0664, - aOutputStream); + getter_AddRefs(fileOut)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr bufStr; +#ifdef NO_BUFFERING + bufStr = fileOut; +#else + rv = NS_NewBufferedOutputStream(fileOut, NS_OUTPUT_STREAM_BUFFER_SIZE, + getter_AddRefs(bufStr)); + if (NS_FAILED(rv)) return rv; +#endif + + *aOutputStream = bufStr; + NS_ADDREF(*aOutputStream); + + // printf("opening %s for writing\n", (const char*)mSpec); PR_LOG(gFileTransportLog, PR_LOG_DEBUG, ("nsFileTransport: opening local file %s for output (%x)", (const char*)mSpec, rv)); @@ -189,15 +227,15 @@ public: nsLocalFileSystem(nsIFile* file) : mFile(file) { NS_INIT_REFCNT(); -#ifdef PR_LOGGING +//#ifdef PR_LOGGING (void)mFile->GetPath(&mSpec); -#endif +//#endif } virtual ~nsLocalFileSystem() { -#ifdef PR_LOGGING +//#ifdef PR_LOGGING if (mSpec) nsCRT::free(mSpec); -#endif +//#endif } static nsresult Create(nsIFile* file, nsIFileSystem* *result) { @@ -211,9 +249,9 @@ public: protected: nsCOMPtr mFile; -#ifdef PR_LOGGING +//#ifdef PR_LOGGING char* mSpec; -#endif +//#endif }; NS_IMPL_ISUPPORTS1(nsLocalFileSystem, nsIFileSystem); @@ -577,20 +615,29 @@ nsFileTransport::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **resu if (mState != CLOSED) return NS_ERROR_IN_PROGRESS; - nsCOMPtr str; + nsCOMPtr fileOut; rv = NS_NewFileOutputStream(mFile, PR_CREATE_FILE | PR_WRONLY, 0664, - getter_AddRefs(str)); + getter_AddRefs(fileOut)); if (NS_FAILED(rv)) return rv; - *result = str; + nsCOMPtr bufStr; +#ifdef NO_BUFFERING + bufStr = fileOut; +#else + rv = NS_NewBufferedOutputStream(fileOut, NS_OUTPUT_STREAM_BUFFER_SIZE, + getter_AddRefs(bufStr)); + if (NS_FAILED(rv)) return rv; +#endif + + *result = bufStr; NS_ADDREF(*result); mOffset = startPosition; if (mOffset > 0) { - // if we need to set a starting offset, QI for nsIRandomAccessStore - nsCOMPtr ras = + // if we need to set a starting offset, QI for nsISeekableStream + nsCOMPtr ras = do_QueryInterface(*result, &mStatus); if (NS_FAILED(mStatus)) return NS_ERROR_IN_PROGRESS; @@ -802,8 +849,8 @@ nsFileTransport::Process(void) } if (mOffset > 0) { - // if we need to set a starting offset, QI for the nsIRandomAccessStore and set it - nsCOMPtr ras = do_QueryInterface(mSource, &mStatus); + // if we need to set a starting offset, QI for the nsISeekableStream and set it + nsCOMPtr ras = do_QueryInterface(mSource, &mStatus); if (NS_FAILED(mStatus)) { mState = END_READ; return; @@ -927,8 +974,8 @@ nsFileTransport::Process(void) } if (mOffset > 0) { - // if we need to set a starting offset, QI for the nsIRandomAccessStore and set it - nsCOMPtr ras = do_QueryInterface(mSink, &mStatus); + // if we need to set a starting offset, QI for the nsISeekableStream and set it + nsCOMPtr ras = do_QueryInterface(mSink, &mStatus); if (NS_FAILED(mStatus)) { mState = END_WRITE; return; diff --git a/netwerk/build/nsNetModule.cpp b/netwerk/build/nsNetModule.cpp index fedfdcf1779..38ef0ead102 100644 --- a/netwerk/build/nsNetModule.cpp +++ b/netwerk/build/nsNetModule.cpp @@ -42,6 +42,7 @@ #include "nsAsyncStreamListener.h" #include "nsSyncStreamListener.h" #include "nsFileStreams.h" +#include "nsBufferedStreams.h" /////////////////////////////////////////////////////////////////////////////// // Module implementation for the net library @@ -123,6 +124,14 @@ static nsModuleComponentInfo gNetModuleInfo[] = { NS_NOAUTHORITYURLPARSER_CID, "component://netscape/network/no-authority-urlparser", nsNoAuthURLParser::Create }, + { NS_BUFFEREDINPUTSTREAM_CLASSNAME, + NS_BUFFEREDINPUTSTREAM_CID, + NS_BUFFEREDINPUTSTREAM_PROGID, + nsBufferedInputStream::Create }, + { NS_BUFFEREDOUTPUTSTREAM_CLASSNAME, + NS_BUFFEREDOUTPUTSTREAM_CID, + NS_BUFFEREDOUTPUTSTREAM_PROGID, + nsBufferedOutputStream::Create } }; NS_IMPL_NSGETMODULE("net", gNetModuleInfo) diff --git a/netwerk/protocol/http/src/nsHTTPEncodeStream.cpp b/netwerk/protocol/http/src/nsHTTPEncodeStream.cpp index 131cb313a34..1cd1df772ff 100644 --- a/netwerk/protocol/http/src/nsHTTPEncodeStream.cpp +++ b/netwerk/protocol/http/src/nsHTTPEncodeStream.cpp @@ -45,7 +45,7 @@ nsHTTPEncodeStream::~nsHTTPEncodeStream() { } -NS_IMPL_ISUPPORTS2(nsHTTPEncodeStream, nsIInputStream, nsIRandomAccessStore); +NS_IMPL_ISUPPORTS2(nsHTTPEncodeStream, nsIInputStream, nsISeekableStream); NS_METHOD nsHTTPEncodeStream::Create(nsIInputStream *rawStream, PRUint32 flags, @@ -158,13 +158,13 @@ nsHTTPEncodeStream::Read(char* outBuf, PRUint32 outBufCnt, PRUint32 *result) } //////////////////////////////////////////////////////////////////////////////// -// nsIRandomAccessStore methods: +// nsISeekableStream methods: NS_IMETHODIMP nsHTTPEncodeStream::Seek(PRInt32 whence, PRInt32 offset) { nsresult rv; - nsCOMPtr ras = do_QueryInterface(mInput, &rv); + nsCOMPtr ras = do_QueryInterface(mInput, &rv); if (NS_FAILED(rv)) return rv; mPushBackBuffer.SetLength(0); @@ -172,35 +172,13 @@ nsHTTPEncodeStream::Seek(PRInt32 whence, PRInt32 offset) } NS_IMETHODIMP -nsHTTPEncodeStream::Tell(PRInt32* outWhere) +nsHTTPEncodeStream::Tell(PRUint32* outWhere) { nsresult rv; - nsCOMPtr ras = do_QueryInterface(mInput, &rv); + nsCOMPtr ras = do_QueryInterface(mInput, &rv); if (NS_FAILED(rv)) return rv; return ras->Tell(outWhere); } -#if 0 -NS_IMETHODIMP -nsHTTPEncodeStream::GetAtEOF(PRBool* outAtEOF) -{ - nsresult rv; - nsCOMPtr ras = do_QueryInterface(mInput, &rv); - if (NS_FAILED(rv)) return rv; - - return ras->GetAtEOF(outAtEOF); -} - -NS_IMETHODIMP -nsHTTPEncodeStream::SetAtEOF(PRBool inAtEOF) -{ - nsresult rv; - nsCOMPtr ras = do_QueryInterface(mInput, &rv); - if (NS_FAILED(rv)) return rv; - - return ras->SetAtEOF(inAtEOF); -} -#endif - //////////////////////////////////////////////////////////////////////////////// diff --git a/netwerk/protocol/http/src/nsHTTPEncodeStream.h b/netwerk/protocol/http/src/nsHTTPEncodeStream.h index b968bbc00e9..f877b1643b7 100644 --- a/netwerk/protocol/http/src/nsHTTPEncodeStream.h +++ b/netwerk/protocol/http/src/nsHTTPEncodeStream.h @@ -29,21 +29,13 @@ #include "nsIFileStreams.h" class nsHTTPEncodeStream : public nsIInputStream, - public nsIRandomAccessStore + public nsISeekableStream { public: NS_DECL_ISUPPORTS NS_DECL_NSIBASESTREAM NS_DECL_NSIINPUTSTREAM - NS_DECL_NSIRANDOMACCESSSTORE - -#if 0 - NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset); - NS_IMETHOD Tell(PRIntn* outWhere); - // XXX supposedly "protected": - NS_IMETHOD GetAtEOF(PRBool* outAtEOF); - NS_IMETHOD SetAtEOF(PRBool inAtEOF); -#endif + NS_DECL_NSISEEKABLESTREAM // nsHTTPEncodeStream methods: nsHTTPEncodeStream(); diff --git a/netwerk/test/TestFileInput2.cpp b/netwerk/test/TestFileInput2.cpp index 3cc1020acc1..48dbd13830d 100644 --- a/netwerk/test/TestFileInput2.cpp +++ b/netwerk/test/TestFileInput2.cpp @@ -155,14 +155,22 @@ public: PRUint32 copyCount = 0; // Open the input stream: - rv = NS_NewFileInputStream(mInPath, getter_AddRefs(inStr)); + nsCOMPtr fileIn; + rv = NS_NewFileInputStream(mInPath, getter_AddRefs(fileIn)); + if (NS_FAILED(rv)) return rv; + + rv = NS_NewBufferedInputStream(fileIn, 65535, getter_AddRefs(inStr)); if (NS_FAILED(rv)) return rv; // Open the output stream: + nsCOMPtr fileOut; rv = NS_NewFileOutputStream(mOutPath, PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE, 0664, - getter_AddRefs(outStr)); + getter_AddRefs(fileOut)); + if (NS_FAILED(rv)) return rv; + + rv = NS_NewBufferedOutputStream(fileOut, 65535, getter_AddRefs(outStr)); if (NS_FAILED(rv)) return rv; // Copy from one to the other diff --git a/netwerk/test/TestWriteSpeed.cpp b/netwerk/test/TestWriteSpeed.cpp index bd390ff390c..8da23177444 100644 --- a/netwerk/test/TestWriteSpeed.cpp +++ b/netwerk/test/TestWriteSpeed.cpp @@ -26,11 +26,6 @@ #include #include -#define MIN_SIZE 4096 -#define MAX_SIZE (512 * 1024) -#define SIZE_INCREMENT 4096 -#define ITERATIONS 10 - void NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues, double *meanResult, double *stdDevResult) @@ -51,10 +46,11 @@ NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues, } int -Test(const char* filename) +Test(const char* filename, PRInt32 minSize, PRInt32 maxSize, + PRInt32 sizeIncrement, PRInt32 iterations) { fprintf(stdout, " size write: mean stddev iters total: mean stddev iters\n"); - for (PRInt32 size = MIN_SIZE; size <= MAX_SIZE; size += SIZE_INCREMENT) { + for (PRInt32 size = minSize; size <= maxSize; size += sizeIncrement) { // create a buffer of stuff to write char* buf = (char*)PR_Malloc(size); if (buf == NULL) @@ -69,10 +65,12 @@ Test(const char* filename) double writeCount = 0, writeRate = 0, writeRateSquared = 0; double totalCount = 0, totalRate = 0, totalRateSquared = 0; - for (i = 0; i < ITERATIONS; i++) { + for (i = 0; i < iterations; i++) { PRIntervalTime start = PR_IntervalNow(); - PRFileDesc* fd = PR_Open(filename, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0664); + char name[1024]; + sprintf(name, "%s_%d", filename, i); + PRFileDesc* fd = PR_Open(name, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0664); if (fd == NULL) return -1; @@ -119,10 +117,17 @@ Test(const char* filename) return 0; } - - -void -main() +int +main(int argc, char* argv[]) { - Test("y:\\foo"); + if (argc != 5) { + printf("usage: %s \n", argv[0]); + return -1; + } + Test("y:\\foo", + atoi(argv[1]) * 1024, + atoi(argv[2]) * 1024, + atoi(argv[3]) * 1024, + atoi(argv[4])); + return 0; }