Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2022-03-28 22:58:03 +08:00
commit 5f9cb05d1c
10 changed files with 119 additions and 170 deletions

View file

@ -931,6 +931,7 @@ nsresult
nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const NetAddr *addr) nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const NetAddr *addr)
{ {
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "wrong thread"); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "wrong thread");
NS_ASSERTION(!mFD.IsInitialized(), "already initialized");
char buf[kNetAddrMaxCStrBufSize]; char buf[kNetAddrMaxCStrBufSize];
NetAddrToString(addr, buf, sizeof(buf)); NetAddrToString(addr, buf, sizeof(buf));
@ -956,7 +957,6 @@ nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const NetAddr *addr)
{ {
MutexAutoLock lock(mLock); MutexAutoLock lock(mLock);
NS_ASSERTION(!mFD.IsInitialized(), "already initialized");
mFD = fd; mFD = fd;
mFDref = 1; mFDref = 1;
mFDconnected = 1; mFDconnected = 1;
@ -1031,7 +1031,6 @@ nsSocketTransport::ResolveHost()
this, SocketHost().get(), SocketPort(), this, SocketHost().get(), SocketPort(),
mConnectionFlags & nsSocketTransport::BYPASS_CACHE ? mConnectionFlags & nsSocketTransport::BYPASS_CACHE ?
" bypass cache" : "")); " bypass cache" : ""));
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
nsresult rv; nsresult rv;
@ -1238,7 +1237,6 @@ nsresult
nsSocketTransport::InitiateSocket() nsSocketTransport::InitiateSocket()
{ {
SOCKET_LOG(("nsSocketTransport::InitiateSocket [this=%p]\n", this)); SOCKET_LOG(("nsSocketTransport::InitiateSocket [this=%p]\n", this));
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
nsresult rv; nsresult rv;
bool isLocal; bool isLocal;
@ -1322,14 +1320,11 @@ nsSocketTransport::InitiateSocket()
// //
// if we already have a connected socket, then just attach and return. // if we already have a connected socket, then just attach and return.
// //
{ if (mFD.IsInitialized()) {
MutexAutoLock lock(mLock);
if (mFD.IsInitialized()) {
rv = mSocketTransportService->AttachSocket(mFD, this); rv = mSocketTransportService->AttachSocket(mFD, this);
if (NS_SUCCEEDED(rv)) if (NS_SUCCEEDED(rv))
mAttached = true; mAttached = true;
return rv; return rv;
}
} }
// //
@ -1394,20 +1389,19 @@ nsSocketTransport::InitiateSocket()
opt.value.linger.linger = 0; opt.value.linger.linger = 0;
PR_SetSocketOption(fd, &opt); PR_SetSocketOption(fd, &opt);
#endif #endif
// up to here, mFD will only be accessed by us
// inform socket transport about this newly created socket...
rv = mSocketTransportService->AttachSocket(fd, this);
if (NS_FAILED(rv)) {
CloseSocket(fd);
return rv;
}
mAttached = true;
// assign mFD so that we can properly handle OnSocketDetached before we've // assign mFD so that we can properly handle OnSocketDetached before we've
// established a connection. // established a connection.
{ {
MutexAutoLock lock(mLock); MutexAutoLock lock(mLock);
// inform socket transport about this newly created socket...
rv = mSocketTransportService->AttachSocket(fd, this);
if (NS_FAILED(rv)) {
CloseSocket(fd);
return rv;
}
mAttached = true;
mFD = fd; mFD = fd;
mFDref = 1; mFDref = 1;
mFDconnected = false; mFDconnected = false;
@ -1552,12 +1546,8 @@ nsSocketTransport::RecoverFromError()
nsresult rv; nsresult rv;
#ifdef DEBUG // OK to check this outside mLock
{ NS_ASSERTION(!mFDconnected, "socket should not be connected");
MutexAutoLock lock(mLock);
NS_ASSERTION(!mFDconnected, "socket should not be connected");
}
#endif
// all connection failures need to be reported to DNS so that the next // all connection failures need to be reported to DNS so that the next
// time we will use a different address if available. // time we will use a different address if available.
@ -1809,7 +1799,6 @@ nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd)
void void
nsSocketTransport::OnSocketEvent(uint32_t type, nsresult status, nsISupports *param) nsSocketTransport::OnSocketEvent(uint32_t type, nsresult status, nsISupports *param)
{ {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
SOCKET_LOG(("nsSocketTransport::OnSocketEvent [this=%p type=%u status=%x param=%p]\n", SOCKET_LOG(("nsSocketTransport::OnSocketEvent [this=%p type=%u status=%x param=%p]\n",
this, type, status, param)); this, type, status, param));
@ -1922,7 +1911,6 @@ nsSocketTransport::OnSocketEvent(uint32_t type, nsresult status, nsISupports *pa
void void
nsSocketTransport::OnSocketReady(PRFileDesc *fd, int16_t outFlags) nsSocketTransport::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
{ {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
SOCKET_LOG(("nsSocketTransport::OnSocketReady [this=%p outFlags=%hd]\n", SOCKET_LOG(("nsSocketTransport::OnSocketReady [this=%p outFlags=%hd]\n",
this, outFlags)); this, outFlags));
@ -2431,7 +2419,6 @@ nsSocketTransport::Bind(NetAddr *aLocalAddr)
NS_ENSURE_ARG(aLocalAddr); NS_ENSURE_ARG(aLocalAddr);
MutexAutoLock lock(mLock); MutexAutoLock lock(mLock);
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
if (mAttached) { if (mAttached) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

View file

@ -350,13 +350,11 @@ private:
void OnMsgInputPending() void OnMsgInputPending()
{ {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
if (mState == STATE_TRANSFERRING) if (mState == STATE_TRANSFERRING)
mPollFlags |= (PR_POLL_READ | PR_POLL_EXCEPT); mPollFlags |= (PR_POLL_READ | PR_POLL_EXCEPT);
} }
void OnMsgOutputPending() void OnMsgOutputPending()
{ {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
if (mState == STATE_TRANSFERRING) if (mState == STATE_TRANSFERRING)
mPollFlags |= (PR_POLL_WRITE | PR_POLL_EXCEPT); mPollFlags |= (PR_POLL_WRITE | PR_POLL_EXCEPT);
} }

View file

@ -143,11 +143,8 @@ CacheEntry::Callback::~Callback()
MOZ_COUNT_DTOR(CacheEntry::Callback); MOZ_COUNT_DTOR(CacheEntry::Callback);
} }
// We have locks on both this and aEntry
void CacheEntry::Callback::ExchangeEntry(CacheEntry* aEntry) void CacheEntry::Callback::ExchangeEntry(CacheEntry* aEntry)
{ {
aEntry->mLock.AssertCurrentThreadOwns();
mEntry->mLock.AssertCurrentThreadOwns();
if (mEntry == aEntry) if (mEntry == aEntry)
return; return;
@ -212,11 +209,11 @@ CacheEntry::CacheEntry(const nsACString& aStorageID,
, mStorageID(aStorageID) , mStorageID(aStorageID)
, mUseDisk(aUseDisk) , mUseDisk(aUseDisk)
, mSkipSizeCheck(aSkipSizeCheck) , mSkipSizeCheck(aSkipSizeCheck)
, mPinned(aPin)
, mIsDoomed(false) , mIsDoomed(false)
, mSecurityInfoLoaded(false) , mSecurityInfoLoaded(false)
, mPreventCallbacks(false) , mPreventCallbacks(false)
, mHasData(false) , mHasData(false)
, mPinned(aPin)
, mPinningKnown(false) , mPinningKnown(false)
, mState(NOTLOADED) , mState(NOTLOADED)
, mRegistration(NEVERREGISTERED) , mRegistration(NEVERREGISTERED)
@ -300,6 +297,9 @@ nsresult CacheEntry::HashingKey(nsCSubstring const& aStorageID,
void CacheEntry::AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags) void CacheEntry::AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags)
{ {
LOG(("CacheEntry::AsyncOpen [this=%p, state=%s, flags=%d, callback=%p]",
this, StateString(mState), aFlags, aCallback));
bool readonly = aFlags & nsICacheStorage::OPEN_READONLY; bool readonly = aFlags & nsICacheStorage::OPEN_READONLY;
bool bypassIfBusy = aFlags & nsICacheStorage::OPEN_BYPASS_IF_BUSY; bool bypassIfBusy = aFlags & nsICacheStorage::OPEN_BYPASS_IF_BUSY;
bool truncate = aFlags & nsICacheStorage::OPEN_TRUNCATE; bool truncate = aFlags & nsICacheStorage::OPEN_TRUNCATE;
@ -307,20 +307,8 @@ void CacheEntry::AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags
bool multithread = aFlags & nsICacheStorage::CHECK_MULTITHREADED; bool multithread = aFlags & nsICacheStorage::CHECK_MULTITHREADED;
bool secret = aFlags & nsICacheStorage::OPEN_SECRETLY; bool secret = aFlags & nsICacheStorage::OPEN_SECRETLY;
if (MOZ_LOG_TEST(gCache2Log, LogLevel::Debug)) { MOZ_ASSERT(!readonly || !truncate, "Bad flags combination");
MutexAutoLock lock(mLock); MOZ_ASSERT(!(truncate && mState > LOADING), "Must not call truncate on already loaded entry");
LOG(("CacheEntry::AsyncOpen [this=%p, state=%s, flags=%d, callback=%p]",
this, StateString(mState), aFlags, aCallback));
}
#ifdef DEBUG
{
// yes, if logging is on in DEBUG we'll take the lock twice in a row
MutexAutoLock lock(mLock);
MOZ_ASSERT(!readonly || !truncate, "Bad flags combination");
MOZ_ASSERT(!(truncate && mState > LOADING),
"Must not call truncate on already loaded entry");
}
#endif
Callback callback(this, aCallback, readonly, multithread, secret); Callback callback(this, aCallback, readonly, multithread, secret);
@ -482,7 +470,7 @@ NS_IMETHODIMP CacheEntry::OnFileReady(nsresult aResult, bool aIsNew)
mPinned = mFile->IsPinned();; mPinned = mFile->IsPinned();;
mPinningKnown = true; mPinningKnown = true;
LOG((" pinning=%d", (bool)mPinned)); LOG((" pinning=%d", mPinned));
if (mState == READY) { if (mState == READY) {
mHasData = true; mHasData = true;
@ -572,7 +560,6 @@ already_AddRefed<CacheEntryHandle> CacheEntry::ReopenTruncated(bool aMemoryOnly,
void CacheEntry::TransferCallbacks(CacheEntry & aFromEntry) void CacheEntry::TransferCallbacks(CacheEntry & aFromEntry)
{ {
mozilla::MutexAutoLock lock(mLock); mozilla::MutexAutoLock lock(mLock);
aFromEntry.mLock.AssertCurrentThreadOwns();
LOG(("CacheEntry::TransferCallbacks [entry=%p, from=%p]", LOG(("CacheEntry::TransferCallbacks [entry=%p, from=%p]",
this, &aFromEntry)); this, &aFromEntry));
@ -697,10 +684,11 @@ bool CacheEntry::InvokeCallbacks(bool aReadOnly)
bool CacheEntry::InvokeCallback(Callback & aCallback) bool CacheEntry::InvokeCallback(Callback & aCallback)
{ {
mLock.AssertCurrentThreadOwns();
LOG(("CacheEntry::InvokeCallback [this=%p, state=%s, cb=%p]", LOG(("CacheEntry::InvokeCallback [this=%p, state=%s, cb=%p]",
this, StateString(mState), aCallback.mCallback.get())); this, StateString(mState), aCallback.mCallback.get()));
mLock.AssertCurrentThreadOwns();
// When this entry is doomed we want to notify the callback any time // When this entry is doomed we want to notify the callback any time
if (!mIsDoomed) { if (!mIsDoomed) {
// When we are here, the entry must be loaded from disk // When we are here, the entry must be loaded from disk
@ -814,21 +802,15 @@ bool CacheEntry::InvokeCallback(Callback & aCallback)
void CacheEntry::InvokeAvailableCallback(Callback const & aCallback) void CacheEntry::InvokeAvailableCallback(Callback const & aCallback)
{ {
nsresult rv; LOG(("CacheEntry::InvokeAvailableCallback [this=%p, state=%s, cb=%p, r/o=%d, n/w=%d]",
uint32_t state; this, StateString(mState), aCallback.mCallback.get(), aCallback.mReadOnly, aCallback.mNotWanted));
{ // Scope for lock
mozilla::MutexAutoLock lock(mLock);
state = mState;
LOG(
("CacheEntry::InvokeAvailableCallback [this=%p, state=%s, cb=%p, "
"r/o=%d, "
"n/w=%d]",
this, StateString(mState), aCallback.mCallback.get(),
aCallback.mReadOnly, aCallback.mNotWanted));
// When we are here, the entry must be loaded from disk nsresult rv;
MOZ_ASSERT(state > LOADING || mIsDoomed);
} uint32_t const state = mState;
// When we are here, the entry must be loaded from disk
MOZ_ASSERT(state > LOADING || mIsDoomed);
bool onAvailThread; bool onAvailThread;
rv = aCallback.OnAvailThread(&onAvailThread); rv = aCallback.OnAvailThread(&onAvailThread);
@ -929,10 +911,11 @@ CacheEntryHandle* CacheEntry::NewWriteHandle()
void CacheEntry::OnHandleClosed(CacheEntryHandle const* aHandle) void CacheEntry::OnHandleClosed(CacheEntryHandle const* aHandle)
{ {
mozilla::MutexAutoLock lock(mLock);
LOG(("CacheEntry::OnHandleClosed [this=%p, state=%s, handle=%p]", this, StateString(mState), aHandle)); LOG(("CacheEntry::OnHandleClosed [this=%p, state=%s, handle=%p]", this, StateString(mState), aHandle));
if (mIsDoomed && NS_SUCCEEDED(mFileStatus) && mozilla::MutexAutoLock lock(mLock);
if (IsDoomed() && NS_SUCCEEDED(mFileStatus) &&
// Note: mHandlesCount is dropped before this method is called // Note: mHandlesCount is dropped before this method is called
(mHandlesCount == 0 || (mHandlesCount == 0 ||
(mHandlesCount == 1 && mWriter && mWriter != aHandle)) (mHandlesCount == 1 && mWriter && mWriter != aHandle))
@ -1081,12 +1064,8 @@ NS_IMETHODIMP CacheEntry::GetIsForcedValid(bool *aIsForcedValid)
{ {
NS_ENSURE_ARG(aIsForcedValid); NS_ENSURE_ARG(aIsForcedValid);
#ifdef DEBUG MOZ_ASSERT(mState > LOADING);
{
mozilla::MutexAutoLock lock(mLock);
MOZ_ASSERT(mState > LOADING);
}
#endif
if (mPinned) { if (mPinned) {
*aIsForcedValid = true; *aIsForcedValid = true;
return NS_OK; return NS_OK;
@ -1450,11 +1429,12 @@ NS_IMETHODIMP CacheEntry::MetaDataReady()
NS_IMETHODIMP CacheEntry::SetValid() NS_IMETHODIMP CacheEntry::SetValid()
{ {
LOG(("CacheEntry::SetValid [this=%p, state=%s]", this, StateString(mState)));
nsCOMPtr<nsIOutputStream> outputStream; nsCOMPtr<nsIOutputStream> outputStream;
{ // Scope for lock {
mozilla::MutexAutoLock lock(mLock); mozilla::MutexAutoLock lock(mLock);
LOG(("CacheEntry::SetValid [this=%p, state=%s]", this, StateString(mState)));
MOZ_ASSERT(mState > EMPTY); MOZ_ASSERT(mState > EMPTY);
@ -1477,9 +1457,10 @@ NS_IMETHODIMP CacheEntry::SetValid()
NS_IMETHODIMP CacheEntry::Recreate(bool aMemoryOnly, NS_IMETHODIMP CacheEntry::Recreate(bool aMemoryOnly,
nsICacheEntry **_retval) nsICacheEntry **_retval)
{ {
mozilla::MutexAutoLock lock(mLock);
LOG(("CacheEntry::Recreate [this=%p, state=%s]", this, StateString(mState))); LOG(("CacheEntry::Recreate [this=%p, state=%s]", this, StateString(mState)));
mozilla::MutexAutoLock lock(mLock);
RefPtr<CacheEntryHandle> handle = ReopenTruncated(aMemoryOnly, nullptr); RefPtr<CacheEntryHandle> handle = ReopenTruncated(aMemoryOnly, nullptr);
if (handle) { if (handle) {
handle.forget(_retval); handle.forget(_retval);
@ -1619,7 +1600,7 @@ bool CacheEntry::DeferOrBypassRemovalOnPinStatus(bool aPinned)
mozilla::MutexAutoLock lock(mLock); mozilla::MutexAutoLock lock(mLock);
if (mPinningKnown) { if (mPinningKnown) {
LOG((" pinned=%d, caller=%d", (bool)mPinned, aPinned)); LOG((" pinned=%d, caller=%d", mPinned, aPinned));
// Bypass when the pin status of this entry doesn't match the pin status // Bypass when the pin status of this entry doesn't match the pin status
// caller wants to remove // caller wants to remove
return mPinned != aPinned; return mPinned != aPinned;
@ -1892,12 +1873,10 @@ NS_IMETHODIMP CacheOutputCloseListener::Run()
// Memory reporting // Memory reporting
size_t CacheEntry::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) size_t CacheEntry::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{ {
size_t n = 0; size_t n = 0;
MutexAutoLock lock(mLock);
n += mCallbacks.ShallowSizeOfExcludingThis(mallocSizeOf); n += mCallbacks.ShallowSizeOfExcludingThis(mallocSizeOf);
if (mFile) { if (mFile) {
n += mFile->SizeOfIncludingThis(mallocSizeOf); n += mFile->SizeOfIncludingThis(mallocSizeOf);
@ -1917,7 +1896,7 @@ size_t CacheEntry::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
return n; return n;
} }
size_t CacheEntry::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) size_t CacheEntry::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{ {
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf); return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
} }

View file

@ -119,8 +119,8 @@ public:
::mozilla::Atomic<uint32_t, ::mozilla::Relaxed> mSortingExpirationTime; ::mozilla::Atomic<uint32_t, ::mozilla::Relaxed> mSortingExpirationTime;
// Memory reporting // Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private: private:
virtual ~CacheEntry(); virtual ~CacheEntry();
@ -152,8 +152,7 @@ private:
void ExchangeEntry(CacheEntry* aEntry); void ExchangeEntry(CacheEntry* aEntry);
// Returns true when an entry is about to be "defer" doomed and this is // Returns true when an entry is about to be "defer" doomed and this is
// a "defer" callback. The caller must hold a lock (this entry is in the // a "defer" callback.
// caller's mCallback array)
bool DeferDoom(bool *aDoom) const; bool DeferDoom(bool *aDoom) const;
// We are raising reference count here to take into account the pending // We are raising reference count here to take into account the pending
@ -290,10 +289,9 @@ private:
// When mFileStatus is read and found success it is ensured there is mFile and // When mFileStatus is read and found success it is ensured there is mFile and
// that it is after a successful call to Init(). // that it is after a successful call to Init().
::mozilla::Atomic<nsresult, ::mozilla::ReleaseAcquire> mFileStatus; ::mozilla::Atomic<nsresult, ::mozilla::ReleaseAcquire> mFileStatus;
// Set in constructor nsCString mURI;
nsCString const mURI; nsCString mEnhanceID;
nsCString const mEnhanceID; nsCString mStorageID;
nsCString const mStorageID;
// mUseDisk, mSkipSizeCheck, mIsDoomed are plain "bool", not "bool:1", // mUseDisk, mSkipSizeCheck, mIsDoomed are plain "bool", not "bool:1",
// so as to avoid bitfield races with the byte containing // so as to avoid bitfield races with the byte containing
@ -304,9 +302,7 @@ private:
// Whether it should skip max size check. // Whether it should skip max size check.
bool const mSkipSizeCheck; bool const mSkipSizeCheck;
// Set when entry is doomed with AsyncDoom() or DoomAlreadyRemoved(). // Set when entry is doomed with AsyncDoom() or DoomAlreadyRemoved().
Atomic<bool, Relaxed> mIsDoomed; bool mIsDoomed;
// The indication of pinning this entry was open with
Atomic<bool, Relaxed> mPinned;
// Following flags are all synchronized with the cache entry lock. // Following flags are all synchronized with the cache entry lock.
@ -321,6 +317,8 @@ private:
// false: after load and a new file, or dropped to back to false when a writer // false: after load and a new file, or dropped to back to false when a writer
// fails to open an output stream. // fails to open an output stream.
bool mHasData : 1; bool mHasData : 1;
// The indication of pinning this entry was open with
bool mPinned : 1;
// Whether the pinning state of the entry is known (equals to the actual state // Whether the pinning state of the entry is known (equals to the actual state
// of the cache file) // of the cache file)
bool mPinningKnown : 1; bool mPinningKnown : 1;

View file

@ -323,16 +323,6 @@ CacheFile::Init(const nsACString &aKey,
return NS_OK; return NS_OK;
} }
void CacheFile::Key(nsACString& aKey) {
CacheFileAutoLock lock(this);
aKey = mKey;
}
bool CacheFile::IsPinned() {
CacheFileAutoLock lock(this);
return mPinned;
}
nsresult nsresult
CacheFile::OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) CacheFile::OnChunkRead(nsresult aResult, CacheFileChunk *aChunk)
{ {
@ -479,7 +469,6 @@ CacheFile::OnFileOpened(CacheFileHandle *aHandle, nsresult aResult)
bool mAlreadyDoomed; bool mAlreadyDoomed;
} autoDoom(aHandle); } autoDoom(aHandle);
RefPtr<CacheFileMetadata> metadata;
nsCOMPtr<CacheFileListener> listener; nsCOMPtr<CacheFileListener> listener;
bool isNew = false; bool isNew = false;
nsresult retval = NS_OK; nsresult retval = NS_OK;
@ -582,22 +571,20 @@ CacheFile::OnFileOpened(CacheFileHandle *aHandle, nsresult aResult)
return NS_OK; return NS_OK;
} }
} }
if (listener) {
lock.Unlock();
listener->OnFileReady(retval, isNew);
return NS_OK;
}
MOZ_ASSERT(NS_SUCCEEDED(aResult));
MOZ_ASSERT(!mMetadata);
MOZ_ASSERT(mListener);
metadata = mMetadata = new CacheFileMetadata(mHandle, mKey);
} }
if (listener) {
listener->OnFileReady(retval, isNew);
return NS_OK;
}
MOZ_ASSERT(NS_SUCCEEDED(aResult));
MOZ_ASSERT(!mMetadata);
MOZ_ASSERT(mListener);
mMetadata = new CacheFileMetadata(mHandle, mKey); mMetadata = new CacheFileMetadata(mHandle, mKey);
rv = metadata->ReadMetadata(this); rv = mMetadata->ReadMetadata(this);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mListener.swap(listener); mListener.swap(listener);
listener->OnFileReady(rv, false); listener->OnFileReady(rv, false);
@ -624,42 +611,40 @@ CacheFile::OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult)
nsresult nsresult
CacheFile::OnMetadataRead(nsresult aResult) CacheFile::OnMetadataRead(nsresult aResult)
{ {
nsCOMPtr<CacheFileListener> listener; MOZ_ASSERT(mListener);
LOG(("CacheFile::OnMetadataRead() [this=%p, rv=0x%08x]", this, aResult));
bool isNew = false; bool isNew = false;
{ if (NS_SUCCEEDED(aResult)) {
CacheFileAutoLock lock(this); mPinned = mMetadata->Pinned();
MOZ_ASSERT(mListener); mReady = true;
mDataSize = mMetadata->Offset();
LOG(("CacheFile::OnMetadataRead() [this=%p, rv=0x%08]", this, if (mDataSize == 0 && mMetadata->ElementsSize() == 0) {
static_cast<uint32_t>(aResult))); isNew = true;
mMetadata->MarkDirty();
if (NS_SUCCEEDED(aResult)) { } else {
mPinned = mMetadata->Pinned(); const char *altData = mMetadata->GetElement(CacheFileUtils::kAltDataKey);
mReady = true; if (altData &&
mDataSize = mMetadata->Offset(); (NS_FAILED(CacheFileUtils::ParseAlternativeDataInfo(
if (mDataSize == 0 && mMetadata->ElementsSize() == 0) { altData, &mAltDataOffset, nullptr)) ||
mMetadata->MarkDirty(); (mAltDataOffset > mDataSize))) {
// alt-metadata cannot be parsed or alt-data offset is invalid
mMetadata->InitEmptyMetadata();
isNew = true;
mAltDataOffset = -1;
mDataSize = 0;
} else { } else {
const char* altData = CacheFileAutoLock lock(this);
mMetadata->GetElement(CacheFileUtils::kAltDataKey); PreloadChunks(0);
if (altData && (NS_FAILED(CacheFileUtils::ParseAlternativeDataInfo(
altData, &mAltDataOffset, nullptr)) ||
(mAltDataOffset > mDataSize))) {
// alt-metadata cannot be parsed or alt-data offset is invalid
mMetadata->InitEmptyMetadata();
isNew = true;
mAltDataOffset = -1;
mDataSize = 0;
} else {
PreloadChunks(0);
}
} }
InitIndexEntry();
} }
mListener.swap(listener);
InitIndexEntry();
} }
nsCOMPtr<CacheFileListener> listener;
mListener.swap(listener);
listener->OnFileReady(aResult, isNew); listener->OnFileReady(aResult, isNew);
return NS_OK; return NS_OK;
} }
@ -1036,7 +1021,6 @@ CacheFile::Doom(CacheFileListener *aCallback)
nsresult nsresult
CacheFile::DoomLocked(CacheFileListener *aCallback) CacheFile::DoomLocked(CacheFileListener *aCallback)
{ {
AssertOwnsLock();
MOZ_ASSERT(mHandle || mMemoryOnly || mOpeningFile); MOZ_ASSERT(mHandle || mMemoryOnly || mOpeningFile);
LOG(("CacheFile::DoomLocked() [this=%p, listener=%p]", this, aCallback)); LOG(("CacheFile::DoomLocked() [this=%p, listener=%p]", this, aCallback));
@ -1248,7 +1232,6 @@ CacheFile::GetFetchCount(uint32_t *_retval)
nsresult nsresult
CacheFile::GetDiskStorageSizeInKB(uint32_t *aDiskStorageSize) CacheFile::GetDiskStorageSizeInKB(uint32_t *aDiskStorageSize)
{ {
CacheFileAutoLock lock(this);
if (!mHandle) { if (!mHandle) {
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
@ -1272,6 +1255,30 @@ CacheFile::OnFetched()
return mMetadata->OnFetched(); return mMetadata->OnFetched();
} }
void
CacheFile::Lock()
{
mLock.Lock();
}
void
CacheFile::Unlock()
{
// move the elements out of mObjsToRelease
// so that they can be released after we unlock
nsTArray<RefPtr<nsISupports>> objs;
objs.SwapElements(mObjsToRelease);
mLock.Unlock();
}
void
CacheFile::AssertOwnsLock() const
{
mLock.AssertCurrentThreadOwns();
}
void void
CacheFile::ReleaseOutsideLock(RefPtr<nsISupports> aObject) CacheFile::ReleaseOutsideLock(RefPtr<nsISupports> aObject)
{ {
@ -2003,7 +2010,6 @@ CacheFile::NotifyChunkListeners(uint32_t aIndex, nsresult aResult,
bool bool
CacheFile::HaveChunkListeners(uint32_t aIndex) CacheFile::HaveChunkListeners(uint32_t aIndex)
{ {
AssertOwnsLock();
ChunkListeners *listeners; ChunkListeners *listeners;
mChunkListeners.Get(aIndex, &listeners); mChunkListeners.Get(aIndex, &listeners);
return !!listeners; return !!listeners;
@ -2264,7 +2270,6 @@ CacheFile::SetError(nsresult aStatus)
nsresult nsresult
CacheFile::InitIndexEntry() CacheFile::InitIndexEntry()
{ {
AssertOwnsLock();
MOZ_ASSERT(mHandle); MOZ_ASSERT(mHandle);
if (mHandle->IsDoomed()) if (mHandle->IsDoomed())

View file

@ -112,10 +112,9 @@ public:
nsresult OnFetched(); nsresult OnFetched();
bool DataSize(int64_t* aSize); bool DataSize(int64_t* aSize);
void Key(nsACString& aKey); void Key(nsACString& aKey) { aKey = mKey; }
bool IsDoomed(); bool IsDoomed();
bool IsPinned(); bool IsPinned() const { return mPinned; }
// Returns true when there is a potentially unfinished write operation.
bool IsWriteInProgress(); bool IsWriteInProgress();
// Memory reporting // Memory reporting
@ -132,16 +131,10 @@ private:
virtual ~CacheFile(); virtual ~CacheFile();
void Lock() { mLock.Lock(); } void Lock();
void Unlock() { void Unlock();
// move the elements out of mObjsToRelease void AssertOwnsLock() const;
// so that they can be released after we unlock void ReleaseOutsideLock(RefPtr<nsISupports> aObject);
nsTArray<RefPtr<nsISupports>> objs = std::move(mObjsToRelease);
mLock.Unlock();
}
void AssertOwnsLock() const { mLock.AssertCurrentThreadOwns(); }
void ReleaseOutsideLock(RefPtr<nsISupports> aObject);
enum ECallerType { enum ECallerType {
READER = 0, READER = 0,

View file

@ -472,7 +472,6 @@ void
CacheFileChunk::WaitForUpdate(CacheFileChunkListener *aCallback) CacheFileChunk::WaitForUpdate(CacheFileChunkListener *aCallback)
{ {
AssertOwnsLock(); AssertOwnsLock();
mFile->AssertOwnsLock(); // For thread-safety analysis
LOG(("CacheFileChunk::WaitForUpdate() [this=%p, listener=%p]", LOG(("CacheFileChunk::WaitForUpdate() [this=%p, listener=%p]",
this, aCallback)); this, aCallback));
@ -587,7 +586,6 @@ void
CacheFileChunk::UpdateDataSize(uint32_t aOffset, uint32_t aLen) CacheFileChunk::UpdateDataSize(uint32_t aOffset, uint32_t aLen)
{ {
AssertOwnsLock(); AssertOwnsLock();
mFile->AssertOwnsLock(); // For thread-safety analysis
// UpdateDataSize() is called only when we've written some data to the chunk // UpdateDataSize() is called only when we've written some data to the chunk
// and we never write data anymore once some error occurs. // and we never write data anymore once some error occurs.

View file

@ -348,7 +348,6 @@ NS_IMETHODIMP
CacheFileInputStream::Seek(int32_t whence, int64_t offset) CacheFileInputStream::Seek(int32_t whence, int64_t offset)
{ {
CacheFileAutoLock lock(mFile); CacheFileAutoLock lock(mFile);
mFile->AssertOwnsLock(); // For thread-safety analysis
LOG(("CacheFileInputStream::Seek() [this=%p, whence=%d, offset=%lld]", LOG(("CacheFileInputStream::Seek() [this=%p, whence=%d, offset=%lld]",
this, whence, offset)); this, whence, offset));
@ -396,7 +395,6 @@ NS_IMETHODIMP
CacheFileInputStream::Tell(int64_t *_retval) CacheFileInputStream::Tell(int64_t *_retval)
{ {
CacheFileAutoLock lock(mFile); CacheFileAutoLock lock(mFile);
mFile->AssertOwnsLock(); // For thread-safety analysis
if (mClosed) { if (mClosed) {
LOG(("CacheFileInputStream::Tell() - Stream is closed. [this=%p]", this)); LOG(("CacheFileInputStream::Tell() - Stream is closed. [this=%p]", this));

View file

@ -90,7 +90,6 @@ CacheFileOutputStream::Write(const char * aBuf, uint32_t aCount,
uint32_t *_retval) uint32_t *_retval)
{ {
CacheFileAutoLock lock(mFile); CacheFileAutoLock lock(mFile);
mFile->AssertOwnsLock(); // For thread-safety analysis
LOG(("CacheFileOutputStream::Write() [this=%p, count=%d]", this, aCount)); LOG(("CacheFileOutputStream::Write() [this=%p, count=%d]", this, aCount));
@ -258,7 +257,6 @@ NS_IMETHODIMP
CacheFileOutputStream::Seek(int32_t whence, int64_t offset) CacheFileOutputStream::Seek(int32_t whence, int64_t offset)
{ {
CacheFileAutoLock lock(mFile); CacheFileAutoLock lock(mFile);
mFile->AssertOwnsLock(); // For thread-safety analysis
LOG(("CacheFileOutputStream::Seek() [this=%p, whence=%d, offset=%lld]", LOG(("CacheFileOutputStream::Seek() [this=%p, whence=%d, offset=%lld]",
this, whence, offset)); this, whence, offset));
@ -300,7 +298,6 @@ NS_IMETHODIMP
CacheFileOutputStream::Tell(int64_t *_retval) CacheFileOutputStream::Tell(int64_t *_retval)
{ {
CacheFileAutoLock lock(mFile); CacheFileAutoLock lock(mFile);
mFile->AssertOwnsLock(); // For thread-safety analysis
if (mClosed) { if (mClosed) {
LOG(("CacheFileOutputStream::Tell() - Stream is closed. [this=%p]", this)); LOG(("CacheFileOutputStream::Tell() - Stream is closed. [this=%p]", this));
@ -374,8 +371,6 @@ void CacheFileOutputStream::NotifyCloseListener()
void void
CacheFileOutputStream::ReleaseChunk() CacheFileOutputStream::ReleaseChunk()
{ {
mFile->AssertOwnsLock();
LOG(("CacheFileOutputStream::ReleaseChunk() [this=%p, idx=%d]", LOG(("CacheFileOutputStream::ReleaseChunk() [this=%p, idx=%d]",
this, mChunk->Index())); this, mChunk->Index()));

View file

@ -115,8 +115,6 @@ private:
mozilla::Monitor mMonitor; mozilla::Monitor mMonitor;
PRThread* mThread; PRThread* mThread;
// Only set in Init(), before the thread is started, which reads it but never
// writes
UniquePtr<detail::BlockingIOWatcher> mBlockingIOWatcher; UniquePtr<detail::BlockingIOWatcher> mBlockingIOWatcher;
Atomic<nsIThread *> mXPCOMThread; Atomic<nsIThread *> mXPCOMThread;
Atomic<uint32_t, Relaxed> mLowestLevelWaiting; Atomic<uint32_t, Relaxed> mLowestLevelWaiting;
@ -130,7 +128,7 @@ private:
// Raised when nsIEventTarget.Dispatch() is called on this thread // Raised when nsIEventTarget.Dispatch() is called on this thread
Atomic<bool, Relaxed> mHasXPCOMEvents; Atomic<bool, Relaxed> mHasXPCOMEvents;
// See YieldAndRerun() above // See YieldAndRerun() above
bool mRerunCurrentEvent; // Only accessed on the cache thread bool mRerunCurrentEvent;
// Signal to process all pending events and then shutdown // Signal to process all pending events and then shutdown
// Synchronized by mMonitor // Synchronized by mMonitor
bool mShutdown; bool mShutdown;