var fs = require('fs'); var async = require('async'); var path = require('path'); var _DEBUG = false; function NumberedFileOps(logpath, totalFiles, totalSize, gzip) { function getNumberedFile(n, zipped) { var parsed = path.parse(logpath); var result = ''; if (n === 0) { result = parsed.name .replace('.%N', '') .replace('_%N', '') .replace('-%N', '') .replace('%N', '') + parsed.ext; } else if (parsed.name.indexOf('%N') >= 0) { result = parsed.name.replace('%N', String(n)) + parsed.ext; } else { result = parsed.base + '.' + String(n); } if (zipped) { result += '.gz'; } return path.join(parsed.dir, result); } function recursiveFindFilesToDelete( currentFileNumber, cumulativeSize, foundFiles, next ) { var fileToFind = getNumberedFile(currentFileNumber, gzip); fs.stat(fileToFind, function (err, stat) { if (err && err.code === 'ENOENT') { next(null, foundFiles); } else if (err) { next(err); } else { cumulativeSize += stat.size; if ((totalSize > 0 && cumulativeSize > totalSize) || (totalFiles > 0 && currentFileNumber > totalFiles) ) { foundFiles.push(fileToFind); } recursiveFindFilesToDelete( currentFileNumber + 1, cumulativeSize, foundFiles, next ); } }); } function findFilesToDelete(next) { var foundFiles = []; recursiveFindFilesToDelete(1, 0, foundFiles, next); } function deleteFiles(next) { findFilesToDelete(function (err, foundFiles) { if (err) { next(err); } else { async.eachSeries( foundFiles, function (toDel, callback) { if (_DEBUG) console.log('rm %s', toDel); fs.unlink(toDel, ignoreFileNotFound(callback)); }, next ); } }); }; function ignoreFileNotFound(next) { return function (err) { if (!err || err.code === 'ENOENT') { next(); } else { next(err); } }; } function recursiveFindFilesToMove(currentFileNumber, foundFiles, next) { var fileToFind = getNumberedFile(currentFileNumber, gzip); fs.stat(fileToFind, function (err, stat) { if (err && err.code === 'ENOENT') { next(null, foundFiles); } else if (err) { next(err); } else { foundFiles.unshift(currentFileNumber); recursiveFindFilesToMove( currentFileNumber + 1, foundFiles, next ); } }); } function moveFile(numberToMove, next) { var before = getNumberedFile(numberToMove, gzip); var after = getNumberedFile(numberToMove+1, gzip); fs.rename(before, after, ignoreFileNotFound(next)); } function moveIntermediateFiles(next) { var toMove = []; recursiveFindFilesToMove(0, toMove, function (err) { if (err) { return next(err); } async.eachSeries( toMove, moveFile, next ); }); }; function getStreamFilepath(gzipped) { return getNumberedFile(0, gzipped); } function newStreamFilepath(triggerinfo, next) { var startNewFile = !triggerinfo.hasOwnProperty('startNewFile') || triggerinfo.startNewFile; if (startNewFile) { moveIntermediateFiles(function (err) { if (err) { return next(err); } next(null, getNumberedFile(0, false)); }); } else { next(null, getNumberedFile(0, false)); } } return { getStreamFilepath: getStreamFilepath, newStreamFilepath: newStreamFilepath, deleteFiles: deleteFiles, moveIntermediateFiles: moveIntermediateFiles }; } module.exports = NumberedFileOps;