Skip to content

Commit 816729f

Browse files
committed
Fixed race condition
1 parent fb300c2 commit 816729f

File tree

2 files changed

+34
-32
lines changed

2 files changed

+34
-32
lines changed

index.js

+10-18
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ WriteRequest.prototype.onwrite = function (err, e) {
152152
}
153153

154154
if (!err) {
155-
this.file.updateSize(e.currentTarget.length)
155+
this.file.updateSize(e.currentTarget.length, this.truncating)
156156
}
157157

158158
if (this.truncating) {
@@ -166,7 +166,6 @@ WriteRequest.prototype.onwrite = function (err, e) {
166166

167167
WriteRequest.prototype.truncate = function () {
168168
this.truncating = true
169-
this.file.truncate()
170169
this.writer.truncate(this.req.offset)
171170
}
172171

@@ -249,7 +248,10 @@ ReadRequest.prototype.onread = function (err, buf) {
249248
const req = this.req
250249

251250
if (err && this.retry) {
252-
this.retry = false
251+
if (err.code !== 0) {
252+
this.retry = false
253+
}
254+
253255
if (this.lock(this)) {
254256
this.file.clearFile()
255257
this.run(req)
@@ -286,41 +288,35 @@ class EntryFile {
286288
this._lock = mutexify()
287289
this._file = null
288290
this._size = 0
289-
this._truncated = false
290291
}
291292

292293
get size () {
293294
return this._size
294295
}
295296

296-
updateSize (size) {
297-
if (!this._truncated) {
297+
updateSize (size, truncating) {
298+
if (truncating || size > this._size) {
298299
this._size = size
299300
}
300301

301302
this.clearFile()
302303
}
303304

304-
truncate () {
305-
this._truncated = true
306-
}
307-
308305
clearFile () {
309306
this._file = null
310307
}
311308

312309
get (cb) {
313-
if (this._file && !this._truncated) {
310+
if (this._file) {
314311
return cb(null, this._file)
315312
}
316313

317314
this._lock(release => {
318-
if (this._file && !this._truncated) {
315+
if (this._file) {
319316
return release(cb, null, this._file)
320317
}
321318

322319
this._entry.file(file => {
323-
this._truncated = false
324320
this._file = file
325321
this._size = file.size
326322
release(cb, null, file)
@@ -329,10 +325,6 @@ class EntryFile {
329325
}
330326

331327
getWritableFile (cb) {
332-
if (!this._truncated) {
333-
return cb(null, this)
334-
}
335-
336-
this.get(cb)
328+
return cb(null, this)
337329
}
338330
}

test.js

+24-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { promisify } = require('util')
12
const test = require('tape')
23
const randomAccessTest = require('random-access-test')
34
const racf = require('./')
@@ -14,20 +15,8 @@ test('write/read concurrent requests', async t => {
1415
const st = storage('random')
1516

1617
const rand = (min, max) => Math.floor(Math.random() * max) + min
17-
18-
const read = (...args) => new Promise((resolve, reject) => {
19-
st.read(...args, (err) => {
20-
if (err) return reject(err)
21-
resolve()
22-
})
23-
})
24-
25-
const write = (...args) => new Promise((resolve, reject) => {
26-
st.write(...args, (err) => {
27-
if (err) return reject(err)
28-
resolve()
29-
})
30-
})
18+
const read = promisify(st.read.bind(st))
19+
const write = promisify(st.write.bind(st))
3120

3221
try {
3322
await new Promise(resolve => st.open(() => resolve()))
@@ -55,3 +44,24 @@ test('write/read concurrent requests', async t => {
5544
t.end(err)
5645
}
5746
})
47+
48+
test('write concurrent requests over the same offset different size', async t => {
49+
const st = storage('random')
50+
51+
const write = promisify(st.write.bind(st))
52+
53+
try {
54+
await new Promise(resolve => st.open(() => resolve()))
55+
56+
await Promise.all([
57+
write(0, Buffer.alloc(10)),
58+
write(0, Buffer.alloc(1)),
59+
write(0, Buffer.alloc(5))
60+
])
61+
62+
t.pass('should write multiple requests over the same offset different size')
63+
t.end()
64+
} catch (err) {
65+
t.end(err)
66+
}
67+
})

0 commit comments

Comments
 (0)