Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Beat to quarters and clear for action.
Updated dependencies. (Audit now reports 0 problems.) Switched from prototype chain class def to the class keyword sugar. Moved from var to const & let. Pulled the single test file up from a subdir.
- Loading branch information
Showing
5 changed files
with
2,590 additions
and
1,995 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 |
---|---|---|
@@ -1,7 +1,7 @@ | ||
sudo: false | ||
language: node_js | ||
node_js: | ||
- "4" | ||
- "6" | ||
- "7" | ||
- "8" | ||
- "10" | ||
after_success: npm run coverage |
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 |
---|---|---|
@@ -1,117 +1,116 @@ | ||
// This code base means freedom. | ||
|
||
var | ||
'use strict'; | ||
|
||
const | ||
assert = require('assert'), | ||
Skiplist = require('skiplist'), | ||
Xxhash = require('xxhashjs').h64 | ||
; | ||
|
||
var Lightcycle = module.exports = function Lightcycle(settings) | ||
class Lightcycle | ||
{ | ||
settings = settings || {}; | ||
constructor(settings) | ||
{ | ||
settings = settings || {}; | ||
|
||
this.seed = settings.seed || 0xcafed00d; | ||
this.size = Math.round(settings.size) || 128; | ||
assert(this.size > 0, 'you must pass in a positive integer for size'); | ||
this.seed = settings.seed || 0xcafed00d; | ||
this.size = Math.round(settings.size) || 128; | ||
assert(this.size > 0, 'you must pass in a positive integer for size'); | ||
|
||
this.replicas = settings.replicas || this.size; | ||
this.resources = new Skiplist(this.size * this.replicas + 16); // a little padding | ||
this.cache = {}; | ||
this.entries = {}; | ||
}; | ||
this.replicas = settings.replicas || this.size; | ||
this.resources = new Skiplist(this.size * this.replicas + 16); // a little padding | ||
this.cache = {}; | ||
this.entries = {}; | ||
} | ||
|
||
Lightcycle.prototype.seed = 0xcafed00d; | ||
Lightcycle.prototype.size = 128; | ||
Lightcycle.prototype.replicas = 128; | ||
Lightcycle.prototype.resources = null; | ||
Lightcycle.prototype.cache = null; | ||
Lightcycle.prototype.entries = null; | ||
add(resource, id) | ||
{ | ||
assert(resource); | ||
assert(id && typeof id === 'string'); | ||
if (!this.cache[id]) | ||
this.cache[id] = []; | ||
let key; | ||
|
||
// Constants used when rebalancing to leave space. | ||
Lightcycle.SIZE_PAD = 16; | ||
Lightcycle.REPLICAS_PAD = 8; | ||
for (var i = 0; i < this.replicas; i++) | ||
{ | ||
if (this.cache[id][i]) | ||
key = this.cache[id][i]; | ||
else | ||
{ | ||
key = this.hashit(id + String(i)); | ||
this.cache[id][i] = key; | ||
} | ||
this.resources.insert(key, resource); | ||
} | ||
|
||
Lightcycle.prototype.add = function add(resource, id) | ||
{ | ||
assert(resource); | ||
assert(id && typeof id === 'string'); | ||
if (!this.cache[id]) | ||
this.cache[id] = []; | ||
var key; | ||
this.entries[id] = resource; | ||
if (Object.keys(this.entries).length > this.size) | ||
this.rebalance(); | ||
} | ||
|
||
for (var i = 0; i < this.replicas; i++) | ||
remove(id) | ||
{ | ||
if (this.cache[id][i]) | ||
key = this.cache[id][i]; | ||
else | ||
assert(id && typeof id === 'string'); | ||
if (!Array.isArray(this.cache[id])) | ||
return; | ||
|
||
for (var i = 0; i < this.replicas; i++) | ||
{ | ||
key = this.hashit(id + String(i)); | ||
this.cache[id][i] = key; | ||
const key = this.cache[id][i]; | ||
this.resources.remove(key); | ||
} | ||
this.resources.insert(key, resource); | ||
} | ||
|
||
this.entries[id] = resource; | ||
if (Object.keys(this.entries).length > this.size) | ||
this.rebalance(); | ||
}; | ||
|
||
Lightcycle.prototype.remove = function remove(id) | ||
{ | ||
assert(id && typeof id === 'string'); | ||
if (!Array.isArray(this.cache[id])) | ||
return; | ||
var key; | ||
delete this.entries[id]; | ||
} | ||
|
||
for (var i = 0; i < this.replicas; i++) | ||
locate(id) | ||
{ | ||
key = this.cache[id][i]; | ||
this.resources.remove(key); | ||
} | ||
const key = this.hashit(id); | ||
let results = this.resources.findWithCount(key, 1); | ||
|
||
delete this.entries[id]; | ||
}; | ||
if (results.length === 0) | ||
results = this.resources.findWithCount(null, 1); | ||
|
||
Lightcycle.prototype.locate = function locate(id) | ||
{ | ||
var key = this.hashit(id); | ||
var results = this.resources.findWithCount(key, 1); | ||
if (results.length > 0) | ||
return results[0][1]; | ||
|
||
if (results.length === 0) | ||
results = this.resources.findWithCount(null, 1); | ||
return null; | ||
} | ||
|
||
if (results.length > 0) | ||
return results[0][1]; | ||
hashit(input) | ||
{ | ||
if (!Buffer.isBuffer(input)) | ||
input = new Buffer.from(input); | ||
|
||
return null; | ||
}; | ||
const hash = Xxhash(this.seed); | ||
hash.update(input); | ||
let result = hash.digest().toString(16); | ||
while (result.length < 8) result = '0' + result; | ||
|
||
Lightcycle.prototype.hashit = function hashit(input) | ||
{ | ||
if (!Buffer.isBuffer(input)) | ||
input = new Buffer(input); | ||
return result; | ||
} | ||
|
||
var hash = Xxhash(this.seed); | ||
hash.update(input); | ||
var result = hash.digest().toString(16); | ||
while (result.length < 8) result = '0' + result; | ||
all() | ||
{ | ||
return this.entries; | ||
} | ||
|
||
return result; | ||
}; | ||
rebalance() | ||
{ | ||
const ids = Object.keys(this.entries); | ||
|
||
Lightcycle.prototype.all = function all() | ||
{ | ||
return this.entries; | ||
}; | ||
this.size = ids.length + Lightcycle.SIZE_PAD; | ||
this.replicas = ids.length + Lightcycle.REPLICAS_PAD; | ||
this.resources = new Skiplist(this.size * this.replicas); | ||
|
||
Lightcycle.prototype.rebalance = function rebalance() | ||
{ | ||
var ids = Object.keys(this.entries); | ||
for (var i = 0; i < ids.length; i++) | ||
this.add(this.entries[ids[i]], ids[i]); | ||
} | ||
} | ||
|
||
this.size = ids.length + Lightcycle.SIZE_PAD; | ||
this.replicas = ids.length + Lightcycle.REPLICAS_PAD; | ||
this.resources = new Skiplist(this.size * this.replicas); | ||
// Constants used when rebalancing to leave space. | ||
Lightcycle.SIZE_PAD = 16; | ||
Lightcycle.REPLICAS_PAD = 8; | ||
|
||
for (var i = 0; i < ids.length; i++) | ||
this.add(this.entries[ids[i]], ids[i]); | ||
}; | ||
module.exports = Lightcycle; |
Oops, something went wrong.