UNPKG

ndn-js-contrib

Version:

Reusable 'Classes' for Named Data Networking: NameTree, PIT, FIB, ContentStore, Interfaces, and Transports

204 lines (171 loc) 6.15 kB
/** * *@external ContentStore *@see http://rynomad.github.io/ndn-js-contrib/doc/ContentStore.html * */ var leveldown = require("leveldown") , levelup = require("levelup") , Name = require("ndn-js/js/name.js").Name , crypto = require("ndn-js/js/crypto.js") , Data = require("ndn-js/js/data.js").Data , NameTree = require("./NameTree.js") , ContentStore = require("./ContentStore.js") function Repository (path){ var self = this; this._dataPath = path; this._contentStore = new ContentStore(); this._contentStore.setEntryClass(Repository.Entry); return new Promise(function Repository_Constructor_Promise(resolve,reject){ levelup( self._dataPath , {db:leveldown, valueEncoding: "json"} , function Repository_Contstructor_Promise_levelup(err, db){ if (err) return reject(err); self._dataDB = db; self.populateContentStoreNodes() .then(function(){ resolve(self) }) .catch(reject); }); }); } Repository.Open = function Repository_Open(path){ return new Repository(path); }; Repository.Entry = function Repository_Entry(data, repository){ var self = this; this._repository = repository; this.prefix = data.name; return this; }; function Repository_getNameWithDigest(name, packet){ var name = new Name(name) name.append("sha256digest=" + crypto.createHash('sha256') .update(packet) .digest() .toString('hex')); return name; } Repository.Entry.prototype.getData = function Repository_Entry_getData(){ var self = this; return new Promise(function Repository_Entry_getData_Promise(resolve, reject){ self._repository ._dataDB .get(self.prefix.toUri(), function(err, packet){ if (err) return reject(err); var data = new Data() data.wireDecode(new Buffer(packet)); resolve(data); }); }); }; Repository.Entry.prototype.delete = function Repository_Entry_delete(){ var self = this; return new Promise(function Repository_Entry_delete_Promise(resolve, reject){ self._repository ._dataDB .del(self.prefix.toUri(), function(err){ if (err) return reject(err); resolve(self); }); }); }; Repository.Entry.prototype.fulfillsInterest = function Repository_Entry_fulfillsInterest(interest){ return (!!this.prefix && interest.matchesName(this.prefix)); }; Repository.prototype.createNode = function Repository_createNode(data, repository){ var self = this; return new Promise(function Repository_createNode_Promise(resolve,reject){ var entry = new Repository.Entry(data, repository) entry._repository = self; if (!data.content){ // this is a dataShim from populateContentStoreNodes, name should if (data.name.get(-1).toEscapedString().substr(0, 12) !== "sha256digest") // already have a digest, but check anyway... reject(new Error("new Repository.Entry(data, contentStore) : no content to digest or digest component on name" + data.name.toUri())) resolve(new NameTree.Node(data.name, entry)); } else { // we're actually inserting new data var packet = data.wireEncode().buffer , nameWithDigest = Repository_getNameWithDigest(data.name, packet); entry._repository ._dataDB .put(nameWithDigest.toUri(), data.wireEncode().buffer, function(err){ if (err) reject(err); else{ entry.prefix = nameWithDigest; resolve(new NameTree.Node(entry.prefix, entry)); } }); } }) }; Repository.prototype.insert = function Repository_insert(data){ return this._contentStore.insert(data, this); }; Repository.prototype.remove = function Repository_remove(entry){ var self = this; return new Promise(function Repository_remove_Promise(resolve,reject){ self._contentStore.nameTree.remove(entry.prefix); entry.delete() .then(resolve) .catch(reject); }); }; Repository.prototype.lookup = function Repository_lookup(interest){ return this._contentStore.lookup(interest); }; Repository.prototype.populateContentStoreNodes = function Repository_populateContentStoreNodes(){ var self = this; return new Promise(function Repository_populateContentStoreNodes_Promise(resolve,reject){ var proms = []; self._dataDB .createKeyStream() .on("data",function(key){ proms.push(self.createNode({name:new Name(key)}, self) .then(function(node){ return self._contentStore._nameTree.insert(node); })) }) .on("error", function(err){ reject(err); }) .on("close", function(){ }) .on("end", function(){ Promise.all(proms) .then(resolve) .catch(function(err){ self.close() .then(function(){ reject(err); }) }) }); }); }; Repository.prototype.close = function Repository_close(){ var self = this; return new Promise(function Repository_close_Promise(resolve,reject){ self._dataDB.close(function Repository_close_Promise_level(err){ if (err) return reject(err) resolve(self); }); }) }; Repository.prototype.destroy = function Repository_destroy(){ var self = this; return new Promise(function Repository_destroy_Promise(resolve,reject){ if (self._dataDB.isOpen()) return reject(new Error("Repository.destroy(): Repository must call Repository.close() prior to destruction")) leveldown.destroy(self._dataPath, function Repository_destroy_level(err){ if (!err) return resolve(); reject(err); }); }); }; module.exports = Repository;