Skip to content

Commit fde451b

Browse files
author
Nathan Memmott
committed
Support locking of directory entries
Moves the locking algorithm from file entry to file system entry. Fixes whatwg#137
1 parent bd6ef5a commit fde451b

File tree

1 file changed

+80
-40
lines changed

1 file changed

+80
-40
lines changed

index.bs

+80-40
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ specifications do not need to bother implementing [=/file system entry=]'s
110110

111111
Issue(101): Make access check algorithms associated with a FileSystemHandle.
112112

113-
Each [=/file system entry=] has an associated <dfn for="file system entry" id=entry-name>name</dfn> (a [=string=]).
113+
Each [=/file system entry=] has an associated <dfn for="file system entry" id=entry-name>name</dfn> (a [=string=]),
114+
a <dfn for="file system entry">lock</dfn> (a string that may exclusively be "`open`", "`taken-exclusive`" or "`taken-shared`")
115+
and a <dfn for="file system entry" id=file-system-entry-shared-lock-count>lock count</dfn>
116+
(a number representing the number of locks that are taken at a given point in time).
114117

115118
A <dfn>valid file name</dfn> is a [=string=] that is not an empty string, is not equal to "." or "..",
116119
and does not contain '/' or any other character used as path separator on the underlying platform.
@@ -124,50 +127,83 @@ Issue: We should consider having further normative restrictions on file names th
124127
never be allowed using this API, rather than leaving it entirely up to underlying file
125128
systems.
126129

127-
A <dfn export id=file>file entry</dfn> additionally consists of
128-
<dfn for="file entry" export>binary data</dfn> (a [=byte sequence=]), a
129-
<dfn for="file entry">modification timestamp</dfn> (a number representing the number of milliseconds since the <a spec=FileAPI>Unix Epoch</a>),
130-
a <dfn for="file entry">lock</dfn> (a string that may exclusively be "`open`", "`taken-exclusive`" or "`taken-shared`")
131-
and a <dfn for="file entry">shared lock count</dfn> (a number representing the number shared locks that are taken at a given point in time).
132-
133130
A user agent has an associated <dfn>file system queue</dfn> which is the
134131
result of [=starting a new parallel queue=]. This queue is to be used for all
135132
file system operations.
136133

137134
<div algorithm>
138-
To <dfn for="file entry/lock">take</dfn> a [=file entry/lock=] with a |value| of
139-
"`exclusive`" or "`shared`" on a given [=file entry=] |file|:
140-
141-
1. Let |lock| be the |file|'s [=file entry/lock=].
142-
1. Let |count| be the |file|'s [=file entry/shared lock count=].
135+
To <dfn for="file system entry" id=file-entry-lock-take>take a lock</dfn> with a |value| of
136+
"`exclusive`" or "`shared`" on a given [=/file system entry=] |entry|:
137+
138+
1. Let |lock| be the |entry|'s [=file system entry/lock=].
139+
1. Let |count| be the |entry|'s [=file system entry/lock count=].
140+
1. Let |ancestorLockStatus| be the result of [=file system entry/checking for an ancestor lock=] on |entry|.
141+
1. If |ancestorLockStatus| is "`taken`":
142+
1. Return "`failure`".
143+
1. If |entry| is a [=directory entry=]:
144+
1. Let |descendantLockStatus| be the result of [=file system entry/checking for a descendant lock=] on |entry|.
145+
1. If |descendantLockStatus| is "`taken`":
146+
1. Return "`failure`".
147+
1. If |value| is "`exclusive`" or |lock| is "`taken-exclusive`":
148+
1. Return "`failure`".
143149
1. If |value| is "`exclusive`":
144-
1. If |lock| is "`open`":
145-
1. Set lock to "`taken-exclusive`".
146-
1. Return "`success`".
147-
1. If |value| is "`shared`":
148-
1. If |lock| is "`open`":
149-
1. Set |lock| to "`taken-shared`".
150-
1. Set |count| to 1.
151-
1. Return "`success`".
152-
1. Otherwise, if |lock| is "`taken-shared`":
153-
1. Increase |count| by 1.
154-
1. Return "`success`".
155-
1. Return "`failure`".
150+
1. [=Assert=]: |lock| is "`open`".
151+
1. [=Assert=]: |count| is 0.
152+
1. Set lock to "`taken-exclusive`".
153+
1. Otherwise:
154+
1. [=Assert=]: |lock| is not "`taken-exclusive`".
155+
1. Set lock to "`taken-shared`".
156+
1. Increase |count| by 1.
157+
1. Return "`success`".
156158

157159
Note: These steps have to be run on the [=file system queue=].
158160

159161
</div>
160162

161163
<div algorithm>
162-
To <dfn for="file entry/lock">release</dfn> a [=file entry/lock=] on a given
163-
[=file entry=] |file|:
164+
To <dfn for="file system entry">check for an ancestor lock</dfn> on a given
165+
[=/file system entry=] |entry|:
166+
167+
1. Let |parent| be the |entry|'s [=file system entry/parent=].
168+
1. If |parent| is null:
169+
1. Return "`open`".
170+
1. Let |lock| be the |parent|'s [=file system entry/lock=].
171+
1. If |lock| is not "`open`":
172+
1. Return "`taken`".
173+
1. Let |ancestorLockStatus| be the result of [=file system entry/checking for an ancestor lock=] on |parent|.
174+
1. Return |ancestorLockStatus|.
164175

165-
1. Let |lock| be the |file|'s associated [=file entry/lock=].
166-
1. Let |count| be the |file|'s [=file entry/shared lock count=].
167-
1. If |lock| is "`taken-shared`":
168-
1. Decrease |count| by 1.
169-
1. If |count| is 0, set |lock| to "`open`".
170-
1. Otherwise, set |lock| to "`open`".
176+
Note: These steps have to be run on the [=file system queue=].
177+
178+
</div>
179+
180+
<div algorithm>
181+
To <dfn for="file system entry">check for a descendant lock</dfn> on a given
182+
[=directory entry=] |directory|:
183+
184+
1. [=set/For each=] |child| of |directory|'s [=directory entry/children=]:
185+
1. Let |lock| be the |child|'s [=file system entry/lock=].
186+
1. If |lock| is not "`open`":
187+
1. Return "`taken`".
188+
1. If |child| is a [=directory entry=]:
189+
1. Let |descendantLockStatus| be the result of [=file system entry/checking for a descendant lock=] on |child|.
190+
1. If |descendantLockStatus| is "`taken`":
191+
1. Return "`taken`".
192+
1. Return "`open`".
193+
194+
Note: These steps have to be run on the [=file system queue=].
195+
196+
</div>
197+
198+
<div algorithm>
199+
To <dfn for="file system entry/lock">release</dfn> a [=file system entry/lock=] on a given
200+
[=/file system entry=] |entry|:
201+
202+
1. Let |lock| be the |entry|'s associated [=file system entry/lock=].
203+
1. [=Assert=]: |lock| is not "`open`".
204+
1. Let |count| be the |entry|'s [=file system entry/lock count=].
205+
1. Decrease |count| by 1.
206+
1. If |count| is 0, set |lock| to "`open`".
171207

172208
Note: These steps have to be run on the [=file system queue=].
173209

@@ -176,6 +212,10 @@ Note: These steps have to be run on the [=file system queue=].
176212
Note: Locks help prevent concurrent modifications to a file. A {{FileSystemWritableFileStream}}
177213
requires a shared lock, while a {{FileSystemSyncAccessHandle}} requires an exclusive one.
178214

215+
A <dfn export id=file>file entry</dfn> additionally consists of
216+
<dfn for="file entry" export>binary data</dfn> (a [=byte sequence=]) and a
217+
<dfn for="file entry">modification timestamp</dfn> (a number representing the number of milliseconds since the <a spec=FileAPI>Unix Epoch</a>).
218+
179219
A <dfn export id=directory>directory entry</dfn> additionally consists of a [=/set=] of
180220
<dfn for="directory entry">children</dfn>, which are themselves [=/file system entries=].
181221
Each member is either a [=/file entry=] or a [=/directory entry=].
@@ -538,7 +578,7 @@ The <dfn method for=FileSystemFileHandle>getFile()</dfn> method steps are:
538578
the temporary file starts out empty,
539579
otherwise the existing file is first copied to this temporary file.
540580

541-
Creating a {{FileSystemWritableFileStream}} [=file entry/lock/take|takes a shared lock=] on the
581+
Creating a {{FileSystemWritableFileStream}} [=file system entry/take a lock|takes a shared lock=] on the
542582
[=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=].
543583
This prevents the creation of {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}}
544584
for the entry, until the stream is closed.
@@ -575,7 +615,7 @@ The <dfn method for=FileSystemFileHandle>createWritable(|options|)</dfn> method
575615
|result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps.
576616
1. [=Assert=]: |entry| is a [=file entry=].
577617

578-
1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=]
618+
1. Let |lockResult| be the result of [=file system entry/take a lock|taking a lock=]
579619
with "`shared`" on |entry|.
580620

581621
1. [=Queue a storage task=] with |global| to run these steps:
@@ -603,7 +643,7 @@ The <dfn method for=FileSystemFileHandle>createWritable(|options|)</dfn> method
603643
[=file entry=] [=locate an entry|locatable=] by |fileHandle|'s [=FileSystemHandle/locator=].
604644
To ensure the changes are reflected in this file, the handle can be flushed.
605645

606-
Creating a {{FileSystemSyncAccessHandle}} [=file entry/lock/take|takes an exclusive lock=] on the
646+
Creating a {{FileSystemSyncAccessHandle}} [=file system entry/take a lock|takes an exclusive lock=] on the
607647
[=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=].
608648
This prevents the creation of further {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}}
609649
or {{FileSystemWritableFileStream|FileSystemWritableFileStreams}}
@@ -645,7 +685,7 @@ The <dfn method for=FileSystemFileHandle>createSyncAccessHandle()</dfn> method s
645685
|result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps.
646686
1. [=Assert=]: |entry| is a [=file entry=].
647687

648-
1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=]
688+
1. Let |lockResult| be the result of [=file system entry/take a lock|taking a lock=]
649689
with "`exclusive`" on |entry|.
650690

651691
1. [=Queue a storage task=] with |global| to run these steps:
@@ -1181,15 +1221,15 @@ given a [=file entry=] |file| in a [=/Realm=] |realm|:
11811221
file on disk being written to.
11821222

11831223
1. [=Enqueue the following steps=] to the [=file system queue=]:
1184-
1. [=file entry/lock/release|Release the lock=] on
1224+
1. [=file system entry/lock/release|Release the lock=] on
11851225
|stream|'s [=FileSystemWritableFileStream/[[file]]=].
11861226
1. [=Queue a storage task=] with |file|'s [=relevant global object=]
11871227
to [=/resolve=] |closeResult| with `undefined`.
11881228

11891229
1. Return |closeResult|.
11901230
1. Let |abortAlgorithm| be these steps:
11911231
1. [=enqueue steps|Enqueue this step=] to the [=file system queue=]:
1192-
1. [=file entry/lock/release|Release the lock=] on
1232+
1. [=file system entry/lock/release|Release the lock=] on
11931233
|stream|'s [=FileSystemWritableFileStream/[[file]]=].
11941234
1. Let |highWaterMark| be 1.
11951235
1. Let |sizeAlgorithm| be an algorithm that returns `1`.
@@ -1649,7 +1689,7 @@ The <dfn method for=FileSystemSyncAccessHandle>flush()</dfn> method steps are:
16491689
: |handle| . {{FileSystemSyncAccessHandle/close()}}
16501690
:: Closes the access handle or no-ops if the access handle is already closed.
16511691
This disables any further operations on it and
1652-
[=file entry/lock/release|releases the lock=] on the
1692+
[=file system entry/lock/release|releases the lock=] on the
16531693
[=FileSystemSyncAccessHandle/[[file]]=] associated with |handle|.
16541694
</div>
16551695

@@ -1661,7 +1701,7 @@ The <dfn method for=FileSystemSyncAccessHandle>close()</dfn> method steps are:
16611701
1. Set |lockReleased| to false.
16621702
1. Let |file| be [=this=]'s [=FileSystemSyncAccessHandle/[[file]]=].
16631703
1. [=Enqueue the following steps=] to the [=file system queue=]:
1664-
1. [=file entry/lock/release|Release the lock=] on |file|.
1704+
1. [=file system entry/lock/release|Release the lock=] on |file|.
16651705
1. Set |lockReleased| to true.
16661706
1. [=Pause=] until |lockReleased| is true.
16671707

0 commit comments

Comments
 (0)