From cd81e6219e798e10c66cfe3a5ccd9cd83b3b3a55 Mon Sep 17 00:00:00 2001 From: "dougt%netscape.com" Date: Thu, 21 Feb 2002 02:18:33 +0000 Subject: [PATCH] Fixes 122523. Avoid stat call when opening file. This should be a minor performance win on windows. r=dp, sr=dveditz, sr=darin, a=roc+moz for 0.9.9 git-svn-id: svn://10.0.0.236/trunk@115135 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/netwerk/base/src/nsFileStreams.cpp | 183 +++++++++++++-------- mozilla/netwerk/base/src/nsFileStreams.h | 10 +- 2 files changed, 123 insertions(+), 70 deletions(-) diff --git a/mozilla/netwerk/base/src/nsFileStreams.cpp b/mozilla/netwerk/base/src/nsFileStreams.cpp index cbfea2f5175..99d8ce5c21a 100644 --- a/mozilla/netwerk/base/src/nsFileStreams.cpp +++ b/mozilla/netwerk/base/src/nsFileStreams.cpp @@ -102,7 +102,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(nsFileIO, nsIStreamIO) nsFileIO::nsFileIO() - : mIOFlags(0), + : mFD(0), + mIOFlags(0), mPerm(0), mStatus(NS_OK) { @@ -174,65 +175,69 @@ nsFileIO::Open(char **contentType, PRInt32 *contentLength) if (mFile == nsnull) return NS_ERROR_NOT_INITIALIZED; - *contentLength = 0; - *contentType = nsnull; + if (contentLength) + *contentLength = 0; + if (contentType) + *contentType = nsnull; - // don't actually open the file here -- we'll do it on demand in the - // GetInputStream/GetOutputStream methods nsresult rv = NS_OK; - - PRBool exist; - rv = mFile->Exists(&exist); - if (NS_FAILED(rv)) - return rv; + nsCOMPtr localFile = do_QueryInterface(mFile, &rv); + if (NS_FAILED(rv)) return rv; + if (mIOFlags == -1) + mIOFlags = PR_RDONLY; + if (mPerm == -1) + mPerm = 0; - if (!exist) - return NS_ERROR_FILE_NOT_FOUND; + rv = localFile->OpenNSPRFileDesc(mIOFlags, mPerm, &mFD); + if (NS_FAILED(rv)) return NS_ERROR_FILE_NOT_FOUND; //How do we deal with directories/?? - // We'll try to use the file's length, if it has one. If not, - // assume the file to be special, and set the content length - // to -1, which means "read the stream until exhausted". - PRInt64 size; - rv = mFile->GetFileSize(&size); - if (NS_SUCCEEDED(rv)) { - *contentLength = nsInt64(size); + if (contentLength) { + // We'll try to use the file's length, if it has one. If not, + // assume the file to be special, and set the content length + // to -1, which means "read the stream until exhausted". + PRInt64 size; + rv = mFile->GetFileSize(&size); + if (NS_SUCCEEDED(rv)) { + *contentLength = nsInt64(size); if (! *contentLength) *contentLength = -1; - } - else - *contentLength = -1; - - PRBool isDir; - rv = mFile->IsDirectory(&isDir); - if (NS_SUCCEEDED(rv) && isDir) { - // Directories turn into an HTTP-index stream, with - // unbounded (i.e., read 'til the stream says it's done) - // length. - *contentType = nsCRT::strdup(APPLICATION_HTTP_INDEX_FORMAT); - *contentLength = -1; - } - else { - nsIMIMEService* mimeServ = nsnull; - nsFileTransportService* fileTransportService = nsFileTransportService::GetInstance(); - if (fileTransportService) { - mimeServ = fileTransportService->GetCachedMimeService(); - if (mimeServ) { - rv = mimeServ->GetTypeFromFile(mFile, contentType); - } } - - if (!mimeServ || (NS_FAILED(rv))) { - // if all else fails treat it as text/html? - *contentType = nsCRT::strdup(UNKNOWN_CONTENT_TYPE); - if (*contentType == nsnull) - rv = NS_ERROR_OUT_OF_MEMORY; - else - rv = NS_OK; + else + *contentLength = -1; + } + if (contentType) { + PRBool isDir; + rv = mFile->IsDirectory(&isDir); + if (NS_SUCCEEDED(rv) && isDir) { + // Directories turn into an HTTP-index stream, with + // unbounded (i.e., read 'til the stream says it's done) + // length. + *contentType = strdup(APPLICATION_HTTP_INDEX_FORMAT); + *contentLength = -1; + } + else { + // must we really go though this? dougt + nsIMIMEService* mimeServ = nsnull; + nsFileTransportService* fileTransportService = nsFileTransportService::GetInstance(); + if (fileTransportService) { + mimeServ = fileTransportService->GetCachedMimeService(); + if (mimeServ) { + rv = mimeServ->GetTypeFromFile(mFile, contentType); + } + } + + if (!mimeServ || (NS_FAILED(rv))) { + // if all else fails treat it as text/html? + *contentType = strdup(UNKNOWN_CONTENT_TYPE); + if (*contentType == nsnull) + rv = NS_ERROR_OUT_OF_MEMORY; + else + rv = NS_OK; + } } } PR_LOG(gFileIOLog, PR_LOG_DEBUG, - ("nsFileIO: logically opening %s: type=%s len=%d", - mSpec, *contentType, *contentLength)); + ("nsFileIO: logically opening %s", mSpec)); return rv; } @@ -253,16 +258,26 @@ NS_IMETHODIMP nsFileIO::GetInputStream(nsIInputStream * *aInputStream) { NS_ASSERTION(mFile, "File must not be null"); - if (mFile == nsnull) + if (!mFile) return NS_ERROR_NOT_INITIALIZED; nsresult rv; + + if (!mFD) { + // NS_ASSERTION(mFD, "Your suppose to call Open()"); + + rv = Open(nsnull, nsnull); + if (NS_FAILED(rv)) // file or directory does not exist + return rv; + } + PRBool isDir; rv = mFile->IsDirectory(&isDir); if (NS_FAILED(rv)) // file or directory does not exist return rv; if (isDir) { + PR_Close(mFD); rv = nsDirectoryIndexStream::Create(mFile, aInputStream); PR_LOG(gFileIOLog, PR_LOG_DEBUG, ("nsFileIO: opening local dir %s for input (%x)", @@ -274,14 +289,15 @@ nsFileIO::GetInputStream(nsIInputStream * *aInputStream) if (fileIn == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(fileIn); - rv = fileIn->Init(mFile, mIOFlags, mPerm, PR_FALSE); + rv = fileIn->InitWithFileDescriptor(mFD, mFile, PR_FALSE); if (NS_SUCCEEDED(rv)) { #ifdef NS_NO_INPUT_BUFFERING *aInputStream = fileIn; NS_ADDREF(*aInputStream); #else rv = NS_NewBufferedInputStream(aInputStream, - fileIn, NS_INPUT_STREAM_BUFFER_SIZE); + fileIn, + NS_INPUT_STREAM_BUFFER_SIZE); #endif } NS_RELEASE(fileIn); @@ -300,6 +316,15 @@ nsFileIO::GetOutputStream(nsIOutputStream * *aOutputStream) return NS_ERROR_NOT_INITIALIZED; nsresult rv; + + if (!mFD) { + nsXPIDLCString contentType; + PRInt32 contentLength; + rv = Open(getter_Copies(contentType), &contentLength); + if (NS_FAILED(rv)) // file or directory does not exist + return rv; + } + PRBool isDir; rv = mFile->IsDirectory(&isDir); if (NS_SUCCEEDED(rv) && isDir) { @@ -310,7 +335,7 @@ nsFileIO::GetOutputStream(nsIOutputStream * *aOutputStream) if (fileOut == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(fileOut); - rv = fileOut->Init(mFile, mIOFlags, mPerm); + rv = fileOut->InitWithFileDescriptor(mFD, mFile); if (NS_SUCCEEDED(rv)) { nsCOMPtr bufStr; #ifdef NS_NO_OUTPUT_BUFFERING @@ -318,7 +343,8 @@ nsFileIO::GetOutputStream(nsIOutputStream * *aOutputStream) NS_ADDREF(*aOutputStream); #else rv = NS_NewBufferedOutputStream(aOutputStream, - fileOut, NS_OUTPUT_STREAM_BUFFER_SIZE); + fileOut, + NS_OUTPUT_STREAM_BUFFER_SIZE); #endif } NS_RELEASE(fileOut); @@ -457,11 +483,8 @@ nsFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) NS_IMETHODIMP nsFileInputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm, PRBool deleteOnClose) -{ - NS_ASSERTION(mFD == nsnull, "already inited"); - if (mFD != nsnull) - return NS_ERROR_FAILURE; - nsresult rv; +{ + nsresult rv = NS_OK; nsCOMPtr localFile = do_QueryInterface(file, &rv); if (NS_FAILED(rv)) return rv; if (ioFlags == -1) @@ -469,10 +492,22 @@ nsFileInputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm, PRBool del if (perm == -1) perm = 0; - mLineBuffer = nsnull; - - rv = localFile->OpenNSPRFileDesc(ioFlags, perm, &mFD); + PRFileDesc* fd; + rv = localFile->OpenNSPRFileDesc(ioFlags, perm, &fd); if (NS_FAILED(rv)) return rv; + + return InitWithFileDescriptor(fd, file, deleteOnClose); +} + +nsresult +nsFileInputStream::InitWithFileDescriptor(PRFileDesc* fd, nsIFile* file, PRBool deleteOnClose) +{ + NS_ASSERTION(mFD == nsnull, "already inited"); + if (mFD || !fd) + return NS_ERROR_FAILURE; + + mLineBuffer = nsnull; + mFD = fd; if (deleteOnClose) { // POSIX compatible filesystems allow a file to be unlinked while a @@ -480,7 +515,7 @@ nsFileInputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm, PRBool del // opened the file descriptor, we'll try to remove the file. if that // fails, then we'll just remember the nsIFile and remove it after we // close the file descriptor. - rv = file->Remove(PR_FALSE); + nsresult rv = file->Remove(PR_FALSE); if (NS_FAILED(rv)) mFileToDelete = file; } @@ -605,9 +640,6 @@ nsFileOutputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) NS_IMETHODIMP nsFileOutputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm) { - NS_ASSERTION(mFD == nsnull, "already inited"); - if (mFD != nsnull) - return NS_ERROR_FAILURE; nsresult rv; nsCOMPtr localFile = do_QueryInterface(file, &rv); if (NS_FAILED(rv)) return rv; @@ -615,7 +647,22 @@ nsFileOutputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm) ioFlags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE; if (perm <= 0) perm = 0664; - return localFile->OpenNSPRFileDesc(ioFlags, perm, &mFD); + PRFileDesc* fd; + rv = localFile->OpenNSPRFileDesc(ioFlags, perm, &fd); + if (NS_FAILED(rv)) return rv; + + return InitWithFileDescriptor(fd, file); +} + + +nsresult +nsFileOutputStream::InitWithFileDescriptor(PRFileDesc* fd, nsIFile* file) +{ + NS_ASSERTION(mFD == nsnull, "already inited"); + if (mFD || !fd) + return NS_ERROR_FAILURE; + mFD = fd; + return NS_OK; } NS_IMETHODIMP diff --git a/mozilla/netwerk/base/src/nsFileStreams.h b/mozilla/netwerk/base/src/nsFileStreams.h index d0bb4dedef4..34be5666177 100644 --- a/mozilla/netwerk/base/src/nsFileStreams.h +++ b/mozilla/netwerk/base/src/nsFileStreams.h @@ -66,6 +66,7 @@ public: protected: nsCOMPtr mFile; + PRFileDesc* mFD; PRInt32 mIOFlags; PRInt32 mPerm; nsresult mStatus; @@ -103,7 +104,10 @@ public: NS_DECL_NSIFILEINPUTSTREAM NS_DECL_NSILINEINPUTSTREAM - nsFileInputStream() : nsFileStream() {} + nsFileInputStream() : nsFileStream() + { + mLineBuffer = nsnull; + } virtual ~nsFileInputStream() { Close(); @@ -111,6 +115,7 @@ public: static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); + nsresult InitWithFileDescriptor(PRFileDesc* fd, nsIFile* file, PRBool deleteOnClose); protected: nsLineBuffer *mLineBuffer; nsCOMPtr mFileToDelete; @@ -128,9 +133,10 @@ public: nsFileOutputStream() : nsFileStream() {} virtual ~nsFileOutputStream() { nsFileOutputStream::Close(); } - + static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); + nsresult InitWithFileDescriptor(PRFileDesc* fd, nsIFile* file); }; ////////////////////////////////////////////////////////////////////////////////