pax_global_header00006660000000000000000000000064131062071640014512gustar00rootroot0000000000000052 comment=55dc4fa35e8f73de57661957d475560a0d04215c dirty.js-1.0.0/000077500000000000000000000000001310620716400132565ustar00rootroot00000000000000dirty.js-1.0.0/.gitignore000066400000000000000000000000251310620716400152430ustar00rootroot00000000000000*.dirty node_modules dirty.js-1.0.0/.travis.yml000066400000000000000000000000621310620716400153650ustar00rootroot00000000000000language: node_js node_js: - "0.10" - "0.8" dirty.js-1.0.0/LICENSE.txt000066400000000000000000000020741310620716400151040ustar00rootroot00000000000000Copyright (c) 2010 Debuggable Limited 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 above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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.dirty.js-1.0.0/Makefile000066400000000000000000000005471310620716400147240ustar00rootroot00000000000000test: npm test benchmark-v8: @find benchmark/v8/*.js | xargs -n 1 -t node benchmark-php: @find benchmark/php/*.php | xargs -n 1 -t php benchmark-dirty: @find benchmark/dirty/*.js | xargs -n 1 -t node benchmark-all: benchmark-v8 benchmark-php benchmark-dirty benchmark: benchmark-dirty clean: @find . -name *.dirty | xargs rm .PHONY: test benchmark dirty.js-1.0.0/README.md000066400000000000000000000070321310620716400145370ustar00rootroot00000000000000# node-dirty ## Purpose A tiny & fast key value store with append-only disk log. Ideal for apps with < 1 million records. ## Installation ```bash npm install dirty ``` ## Why dirty? This module is called dirty because: * The file format is newline separated JSON * Your database lives in the same process as your application, they share memory * There is no query language, you just `forEach` through all records So dirty means that you will hit a very hard wall with this database after ~1 million records, but it is a wonderful solution for anything smaller than that. ## Tutorial ```javascript var dirty = require('dirty'); var db = dirty('user.db'); db.on('load', function() { db.set('john', {eyes: 'blue'}); console.log('Added john, he has %s eyes.', db.get('john').eyes); db.set('bob', {eyes: 'brown'}, function() { console.log('User bob is now saved on disk.') }); db.forEach(function(key, val) { console.log('Found key: %s, val: %j', key, val); }); }); db.on('drain', function() { console.log('All records are saved on disk now.'); }); ``` Output: Added john, he has blue eyes. Found key: john, val: {"eyes":"blue"} Found key: bob, val: {"eyes":"brown"} User bob is now saved on disk. All records are saved on disk now. ## API ### new Dirty([path]) Creates a new dirty database. If `path` does not exist yet, it is created. You can also omit the `path` if you don't want disk persistence (useful for testing). The constructor can be invoked in multiple ways: ```javascript require('dirty')('my.db'); require('dirty').Dirty('my.db'); new (require('dirty'))('my.db'); new (require('dirty').Dirty)('my.db'); ``` ### dirty.path The path of the dirty database. ### dirty.set(key, value, [cb]) Set's the given `key` / `val` pair. The state of the database is affected instantly, the optional `cb` callback is fired when the record was written to disk. `val` can be any JSON-serializable type, it does not have to be an object. ### dirty.get(key) Retrieves the value for the given `key`. ### dirty.rm(key, cb) Removes the record with the given `key`. This is identical to setting the `key`'s value to `undefined`. ### dirty.forEach(fn) Calls the given `fn` function for every document in the database. The passed arguments are `key` and `val`. You can return `false` to abort a query (useful if you are only interested in a limited number of records). This function is blocking and runs at ~4 Mhz. ### dirty.close() Close the dirty db file handle. ### dirty event: 'load' (length) Emitted once the database file has finished loading. It is not safe to access records before this event fires. Writing records however should be fine. `length` is the amount of records the database is holding. This only counts each key once, even if it had been overwritten. You can chain the on load to the contructor as follows: ```javascript var db = dirty(file).on('load', function() { ... }); ``` ### dirty event: 'drain' () Emitted whenever all records have been written to disk. ### dirty event: 'read_close' () Emitted once the database file read stream closed. ### dirty event : 'write_close' () Emitted once the database file write stream closed. ## Tests [![Build Status](https://travis-ci.org/felixge/node-dirty.png)](https://travis-ci.org/felixge/node-dirty) Dirty utilizes the [Mocha](http://visionmedia.github.com/mocha/) test framework. ```bash git clone https://github.com/felixge/node-dirty cd node-dirty npm install npm test ``` ## License node-dirty is licensed under the MIT license. dirty.js-1.0.0/benchmark/000077500000000000000000000000001310620716400152105ustar00rootroot00000000000000dirty.js-1.0.0/benchmark/dirty/000077500000000000000000000000001310620716400163435ustar00rootroot00000000000000dirty.js-1.0.0/benchmark/dirty/for-each.js000066400000000000000000000011031310620716400203600ustar00rootroot00000000000000var config = require('../../test/config'); var COUNT = 1e6, dirty = require(config.LIB_DIRTY)(), util = require('util'); for (var i = 0; i < COUNT; i++) { dirty.set(i, i); } var start = Date.now(), i = 0; dirty.forEach(function(key, doc) { if (!key && key !== 0) { throw new Error('implementation fail'); } }); var ms = Date.now() - start, mhz = ((COUNT / (ms / 1000)) / 1e6).toFixed(2), million = COUNT / 1e6; // Can't use console.log() since since I also test this in ancient node versions util.log(mhz+' Mhz ('+million+' million in '+ms+' ms)'); dirty.js-1.0.0/benchmark/dirty/get.js000066400000000000000000000010731310620716400174610ustar00rootroot00000000000000var config = require('../../test/config'); var COUNT = 1e6, dirty = require(config.LIB_DIRTY)(), util = require('util'); for (var i = 0; i < COUNT; i++) { dirty.set(i, i); } var start = Date.now(); for (var i = 0; i < COUNT; i++) { if (dirty.get(i) !== i) { throw new Error('implementation fail'); } } var ms = Date.now() - start, mhz = ((COUNT / (ms / 1000)) / 1e6).toFixed(2), million = COUNT / 1e6; // Can't use console.log() since since I also test this in ancient node versions util.log(mhz+' Mhz ('+million+' million in '+ms+' ms)'); dirty.js-1.0.0/benchmark/dirty/load.js000066400000000000000000000014121310620716400176160ustar00rootroot00000000000000var config = require('../../test/config'); var COUNT = 1e4, DB_FILE = config.TMP_PATH + '/benchmark-set-drain.dirty', dirty = require(config.LIB_DIRTY)(DB_FILE), util = require('util'), loaded = false; for (var i = 0; i < COUNT; i++) { dirty.set(i, i); } dirty.on('drain', function() { var start = Date.now(); require('dirty')(DB_FILE).on('load', function(length) { var ms = Date.now() - start, mhz = ((COUNT / (ms / 1000)) / 1e3).toFixed(2), million = COUNT / 1e6; // Can't use console.log() since since I also test this in ancient node versions util.log(mhz+' Hz ('+million+' million in '+ms+' ms)'); loaded = true; assert.equal(length, COUNT); }); }); process.on('exit', function() { assert.ok(loaded); }); dirty.js-1.0.0/benchmark/dirty/set-drain-256-bytes-per-doc.js000066400000000000000000000016071310620716400235600ustar00rootroot00000000000000var config = require('../../test/config'); var COUNT = 1e5, dirty = require(config.LIB_DIRTY)(config.TMP_PATH + '/benchmark-set-drain.dirty'), util = require('util'), drained = false; var start = Date.now(); for (var i = 0; i < COUNT; i++) { dirty.set(i, 'This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string'); } dirty.on('drain', function() { var ms = Date.now() - start, mhz = ((COUNT / (ms / 1000)) / 1e3).toFixed(2), million = COUNT / 1e6; // Can't use console.log() since since I also test this in ancient node versions util.log(mhz+' Hz ('+million+' million in '+ms+' ms)'); drained = true; }); process.on('exit', function() { assert.ok(drained); }); dirty.js-1.0.0/benchmark/dirty/set-drain.js000066400000000000000000000012061310620716400205660ustar00rootroot00000000000000var config = require('../../test/config'); var COUNT = 1e4, dirty = require(config.LIB_DIRTY)(config.TMP_PATH + '/benchmark-set-drain.dirty'), util = require('util'), drained = false; var start = Date.now(); for (var i = 0; i < COUNT; i++) { dirty.set(i, i); } dirty.on('drain', function() { var ms = Date.now() - start, mhz = ((COUNT / (ms / 1000)) / 1e3).toFixed(2), million = COUNT / 1e6; // Can't use console.log() since since I also test this in ancient node versions util.log(mhz+' Hz ('+million+' million in '+ms+' ms)'); drained = true; }); process.on('exit', function() { assert.ok(drained); }); dirty.js-1.0.0/benchmark/dirty/set.js000066400000000000000000000007611310620716400175000ustar00rootroot00000000000000var config = require('../../test/config'); var COUNT = 1e6, dirty = require(config.LIB_DIRTY)(config.TMP_PATH + '/benchmark-set.dirty'), util = require('util'); var start = Date.now(); for (var i = 0; i < COUNT; i++) { dirty.set(i, i); } var ms = Date.now() - start, mhz = ((COUNT / (ms / 1000)) / 1e6).toFixed(2), million = COUNT / 1e6; // Can't use console.log() since since I also test this in ancient node versions util.log(mhz+' Mhz ('+million+' million in '+ms+' ms)'); dirty.js-1.0.0/benchmark/php/000077500000000000000000000000001310620716400157775ustar00rootroot00000000000000dirty.js-1.0.0/benchmark/php/array-get.php000066400000000000000000000006421310620716400204050ustar00rootroot00000000000000