mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 988816 - Allow to keep file descriptor in JAR cache. r=aklotz, jduell
This commit is contained in:
parent
a968b880df
commit
b601c06562
@ -6,6 +6,12 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
%{C++
|
||||
struct PRFileDesc;
|
||||
%}
|
||||
|
||||
[ptr] native PRFileDescStar(PRFileDesc);
|
||||
|
||||
interface nsIUTF8StringEnumerator;
|
||||
interface nsIInputStream;
|
||||
interface nsIFile;
|
||||
@ -192,7 +198,7 @@ interface nsIZipReader : nsISupports
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIZipReaderCache
|
||||
|
||||
[scriptable, uuid(748050ac-3ab6-4472-bc2a-cb1564ac6a81)]
|
||||
[scriptable, uuid(94ecd586-d405-4801-93d3-8ac7bef81bde)]
|
||||
interface nsIZipReaderCache : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -228,6 +234,20 @@ interface nsIZipReaderCache : nsISupports
|
||||
* See getZip
|
||||
*/
|
||||
nsIZipReader getInnerZip(in nsIFile zipFile, in AUTF8String zipEntry);
|
||||
|
||||
/**
|
||||
* Whether to keep NSPR file descriptor for newly opened files in the cache.
|
||||
* When aMustCacheFd is enabled and a file is given, the file will be flushed
|
||||
* from the cache if its file descriptor was not cached.
|
||||
* Note: currently not supported on Windows platform.
|
||||
*/
|
||||
void setMustCacheFd(in nsIFile zipFile, in bool aMustCacheFd);
|
||||
|
||||
/**
|
||||
* Returns the cached NSPR file descriptor of the file.
|
||||
* Note: currently not supported on Windows platform.
|
||||
*/
|
||||
PRFileDescStar getFd(in nsIFile zipFile);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -141,7 +141,7 @@ nsJAR::Open(nsIFile* zipFile)
|
||||
mZip = zip;
|
||||
return NS_OK;
|
||||
}
|
||||
return mZip->OpenArchive(zipFile);
|
||||
return mZip->OpenArchive(zipFile, mCache ? mCache->IsMustCacheFdEnabled() : false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -391,6 +391,26 @@ nsJAR::GetJarPath(nsACString& aResult)
|
||||
return mZipFile->GetNativePath(aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJAR::GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc)
|
||||
{
|
||||
if (!aNSPRFileDesc) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
*aNSPRFileDesc = nullptr;
|
||||
|
||||
if (!mZip) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<nsZipHandle> handle = mZip->GetFD();
|
||||
if (!handle) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return handle->GetNSPRFileDesc(aNSPRFileDesc);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
// nsJAR private implementation
|
||||
//----------------------------------------------
|
||||
@ -1009,6 +1029,7 @@ NS_IMPL_ISUPPORTS(nsZipReaderCache, nsIZipReaderCache, nsIObserver, nsISupportsW
|
||||
nsZipReaderCache::nsZipReaderCache()
|
||||
: mLock("nsZipReaderCache.mLock")
|
||||
, mZips(16)
|
||||
, mMustCacheFd(false)
|
||||
#ifdef ZIP_CACHE_HIT_RATE
|
||||
,
|
||||
mZipCacheLookups(0),
|
||||
@ -1104,7 +1125,6 @@ nsZipReaderCache::GetZip(nsIFile* zipFile, nsIZipReader* *result)
|
||||
} else {
|
||||
zip = new nsJAR();
|
||||
zip->SetZipReaderCache(this);
|
||||
|
||||
rv = zip->Open(zipFile);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
@ -1162,6 +1182,87 @@ nsZipReaderCache::GetInnerZip(nsIFile* zipFile, const nsACString &entry,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsZipReaderCache::SetMustCacheFd(nsIFile* zipFile, bool aMustCacheFd)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
MOZ_CRASH("Not implemented");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#else
|
||||
mMustCacheFd = aMustCacheFd;
|
||||
|
||||
if (!aMustCacheFd) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!zipFile) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsAutoCString uri;
|
||||
rv = zipFile->GetNativePath(uri);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
uri.Insert(NS_LITERAL_CSTRING("file:"), 0);
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
nsRefPtr<nsJAR> zip;
|
||||
mZips.Get(uri, getter_AddRefs(zip));
|
||||
if (!zip) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Flush the file from the cache if its file descriptor was not cached.
|
||||
PRFileDesc* fd = nullptr;
|
||||
zip->GetNSPRFileDesc(&fd);
|
||||
if (!fd) {
|
||||
#ifdef ZIP_CACHE_HIT_RATE
|
||||
mZipCacheFlushes++;
|
||||
#endif
|
||||
zip->SetZipReaderCache(nullptr);
|
||||
mZips.Remove(uri);
|
||||
}
|
||||
return NS_OK;
|
||||
#endif /* XP_WIN */
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsZipReaderCache::GetFd(nsIFile* zipFile, PRFileDesc** aRetVal)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
MOZ_CRASH("Not implemented");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#else
|
||||
if (!zipFile) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsAutoCString uri;
|
||||
rv = zipFile->GetNativePath(uri);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
uri.Insert(NS_LITERAL_CSTRING("file:"), 0);
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
nsRefPtr<nsJAR> zip;
|
||||
mZips.Get(uri, getter_AddRefs(zip));
|
||||
if (!zip) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
zip->ClearReleaseTime();
|
||||
rv = zip->GetNSPRFileDesc(aRetVal);
|
||||
// Do this to avoid possible deadlock on mLock with ReleaseZip().
|
||||
MutexAutoUnlock unlock(mLock);
|
||||
nsRefPtr<nsJAR> zipTemp = zip.forget();
|
||||
return rv;
|
||||
#endif /* XP_WIN */
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
FindOldestZip(const nsACString &aKey, nsJAR* aZip, void* aClosure)
|
||||
{
|
||||
|
@ -95,6 +95,8 @@ class nsJAR : public nsIZipReader
|
||||
mCache = cache;
|
||||
}
|
||||
|
||||
nsresult GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc);
|
||||
|
||||
protected:
|
||||
typedef nsClassHashtable<nsCStringHashKey, nsJARManifestItem> ManifestDataHashtable;
|
||||
|
||||
@ -195,6 +197,10 @@ public:
|
||||
|
||||
nsresult ReleaseZip(nsJAR* reader);
|
||||
|
||||
bool IsMustCacheFdEnabled() {
|
||||
return mMustCacheFd;
|
||||
}
|
||||
|
||||
typedef nsRefPtrHashtable<nsCStringHashKey, nsJAR> ZipsHashtable;
|
||||
|
||||
protected:
|
||||
@ -204,6 +210,7 @@ protected:
|
||||
mozilla::Mutex mLock;
|
||||
uint32_t mCacheSize;
|
||||
ZipsHashtable mZips;
|
||||
bool mMustCacheFd;
|
||||
|
||||
#ifdef ZIP_CACHE_HIT_RATE
|
||||
uint32_t mZipCacheLookups;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/net/RemoteOpenFileChild.h"
|
||||
#include "nsITabChild.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::net;
|
||||
@ -357,13 +358,34 @@ nsJARChannel::LookupFile()
|
||||
mJarFile = remoteFile;
|
||||
|
||||
nsIZipReaderCache *jarCache = gJarHandler->JarCache();
|
||||
if (jarCache && !mEnsureChildFd) {
|
||||
if (jarCache) {
|
||||
bool cached = false;
|
||||
rv = jarCache->IsCached(mJarFile, &cached);
|
||||
if (NS_SUCCEEDED(rv) && cached) {
|
||||
// zipcache already has file mmapped: don't open on parent,
|
||||
// just return and proceed to cache hit in CreateJarInput()
|
||||
// just return and proceed to cache hit in CreateJarInput().
|
||||
// When the file descriptor is needed, get it from JAR cache
|
||||
// if available, otherwise do the remote open to get a new
|
||||
// one.
|
||||
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
|
||||
// Windows/OSX desktop builds skip remoting, we don't need
|
||||
// file descriptor here.
|
||||
return NS_OK;
|
||||
#else
|
||||
if (!mEnsureChildFd) {
|
||||
return NS_OK;
|
||||
}
|
||||
PRFileDesc *fd = nullptr;
|
||||
jarCache->GetFd(mJarFile, &fd);
|
||||
if (fd) {
|
||||
PROsfd osfd = dup(PR_FileDesc2NativeHandle(fd));
|
||||
if (osfd == -1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
remoteFile->SetNSPRFileDesc(PR_ImportFile(osfd));
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,6 +399,10 @@ nsJARChannel::LookupFile()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mEnsureChildFd && jarCache) {
|
||||
jarCache->SetMustCacheFd(remoteFile, true);
|
||||
}
|
||||
|
||||
// Open file on parent: OnRemoteFileOpenComplete called when done
|
||||
nsCOMPtr<nsITabChild> tabChild;
|
||||
NS_QueryNotificationCallbacks(this, tabChild);
|
||||
@ -1044,7 +1070,11 @@ nsJARChannel::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status)
|
||||
mCallbacks = 0;
|
||||
mProgressSink = 0;
|
||||
|
||||
if (mOpeningRemote) {
|
||||
if (mEnsureChildFd) {
|
||||
nsIZipReaderCache *jarCache = gJarHandler->JarCache();
|
||||
if (jarCache) {
|
||||
jarCache->SetMustCacheFd(mJarFile, false);
|
||||
}
|
||||
// To deallocate file descriptor by RemoteOpenFileChild destructor.
|
||||
mJarFile = nullptr;
|
||||
}
|
||||
|
@ -171,7 +171,8 @@ nsZipHandle::nsZipHandle()
|
||||
NS_IMPL_ADDREF(nsZipHandle)
|
||||
NS_IMPL_RELEASE(nsZipHandle)
|
||||
|
||||
nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret, PRFileDesc **aFd)
|
||||
nsresult nsZipHandle::Init(nsIFile *file, bool aMustCacheFd, nsZipHandle **ret,
|
||||
PRFileDesc **aFd)
|
||||
{
|
||||
mozilla::AutoFDClose fd;
|
||||
int32_t flags = PR_RDONLY;
|
||||
@ -208,6 +209,10 @@ nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret, PRFileDesc **aFd)
|
||||
if (aFd) {
|
||||
*aFd = fd.forget();
|
||||
}
|
||||
#else
|
||||
if (aMustCacheFd) {
|
||||
handle->mNSPRFileDesc = fd.forget();
|
||||
}
|
||||
#endif
|
||||
handle->mMap = map;
|
||||
handle->mFile.Init(file);
|
||||
@ -244,6 +249,16 @@ int64_t nsZipHandle::SizeOfMapping()
|
||||
return mLen;
|
||||
}
|
||||
|
||||
nsresult nsZipHandle::GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc)
|
||||
{
|
||||
if (!aNSPRFileDesc) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
*aNSPRFileDesc = mNSPRFileDesc;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsZipHandle::~nsZipHandle()
|
||||
{
|
||||
if (mMap) {
|
||||
@ -279,14 +294,15 @@ nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle, PRFileDesc *aFd)
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsZipArchive::OpenArchive(nsIFile *aFile)
|
||||
nsresult nsZipArchive::OpenArchive(nsIFile *aFile, bool aMustCacheFd)
|
||||
{
|
||||
nsRefPtr<nsZipHandle> handle;
|
||||
#if defined(XP_WIN)
|
||||
mozilla::AutoFDClose fd;
|
||||
nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle), &fd.rwget());
|
||||
nsresult rv = nsZipHandle::Init(aFile, aMustCacheFd, getter_AddRefs(handle),
|
||||
&fd.rwget());
|
||||
#else
|
||||
nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle));
|
||||
nsresult rv = nsZipHandle::Init(aFile, aMustCacheFd, getter_AddRefs(handle));
|
||||
#endif
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
@ -120,10 +120,11 @@ public:
|
||||
*
|
||||
* Convenience function that generates nsZipHandle
|
||||
*
|
||||
* @param aFile The file used to access the zip
|
||||
* @param aFile The file used to access the zip
|
||||
* @param aMustCacheFd Optional flag to keep the PRFileDesc in nsZipHandle
|
||||
* @return status code
|
||||
*/
|
||||
nsresult OpenArchive(nsIFile *aFile);
|
||||
nsresult OpenArchive(nsIFile *aFile, bool aMustCacheFd = false);
|
||||
|
||||
/**
|
||||
* Test the integrity of items in this archive by running
|
||||
@ -380,7 +381,7 @@ class nsZipHandle {
|
||||
friend class nsZipArchive;
|
||||
friend class mozilla::FileLocation;
|
||||
public:
|
||||
static nsresult Init(nsIFile *file, nsZipHandle **ret,
|
||||
static nsresult Init(nsIFile *file, bool aMustCacheFd, nsZipHandle **ret,
|
||||
PRFileDesc **aFd = nullptr);
|
||||
static nsresult Init(nsZipArchive *zip, const char *entry,
|
||||
nsZipHandle **ret);
|
||||
@ -390,6 +391,8 @@ public:
|
||||
|
||||
int64_t SizeOfMapping();
|
||||
|
||||
nsresult GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc);
|
||||
|
||||
protected:
|
||||
const uint8_t * mFileData; /* pointer to mmaped file */
|
||||
uint32_t mLen; /* length of file and memory mapped area */
|
||||
@ -400,6 +403,7 @@ private:
|
||||
~nsZipHandle();
|
||||
|
||||
PRFileMap * mMap; /* nspr datastructure for mmap */
|
||||
mozilla::AutoFDClose mNSPRFileDesc;
|
||||
nsAutoPtr<nsZipItemPtr<uint8_t> > mBuf;
|
||||
mozilla::ThreadSafeAutoRefCnt mRefCnt; /* ref count */
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
@ -249,6 +249,18 @@ RemoteOpenFileChild::AsyncRemoteFileOpen(int32_t aFlags,
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
RemoteOpenFileChild::SetNSPRFileDesc(PRFileDesc* aNSPRFileDesc)
|
||||
{
|
||||
MOZ_ASSERT(!mNSPRFileDesc);
|
||||
if (mNSPRFileDesc) {
|
||||
return NS_ERROR_ALREADY_OPENED;
|
||||
}
|
||||
|
||||
mNSPRFileDesc = aNSPRFileDesc;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteOpenFileChild::OnCachedFileDescriptor(const nsAString& aPath,
|
||||
const FileDescriptor& aFD)
|
||||
|
@ -77,6 +77,8 @@ public:
|
||||
nsITabChild* aTabChild,
|
||||
nsILoadContext *aLoadContext);
|
||||
|
||||
nsresult SetNSPRFileDesc(PRFileDesc* aNSPRFileDesc);
|
||||
|
||||
void ReleaseIPDLReference()
|
||||
{
|
||||
Release();
|
||||
|
Loading…
Reference in New Issue
Block a user