123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- var fs = require('fs')
- var polyfills = require('./polyfills.js')
- var legacy = require('./legacy-streams.js')
- var clone = require('./clone.js')
- var util = require('util')
- var gracefulQueue
- var previousSymbol
- if (typeof Symbol === 'function' && typeof Symbol.for === 'function') {
- gracefulQueue = Symbol.for('graceful-fs.queue')
-
- previousSymbol = Symbol.for('graceful-fs.previous')
- } else {
- gracefulQueue = '___graceful-fs.queue'
- previousSymbol = '___graceful-fs.previous'
- }
- function noop () {}
- function publishQueue(context, queue) {
- Object.defineProperty(context, gracefulQueue, {
- get: function() {
- return queue
- }
- })
- }
- var debug = noop
- if (util.debuglog)
- debug = util.debuglog('gfs4')
- else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
- debug = function() {
- var m = util.format.apply(util, arguments)
- m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ')
- console.error(m)
- }
- if (!fs[gracefulQueue]) {
-
- var queue = global[gracefulQueue] || []
- publishQueue(fs, queue)
-
-
-
-
- fs.close = (function (fs$close) {
- function close (fd, cb) {
- return fs$close.call(fs, fd, function (err) {
-
- if (!err) {
- resetQueue()
- }
- if (typeof cb === 'function')
- cb.apply(this, arguments)
- })
- }
- Object.defineProperty(close, previousSymbol, {
- value: fs$close
- })
- return close
- })(fs.close)
- fs.closeSync = (function (fs$closeSync) {
- function closeSync (fd) {
-
- fs$closeSync.apply(fs, arguments)
- resetQueue()
- }
- Object.defineProperty(closeSync, previousSymbol, {
- value: fs$closeSync
- })
- return closeSync
- })(fs.closeSync)
- if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
- process.on('exit', function() {
- debug(fs[gracefulQueue])
- require('assert').equal(fs[gracefulQueue].length, 0)
- })
- }
- }
- if (!global[gracefulQueue]) {
- publishQueue(global, fs[gracefulQueue]);
- }
- module.exports = patch(clone(fs))
- if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) {
- module.exports = patch(fs)
- fs.__patched = true;
- }
- function patch (fs) {
-
- polyfills(fs)
- fs.gracefulify = patch
- fs.createReadStream = createReadStream
- fs.createWriteStream = createWriteStream
- var fs$readFile = fs.readFile
- fs.readFile = readFile
- function readFile (path, options, cb) {
- if (typeof options === 'function')
- cb = options, options = null
- return go$readFile(path, options, cb)
- function go$readFile (path, options, cb, startTime) {
- return fs$readFile(path, options, function (err) {
- if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
- enqueue([go$readFile, [path, options, cb], err, startTime || Date.now(), Date.now()])
- else {
- if (typeof cb === 'function')
- cb.apply(this, arguments)
- }
- })
- }
- }
- var fs$writeFile = fs.writeFile
- fs.writeFile = writeFile
- function writeFile (path, data, options, cb) {
- if (typeof options === 'function')
- cb = options, options = null
- return go$writeFile(path, data, options, cb)
- function go$writeFile (path, data, options, cb, startTime) {
- return fs$writeFile(path, data, options, function (err) {
- if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
- enqueue([go$writeFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()])
- else {
- if (typeof cb === 'function')
- cb.apply(this, arguments)
- }
- })
- }
- }
- var fs$appendFile = fs.appendFile
- if (fs$appendFile)
- fs.appendFile = appendFile
- function appendFile (path, data, options, cb) {
- if (typeof options === 'function')
- cb = options, options = null
- return go$appendFile(path, data, options, cb)
- function go$appendFile (path, data, options, cb, startTime) {
- return fs$appendFile(path, data, options, function (err) {
- if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
- enqueue([go$appendFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()])
- else {
- if (typeof cb === 'function')
- cb.apply(this, arguments)
- }
- })
- }
- }
- var fs$copyFile = fs.copyFile
- if (fs$copyFile)
- fs.copyFile = copyFile
- function copyFile (src, dest, flags, cb) {
- if (typeof flags === 'function') {
- cb = flags
- flags = 0
- }
- return go$copyFile(src, dest, flags, cb)
- function go$copyFile (src, dest, flags, cb, startTime) {
- return fs$copyFile(src, dest, flags, function (err) {
- if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
- enqueue([go$copyFile, [src, dest, flags, cb], err, startTime || Date.now(), Date.now()])
- else {
- if (typeof cb === 'function')
- cb.apply(this, arguments)
- }
- })
- }
- }
- var fs$readdir = fs.readdir
- fs.readdir = readdir
- var noReaddirOptionVersions = /^v[0-5]\./
- function readdir (path, options, cb) {
- if (typeof options === 'function')
- cb = options, options = null
- var go$readdir = noReaddirOptionVersions.test(process.version)
- ? function go$readdir (path, options, cb, startTime) {
- return fs$readdir(path, fs$readdirCallback(
- path, options, cb, startTime
- ))
- }
- : function go$readdir (path, options, cb, startTime) {
- return fs$readdir(path, options, fs$readdirCallback(
- path, options, cb, startTime
- ))
- }
- return go$readdir(path, options, cb)
- function fs$readdirCallback (path, options, cb, startTime) {
- return function (err, files) {
- if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
- enqueue([
- go$readdir,
- [path, options, cb],
- err,
- startTime || Date.now(),
- Date.now()
- ])
- else {
- if (files && files.sort)
- files.sort()
- if (typeof cb === 'function')
- cb.call(this, err, files)
- }
- }
- }
- }
- if (process.version.substr(0, 4) === 'v0.8') {
- var legStreams = legacy(fs)
- ReadStream = legStreams.ReadStream
- WriteStream = legStreams.WriteStream
- }
- var fs$ReadStream = fs.ReadStream
- if (fs$ReadStream) {
- ReadStream.prototype = Object.create(fs$ReadStream.prototype)
- ReadStream.prototype.open = ReadStream$open
- }
- var fs$WriteStream = fs.WriteStream
- if (fs$WriteStream) {
- WriteStream.prototype = Object.create(fs$WriteStream.prototype)
- WriteStream.prototype.open = WriteStream$open
- }
- Object.defineProperty(fs, 'ReadStream', {
- get: function () {
- return ReadStream
- },
- set: function (val) {
- ReadStream = val
- },
- enumerable: true,
- configurable: true
- })
- Object.defineProperty(fs, 'WriteStream', {
- get: function () {
- return WriteStream
- },
- set: function (val) {
- WriteStream = val
- },
- enumerable: true,
- configurable: true
- })
-
- var FileReadStream = ReadStream
- Object.defineProperty(fs, 'FileReadStream', {
- get: function () {
- return FileReadStream
- },
- set: function (val) {
- FileReadStream = val
- },
- enumerable: true,
- configurable: true
- })
- var FileWriteStream = WriteStream
- Object.defineProperty(fs, 'FileWriteStream', {
- get: function () {
- return FileWriteStream
- },
- set: function (val) {
- FileWriteStream = val
- },
- enumerable: true,
- configurable: true
- })
- function ReadStream (path, options) {
- if (this instanceof ReadStream)
- return fs$ReadStream.apply(this, arguments), this
- else
- return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
- }
- function ReadStream$open () {
- var that = this
- open(that.path, that.flags, that.mode, function (err, fd) {
- if (err) {
- if (that.autoClose)
- that.destroy()
- that.emit('error', err)
- } else {
- that.fd = fd
- that.emit('open', fd)
- that.read()
- }
- })
- }
- function WriteStream (path, options) {
- if (this instanceof WriteStream)
- return fs$WriteStream.apply(this, arguments), this
- else
- return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
- }
- function WriteStream$open () {
- var that = this
- open(that.path, that.flags, that.mode, function (err, fd) {
- if (err) {
- that.destroy()
- that.emit('error', err)
- } else {
- that.fd = fd
- that.emit('open', fd)
- }
- })
- }
- function createReadStream (path, options) {
- return new fs.ReadStream(path, options)
- }
- function createWriteStream (path, options) {
- return new fs.WriteStream(path, options)
- }
- var fs$open = fs.open
- fs.open = open
- function open (path, flags, mode, cb) {
- if (typeof mode === 'function')
- cb = mode, mode = null
- return go$open(path, flags, mode, cb)
- function go$open (path, flags, mode, cb, startTime) {
- return fs$open(path, flags, mode, function (err, fd) {
- if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
- enqueue([go$open, [path, flags, mode, cb], err, startTime || Date.now(), Date.now()])
- else {
- if (typeof cb === 'function')
- cb.apply(this, arguments)
- }
- })
- }
- }
- return fs
- }
- function enqueue (elem) {
- debug('ENQUEUE', elem[0].name, elem[1])
- fs[gracefulQueue].push(elem)
- retry()
- }
- var retryTimer
- function resetQueue () {
- var now = Date.now()
- for (var i = 0; i < fs[gracefulQueue].length; ++i) {
-
-
- if (fs[gracefulQueue][i].length > 2) {
- fs[gracefulQueue][i][3] = now
- fs[gracefulQueue][i][4] = now
- }
- }
-
- retry()
- }
- function retry () {
-
- clearTimeout(retryTimer)
- retryTimer = undefined
- if (fs[gracefulQueue].length === 0)
- return
- var elem = fs[gracefulQueue].shift()
- var fn = elem[0]
- var args = elem[1]
-
- var err = elem[2]
- var startTime = elem[3]
- var lastTime = elem[4]
-
-
- if (startTime === undefined) {
- debug('RETRY', fn.name, args)
- fn.apply(null, args)
- } else if (Date.now() - startTime >= 60000) {
-
- debug('TIMEOUT', fn.name, args)
- var cb = args.pop()
- if (typeof cb === 'function')
- cb.call(null, err)
- } else {
-
- var sinceAttempt = Date.now() - lastTime
-
-
- var sinceStart = Math.max(lastTime - startTime, 1)
-
-
- var desiredDelay = Math.min(sinceStart * 1.2, 100)
-
- if (sinceAttempt >= desiredDelay) {
- debug('RETRY', fn.name, args)
- fn.apply(null, args.concat([startTime]))
- } else {
-
-
- fs[gracefulQueue].push(elem)
- }
- }
-
- if (retryTimer === undefined) {
- retryTimer = setTimeout(retry, 0)
- }
- }
|