Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "FileInfo.h"
8 :
9 : #include "FileManager.h"
10 : #include "IndexedDatabaseManager.h"
11 : #include "mozilla/Assertions.h"
12 : #include "mozilla/Attributes.h"
13 : #include "mozilla/Mutex.h"
14 : #include "mozilla/dom/quota/QuotaManager.h"
15 : #include "nsError.h"
16 : #include "nsThreadUtils.h"
17 :
18 : namespace mozilla {
19 : namespace dom {
20 : namespace indexedDB {
21 :
22 : using namespace mozilla::dom::quota;
23 :
24 : namespace {
25 :
26 : template <typename IdType>
27 : class FileInfoImpl final
28 : : public FileInfo
29 : {
30 : IdType mFileId;
31 :
32 : public:
33 0 : FileInfoImpl(FileManager* aFileManager, IdType aFileId)
34 : : FileInfo(aFileManager)
35 0 : , mFileId(aFileId)
36 : {
37 0 : MOZ_ASSERT(aFileManager);
38 0 : MOZ_ASSERT(aFileId > 0);
39 0 : }
40 :
41 : private:
42 0 : ~FileInfoImpl()
43 0 : { }
44 :
45 : virtual int64_t
46 0 : Id() const override
47 : {
48 0 : return int64_t(mFileId);
49 : }
50 : };
51 :
52 : class CleanupFileRunnable final
53 : : public Runnable
54 : {
55 : RefPtr<FileManager> mFileManager;
56 : int64_t mFileId;
57 :
58 : public:
59 : static void
60 : DoCleanup(FileManager* aFileManager, int64_t aFileId);
61 :
62 0 : CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId)
63 0 : : Runnable("dom::indexedDB::CleanupFileRunnable")
64 : , mFileManager(aFileManager)
65 0 : , mFileId(aFileId)
66 : {
67 0 : MOZ_ASSERT(aFileManager);
68 0 : MOZ_ASSERT(aFileId > 0);
69 0 : }
70 :
71 : NS_DECL_ISUPPORTS_INHERITED
72 :
73 : private:
74 0 : ~CleanupFileRunnable()
75 0 : { }
76 :
77 : NS_DECL_NSIRUNNABLE
78 : };
79 :
80 : } // namespace
81 :
82 0 : FileInfo::FileInfo(FileManager* aFileManager)
83 0 : : mFileManager(aFileManager)
84 : {
85 0 : MOZ_ASSERT(aFileManager);
86 0 : }
87 :
88 0 : FileInfo::~FileInfo()
89 : {
90 0 : }
91 :
92 : // static
93 : FileInfo*
94 0 : FileInfo::Create(FileManager* aFileManager, int64_t aId)
95 : {
96 0 : MOZ_ASSERT(aFileManager);
97 0 : MOZ_ASSERT(aId > 0);
98 :
99 0 : if (aId <= INT16_MAX) {
100 0 : return new FileInfoImpl<int16_t>(aFileManager, aId);
101 : }
102 :
103 0 : if (aId <= INT32_MAX) {
104 0 : return new FileInfoImpl<int32_t>(aFileManager, aId);
105 : }
106 :
107 0 : return new FileInfoImpl<int64_t>(aFileManager, aId);
108 : }
109 :
110 : void
111 0 : FileInfo::GetReferences(int32_t* aRefCnt,
112 : int32_t* aDBRefCnt,
113 : int32_t* aSliceRefCnt)
114 : {
115 0 : MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
116 :
117 0 : MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
118 :
119 0 : if (aRefCnt) {
120 0 : *aRefCnt = mRefCnt;
121 : }
122 :
123 0 : if (aDBRefCnt) {
124 0 : *aDBRefCnt = mDBRefCnt;
125 : }
126 :
127 0 : if (aSliceRefCnt) {
128 0 : *aSliceRefCnt = mSliceRefCnt;
129 : }
130 0 : }
131 :
132 : void
133 0 : FileInfo::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount,
134 : int32_t aDelta,
135 : CustomCleanupCallback* aCustomCleanupCallback)
136 : {
137 : // XXX This can go away once DOM objects no longer hold FileInfo objects...
138 : // Looking at you, BlobImplBase...
139 : // BlobImplBase is being addressed in bug 1068975.
140 0 : if (IndexedDatabaseManager::IsClosed()) {
141 0 : MOZ_ASSERT(&aRefCount == &mRefCnt);
142 0 : MOZ_ASSERT(aDelta == 1 || aDelta == -1);
143 :
144 0 : if (aDelta > 0) {
145 0 : ++aRefCount;
146 : } else {
147 0 : nsrefcnt count = --aRefCount;
148 0 : if (!count) {
149 0 : mRefCnt = 1;
150 0 : delete this;
151 : }
152 : }
153 0 : return;
154 : }
155 :
156 0 : MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
157 :
158 : bool needsCleanup;
159 : {
160 0 : MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
161 :
162 0 : aRefCount = aRefCount + aDelta;
163 :
164 0 : if (mRefCnt + mDBRefCnt + mSliceRefCnt > 0) {
165 0 : return;
166 : }
167 :
168 0 : mFileManager->mFileInfos.Remove(Id());
169 :
170 0 : needsCleanup = !mFileManager->Invalidated();
171 : }
172 :
173 0 : if (needsCleanup) {
174 0 : if (aCustomCleanupCallback) {
175 0 : nsresult rv = aCustomCleanupCallback->Cleanup(mFileManager, Id());
176 0 : if (NS_FAILED(rv)) {
177 0 : NS_WARNING("Custom cleanup failed!");
178 : }
179 : } else {
180 0 : Cleanup();
181 : }
182 : }
183 :
184 0 : delete this;
185 : }
186 :
187 : bool
188 0 : FileInfo::LockedClearDBRefs()
189 : {
190 0 : MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
191 :
192 0 : IndexedDatabaseManager::FileMutex().AssertCurrentThreadOwns();
193 :
194 0 : mDBRefCnt = 0;
195 :
196 0 : if (mRefCnt || mSliceRefCnt) {
197 0 : return true;
198 : }
199 :
200 : // In this case, we are not responsible for removing the file info from the
201 : // hashtable. It's up to FileManager which is the only caller of this method.
202 :
203 0 : MOZ_ASSERT(mFileManager->Invalidated());
204 :
205 0 : delete this;
206 :
207 0 : return false;
208 : }
209 :
210 : void
211 0 : FileInfo::Cleanup()
212 : {
213 0 : int64_t id = Id();
214 :
215 : // IndexedDatabaseManager is main-thread only.
216 0 : if (!NS_IsMainThread()) {
217 : RefPtr<CleanupFileRunnable> cleaner =
218 0 : new CleanupFileRunnable(mFileManager, id);
219 :
220 0 : MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(cleaner));
221 0 : return;
222 : }
223 :
224 0 : CleanupFileRunnable::DoCleanup(mFileManager, id);
225 : }
226 :
227 : // static
228 : void
229 0 : CleanupFileRunnable::DoCleanup(FileManager* aFileManager, int64_t aFileId)
230 : {
231 0 : MOZ_ASSERT(NS_IsMainThread());
232 0 : MOZ_ASSERT(aFileManager);
233 0 : MOZ_ASSERT(aFileId > 0);
234 :
235 0 : if (NS_WARN_IF(QuotaManager::IsShuttingDown())) {
236 0 : return;
237 : }
238 :
239 0 : RefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
240 0 : MOZ_ASSERT(mgr);
241 :
242 0 : if (NS_FAILED(mgr->AsyncDeleteFile(aFileManager, aFileId))) {
243 0 : NS_WARNING("Failed to delete file asynchronously!");
244 : }
245 : }
246 :
247 0 : NS_IMPL_ISUPPORTS_INHERITED0(CleanupFileRunnable, Runnable)
248 :
249 : NS_IMETHODIMP
250 0 : CleanupFileRunnable::Run()
251 : {
252 0 : MOZ_ASSERT(NS_IsMainThread());
253 :
254 0 : DoCleanup(mFileManager, mFileId);
255 :
256 0 : return NS_OK;
257 : }
258 :
259 : } // namespace indexedDB
260 : } // namespace dom
261 : } // namespace mozilla
|