1
1
const ras = require ( 'random-access-storage' )
2
+ const mutexify = require ( 'mutexify' )
2
3
3
4
const TYPE = { type : 'octet/stream' }
4
5
const requestFileSystem = window . requestFileSystem || window . webkitRequestFileSystem
@@ -29,19 +30,20 @@ function createFile (name, opts) {
29
30
30
31
var fs = null
31
32
var entry = null
33
+ var file = null
32
34
var toDestroy = null
33
35
var readers = [ ]
34
36
var writers = [ ]
35
37
36
38
return ras ( { read, write, open, stat, close, destroy} )
37
39
38
40
function read ( req ) {
39
- const r = readers . pop ( ) || new ReadRequest ( readers , entry , mutex )
41
+ const r = readers . pop ( ) || new ReadRequest ( readers , entry , file , mutex )
40
42
r . run ( req )
41
43
}
42
44
43
45
function write ( req ) {
44
- const w = writers . pop ( ) || new WriteRequest ( writers , entry , mutex )
46
+ const w = writers . pop ( ) || new WriteRequest ( writers , entry , file , mutex )
45
47
w . run ( req )
46
48
}
47
49
@@ -51,9 +53,10 @@ function createFile (name, opts) {
51
53
}
52
54
53
55
function stat ( req ) {
54
- entry . file ( file => {
56
+ file . get ( ( err , file ) => {
57
+ if ( err ) return req . callback ( err )
55
58
req . callback ( null , file )
56
- } , err => req . callback ( err ) )
59
+ } )
57
60
}
58
61
59
62
function destroy ( req ) {
@@ -78,7 +81,11 @@ function createFile (name, opts) {
78
81
mkdirp ( parentFolder ( name ) , function ( ) {
79
82
fs . root . getFile ( name , { create : true } , function ( e ) {
80
83
entry = toDestroy = e
81
- req . callback ( null )
84
+ file = new EntryFile ( entry )
85
+ file . get ( ( err ) => {
86
+ if ( err ) return onerror ( err )
87
+ req . callback ( null )
88
+ } )
82
89
} , onerror )
83
90
} )
84
91
} , onerror )
@@ -107,9 +114,10 @@ function parentFolder (path) {
107
114
return / ^ \w : $ / . test ( p ) ? '' : p
108
115
}
109
116
110
- function WriteRequest ( pool , entry , mutex ) {
117
+ function WriteRequest ( pool , entry , file , mutex ) {
111
118
this . pool = pool
112
119
this . entry = entry
120
+ this . file = file
113
121
this . mutex = mutex
114
122
this . writer = null
115
123
this . req = null
@@ -122,7 +130,8 @@ WriteRequest.prototype.makeWriter = function () {
122
130
this . entry . createWriter ( function ( writer ) {
123
131
self . writer = writer
124
132
125
- writer . onwriteend = function ( ) {
133
+ writer . onwriteend = function ( e ) {
134
+ self . file . updateSize ( e . currentTarget . length )
126
135
self . onwrite ( null )
127
136
}
128
137
@@ -164,21 +173,21 @@ WriteRequest.prototype.lock = function () {
164
173
}
165
174
166
175
WriteRequest . prototype . run = function ( req ) {
167
- this . entry . file ( file => {
168
- this . req = req
169
- if ( ! this . writer || this . writer . length !== file . size ) return this . makeWriter ( )
176
+ var file = this . file
170
177
171
- const end = req . offset + req . size
172
- if ( end > file . size && ! this . lock ( ) ) return
178
+ this . req = req
179
+ if ( ! this . writer || this . writer . length !== file . size ) return this . makeWriter ( )
173
180
174
- if ( req . offset > this . writer . length ) {
175
- if ( req . offset > file . size ) return this . truncate ( )
176
- return this . makeWriter ( )
177
- }
181
+ const end = req . offset + req . size
182
+ if ( end > file . size && ! this . lock ( ) ) return
183
+
184
+ if ( req . offset > this . writer . length ) {
185
+ if ( req . offset > file . size ) return this . truncate ( )
186
+ return this . makeWriter ( )
187
+ }
178
188
179
- this . writer . seek ( req . offset )
180
- this . writer . write ( new Blob ( [ req . data ] , TYPE ) )
181
- } , err => req . callback ( err ) )
189
+ this . writer . seek ( req . offset )
190
+ this . writer . write ( new Blob ( [ req . data ] , TYPE ) )
182
191
}
183
192
184
193
function Mutex ( ) {
@@ -202,9 +211,10 @@ Mutex.prototype.lock = function (req) {
202
211
return true
203
212
}
204
213
205
- function ReadRequest ( pool , entry , mutex ) {
214
+ function ReadRequest ( pool , entry , file , mutex ) {
206
215
this . pool = pool
207
216
this . entry = entry
217
+ this . file = file
208
218
this . mutex = mutex
209
219
this . reader = new FileReader ( )
210
220
this . req = null
@@ -251,10 +261,53 @@ ReadRequest.prototype.onread = function (err, buf) {
251
261
}
252
262
253
263
ReadRequest . prototype . run = function ( req ) {
254
- this . entry . file ( file => {
264
+ this . file . get ( ( err , file ) => {
265
+ if ( err ) return req . callback ( err )
266
+
255
267
const end = req . offset + req . size
256
268
this . req = req
257
269
if ( end > file . size ) return this . onread ( new Error ( 'Could not satisfy length' ) , null )
258
270
this . reader . readAsArrayBuffer ( file . slice ( req . offset , end ) )
259
- } , err => req . callback ( err ) )
271
+ } )
272
+ }
273
+
274
+ class EntryFile {
275
+ constructor ( entry ) {
276
+ this . _entry = entry
277
+ this . _lock = mutexify ( )
278
+ this . _file = null
279
+ this . _size = 0
280
+ }
281
+
282
+ get locked ( ) {
283
+ return this . _lock . locked
284
+ }
285
+
286
+ get size ( ) {
287
+ return this . _size
288
+ }
289
+
290
+ updateSize ( size ) {
291
+ this . _size = size
292
+ this . _file = null
293
+ }
294
+
295
+ get ( cb ) {
296
+ if ( this . _file ) {
297
+ cb ( null , this . _file )
298
+ return
299
+ }
300
+
301
+ this . _lock ( release => {
302
+ if ( this . _file ) {
303
+ return release ( cb , null , this . _file )
304
+ }
305
+
306
+ this . _entry . file ( file => {
307
+ this . _file = file
308
+ this . _size = file . size
309
+ release ( cb , null , file )
310
+ } , err => release ( cb , err ) )
311
+ } )
312
+ }
260
313
}
0 commit comments