Revision 1c65dd5c
Added by koszko over 1 year ago
common/indexeddb.js | ||
---|---|---|
3 | 3 |
* |
4 | 4 |
* Function: Facilitate use of IndexedDB within Haketilo. |
5 | 5 |
* |
6 |
* Copyright (C) 2021 Wojtek Kosior <koszko@koszko.org> |
|
6 |
* Copyright (C) 2021, 2022 Wojtek Kosior <koszko@koszko.org>
|
|
7 | 7 |
* |
8 | 8 |
* This program is free software: you can redistribute it and/or modify |
9 | 9 |
* it under the terms of the GNU General Public License as published by |
... | ... | |
59 | 59 |
const version_nr = ver => ver.slice(0, 3).reduce(nr_reductor, [2, 0])[1]; |
60 | 60 |
|
61 | 61 |
const stores = [ |
62 |
["files", {keyPath: "hash_key"}],
|
|
63 |
["file_uses", {keyPath: "hash_key"}],
|
|
62 |
["files", {keyPath: "sha256"}],
|
|
63 |
["file_uses", {keyPath: "sha256"}],
|
|
64 | 64 |
["resource", {keyPath: "identifier"}], |
65 | 65 |
["mapping", {keyPath: "identifier"}], |
66 | 66 |
["settings", {keyPath: "name"}], |
... | ... | |
110 | 110 |
for (const [store_name, key_mode] of stores) |
111 | 111 |
store = opened_db.createObjectStore(store_name, key_mode); |
112 | 112 |
|
113 |
const ctx = make_context(store.transaction, initial_data.files);
|
|
113 |
const ctx = make_context(store.transaction, initial_data.file); |
|
114 | 114 |
await _save_items(initial_data.resources, initial_data.mappings, ctx); |
115 | 115 |
|
116 | 116 |
return opened_db; |
... | ... | |
175 | 175 |
|
176 | 176 |
/* |
177 | 177 |
* item_store_names should be an array with either string "mapping", string |
178 |
* "resource" or both. files should be an object with values being contents of |
|
179 |
* files that are to be possibly saved in this transaction and keys of the form |
|
180 |
* `sha256-<file's-sha256-sum>`. |
|
178 |
* "resource" or both. files should be an object with an "sha256" property whose |
|
179 |
* values will be yet another object with values being contents of files that |
|
180 |
* are to be possibly saved in this transaction and keys being hexadecimal |
|
181 |
* representations of files' SHA256 sums. |
|
181 | 182 |
* |
182 | 183 |
* Returned is a context object wrapping the transaction and handling the |
183 | 184 |
* counting of file references in IndexedDB. |
... | ... | |
192 | 193 |
|
193 | 194 |
async function incr_file_uses(context, file_ref, by=1) |
194 | 195 |
{ |
195 |
const hash_key = file_ref.hash_key;
|
|
196 |
let uses = context.file_uses[hash_key];
|
|
196 |
const sha256 = file_ref.sha256;
|
|
197 |
let uses = context.file_uses[sha256];
|
|
197 | 198 |
if (uses === undefined) { |
198 |
uses = await idb_get(context.transaction, "file_uses", hash_key);
|
|
199 |
uses = await idb_get(context.transaction, "file_uses", sha256);
|
|
199 | 200 |
if (uses) |
200 | 201 |
[uses.new, uses.initial] = [false, uses.uses]; |
201 | 202 |
else |
202 |
uses = {hash_key, uses: 0, new: true, initial: 0};
|
|
203 |
uses = {sha256, uses: 0, new: true, initial: 0};
|
|
203 | 204 |
|
204 |
context.file_uses[hash_key] = uses;
|
|
205 |
context.file_uses[sha256] = uses;
|
|
205 | 206 |
} |
206 | 207 |
|
207 | 208 |
uses.uses = uses.uses + by; |
... | ... | |
213 | 214 |
{ |
214 | 215 |
for (const uses of Object.values(context.file_uses)) { |
215 | 216 |
if (uses.uses < 0) |
216 |
console.error("internal error: uses < 0 for file " + uses.hash_key);
|
|
217 |
console.error("internal error: uses < 0 for file " + uses.sha256);
|
|
217 | 218 |
|
218 | 219 |
const is_new = uses.new; |
219 | 220 |
const initial_uses = uses.initial; |
220 |
const hash_key = uses.hash_key;
|
|
221 |
const sha256 = uses.sha256;
|
|
221 | 222 |
|
222 | 223 |
delete uses.new; |
223 | 224 |
delete uses.initial; |
224 | 225 |
|
225 | 226 |
if (uses.uses < 1) { |
226 | 227 |
if (!is_new) { |
227 |
idb_del(context.transaction, "file_uses", hash_key);
|
|
228 |
idb_del(context.transaction, "files", hash_key);
|
|
228 |
idb_del(context.transaction, "file_uses", sha256);
|
|
229 |
idb_del(context.transaction, "files", sha256);
|
|
229 | 230 |
} |
230 | 231 |
|
231 | 232 |
continue; |
... | ... | |
239 | 240 |
if (initial_uses > 0) |
240 | 241 |
continue; |
241 | 242 |
|
242 |
const file = context.files[hash_key];
|
|
243 |
const file = context.files.sha256[sha256];
|
|
243 | 244 |
if (file === undefined) { |
244 | 245 |
context.transaction.abort(); |
245 |
throw "file not present: " + hash_key;
|
|
246 |
throw "file not present: " + sha256;
|
|
246 | 247 |
} |
247 | 248 |
|
248 |
idb_put(context.transaction, "files", {hash_key, contents: file});
|
|
249 |
idb_put(context.transaction, "files", {sha256, contents: file});
|
|
249 | 250 |
} |
250 | 251 |
|
251 | 252 |
return context.result; |
... | ... | |
283 | 284 |
* } |
284 | 285 |
* }, |
285 | 286 |
* }, |
286 |
* files: { |
|
287 |
* "sha256-f9444510dc7403e41049deb133f6892aa6a63c05591b2b59e4ee5b234d7bbd99": "console.log(\"hello\");\n", |
|
288 |
* "sha256-b857cd521cc82fff30f0d316deba38b980d66db29a5388eb6004579cf743c6fd": "console.log(\"bye\");" |
|
287 |
* file: { |
|
288 |
* sha256: { |
|
289 |
* "f9444510dc7403e41049deb133f6892aa6a63c05591b2b59e4ee5b234d7bbd99": "console.log(\"hello\");\n", |
|
290 |
* "b857cd521cc82fff30f0d316deba38b980d66db29a5388eb6004579cf743c6fd": "console.log(\"bye\");" |
|
291 |
* } |
|
289 | 292 |
* } |
290 | 293 |
* } |
291 | 294 |
*/ |
292 | 295 |
async function save_items(data) |
293 | 296 |
{ |
294 | 297 |
const item_store_names = ["resource", "mapping"]; |
295 |
const context = await start_items_transaction(item_store_names, data.files);
|
|
298 |
const context = await start_items_transaction(item_store_names, data.file); |
|
296 | 299 |
|
297 | 300 |
return _save_items(data.resources, data.mappings, context); |
298 | 301 |
} |
Also available in: Unified diff
adapt to changes in file path format
From now on we assume Hydrilla serves file contents at 'file/sha256/' instead of 'file/sha256-'.
With this commit we also stop using the "hash_key" property internally.