diff --git a/netwerk/protocol/file/src/nsFileChannel.cpp b/netwerk/protocol/file/src/nsFileChannel.cpp index b8d25621556..fc98e7f8091 100644 --- a/netwerk/protocol/file/src/nsFileChannel.cpp +++ b/netwerk/protocol/file/src/nsFileChannel.cpp @@ -25,7 +25,6 @@ #include "nsIIOService.h" #include "nsIServiceManager.h" #include "nsFileProtocolHandler.h" -#include "nsIBuffer.h" #include "nsIBufferInputStream.h" #include "nsIBufferOutputStream.h" #include "nsAutoLock.h" @@ -69,8 +68,8 @@ nsFileChannel::Init(nsFileProtocolHandler* handler, mGetter = getter; NS_IF_ADDREF(mGetter); - mLock = PR_NewLock(); - if (mLock == nsnull) + mMonitor = PR_NewMonitor(); + if (mMonitor == nsnull) return NS_ERROR_OUT_OF_MEMORY; if (getter) { @@ -106,8 +105,8 @@ nsFileChannel::~nsFileChannel() NS_ASSERTION(mFileStream == nsnull, "channel not closed"); NS_ASSERTION(mBufferInputStream == nsnull, "channel not closed"); NS_ASSERTION(mBufferOutputStream == nsnull, "channel not closed"); - if (mLock) - PR_DestroyLock(mLock); + if (mMonitor) + PR_DestroyMonitor(mMonitor); } NS_IMETHODIMP @@ -153,7 +152,7 @@ nsFileChannel::IsPending(PRBool *result) NS_IMETHODIMP nsFileChannel::Cancel() { - nsAutoLock lock(mLock); + nsAutoMonitor mon(mMonitor); nsresult rv = NS_OK; mStatus = NS_BINDING_ABORTED; @@ -167,7 +166,7 @@ nsFileChannel::Cancel() NS_IMETHODIMP nsFileChannel::Suspend() { - nsAutoLock lock(mLock); + nsAutoMonitor mon(mMonitor); nsresult rv = NS_OK; if (!mSuspended) { @@ -181,7 +180,7 @@ nsFileChannel::Suspend() NS_IMETHODIMP nsFileChannel::Resume() { - nsAutoLock lock(mLock); + nsAutoMonitor mon(mMonitor); nsresult rv = NS_OK; if (!mSuspended) { @@ -193,7 +192,7 @@ nsFileChannel::Resume() } //////////////////////////////////////////////////////////////////////////////// - +#if 0 class nsAsyncOutputStream : public nsIBufferOutputStream { public: NS_DECL_ISUPPORTS @@ -216,7 +215,11 @@ public: } NS_IMETHOD Flush() { - return mOutputStream->Flush(); + nsresult rv; + rv = mOutputStream->Flush(); + if (NS_FAILED(rv)) return rv; + rv = mListener->OnStopRequest(mChannel, mContext, /*mStatus*/rv, nsnull); + return rv; } // nsIBufferOutputStream methods: @@ -234,6 +237,14 @@ public: return rv; } + NS_IMETHOD GetNonBlocking(PRBool *aNonBlocking) { + return mOutputStream->GetNonBlocking(aNonBlocking); + } + + NS_IMETHOD SetNonBlocking(PRBool aNonBlocking) { + return mOutputStream->SetNonBlocking(aNonBlocking); + } + nsAsyncOutputStream() : mContext(nsnull), mListener(nsnull), mInputStream(nsnull), mOutputStream(nsnull), mOffset(0) @@ -295,7 +306,7 @@ protected: }; NS_IMPL_ISUPPORTS(nsAsyncOutputStream, nsCOMTypeInfo::GetIID()); - +#endif //////////////////////////////////////////////////////////////////////////////// // From nsIChannel //////////////////////////////////////////////////////////////////////////////// @@ -312,20 +323,26 @@ NS_IMETHODIMP nsFileChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount, nsIInputStream **result) { - nsAutoLock lock(mLock); + nsAutoMonitor mon(mMonitor); nsresult rv; if (mState != QUIESCENT) return NS_ERROR_IN_PROGRESS; + rv = NS_NewPipe(&mBufferInputStream, &mBufferOutputStream, + NS_FILE_TRANSPORT_SEGMENT_SIZE, + NS_FILE_TRANSPORT_BUFFER_SIZE, PR_TRUE, this); + if (NS_FAILED(rv)) return rv; +#if 0 NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv); if (NS_FAILED(rv)) return rv; - rv = NS_NewPipe(&mBufferInputStream, &mBufferOutputStream, - NS_FILE_TRANSPORT_SEGMENT_SIZE, - NS_FILE_TRANSPORT_BUFFER_SIZE, PR_TRUE, nsnull); -// rv = serv->NewSyncStreamListener(&mBufferInputStream, &mBufferOutputStream, &mListener); + rv = serv->NewSyncStreamListener(&mBufferInputStream, &mBufferOutputStream, &mListener); + if (NS_FAILED(rv)) return rv; +#endif + + rv = mBufferOutputStream->SetNonBlocking(PR_TRUE); if (NS_FAILED(rv)) return rv; mState = START_READ; @@ -344,7 +361,7 @@ nsFileChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount, NS_IMETHODIMP nsFileChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **result) { - nsAutoLock lock(mLock); + nsAutoMonitor mon(mMonitor); nsresult rv; @@ -392,7 +409,7 @@ nsFileChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount, nsISupports *ctxt, nsIStreamListener *listener) { - nsAutoLock lock(mLock); + nsAutoMonitor mon(mMonitor); nsresult rv; @@ -409,13 +426,24 @@ nsFileChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount, rv = serv->NewAsyncStreamListener(listener, mEventQueue, &mListener); if (NS_FAILED(rv)) return rv; +#if 0 rv = nsAsyncOutputStream::Create(&mBufferInputStream, &mBufferOutputStream, this, ctxt, mListener, NS_FILE_TRANSPORT_SEGMENT_SIZE, NS_FILE_TRANSPORT_BUFFER_SIZE); if (NS_FAILED(rv)) return rv; +#else + rv = NS_NewPipe(&mBufferInputStream, &mBufferOutputStream, + NS_FILE_TRANSPORT_SEGMENT_SIZE, + NS_FILE_TRANSPORT_BUFFER_SIZE, PR_TRUE, this); + if (NS_FAILED(rv)) return rv; +#endif + rv = mBufferOutputStream->SetNonBlocking(PR_TRUE); + if (NS_FAILED(rv)) return rv; + + NS_ASSERTION(mContext == nsnull, "context not released"); mContext = ctxt; NS_IF_ADDREF(mContext); @@ -435,7 +463,7 @@ nsFileChannel::AsyncWrite(nsIInputStream *fromStream, nsISupports *ctxt, nsIStreamObserver *observer) { - nsAutoLock lock(mLock); + nsAutoMonitor mon(mMonitor); return NS_ERROR_NOT_IMPLEMENTED; } @@ -524,7 +552,7 @@ nsWriteToFile(void* closure, void nsFileChannel::Process(void) { - nsAutoLock lock(mLock); + nsAutoMonitor mon(mMonitor); switch (mState) { case START_READ: { @@ -558,6 +586,13 @@ nsFileChannel::Process(void) PRUint32 amt; mStatus = mBufferOutputStream->WriteFrom(fileStr, inLen, &amt); if (NS_FAILED(mStatus)) goto error; + if (mStatus == NS_BASE_STREAM_WOULD_BLOCK || amt == 0) { + // Our nsIBufferObserver will have been called from WriteFrom + // which in turn calls Suspend, so we should end up suspending + // this file channel. + Suspend(); + return; + } // and feed the buffer to the application via the buffer stream: if (mListener) { @@ -639,6 +674,22 @@ nsFileChannel::Process(void) return; } +//////////////////////////////////////////////////////////////////////////////// +// nsIBufferObserver methods: +//////////////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP +nsFileChannel::OnFull(nsIBuffer* buffer) +{ + return Suspend(); +} + +NS_IMETHODIMP +nsFileChannel::OnEmpty(nsIBuffer* buffer) +{ + return Resume(); +} + //////////////////////////////////////////////////////////////////////////////// // From nsIFileChannel //////////////////////////////////////////////////////////////////////////////// diff --git a/netwerk/protocol/file/src/nsFileChannel.h b/netwerk/protocol/file/src/nsFileChannel.h index 629386a4d58..aa7153e733a 100644 --- a/netwerk/protocol/file/src/nsFileChannel.h +++ b/netwerk/protocol/file/src/nsFileChannel.h @@ -24,6 +24,7 @@ #include "nsFileSpec.h" #include "prlock.h" #include "nsIEventQueueService.h" +#include "nsIBuffer.h" class nsIEventSinkGetter; class nsIStreamListener; @@ -33,7 +34,10 @@ class nsIBuffer; class nsIBufferInputStream; class nsIBufferOutputStream; -class nsFileChannel : public nsIFileChannel, public nsIRunnable { +class nsFileChannel : public nsIFileChannel, + public nsIRunnable, + public nsIBufferObserver +{ public: NS_DECL_ISUPPORTS @@ -137,6 +141,13 @@ public: NS_IMETHOD Run(void); + //////////////////////////////////////////////////////////////////////////// + // nsIBufferObserver: + + NS_IMETHOD OnFull(nsIBuffer* buffer); + + NS_IMETHOD OnEmpty(nsIBuffer* buffer); + //////////////////////////////////////////////////////////////////////////// // nsFileChannel: @@ -184,11 +195,11 @@ protected: PRUint32 mSourceOffset; PRInt32 mAmount; - PRLock* mLock; + PRMonitor* mMonitor; PRUint32 mLoadAttributes; }; #define NS_FILE_TRANSPORT_SEGMENT_SIZE (4*1024) -#define NS_FILE_TRANSPORT_BUFFER_SIZE (32*1024) +#define NS_FILE_TRANSPORT_BUFFER_SIZE (1024*1024)//(32*1024) #endif // nsFileChannel_h__