|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=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 "DatabaseInfo.h" |
|
8 |
|
9 #include "nsDataHashtable.h" |
|
10 #include "nsThreadUtils.h" |
|
11 |
|
12 USING_INDEXEDDB_NAMESPACE |
|
13 |
|
14 namespace { |
|
15 |
|
16 typedef nsDataHashtable<nsCStringHashKey, DatabaseInfo*> |
|
17 DatabaseHash; |
|
18 |
|
19 DatabaseHash* gDatabaseHash = nullptr; |
|
20 |
|
21 PLDHashOperator |
|
22 EnumerateObjectStoreNames(const nsAString& aKey, |
|
23 ObjectStoreInfo* aData, |
|
24 void* aUserArg) |
|
25 { |
|
26 nsTArray<nsString>* array = static_cast<nsTArray<nsString>*>(aUserArg); |
|
27 if (!array->InsertElementSorted(aData->name)) { |
|
28 NS_ERROR("Out of memory?"); |
|
29 return PL_DHASH_STOP; |
|
30 } |
|
31 return PL_DHASH_NEXT; |
|
32 } |
|
33 |
|
34 PLDHashOperator |
|
35 CloneObjectStoreInfo(const nsAString& aKey, |
|
36 ObjectStoreInfo* aData, |
|
37 void* aUserArg) |
|
38 { |
|
39 ObjectStoreInfoHash* hash = static_cast<ObjectStoreInfoHash*>(aUserArg); |
|
40 |
|
41 nsRefPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo(*aData)); |
|
42 |
|
43 hash->Put(aKey, newInfo); |
|
44 |
|
45 return PL_DHASH_NEXT; |
|
46 } |
|
47 |
|
48 } |
|
49 |
|
50 DatabaseInfo::~DatabaseInfo() |
|
51 { |
|
52 // Clones are never in the hash. |
|
53 if (!cloned) { |
|
54 DatabaseInfo::Remove(id); |
|
55 } |
|
56 } |
|
57 |
|
58 ObjectStoreInfo::ObjectStoreInfo(ObjectStoreInfo& aOther) |
|
59 : nextAutoIncrementId(aOther.nextAutoIncrementId), |
|
60 comittedAutoIncrementId(aOther.comittedAutoIncrementId) |
|
61 { |
|
62 *static_cast<ObjectStoreInfoGuts*>(this) = |
|
63 static_cast<ObjectStoreInfoGuts&>(aOther); |
|
64 |
|
65 // Doesn't copy the refcount |
|
66 MOZ_COUNT_CTOR(ObjectStoreInfo); |
|
67 } |
|
68 |
|
69 #ifdef NS_BUILD_REFCNT_LOGGING |
|
70 |
|
71 IndexInfo::IndexInfo() |
|
72 : id(INT64_MIN), |
|
73 keyPath(0), |
|
74 unique(false), |
|
75 multiEntry(false) |
|
76 { |
|
77 MOZ_COUNT_CTOR(IndexInfo); |
|
78 } |
|
79 |
|
80 IndexInfo::IndexInfo(const IndexInfo& aOther) |
|
81 : name(aOther.name), |
|
82 id(aOther.id), |
|
83 keyPath(aOther.keyPath), |
|
84 unique(aOther.unique), |
|
85 multiEntry(aOther.multiEntry) |
|
86 { |
|
87 MOZ_COUNT_CTOR(IndexInfo); |
|
88 } |
|
89 |
|
90 IndexInfo::~IndexInfo() |
|
91 { |
|
92 MOZ_COUNT_DTOR(IndexInfo); |
|
93 } |
|
94 |
|
95 ObjectStoreInfo::ObjectStoreInfo() |
|
96 : nextAutoIncrementId(0), |
|
97 comittedAutoIncrementId(0) |
|
98 { |
|
99 MOZ_COUNT_CTOR(ObjectStoreInfo); |
|
100 } |
|
101 |
|
102 ObjectStoreInfo::~ObjectStoreInfo() |
|
103 { |
|
104 MOZ_COUNT_DTOR(ObjectStoreInfo); |
|
105 } |
|
106 |
|
107 IndexUpdateInfo::IndexUpdateInfo() |
|
108 : indexId(0), |
|
109 indexUnique(false) |
|
110 { |
|
111 MOZ_COUNT_CTOR(IndexUpdateInfo); |
|
112 } |
|
113 |
|
114 IndexUpdateInfo::IndexUpdateInfo(const IndexUpdateInfo& aOther) |
|
115 : indexId(aOther.indexId), |
|
116 indexUnique(aOther.indexUnique), |
|
117 value(aOther.value) |
|
118 { |
|
119 MOZ_COUNT_CTOR(IndexUpdateInfo); |
|
120 } |
|
121 |
|
122 IndexUpdateInfo::~IndexUpdateInfo() |
|
123 { |
|
124 MOZ_COUNT_DTOR(IndexUpdateInfo); |
|
125 } |
|
126 |
|
127 #endif /* NS_BUILD_REFCNT_LOGGING */ |
|
128 |
|
129 // static |
|
130 bool |
|
131 DatabaseInfo::Get(const nsACString& aId, |
|
132 DatabaseInfo** aInfo) |
|
133 { |
|
134 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
135 NS_ASSERTION(!aId.IsEmpty(), "Bad id!"); |
|
136 |
|
137 if (gDatabaseHash && |
|
138 gDatabaseHash->Get(aId, aInfo)) { |
|
139 NS_IF_ADDREF(*aInfo); |
|
140 return true; |
|
141 } |
|
142 return false; |
|
143 } |
|
144 |
|
145 // static |
|
146 bool |
|
147 DatabaseInfo::Put(DatabaseInfo* aInfo) |
|
148 { |
|
149 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
150 NS_ASSERTION(aInfo, "Null pointer!"); |
|
151 |
|
152 if (!gDatabaseHash) { |
|
153 nsAutoPtr<DatabaseHash> databaseHash(new DatabaseHash()); |
|
154 gDatabaseHash = databaseHash.forget(); |
|
155 } |
|
156 |
|
157 if (gDatabaseHash->Get(aInfo->id, nullptr)) { |
|
158 NS_ERROR("Already know about this database!"); |
|
159 return false; |
|
160 } |
|
161 |
|
162 gDatabaseHash->Put(aInfo->id, aInfo); |
|
163 |
|
164 return true; |
|
165 } |
|
166 |
|
167 // static |
|
168 void |
|
169 DatabaseInfo::Remove(const nsACString& aId) |
|
170 { |
|
171 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
172 |
|
173 if (gDatabaseHash) { |
|
174 gDatabaseHash->Remove(aId); |
|
175 |
|
176 if (!gDatabaseHash->Count()) { |
|
177 delete gDatabaseHash; |
|
178 gDatabaseHash = nullptr; |
|
179 } |
|
180 } |
|
181 } |
|
182 |
|
183 bool |
|
184 DatabaseInfo::GetObjectStoreNames(nsTArray<nsString>& aNames) |
|
185 { |
|
186 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
187 |
|
188 aNames.Clear(); |
|
189 if (objectStoreHash) { |
|
190 objectStoreHash->EnumerateRead(EnumerateObjectStoreNames, &aNames); |
|
191 } |
|
192 return true; |
|
193 } |
|
194 |
|
195 bool |
|
196 DatabaseInfo::ContainsStoreName(const nsAString& aName) |
|
197 { |
|
198 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
199 |
|
200 return objectStoreHash && objectStoreHash->Get(aName, nullptr); |
|
201 } |
|
202 |
|
203 ObjectStoreInfo* |
|
204 DatabaseInfo::GetObjectStore(const nsAString& aName) |
|
205 { |
|
206 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
207 |
|
208 if (objectStoreHash) { |
|
209 return objectStoreHash->GetWeak(aName); |
|
210 } |
|
211 |
|
212 return nullptr; |
|
213 } |
|
214 |
|
215 bool |
|
216 DatabaseInfo::PutObjectStore(ObjectStoreInfo* aInfo) |
|
217 { |
|
218 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
219 NS_ASSERTION(aInfo, "Null pointer!"); |
|
220 |
|
221 if (!objectStoreHash) { |
|
222 nsAutoPtr<ObjectStoreInfoHash> hash(new ObjectStoreInfoHash()); |
|
223 objectStoreHash = hash.forget(); |
|
224 } |
|
225 |
|
226 if (objectStoreHash->Get(aInfo->name, nullptr)) { |
|
227 NS_ERROR("Already have an entry for this objectstore!"); |
|
228 return false; |
|
229 } |
|
230 |
|
231 objectStoreHash->Put(aInfo->name, aInfo); |
|
232 return true; |
|
233 } |
|
234 |
|
235 void |
|
236 DatabaseInfo::RemoveObjectStore(const nsAString& aName) |
|
237 { |
|
238 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
239 NS_ASSERTION(GetObjectStore(aName), "Don't know about this one!"); |
|
240 |
|
241 if (objectStoreHash) { |
|
242 objectStoreHash->Remove(aName); |
|
243 } |
|
244 } |
|
245 |
|
246 already_AddRefed<DatabaseInfo> |
|
247 DatabaseInfo::Clone() |
|
248 { |
|
249 nsRefPtr<DatabaseInfo> dbInfo(new DatabaseInfo()); |
|
250 |
|
251 dbInfo->cloned = true; |
|
252 dbInfo->name = name; |
|
253 dbInfo->group = group; |
|
254 dbInfo->origin = origin; |
|
255 dbInfo->version = version; |
|
256 dbInfo->persistenceType = persistenceType; |
|
257 dbInfo->id = id; |
|
258 dbInfo->filePath = filePath; |
|
259 dbInfo->nextObjectStoreId = nextObjectStoreId; |
|
260 dbInfo->nextIndexId = nextIndexId; |
|
261 |
|
262 if (objectStoreHash) { |
|
263 dbInfo->objectStoreHash = new ObjectStoreInfoHash(); |
|
264 objectStoreHash->EnumerateRead(CloneObjectStoreInfo, |
|
265 dbInfo->objectStoreHash); |
|
266 } |
|
267 |
|
268 return dbInfo.forget(); |
|
269 } |