@ -26,6 +26,7 @@ function Persistence (options) {
this . db = options . db ;
this . db = options . db ;
this . inMemoryOnly = this . db . inMemoryOnly ;
this . inMemoryOnly = this . db . inMemoryOnly ;
this . filename = this . db . filename ;
this . filename = this . db . filename ;
this . corruptAlertThreshold = options . corruptAlertThreshold !== undefined ? options . corruptAlertThreshold : 0.1 ;
if ( ! this . inMemoryOnly && this . filename ) {
if ( ! this . inMemoryOnly && this . filename ) {
if ( this . filename . charAt ( this . filename . length - 1 ) === '~' ) {
if ( this . filename . charAt ( this . filename . length - 1 ) === '~' ) {
@ -241,11 +242,12 @@ Persistence.prototype.treatRawData = function (rawData) {
, tdata = [ ]
, tdata = [ ]
, i
, i
, indexes = { }
, indexes = { }
, corruptItems = - 1 // Last line of every data file is usually blank so not really corrupt
;
;
for ( i = 0 ; i < data . length ; i += 1 ) {
for ( i = 0 ; i < data . length ; i += 1 ) {
var doc ;
var doc ;
try {
try {
doc = model . deserialize ( this . beforeDeserialization ( data [ i ] ) ) ;
doc = model . deserialize ( this . beforeDeserialization ( data [ i ] ) ) ;
if ( doc . _id ) {
if ( doc . _id ) {
@ -260,8 +262,14 @@ Persistence.prototype.treatRawData = function (rawData) {
delete indexes [ doc . $$indexRemoved ] ;
delete indexes [ doc . $$indexRemoved ] ;
}
}
} catch ( e ) {
} catch ( e ) {
corruptItems += 1 ;
}
}
}
}
// A bit lenient on corruption
if ( data . length > 0 && corruptItems / data . length > this . corruptAlertThreshold ) {
throw "More than 10% of the data file is corrupt, the wrong beforeDeserialization hook may be used. Cautiously refusing to start NeDB to prevent dataloss"
}
Object . keys ( dataById ) . forEach ( function ( k ) {
Object . keys ( dataById ) . forEach ( function ( k ) {
tdata . push ( dataById [ k ] ) ;
tdata . push ( dataById [ k ] ) ;
@ -320,10 +328,14 @@ Persistence.prototype.loadDatabase = function (cb) {
Persistence . ensureDirectoryExists ( path . dirname ( self . filename ) , function ( err ) {
Persistence . ensureDirectoryExists ( path . dirname ( self . filename ) , function ( err ) {
self . ensureDatafileIntegrity ( function ( exists ) {
self . ensureDatafileIntegrity ( function ( exists ) {
storage . readFile ( self . filename , 'utf8' , function ( err , rawData ) {
storage . readFile ( self . filename , 'utf8' , function ( err , rawData ) {
if ( err ) { return cb ( err ) ; }
if ( err ) { return cb ( err ) ; }
var treatedData = self . treatRawData ( rawData ) ;
try {
var treatedData = self . treatRawData ( rawData ) ;
} catch ( e ) {
return cb ( e ) ;
}
// Recreate all indexes in the datafile
// Recreate all indexes in the datafile
Object . keys ( treatedData . indexes ) . forEach ( function ( key ) {
Object . keys ( treatedData . indexes ) . forEach ( function ( key ) {
self . db . indexes [ key ] = new Index ( treatedData . indexes [ key ] ) ;
self . db . indexes [ key ] = new Index ( treatedData . indexes [ key ] ) ;