@ -50,15 +50,25 @@ storage.flushToStorage = (options, callback) => {
flags = options . isDir ? 'r' : 'r+'
flags = options . isDir ? 'r' : 'r+'
}
}
// Windows can't fsync (FlushFileBuffers) directories. We can live with this as it cannot cause 100% dataloss
/ * *
// except in the very rare event of the first time database is loaded and a crash happens
* Some OSes and / or storage backends ( augmented node fs ) do not support fsync ( FlushFileBuffers ) directories ,
if ( flags === 'r' && ( process . platform === 'win32' || process . platform === 'win64' ) ) return callback ( null )
* or calling open ( ) on directories at all . Flushing fails silently in this case , supported by following heuristics :
* + isDir === true
* | -- open ( < dir > ) - > ( err . code === 'EISDIR' ) : can ' t call open ( ) on directories ( eg . BrowserFS )
* ` -- fsync(<dir>) -> (errFS.code === 'EPERM' || errFS.code === 'EISDIR'): can't fsync directory: permissions are checked
* on open ( ) ; EPERM error should only occur on fsync incapability and not for general lack of permissions ( e . g . Windows )
*
* We can live with this as it cannot cause 100 % dataloss except in the very rare event of the first time
* database is loaded and a crash happens .
* /
fs . open ( filename , flags , ( err , fd ) => {
fs . open ( filename , flags , ( err , fd ) => {
if ( err ) return callback ( err )
if ( err ) {
return callback ( ( err . code === 'EISDIR' && options . isDir ) ? null : err )
}
fs . fsync ( fd , errFS => {
fs . fsync ( fd , errFS => {
fs . close ( fd , errC => {
fs . close ( fd , errC => {
if ( errFS || errC ) {
if ( ( errFS || errC ) && ! ( ( errFS . code === 'EPERM' || errFS . code === 'EISDIR' ) && options . isDir ) ) {
const e = new Error ( 'Failed to flush to storage' )
const e = new Error ( 'Failed to flush to storage' )
e . errorOnFsync = errFS
e . errorOnFsync = errFS
e . errorOnClose = errC
e . errorOnClose = errC