123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- "use strict";
- var BaseRollingFileStream = require('./BaseRollingFileStream')
- , debug = require('debug')('streamroller:RollingFileStream')
- , util = require('util')
- , path = require('path')
- , child_process = require('child_process')
- , fs = require('fs');
- module.exports = RollingFileStream;
- function RollingFileStream (filename, size, backups, options) {
- //if you don't specify a size, this will behave like a normal file stream
- this.size = size || Number.MAX_SAFE_INTEGER;
- this.backups = backups || 1;
- function throwErrorIfArgumentsAreNotValid() {
- if (!filename || size <= 0) {
- throw new Error("You must specify a filename and file size");
- }
- }
- throwErrorIfArgumentsAreNotValid();
- RollingFileStream.super_.call(this, filename, options);
- }
- util.inherits(RollingFileStream, BaseRollingFileStream);
- RollingFileStream.prototype.shouldRoll = function() {
- debug("should roll with current size ", this.currentSize, " and max size ", this.size);
- return this.currentSize >= this.size;
- };
- RollingFileStream.prototype.roll = function(filename, callback) {
- var that = this;
- var fileNameObj = path.parse(filename);
- var dir = fileNameObj.dir;
- var name = fileNameObj.name;
- var ext = fileNameObj.ext === '' ? '' : fileNameObj.ext.substring(1);
- var nameMatcher = new RegExp('^' + name);
- function justTheseFiles (item) {
- return nameMatcher.test(item);
- }
- function getExtensions(filename_) {
- return filename_.substring((name + '.').length).split('.');
- }
- function index(filename_) {
- debug('Calculating index of '+filename_);
- var exts = getExtensions(filename_);
- if (exts[exts.length - 1] === 'gz') {
- exts.pop();
- }
- if (that.options.keepFileExt) {
- return parseInt(exts[0], 10) || 0;
- } else {
- return parseInt(exts[exts.length - 1]) || 0;
- }
- }
- function byIndex(a, b) {
- if (index(a) > index(b)) {
- return 1;
- } else if (index(a) < index(b) ) {
- return -1;
- } else {
- return 0;
- }
- }
- function increaseFileIndex (fileToRename, cb) {
- var idx = index(fileToRename);
- debug('Index of ' + fileToRename + ' is ' + idx);
- if (idx < that.backups) {
- var newIdx = (idx + 1).toString();
- var fileNameItems = [name];
- if (ext) {
- if (that.options.keepFileExt) {
- fileNameItems.push(newIdx, ext);
- } else {
- fileNameItems.push(ext, newIdx);
- }
- } else {
- fileNameItems.push(newIdx);
- }
- var destination = path.join(dir, fileNameItems.join('.'));
- if (that.options.compress && path.extname(fileToRename) === '.gz') {
- destination += '.gz';
- }
- //on windows, you can get a EEXIST error if you rename a file to an existing file
- //so, we'll try to delete the file we're renaming to first
- fs.unlink(destination, function (err) {
- //ignore err: if we could not delete, it's most likely that it doesn't exist
- debug('Renaming ' + fileToRename + ' -> ' + destination);
- fs.rename(path.join(dir, fileToRename), destination, function(err) {
- if (err) {
- cb(err);
- } else {
- if (that.options.compress && path.extname(fileToRename) !== '.gz') {
- that.compress(destination, cb);
- } else {
- cb();
- }
- }
- });
- });
- } else {
- cb();
- }
- }
- function renameTheFiles(cb) {
- //roll the backups (rename file.n to file.n+1, where n <= numBackups)
- debug("Renaming the old files");
- fs.readdir(path.dirname(filename), function (err, files) {
- if (err) {
- return cb(err);
- }
- var filesToProcess = files.filter(justTheseFiles).sort(byIndex);
- (function processOne(err) {
- var file = filesToProcess.pop();
- if (!file || err) { return cb(err); }
- increaseFileIndex(file, processOne);
- })();
- });
- }
- debug("Rolling, rolling, rolling");
- this.closeTheStream(
- renameTheFiles.bind(null,
- this.openTheStream.bind(this,
- callback)));
- };
|