Hi by view the error at FileStorage.js in swarm at line 122 I knew that this library using rename method missing callback function.
So my solution is to replace that file with content call rename with callback function with following steps:
Step 1. create the js file with name modified_FileStorage.js the same folder with Dockerfile with content:
"use strict";
var fs = require('fs');
var path = require('path');
var env = require('./env');
var Spec = require('./Spec');
var Storage = require('./Storage');
/**
* An improvised filesystem-based storage implementation.
* Objects are saved into separate files in a hashed directory
* tree. Ongoing operations are streamed into a log file.
* One can go surprisingly far with this kind of an approach.
* https://news.ycombinator.com/item?id=7872239 */
function FileStorage (dir) {
Storage.call(this);
this._host = null; //will be set during Host creation
this.dir = path.resolve(dir);
if (!fs.existsSync(this.dir)) {
fs.mkdirSync(this.dir);
}
this._id = 'file';
this.tail = {};
this.loadLog();
this.rotateLog();
}
FileStorage.prototype = new Storage();
module.exports = FileStorage;
FileStorage.prototype.stateFileName = function (spec) {
var base = path.resolve(this.dir, spec.type());
var file = path.resolve(base, spec.id());
return file; // TODO hashing?
};
FileStorage.prototype.logFileName = function () {
return path.resolve(this.dir, "_log");
};
FileStorage.prototype.writeState = function (spec, state, cb) {
var self = this;
var ti = spec.filter('/#');
var fileName = this.stateFileName(ti);
var dir = path.dirname(fileName);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
var save = JSON.stringify(state, undefined, 2);
// dump JSON to the tmp file
delete self.tails[ti]; // TODO save 'em in case write fails
fs.writeFile(fileName, save, function onSave(err) {
if (err) {
console.error("failed to flush state; can't trim the log", err);
}
cb(err);
});
};
FileStorage.prototype.writeOp = function (spec, value, cb) {
var self = this;
var ti = spec.filter('/#');
var vm = spec.filter('!.');
var tail = this.tails[ti] || (this.tails[ti] = {});
if (vm in tail) {
console.error('op replay @storage',vm,new Error().stack);
return;
}
var clone = JSON.parse(JSON.stringify(value)); // FIXME performance please
tail[vm] = clone;
var record = ',\n"'+spec+'":\t'+JSON.stringify(clone);
this.logFile.write (record, function onFail(err) {
if (err) { self.close(null,err); }
cb(err);
});
};
FileStorage.prototype.readState = function (ti, callback) {
var statefn = this.stateFileName(ti);
// read in the state
fs.readFile(statefn, function onRead(err, data) { // FIXME fascism
var state = err ? {_version: '!0'} : JSON.parse(data.toString());
callback(null,state||null); // important: no state is "null"
});
};
FileStorage.prototype.readOps = function (ti, callback) {
var tail = this.tails[ti];
if (tail) {
var unjsoned = {};
for(var key in tail) {
unjsoned[key] = tail[key];
}
tail = unjsoned;
}
callback(null, tail||null);
};
FileStorage.prototype.close = function (callback,error) {
if (error) {
console.log("fatal IO error", error);
}
if (this.logFile) {
this.rotateLog(true, callback);
} else {
callback();
}
};
FileStorage.prototype.rotateLog = function (noOpen, callback) {
var self = this;
if (this.logFile) {
this.logFile.end('}', callback);
this.logFile = null;
callback = undefined;
}
if (!noOpen) {
var the_log_file = this.logFileName();
if (fs.existsSync(the_log_file)) {
fs.rename(the_log_file, the_log_file+'.bak', function() {
console.log("rename logfile " + the_log_file + " done");
});
}
this.logFile = fs.createWriteStream(this.logFileName()); // TODO file swap
this.logFile.on('error', function (err) {
self.close(null,err);
});
var json = JSON.stringify(this.tails, undefined, 2);
json = '{"":\n' + json; // open-ended JSON
this.logFile.write (json, function onFail(err) {
if (err) { self.close(null,err); }
});
}
if (callback) {
callback();
}
};
FileStorage.prototype.loadLog = function () {
if ( !fs.existsSync(this.logFileName()) ) {
return;
}
var json = fs.readFileSync(this.logFileName(), {encoding:"utf8"});
if (!json) { return; }
var log;
try {
log = JSON.parse(json);
} catch (ex) {
// open-ended JSON
log = JSON.parse(json + '}');
}
this.tails = log[''];
delete log[''];
for(var s in log) {
var spec = new Spec(s);
if (spec.pattern()==='/#!.') {
var ti = spec.filter('/#');
var vm = spec.filter('!.');
var tail = this.tails[ti] || (this.tails[ti] = {});
tail[vm] = log[spec];
}
}
};
(this file was modified with the copy from https://raw.githubusercontent.com/gritzko/swarm/0.3/lib/FileStorage.js)
Step 2: add the line to copy the modified file in Dockerfile like this:
FROM node
.....
RUN npm install > /dev/null
COPY modified_FileStorage.js /todo/node_modules/swarm/lib/FileStorage.js
EXPOSE 8000
CMD ["npm", "start"]