Commit graph

33 commits

Author SHA1 Message Date
Fabian d5c9b29942 Upgrade jshint 2020-12-31 19:14:29 -06:00
Ernest Wong dbfa0edc3c Filestorage: Split read() logic into different cases for readability 2020-08-30 19:37:15 -05:00
Ernest Wong 607078f59d Filestorage: Optimise .read to single IndexedDB request for 4k block
Reusing the naming scheme of
sha256sum
sha256sum-0
sha256sum-1
sha256sum-2
etc
but the extra metadata such as total file size and block count are no
longer needed in the first block.
2020-08-30 19:37:15 -05:00
Fabian c20a54a9e4 Don't print full array in assertion (slow) 2020-08-30 19:37:15 -05:00
Ernest Wong e5e1f68244 Fix type error for logging filestorage error 2020-08-30 19:37:15 -05:00
Ernest Wong 4651e28177 Fix type annotations for async functions 2020-08-30 19:37:15 -05:00
Ernest Wong 1155faae25 Filestorage: Simplify IndexedDBFileStorage#set - remove async 2020-08-30 19:37:15 -05:00
Ernest Wong 602cfe0e3c Filestorage: Fix IndexedDB error logging 2020-08-30 19:37:15 -05:00
Ernest Wong 75bee02ac7 Filestorage: Don't wait before issuing next store.put request 2020-08-30 19:37:15 -05:00
Ernest Wong aadae9242c Filestorage: Clone array views to avoid serializing full array buffer
IndexedDB uses the StructuredSerializeForStorage algorithm to store
records into the database.

It appears that the html5 spec defines the StructuredSerializeForStorage
algorithm in a way that, when we serialize a TypedArray, the associated
ArrayBuffer is also serialized. Meaning even if the TypedArray is a view
of a single byte in the ArrayBuffer, the potentially-megabytes of data
in the ArrayBuffer are also copied over.

This makes sense. After deserialization, you'd expect the TypedArray to
function the same way as before meaning it should have the same
`.byteOffset` and `.buffer` properties.

However, it is easy to overlook this and think that a TypedArray viewing
2 bytes will only have the 2 bytes stored in the database.

This commit fixes a source of crashes. When calling
IndexedDBFileStorage#set() with a 3Mb file, the file is to be stored as
approx 800 lots of 4k blocks. However, in reality, 800 lots of 3 Mb array
buffers are being stored into the database. As the transaction is not
committed until the last request has been placed, I suspect that Chrome was
trying to store those 2.4 Gb worth of data in memory and did not handle
this case properly, leading to out-of-memory.

This commit also fixes a source of poor performance. When calling
IndexedDBFileStorage#read() to read 4k of a 48 Mb file, the browser seems
to be deserializing the entire 48 Mb into memory and garbage collecting
it even though only 4k is needed.
2020-08-30 19:37:15 -05:00
Ernest Wong ad3bf2afe0 Filestorage: Export classes properly to all platforms 2020-08-30 19:37:15 -05:00
Ernest Wong c273741405 Add tests for file storage chunking 2020-08-30 19:37:15 -05:00
Ernest Wong a841194d28 Filestorage: Reuse IDBObjectStore throughout transaction
- More like passing the same reference to it when calling db_get/set.
- In reality, it was still the same store object being accessed, but
this commit improves the coherence of the db_get/set helper methods.
2020-08-30 19:37:15 -05:00
Ernest Wong bf35f0ab0b Filestorage: Avoid additional allocation for small files 2020-08-30 19:37:15 -05:00
Ernest Wong 840415a052 Filestorage: (minor) Improve naming can_uncache() -> uncache() 2020-08-30 19:37:15 -05:00
Ernest Wong 738edf7b6c Filestorage: Initialise IndexedDB before constructor
Simplifies several checks
2020-08-30 19:37:15 -05:00
Ernest Wong 9db722f71f Filestorage: Improve usefulness of IndexedDB error messages 2020-08-30 19:37:15 -05:00
Ernest Wong c625bba498 Filestorage: Implement cache cleanup - avoid memory growth 2020-08-30 19:37:15 -05:00
Ernest Wong 3a74e66b72 Filestorage: Expose load_from_server 2020-08-30 19:37:15 -05:00
Ernest Wong 62c880b415 Filestorage: Integrate chunking and revert unnecessary chunking
- Integrate new FileStorage interface with lib/filesystem.js
- Simplify the FileStorage interface with the intention that it only
serves read-only files.
2020-08-30 19:37:15 -05:00
Ernest Wong afd27597d7 Filestorage: Draft chunking behind new FileStorage interface 2020-08-30 19:37:15 -05:00
Ernest Wong efa45a3d11 Filestorage: Make filestorage .get .set atomic
...by sticking to the same transaction throughout an operation.
2020-08-30 19:37:15 -05:00
Ernest Wong 7cfe865556 Filestorage: Draft chunking behind existing FileStorage interface 2020-08-30 19:37:15 -05:00
Ernest Wong 8b64844d27 Filestorage: Give project-related name for IndexedDB Storage 2020-08-30 19:37:15 -05:00
Ernest Wong 83b283ebbe Filestorage: Replace the two server classes with a wrapper class
Simplifies both the filestorage.js code as well as the starter.js code
that uses these FileStorage classes.

Now, the ServerFileStorageWrapper decorates the other FileStorage
classes by loading from the server when the file is not available.

Moreover, the previous starter.js was incorrectly passing the `baseurl`
parameter (it was passing it when baseurl was not defined nor needed).
2020-08-30 19:37:15 -05:00
Ernest Wong 93d9f6923e Filestorage: Prevent overlapped reinitialization of IndexedDB
Catches cases when IndexDBFileStorage#init is accidentally called in
multiple places.
2020-08-30 19:37:15 -05:00
Ernest Wong a85dd50169 Filestorage: Improve assert coverage and robustness
Checks that sha256sum is also not undefrined nor null.
Avoids ReferenceError when window is not defined e.g. on NodeJS.
2020-08-30 19:37:15 -05:00
Ernest Wong c2dcb440dd Filestorage: Refactor fallback and load-from-server
Fallback logic is moved to the caller's responsibility.

Empty FileStorages and FileStorages that load from the server are
separated into different classes. This is to avoid faults where the
caller of the constructor forgets to pass in a `baseurl` parameter and
leads to some confusing bug.
2020-08-30 19:37:15 -05:00
Ernest Wong 6a06a7108a Tidy: file_storage snake case and interface naming convention 2020-08-30 19:37:15 -05:00
Ernest Wong 6fe226eec9 Filestorage: Reuse write-to-indexeddb logic 2020-08-30 19:29:54 -05:00
Ernest Wong 27a825dce3 Filestorage: Preserve key names when writing into indexeddb 2020-08-30 19:29:54 -05:00
Ernest Wong a0c984dc8d Filesystem: Introduce IndexedDBFileStorage
Uses MemoryFileStorage as a fallback when:
- v86 is used in a browserless environment, e.g. NodeJS
- browser doesn't support indexedDB
- opening indexedDB fails
- existing database is a newer version
- existing database is an old version and is under use - blocking
current v86 instance to connect to it.
2020-08-30 19:29:54 -05:00
Ernest Wong 0a67e3532f Filesystem: Introduce FileStorage class for server-loaded files 2020-08-30 19:29:54 -05:00