forked from jrop/nedb-promise
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/** | ||
* Load and modify part of fs to ensure writeFile will crash after writing 5000 bytes | ||
*/ | ||
var fs = require('fs'); | ||
|
||
function rethrow() { | ||
// Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and | ||
// is fairly slow to generate. | ||
if (DEBUG) { | ||
var backtrace = new Error(); | ||
return function(err) { | ||
if (err) { | ||
backtrace.stack = err.name + ': ' + err.message + | ||
backtrace.stack.substr(backtrace.name.length); | ||
throw backtrace; | ||
} | ||
}; | ||
} | ||
|
||
return function(err) { | ||
if (err) { | ||
throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs | ||
} | ||
}; | ||
} | ||
|
||
function maybeCallback(cb) { | ||
return typeof cb === 'function' ? cb : rethrow(); | ||
} | ||
|
||
function isFd(path) { | ||
return (path >>> 0) === path; | ||
} | ||
|
||
function assertEncoding(encoding) { | ||
if (encoding && !Buffer.isEncoding(encoding)) { | ||
throw new Error('Unknown encoding: ' + encoding); | ||
} | ||
} | ||
|
||
var onePassDone = false; | ||
function writeAll(fd, isUserFd, buffer, offset, length, position, callback_) { | ||
var callback = maybeCallback(arguments[arguments.length - 1]); | ||
|
||
if (onePassDone) { process.exit(1); } // Crash on purpose before rewrite done | ||
var l = Math.min(5000, length); // Force write by chunks of 5000 bytes to ensure data will be incomplete on crash | ||
|
||
// write(fd, buffer, offset, length, position, callback) | ||
fs.write(fd, buffer, offset, l, position, function(writeErr, written) { | ||
if (writeErr) { | ||
if (isUserFd) { | ||
if (callback) callback(writeErr); | ||
} else { | ||
fs.close(fd, function() { | ||
if (callback) callback(writeErr); | ||
}); | ||
} | ||
} else { | ||
onePassDone = true; | ||
if (written === length) { | ||
if (isUserFd) { | ||
if (callback) callback(null); | ||
} else { | ||
fs.close(fd, callback); | ||
} | ||
} else { | ||
offset += written; | ||
length -= written; | ||
if (position !== null) { | ||
position += written; | ||
} | ||
writeAll(fd, isUserFd, buffer, offset, length, position, callback); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
fs.writeFile = function(path, data, options, callback_) { | ||
var callback = maybeCallback(arguments[arguments.length - 1]); | ||
|
||
if (!options || typeof options === 'function') { | ||
options = { encoding: 'utf8', mode: 438, flag: 'w' }; // Mode 438 == 0o666 (compatibility with older Node releases) | ||
} else if (typeof options === 'string') { | ||
options = { encoding: options, mode: 438, flag: 'w' }; // Mode 438 == 0o666 (compatibility with older Node releases) | ||
} else if (typeof options !== 'object') { | ||
throwOptionsError(options); | ||
} | ||
|
||
assertEncoding(options.encoding); | ||
|
||
var flag = options.flag || 'w'; | ||
|
||
if (isFd(path)) { | ||
writeFd(path, true); | ||
return; | ||
} | ||
|
||
fs.open(path, flag, options.mode, function(openErr, fd) { | ||
if (openErr) { | ||
if (callback) callback(openErr); | ||
} else { | ||
writeFd(fd, false); | ||
} | ||
}); | ||
|
||
function writeFd(fd, isUserFd) { | ||
var buffer = (data instanceof Buffer) ? data : new Buffer('' + data, | ||
options.encoding || 'utf8'); | ||
var position = /a/.test(flag) ? null : 0; | ||
|
||
writeAll(fd, isUserFd, buffer, 0, buffer.length, position, callback); | ||
} | ||
}; | ||
|
||
|
||
|
||
|
||
// End of fs modification | ||
var Nedb = require('../lib/datastore.js') | ||
, db = new Nedb({ filename: 'workspace/lac.db' }) | ||
; | ||
|
||
db.loadDatabase(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
var fs = require('fs') | ||
, child_process = require('child_process') | ||
, [AsyncWaterfall, AsyncWhilst] = [require('async/waterfall'), require('async/whilst')] | ||
, Nedb = require('../nedb/datastore') | ||
, db = new Nedb({ filename: './workspace/openfds.db', autoload: true }) | ||
, N = 64 // Half the allowed file descriptors | ||
, i, fds | ||
; | ||
|
||
function multipleOpen (filename, N, callback) { | ||
AsyncWhilst( function () { return i < N; } | ||
, function (cb) { | ||
fs.open(filename, 'r', function (err, fd) { | ||
i ++; | ||
if (fd) { fds.push(fd); } | ||
return cb(err); | ||
}); | ||
} | ||
, callback); | ||
} | ||
|
||
AsyncWaterfall([ | ||
// Check that ulimit has been set to the correct value | ||
function (cb) { | ||
i = 0; | ||
fds = []; | ||
multipleOpen('./test_lac/openFdsTestFile', 2 * N + 1, function (err) { | ||
if (!err) { console.log("No error occured while opening a file too many times"); } | ||
fds.forEach(function (fd) { fs.closeSync(fd); }); | ||
return cb(); | ||
}) | ||
} | ||
, function (cb) { | ||
i = 0; | ||
fds = []; | ||
multipleOpen('./test_lac/openFdsTestFile2', N, function (err) { | ||
if (err) { console.log('An unexpected error occured when opening file not too many times: ' + err); } | ||
fds.forEach(function (fd) { fs.closeSync(fd); }); | ||
return cb(); | ||
}) | ||
} | ||
// Then actually test NeDB persistence | ||
, function () { | ||
db.remove({}, { multi: true }, function (err) { | ||
if (err) { console.log(err); } | ||
db.insert({ hello: 'world' }, function (err) { | ||
if (err) { console.log(err); } | ||
|
||
i = 0; | ||
AsyncWhilst( function () { return i < 2 * N + 1; } | ||
, function (cb) { | ||
db.persistence.persistCachedDatabase(function (err) { | ||
if (err) { return cb(err); } | ||
i ++; | ||
return cb(); | ||
}); | ||
} | ||
, function (err) { | ||
if (err) { console.log("Got unexpected error during one peresistence operation: " + err); } | ||
} | ||
); | ||
|
||
}); | ||
}); | ||
} | ||
]); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
ulimit -n 128 | ||
node ./test_lac/openFds.test.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Random stuff |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Some other random stuff |