Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80629 views
1
// Monkey-patching the fs module.
2
// It's ugly, but there is simply no other way to do this.
3
var fs = module.exports = require('fs')
4
5
var assert = require('assert')
6
7
// fix up some busted stuff, mostly on windows and old nodes
8
require('./polyfills.js')
9
10
// The EMFILE enqueuing stuff
11
12
var util = require('util')
13
14
function noop () {}
15
16
var debug = noop
17
if (util.debuglog)
18
debug = util.debuglog('gfs')
19
else if (/\bgfs\b/i.test(process.env.NODE_DEBUG || ''))
20
debug = function() {
21
var m = util.format.apply(util, arguments)
22
m = 'GFS: ' + m.split(/\n/).join('\nGFS: ')
23
console.error(m)
24
}
25
26
if (/\bgfs\b/i.test(process.env.NODE_DEBUG || '')) {
27
process.on('exit', function() {
28
debug('fds', fds)
29
debug(queue)
30
assert.equal(queue.length, 0)
31
})
32
}
33
34
35
var originalOpen = fs.open
36
fs.open = open
37
38
function open(path, flags, mode, cb) {
39
if (typeof mode === "function") cb = mode, mode = null
40
if (typeof cb !== "function") cb = noop
41
new OpenReq(path, flags, mode, cb)
42
}
43
44
function OpenReq(path, flags, mode, cb) {
45
this.path = path
46
this.flags = flags
47
this.mode = mode
48
this.cb = cb
49
Req.call(this)
50
}
51
52
util.inherits(OpenReq, Req)
53
54
OpenReq.prototype.process = function() {
55
originalOpen.call(fs, this.path, this.flags, this.mode, this.done)
56
}
57
58
var fds = {}
59
OpenReq.prototype.done = function(er, fd) {
60
debug('open done', er, fd)
61
if (fd)
62
fds['fd' + fd] = this.path
63
Req.prototype.done.call(this, er, fd)
64
}
65
66
67
var originalReaddir = fs.readdir
68
fs.readdir = readdir
69
70
function readdir(path, cb) {
71
if (typeof cb !== "function") cb = noop
72
new ReaddirReq(path, cb)
73
}
74
75
function ReaddirReq(path, cb) {
76
this.path = path
77
this.cb = cb
78
Req.call(this)
79
}
80
81
util.inherits(ReaddirReq, Req)
82
83
ReaddirReq.prototype.process = function() {
84
originalReaddir.call(fs, this.path, this.done)
85
}
86
87
ReaddirReq.prototype.done = function(er, files) {
88
if (files && files.sort)
89
files = files.sort()
90
Req.prototype.done.call(this, er, files)
91
onclose()
92
}
93
94
95
var originalClose = fs.close
96
fs.close = close
97
98
function close (fd, cb) {
99
debug('close', fd)
100
if (typeof cb !== "function") cb = noop
101
delete fds['fd' + fd]
102
originalClose.call(fs, fd, function(er) {
103
onclose()
104
cb(er)
105
})
106
}
107
108
109
var originalCloseSync = fs.closeSync
110
fs.closeSync = closeSync
111
112
function closeSync (fd) {
113
try {
114
return originalCloseSync(fd)
115
} finally {
116
onclose()
117
}
118
}
119
120
121
// Req class
122
function Req () {
123
// start processing
124
this.done = this.done.bind(this)
125
this.failures = 0
126
this.process()
127
}
128
129
Req.prototype.done = function (er, result) {
130
var tryAgain = false
131
if (er) {
132
var code = er.code
133
var tryAgain = code === "EMFILE"
134
if (process.platform === "win32")
135
tryAgain = tryAgain || code === "OK"
136
}
137
138
if (tryAgain) {
139
this.failures ++
140
enqueue(this)
141
} else {
142
var cb = this.cb
143
cb(er, result)
144
}
145
}
146
147
var queue = []
148
149
function enqueue(req) {
150
queue.push(req)
151
debug('enqueue %d %s', queue.length, req.constructor.name, req)
152
}
153
154
function onclose() {
155
var req = queue.shift()
156
if (req) {
157
debug('process', req.constructor.name, req)
158
req.process()
159
}
160
}
161
162