Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

graceful-fs@1.2.2

  • Loading branch information...
commit fa6ddb285752b8c1467bc8b2bb6c9e854553fa28 1 parent e196ccc
@isaacs isaacs authored
View
42 node_modules/graceful-fs/LICENSE
@@ -1,23 +1,27 @@
-Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+Copyright (c) Isaac Z. Schlueter ("Author")
All rights reserved.
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
+The BSD License
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
79 node_modules/graceful-fs/graceful-fs.js
@@ -1,30 +1,22 @@
// this keeps a queue of opened file descriptors, and will make
// fs operations wait until some have closed before trying to open more.
-var fs_ = require("fs")
+var fs = exports = module.exports = {}
+fs._originalFs = require("fs")
-var fs = module.exports = {}
-
-Object.getOwnPropertyNames(fs_).forEach(function(prop) {
- var desc = Object.getOwnPropertyDescriptor(fs_, prop)
+Object.getOwnPropertyNames(fs._originalFs).forEach(function(prop) {
+ var desc = Object.getOwnPropertyDescriptor(fs._originalFs, prop)
Object.defineProperty(fs, prop, desc)
})
var queue = []
, constants = require("constants")
-exports = module.exports = fs
fs._curOpen = 0
fs.MIN_MAX_OPEN = 64
fs.MAX_OPEN = 1024
-var originalOpen = fs.open
- , originalOpenSync = fs.openSync
- , originalClose = fs.close
- , originalCloseSync = fs.closeSync
-
-
// prevent EMFILE errors
function OpenReq (path, flags, mode, cb) {
this.path = path
@@ -61,7 +53,7 @@ function gracefulOpen (path, flags, mode, cb) {
function open (path, flags, mode, cb) {
cb = cb || noop
fs._curOpen ++
- originalOpen.call(fs, path, flags, mode, function (er, fd) {
+ fs._originalFs.open.call(fs, path, flags, mode, function (er, fd) {
if (er) onclose()
cb(er, fd)
})
@@ -69,7 +61,7 @@ function open (path, flags, mode, cb) {
fs.openSync = function (path, flags, mode) {
var ret
- ret = originalOpenSync.call(fs, path, flags, mode)
+ ret = fs._originalFs.openSync.call(fs, path, flags, mode)
fs._curOpen ++
return ret
}
@@ -83,21 +75,72 @@ function flush () {
while (fs._curOpen < fs.MAX_OPEN) {
var req = queue.shift()
if (!req) return
- open(req.path, req.flags || "r", req.mode || 0777, req.cb)
+ switch (req.constructor.name) {
+ case 'OpenReq':
+ open(req.path, req.flags || "r", req.mode || 0777, req.cb)
+ break
+ case 'ReaddirReq':
+ readdir(req.path, req.cb)
+ break
+ default:
+ throw new Error('Unknown req type: ' + req.constructor.name)
+ }
}
}
fs.close = function (fd, cb) {
cb = cb || noop
- originalClose.call(fs, fd, function (er) {
+ fs._originalFs.close.call(fs, fd, function (er) {
onclose()
cb(er)
})
}
fs.closeSync = function (fd) {
- onclose()
- return originalCloseSync.call(fs, fd)
+ try {
+ return fs._originalFs.closeSync.call(fs, fd)
+ } finally {
+ onclose()
+ }
+}
+
+
+// readdir takes a fd as well.
+// however, the sync version closes it right away, so
+// there's no need to wrap.
+// It would be nice to catch when it throws an EMFILE,
+// but that's relatively rare anyway.
+
+fs.readdir = gracefulReaddir
+
+function gracefulReaddir (path, cb) {
+ if (fs._curOpen >= fs.MAX_OPEN) {
+ queue.push(new ReaddirReq(path, cb))
+ setTimeout(flush)
+ return
+ }
+
+ readdir(path, function (er, files) {
+ if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
+ fs.MAX_OPEN = fs._curOpen - 1
+ return fs.readdir(path, cb)
+ }
+ cb(er, files)
+ })
+}
+
+function readdir (path, cb) {
+ cb = cb || noop
+ fs._curOpen ++
+ fs._originalFs.readdir.call(fs, path, function (er, files) {
+ onclose()
+ cb(er, files)
+ })
+}
+
+function ReaddirReq (path, cb) {
+ this.path = path
+ this.cb = cb
}
View
6 node_modules/graceful-fs/package.json
@@ -6,7 +6,7 @@
},
"name": "graceful-fs",
"description": "A drop-in replacement for fs, making various improvements.",
- "version": "1.2.1",
+ "version": "1.2.2",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-graceful-fs.git"
@@ -43,6 +43,6 @@
"bugs": {
"url": "https://github.com/isaacs/node-graceful-fs/issues"
},
- "_id": "graceful-fs@1.2.1",
- "_from": "graceful-fs@~1.2.0"
+ "_id": "graceful-fs@1.2.2",
+ "_from": "graceful-fs@latest"
}
View
158 node_modules/graceful-fs/test/ulimit.js
@@ -0,0 +1,158 @@
+var test = require('tap').test
+
+// simulated ulimit
+// this is like graceful-fs, but in reverse
+var fs_ = require('fs')
+var fs = require('../graceful-fs.js')
+var files = fs.readdirSync(__dirname)
+
+// Ok, no more actual file reading!
+
+var fds = 0
+var nextFd = 60
+var limit = 8
+fs_.open = function (path, flags, mode, cb) {
+ process.nextTick(function() {
+ ++fds
+ if (fds >= limit) {
+ --fds
+ var er = new Error('EMFILE Curses!')
+ er.code = 'EMFILE'
+ er.path = path
+ return cb(er)
+ } else {
+ cb(null, nextFd++)
+ }
+ })
+}
+
+fs_.openSync = function (path, flags, mode) {
+ if (fds >= limit) {
+ var er = new Error('EMFILE Curses!')
+ er.code = 'EMFILE'
+ er.path = path
+ throw er
+ } else {
+ ++fds
+ return nextFd++
+ }
+}
+
+fs_.close = function (fd, cb) {
+ process.nextTick(function () {
+ --fds
+ cb()
+ })
+}
+
+fs_.closeSync = function (fd) {
+ --fds
+}
+
+fs_.readdir = function (path, cb) {
+ process.nextTick(function() {
+ if (fds >= limit) {
+ var er = new Error('EMFILE Curses!')
+ er.code = 'EMFILE'
+ er.path = path
+ return cb(er)
+ } else {
+ ++fds
+ process.nextTick(function () {
+ --fds
+ cb(null, [__filename, "some-other-file.js"])
+ })
+ }
+ })
+}
+
+fs_.readdirSync = function (path) {
+ if (fds >= limit) {
+ var er = new Error('EMFILE Curses!')
+ er.code = 'EMFILE'
+ er.path = path
+ throw er
+ } else {
+ return [__filename, "some-other-file.js"]
+ }
+}
+
+
+test('open emfile autoreduce', function (t) {
+ fs.MIN_MAX_OPEN = 4
+ t.equal(fs.MAX_OPEN, 1024)
+
+ var max = 12
+ for (var i = 0; i < max; i++) {
+ fs.open(__filename, 'r', next(i))
+ }
+
+ var phase = 0
+
+ var expect =
+ [ [ 0, 60, null, 1024, 4, 12, 1 ],
+ [ 1, 61, null, 1024, 4, 12, 2 ],
+ [ 2, 62, null, 1024, 4, 12, 3 ],
+ [ 3, 63, null, 1024, 4, 12, 4 ],
+ [ 4, 64, null, 1024, 4, 12, 5 ],
+ [ 5, 65, null, 1024, 4, 12, 6 ],
+ [ 6, 66, null, 1024, 4, 12, 7 ],
+ [ 7, 67, null, 6, 4, 5, 1 ],
+ [ 8, 68, null, 6, 4, 5, 2 ],
+ [ 9, 69, null, 6, 4, 5, 3 ],
+ [ 10, 70, null, 6, 4, 5, 4 ],
+ [ 11, 71, null, 6, 4, 5, 5 ] ]
+
+ var actual = []
+
+ function next (i) { return function (er, fd) {
+ if (er)
+ throw er
+ actual.push([i, fd, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds])
+
+ if (i === max - 1) {
+ t.same(actual, expect)
+ t.ok(fs.MAX_OPEN < limit)
+ t.end()
+ }
+
+ fs.close(fd)
+ } }
+})
+
+test('readdir emfile autoreduce', function (t) {
+ fs.MAX_OPEN = 1024
+ var max = 12
+ for (var i = 0; i < max; i ++) {
+ fs.readdir(__dirname, next(i))
+ }
+
+ var expect =
+ [ [0,[__filename,"some-other-file.js"],null,7,4,7,7],
+ [1,[__filename,"some-other-file.js"],null,7,4,7,6],
+ [2,[__filename,"some-other-file.js"],null,7,4,7,5],
+ [3,[__filename,"some-other-file.js"],null,7,4,7,4],
+ [4,[__filename,"some-other-file.js"],null,7,4,7,3],
+ [5,[__filename,"some-other-file.js"],null,7,4,6,2],
+ [6,[__filename,"some-other-file.js"],null,7,4,5,1],
+ [7,[__filename,"some-other-file.js"],null,7,4,4,0],
+ [8,[__filename,"some-other-file.js"],null,7,4,3,3],
+ [9,[__filename,"some-other-file.js"],null,7,4,2,2],
+ [10,[__filename,"some-other-file.js"],null,7,4,1,1],
+ [11,[__filename,"some-other-file.js"],null,7,4,0,0] ]
+
+ var actual = []
+
+ function next (i) { return function (er, files) {
+ if (er)
+ throw er
+ var line = [i, files, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds ]
+ actual.push(line)
+
+ if (i === max - 1) {
+ t.ok(fs.MAX_OPEN < limit)
+ t.same(actual, expect)
+ t.end()
+ }
+ } }
+})
View
2  package.json
@@ -38,7 +38,7 @@
"ini": "~1.1.0",
"slide": "~1.1.4",
"abbrev": "~1.0.4",
- "graceful-fs": "~1.2.0",
+ "graceful-fs": "~1.2.2",
"minimatch": "~0.2.12",
"nopt": "~2.1.1",
"rimraf": "2",
Please sign in to comment.
Something went wrong with that request. Please try again.