Re: Request for feedback: Filesystem API

On Fri, Aug 16, 2013 at 3:13 AM, Janusz Majnert <j.majnert@samsung.com> wrote:
> Hi,
> I have four questions:

Hi Janusz,

Thanks for looking over the proposal!

> 1. In your emails and examples you use "location" and "offset" attributes of
> FileHandle. I assume this is a copy&paste mistake?

Indeed. It should be "offset" everywhere.

> 2. Offset handling:
> a) What happens when I set offset to a value larger that the file size and
> do a write?

My thinking was that we would 0-pad to extend the file length to where
the write starts.

> Variation: what happens if I do:
>
> var fileHandle;
> navigator.getFilesystem().then(function(root) {
>     return root.openWrite("highscores"); //highscores is 100-bytes long
>  }).then(function(handle) {
>     fileHandle = handle;
>     return fileHandle.read(1000); //offset is set to 1000?

This read would result in an error.

>  }).then(function(buffer) {
>     result=calculateSomething(buffer);
>     fileHandle.write(result); //append result at offset 100 or 1000?

Which means that this code isn't called at all. The first argument to
.then() is the success callback which is only called if the promise
successfully returned a value.

> b) If I open a text file using some multi-byte encoding and call
> readText(2), will that increment the offset attribute by 2 or by the actual
> amount of bytes read? Note that incrementing by amount of bytes might not be
> possible before doing IO.
>
> c) If I open a text file using some multi-byte encoding then mix calls to
> read() and readText()? Or if I first set offset to some arbitrary value,
> that just happens to be not aligned with the code-point boundary and call
> readText()?

It's unclear if readText will make it into the first version. We
should probably get agreement on binary data handling before adding
text data to the mix.

That said, my thinking was that readText operates on byte ranges. I.e.
the size passed to readText is not how many characters to read, but
rather how many bytes to read. That means that .readText(2) always
increases .offset by 2, but you won't always get back a string which
is 2 characters long.

This matches how Blob and FileReader does text handling.

> 3. In the example from point 2a, when is the FileHandle closed? After all
> promises get resolved (which you wrote is the point where the file is
> closed) the script still holds the "fileHandle" variable.

Yes. The FileHandle is closed once all promises are resolved and there
are no more operations scheduled. This is exactly how IDB and WebSQL
transactions work, just using a promise syntax.

The fact that there is still a reference to fileHandle doesn't affect
anything. In general it's a bad idea to do resource management through
variable references in GCed languages. It's all too easy to end up
holding an object alive longer than intended.

> 4. Assuming the code below:
>
> var fileHandle;
> navigator.getFilesystem().then(function(root) {
>     return root.openWrite("somefile");
>  }).then(function(handle) {
>     fileHandle = handle;
>     return fileHandle.read(100);    //Read 1
>  }).then(function(buffer) {
>     return fileHandle.read(100);    //Read 2
>  });
>
> someElement.onclick=function (){
>     fileHandle.offset=5;
>     fileHandle.read(100);           //Read 3
> }
>
> If someElement is clicked after Read 1 but before Read 2, then what are the
> offsets where Read 2 and Read 3 start?

The read operation in the click handler will *always* fail. No matter
if the click happens before or after Read 2. The FileHandle has an
'active' flag, when the 'active' flag is set to false, calling .read
will always result in a failed read.

The 'active' flag is set to true right before resolving the original
promise returned from openRead/openWrite and then set back to false
after the promise has been resolved. It is again set back to true when
resolving a promise returned from a read/write operation and then set
back to false after the promise has been resolved.

This means that code like the one in your example above fails
consistently rather than becomes racy.

Again, this mimics the behavior of WebSQL and IDB transactions.

We should probably not just make .read/.write fail when the 'active'
flag is false, but also make the .offset setter fail.

> Note: I may be misunderstanding how Promises work, so please
> excuse me if any of my questions above make no sense.

This is actually unrelated to promises. It's just related to the
timing of when we set the 'active' flag to true and to false.

/ Jonas

Received on Friday, 16 August 2013 18:51:45 UTC