mirror of
https://github.com/amark/gun.git
synced 2025-06-05 05:36:55 +00:00
thanks @rogowski book test read/memory/disk variations
This commit is contained in:
parent
9abebd7673
commit
0665787e2b
13
lib/book.js
13
lib/book.js
@ -28,6 +28,7 @@ var sT = setTimeout, B = sT.Book || (sT.Book = function(text){
|
||||
function page(word){
|
||||
var b = this, l = b.list, i = spot(B.encode(word), l), p = l[i];
|
||||
if('string' == typeof p){ l[i] = p = {size: -1, first: p, substring: sub, toString: to, book: b, get: b} } // TODO: test, how do we arrive at this condition again?
|
||||
p.i = i;
|
||||
return p;
|
||||
// TODO: BUG! What if we get the page, it turns out to be too big & split, we must then RE get the page!
|
||||
}
|
||||
@ -81,7 +82,7 @@ function set(word, is){
|
||||
page.sort = 1;
|
||||
b(word, is);
|
||||
page.size += size(word) + size(is);
|
||||
if(PAGE < page.size){ split(page, b) }
|
||||
if((b.PAGE || PAGE) < page.size){ split(page, b) }
|
||||
return b;
|
||||
}
|
||||
|
||||
@ -112,16 +113,16 @@ function size(t){ return (t||'').length||1 } // bits/numbers less size? Bug or f
|
||||
function subt(i,j){ return this.word }
|
||||
//function tot(){ return this.text = this.text || "'"+(this.word)+"'"+(this.is)+"'" }
|
||||
function tot(){ var tmp;
|
||||
if((tmp = this.page) && tmp.saving){ delete tmp.book.all[this.word]; }
|
||||
//if((tmp = this.page) && tmp.saving){ delete tmp.book.all[this.word]; } // TODO: BUG! Book can't know about RAD, this was from RAD, so this MIGHT be correct but we need to refactor. Make sure to add tests that will re-trigger this.
|
||||
return this.text = this.text || "'"+(this.word)+"'"+(this.is)+"'";
|
||||
}
|
||||
function sub(i,j){ return (this.first||this.word||(from(this)||'')[0]||'').substring(i,j) }
|
||||
function to(){ return this.text = this.text || text(this) }
|
||||
function join(){ return this.join('|') }
|
||||
function text(p){
|
||||
if(!p.list){ return (p.from||'')+'' }
|
||||
if(!p.from){ return '|'+((p.list && (p.list = p.list.sort()).join('|'))||'')+'|' }
|
||||
return '|'+/*from(p).concat(p.list)*/p.list.sort().join('|')+'|'; // commenting out this sub-portion of code fixed a more basic test, but will probably cause a bug with a FROM + MEMORY.
|
||||
if(!p.list){ return (typeof p.from == 'string')? (p.from||'')+'' : '|'+p.from+'|' }
|
||||
if(!p.from){ return '|'+((p.list && (p.list = p.list.sort()).join('|'))||'')+'|' }
|
||||
return '|'+from(p).concat(p.list).sort().join('|')+'|'; // commenting out this sub-portion of code fixed a more basic test, but will probably cause a bug with a FROM + MEMORY.
|
||||
}
|
||||
|
||||
B.encode = function(d, _){ _ = _ || "'";
|
||||
@ -144,4 +145,4 @@ B.hash = function(s, c){ // via SO
|
||||
}
|
||||
|
||||
try{module.exports=B}catch(e){}
|
||||
}());
|
||||
}());
|
@ -20,6 +20,7 @@
|
||||
//console.log("OFF");return;
|
||||
// ON WRITE:
|
||||
// batch until read from disk is done (and if a write was going, do that first)
|
||||
if(!valid(word, is, reply)){ return }
|
||||
b(word, is);
|
||||
write(word, reply);
|
||||
return r;
|
||||
@ -27,12 +28,34 @@
|
||||
|
||||
|
||||
async function read(word, reply, page){
|
||||
var p = page;//b.page(word);
|
||||
var p = page || b.page(word);
|
||||
reply = reply.call ? reply : () => { };
|
||||
log(`read() ${word.slice(0, 40)}`);
|
||||
get(p, function(err, disk){
|
||||
if(err){ log("ERR! in read() get() cb", err); reply(err); return }
|
||||
p.from = disk || p.from;
|
||||
if(!disk){
|
||||
// do something to show whatever we have in-memory is going to be the disk.
|
||||
}
|
||||
if(disk){
|
||||
disk = Book(p.from = disk);
|
||||
disk.PAGE = Infinity; // THIS BOOK IS ONLY TEMPORARY!
|
||||
(p.list||[]).forEach(function(has){
|
||||
disk(has.word, has.is);
|
||||
});
|
||||
// TODO: BUG! What happens if the merge causes too large of a page and it splits... WRITE TESTS TO HANDLE.
|
||||
disk = disk.list[0];
|
||||
disk.first = p.first = (disk.first < p.first? disk.first : p.first);
|
||||
/*disk.book = disk.get = b;
|
||||
disk.saving = p.saving;
|
||||
disk.i = p.i;
|
||||
p = b.list[p.i] = disk;*/
|
||||
p.from = disk.from;
|
||||
p.list = disk.list;
|
||||
p.size = disk.size;
|
||||
p.text = disk.text;
|
||||
} else {
|
||||
//p.from = disk || p.from; // TODO: NEED TO MERGE! AND HANDLE ERR!
|
||||
}
|
||||
//p.from = disk || p.from;
|
||||
reply(null, p, b);
|
||||
})
|
||||
}
|
||||
@ -42,13 +65,13 @@
|
||||
var p = b.page(word), tmp;
|
||||
if(tmp = p.saving){ reply && tmp.push(reply); return } p.saving = [reply];
|
||||
var S = +new Date; log(" writing", p.substring(), 'since last', S - p.saved, RAD.c, 'records', env.count++, 'mid-swap.');
|
||||
get(p, function(err, disk){
|
||||
read(p, function(err, disk){
|
||||
if(err){ log("ERR! in write() get() cb ", err); return }
|
||||
//log(' get() - p.saving ', (p.saving || []).length);
|
||||
if(p.from && disk){
|
||||
//log(" get() merge: p.from ", p.toString().slice(0, 40), " disk.length", disk?.length || 0);
|
||||
}
|
||||
p.from = disk || p.from; // TODO: NEED TO MERGE! AND HANDLE ERR!
|
||||
// CODE CUT OUT AND MOVED TO READ
|
||||
// var save = '' + p; if(!p.from){ p.from = save }
|
||||
// p.list = p.text = p.from = 0;
|
||||
// p.first = p.first.word || p.first;
|
||||
@ -59,7 +82,7 @@
|
||||
// log({ tmp });
|
||||
write(word, reply);
|
||||
});
|
||||
})
|
||||
}, p);
|
||||
}
|
||||
function put(file, data, cb){
|
||||
file.first && (file = Book.slot(file.first)[0]);
|
||||
@ -117,6 +140,11 @@
|
||||
function ename(t) { return encodeURIComponent(t).replace(/\*/g, '%2A').slice(0, 250) }
|
||||
function fname(p) { return opt.file + '/' + ename(p.substring()) }
|
||||
|
||||
function valid(word, is, reply){
|
||||
if(is !== is){ reply(word +" cannot be NaN!"); return }
|
||||
return true;
|
||||
}
|
||||
|
||||
return r;
|
||||
}), MAX = 1000/* 300000000 */;
|
||||
|
||||
|
@ -32,10 +32,10 @@ var names = ["Adalard","Adora","Aia","Albertina","Alfie","Allyn","Amabil","Ammam
|
||||
|
||||
var opt = {};
|
||||
opt.file = 'radatatest';
|
||||
var Radisk = (setTimeout.RAD) || require('../../lib/radisk');
|
||||
var RAD = (setTimeout.RAD) || require('../../lib/radisk');
|
||||
//opt.store = ((Gun.window && Gun.window.RindexedDB) || require('../../lib/rfs'))(opt);
|
||||
opt.chunk = 1000;
|
||||
var rad = Radisk(opt), esc = String.fromCharCode(27);
|
||||
var rad = RAD(opt), esc = String.fromCharCode(27);
|
||||
|
||||
describe('Book', function(){
|
||||
this.timeout(1000 * 9);
|
||||
@ -89,10 +89,10 @@ var names = ["Adalard","Adora","Aia","Albertina","Alfie","Allyn","Amabil","Ammam
|
||||
false,
|
||||
-Infinity,
|
||||
Infinity,
|
||||
NaN,
|
||||
-0
|
||||
];
|
||||
var prim = ['alice', 'bob'];
|
||||
//var prim = ['alice', 'bob'];
|
||||
//var prim = [null];
|
||||
root.rad = rad;
|
||||
|
||||
describe('can in-memory write & read all primitives', done => { prim.forEach(function(type){
|
||||
@ -106,11 +106,10 @@ var names = ["Adalard","Adora","Aia","Albertina","Alfie","Allyn","Amabil","Ammam
|
||||
});});
|
||||
|
||||
describe('can disk write & read all primitives', done => { prim.forEach(function(type){
|
||||
var r = rad;
|
||||
it('save '+type, done => { setTimeout(function(){
|
||||
r('type-'+type, type, function(err, ok){
|
||||
rad('type-'+type, type, function(err, ok){
|
||||
expect(err).to.not.be.ok();
|
||||
r('type-'+type, function(err, page){
|
||||
rad('type-'+type, function(err, page){
|
||||
var val = page.get('type-'+type);
|
||||
expect(val).to.be(type);
|
||||
done();
|
||||
@ -119,6 +118,81 @@ var names = ["Adalard","Adora","Aia","Albertina","Alfie","Allyn","Amabil","Ammam
|
||||
},1); });
|
||||
});});
|
||||
|
||||
describe('error on invalid primitives', function(){
|
||||
it('test invalid', done => {
|
||||
rad('type-NaN', NaN, function(err, ok){
|
||||
expect(err).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Async Race Conditions', function(){
|
||||
|
||||
it('make sure word does not get duplicated when data is re-saved after read', done => {
|
||||
var opt = {file: 'zadata'}
|
||||
var prev = RAD(opt);
|
||||
|
||||
prev('helloz', 'world', function(err, ok){
|
||||
|
||||
prev('helloz', function(err, page){
|
||||
prev('zalice', 'yay', function(err){
|
||||
expect(page.text.split('helloz').length).to.be(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
/*
|
||||
(A) READ ONLY: we receive a message, we READ only - parseless is important.
|
||||
(B) READ & WRITE: we write a page, and it already exists on disk.
|
||||
(C) WRITE ONLY: we write a page, and it is new to disk.
|
||||
*/
|
||||
});
|
||||
|
||||
it('test if adding an in-memory word merges with previously written disk data', done => {
|
||||
var prev = RAD(opt);
|
||||
|
||||
prev('pa-alice', 'hello', function(err, ok){
|
||||
expect(err).to.not.be.ok();
|
||||
|
||||
setTimeout(function(){
|
||||
var rad = RAD(opt);
|
||||
|
||||
rad('pa-bob', 'banana', function(err, ok){
|
||||
expect(err).to.not.be.ok();
|
||||
//console.log("COMPARE:", rad.book.list[0].text, 'vs', prev.book.list[0].text);
|
||||
var text = rad.book.list[0].text;
|
||||
var i = text.indexOf('pa-alice');
|
||||
expect(i).to.not.be(-1);
|
||||
var ii = text.indexOf('hello');
|
||||
expect((ii - i) < 10).to.be.ok();
|
||||
done();
|
||||
})
|
||||
},99);
|
||||
});
|
||||
});
|
||||
|
||||
it('test if updating an in-memory word merges with previously written disk data', done => {
|
||||
var prev = RAD(opt);
|
||||
prev('pu-alice', 'hello', function(err, ok){
|
||||
expect(err).to.not.be.ok();
|
||||
|
||||
var rad = RAD(opt);
|
||||
|
||||
rad('pu-alice', 'cool', function(err, ok){
|
||||
expect(err).to.not.be.ok();
|
||||
|
||||
var next = RAD(opt);
|
||||
next('pu-alice', function(err, page){
|
||||
expect('cool').to.be(page.get('pu-alice'));
|
||||
done();
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var ntmp = names;
|
||||
|
Loading…
x
Reference in New Issue
Block a user