michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "FileInfo.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "mozilla/dom/quota/QuotaManager.h" michael@0: michael@0: USING_INDEXEDDB_NAMESPACE michael@0: michael@0: namespace { michael@0: michael@0: class CleanupFileRunnable MOZ_FINAL : public nsIRunnable michael@0: { michael@0: public: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSIRUNNABLE michael@0: michael@0: CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId); michael@0: michael@0: private: michael@0: nsRefPtr mFileManager; michael@0: int64_t mFileId; michael@0: }; michael@0: michael@0: } // anonymous namespace michael@0: michael@0: // static michael@0: FileInfo* michael@0: FileInfo::Create(FileManager* aFileManager, int64_t aId) michael@0: { michael@0: MOZ_ASSERT(aId > 0, "Wrong id!"); michael@0: michael@0: if (aId <= INT16_MAX) { michael@0: return new FileInfo16(aFileManager, aId); michael@0: } michael@0: michael@0: if (aId <= INT32_MAX) { michael@0: return new FileInfo32(aFileManager, aId); michael@0: } michael@0: michael@0: return new FileInfo64(aFileManager, aId); michael@0: } michael@0: michael@0: void michael@0: FileInfo::GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt, michael@0: int32_t* aSliceRefCnt) michael@0: { michael@0: if (IndexedDatabaseManager::IsClosed()) { michael@0: NS_ERROR("Shouldn't be called after shutdown!"); michael@0: michael@0: if (aRefCnt) { michael@0: *aRefCnt = -1; michael@0: } michael@0: michael@0: if (aDBRefCnt) { michael@0: *aDBRefCnt = -1; michael@0: } michael@0: michael@0: if (aSliceRefCnt) { michael@0: *aSliceRefCnt = -1; michael@0: } michael@0: michael@0: return; michael@0: } michael@0: michael@0: MutexAutoLock lock(IndexedDatabaseManager::FileMutex()); michael@0: michael@0: if (aRefCnt) { michael@0: *aRefCnt = mRefCnt; michael@0: } michael@0: michael@0: if (aDBRefCnt) { michael@0: *aDBRefCnt = mDBRefCnt; michael@0: } michael@0: michael@0: if (aSliceRefCnt) { michael@0: *aSliceRefCnt = mSliceRefCnt; michael@0: } michael@0: } michael@0: michael@0: void michael@0: FileInfo::UpdateReferences(mozilla::ThreadSafeAutoRefCnt& aRefCount, michael@0: int32_t aDelta, bool aClear) michael@0: { michael@0: if (IndexedDatabaseManager::IsClosed()) { michael@0: NS_ERROR("Shouldn't be called after shutdown!"); michael@0: return; michael@0: } michael@0: michael@0: bool needsCleanup; michael@0: { michael@0: MutexAutoLock lock(IndexedDatabaseManager::FileMutex()); michael@0: michael@0: aRefCount = aClear ? 0 : aRefCount + aDelta; michael@0: michael@0: if (mRefCnt + mDBRefCnt + mSliceRefCnt > 0) { michael@0: return; michael@0: } michael@0: michael@0: mFileManager->mFileInfos.Remove(Id()); michael@0: michael@0: needsCleanup = !mFileManager->Invalidated(); michael@0: } michael@0: michael@0: if (needsCleanup) { michael@0: Cleanup(); michael@0: } michael@0: michael@0: delete this; michael@0: } michael@0: michael@0: void michael@0: FileInfo::Cleanup() michael@0: { michael@0: nsRefPtr cleaner = michael@0: new CleanupFileRunnable(mFileManager, Id()); michael@0: michael@0: // IndexedDatabaseManager is main-thread only. michael@0: if (!NS_IsMainThread()) { michael@0: NS_DispatchToMainThread(cleaner); michael@0: return; michael@0: } michael@0: michael@0: cleaner->Run(); michael@0: } michael@0: michael@0: CleanupFileRunnable::CleanupFileRunnable(FileManager* aFileManager, michael@0: int64_t aFileId) michael@0: : mFileManager(aFileManager), mFileId(aFileId) michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(CleanupFileRunnable, michael@0: nsIRunnable) michael@0: michael@0: NS_IMETHODIMP michael@0: CleanupFileRunnable::Run() michael@0: { michael@0: if (mozilla::dom::quota::QuotaManager::IsShuttingDown()) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsRefPtr mgr = IndexedDatabaseManager::Get(); michael@0: MOZ_ASSERT(mgr); michael@0: michael@0: if (NS_FAILED(mgr->AsyncDeleteFile(mFileManager, mFileId))) { michael@0: NS_WARNING("Failed to delete file asynchronously!"); michael@0: } michael@0: michael@0: return NS_OK; michael@0: }