pomelo-upgrade
Version:
401 lines (375 loc) • 9.93 kB
JavaScript
;
const os = require('os');
const exec = require('child_process').exec;
const logger = require('pomelo-logger-upgrade').getLogger('pomelo', __filename);
const Constants = require('./constants');
const pomelo = require('../pomelo');
const utils = module.exports;
/**
* Invoke callback with check
*/
utils.invokeCallback = function(cb, ...args)
{
if (typeof cb === 'function')
{
cb(...args);
}
};
/**
* Get the count of elements of object
*/
utils.size = function(obj)
{
let count = 0;
for (const i in obj)
{
if (obj.hasOwnProperty(i) && typeof obj[i] !== 'function')
{
count++;
}
}
return count;
};
/**
* Check a string whether ends with another string
*/
utils.endsWith = function(str, suffix)
{
if (typeof str !== 'string' || typeof suffix !== 'string' || suffix.length > str.length)
{
return false;
}
return str.endsWith(suffix);
};
/**
* Check a string whether starts with another string
*/
utils.startsWith = function(str, prefix)
{
if (typeof str !== 'string' || typeof prefix !== 'string' || prefix.length > str.length)
{
return false;
}
return str.startsWith(prefix);
};
/**
* Compare the two arrays and return the difference.
*/
utils.arrayDiff = function(array1, array2)
{
const o = {};
for (let i = 0, len = array2.length; i < len; i++)
{
o[array2[i]] = true;
}
const result = [];
for (let i = 0, len = array1.length; i < len; i++)
{
const v = array1[i];
if (o[v]) continue;
result.push(v);
}
return result;
};
/*
* Date format
*/
utils.format = function(date, format)
{
format = format || 'MMddhhmm';
const o = {
'M+' : date.getMonth() + 1, // month
'd+' : date.getDate(), // day
'h+' : date.getHours(), // hour
'm+' : date.getMinutes(), // minute
's+' : date.getSeconds(), // second
'q+' : Math.floor((date.getMonth() + 3) / 3), // quarter
'S' : date.getMilliseconds() // millisecond
};
if (/(y+)/.test(format))
{
format = format.replace(RegExp.$1, (`${date.getFullYear()}`).substr(4 - RegExp.$1.length));
}
for (const k in o)
{
if (new RegExp(`(${k})`).test(format))
{
format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] :
(`00${o[k]}`).substr((`${o[k]}`).length));
}
}
return format;
};
/**
* check if has Chinese characters.
*/
utils.hasChineseChar = function(str)
{
return /.*[\u4e00-\u9fa5]+.*$/.test(str);
};
/**
* transform unicode to utf8
*/
utils.unicodeToUtf8 = function(str)
{
let i, ch;
let utf8Str = '';
const len = str.length;
for (i = 0; i < len; i++)
{
ch = str.charCodeAt(i);
if ((ch >= 0x0) && (ch <= 0x7F))
{
utf8Str += str.charAt(i);
}
else if ((ch >= 0x80) && (ch <= 0x7FF))
{
utf8Str += String.fromCharCode(0xc0 | ((ch >> 6) & 0x1F));
utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
}
else if ((ch >= 0x800) && (ch <= 0xFFFF))
{
utf8Str += String.fromCharCode(0xe0 | ((ch >> 12) & 0xF));
utf8Str += String.fromCharCode(0x80 | ((ch >> 6) & 0x3F));
utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
}
else if ((ch >= 0x10000) && (ch <= 0x1FFFFF))
{
utf8Str += String.fromCharCode(0xF0 | ((ch >> 18) & 0x7));
utf8Str += String.fromCharCode(0x80 | ((ch >> 12) & 0x3F));
utf8Str += String.fromCharCode(0x80 | ((ch >> 6) & 0x3F));
utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
}
else if ((ch >= 0x200000) && (ch <= 0x3FFFFFF))
{
utf8Str += String.fromCharCode(0xF8 | ((ch >> 24) & 0x3));
utf8Str += String.fromCharCode(0x80 | ((ch >> 18) & 0x3F));
utf8Str += String.fromCharCode(0x80 | ((ch >> 12) & 0x3F));
utf8Str += String.fromCharCode(0x80 | ((ch >> 6) & 0x3F));
utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
}
else if ((ch >= 0x4000000) && (ch <= 0x7FFFFFFF))
{
utf8Str += String.fromCharCode(0xFC | ((ch >> 30) & 0x1));
utf8Str += String.fromCharCode(0x80 | ((ch >> 24) & 0x3F));
utf8Str += String.fromCharCode(0x80 | ((ch >> 18) & 0x3F));
utf8Str += String.fromCharCode(0x80 | ((ch >> 12) & 0x3F));
utf8Str += String.fromCharCode(0x80 | ((ch >> 6) & 0x3F));
utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
}
}
return utf8Str;
};
/**
* Ping server to check if network is available
*
*/
utils.ping = function(host, cb)
{
if (!module.exports.isLocal(host))
{
const cmd = `ping -w 15 ${host}`;
exec(cmd, function(err)
{
if (err)
{
cb(false);
return;
}
cb(true);
});
}
else
{
cb(true);
}
};
/**
* Check if server is exit.
* 检测端口状态
*/
utils.checkPort = function(server, cb)
{
if (!server.port && !server.clientPort)
{
this.invokeCallback(cb, 'leisure');
return;
}
let port = server.port || server.clientPort;
const host = server.host;
const generateCommand = function(host, port)
{
let cmd;
let ssh_params = undefined;
if (pomelo.app)
ssh_params = pomelo.app.get(Constants.RESERVED.SSH_CONFIG_PARAMS);
if (Array.isArray(ssh_params))
{
ssh_params = ssh_params.join(' ');
}
else
{
ssh_params = '';
}
if (!utils.isLocal(host))
{
cmd = `ssh ${host} ${ssh_params} "netstat -an|awk '{print $4}'|grep ${port}|wc -l"`;
}
else
{
cmd = `netstat -an|awk '{print $4}'|grep ${port}|wc -l`;
}
return cmd;
};
const cmd1 = generateCommand(host, port);
exec(cmd1, function(err, stdout)
{
if (err)
{
logger.error('command %s execute with error: %j', cmd1, err.stack);
utils.invokeCallback(cb, 'error');
}
else if (stdout.trim() !== '0')
{
utils.invokeCallback(cb, 'busy');
}
else
{
port = server.clientPort;
if (port)
{
const cmd2 = generateCommand(host, port);
exec(cmd2, function(err, stdout)
{
if (err)
{
logger.error('command %s execute with error: %j', cmd2, err.stack);
utils.invokeCallback(cb, 'error');
}
else if (stdout.trim() !== '0')
{
utils.invokeCallback(cb, 'busy');
}
else
{
utils.invokeCallback(cb, 'leisure');
}
});
}
else
{
utils.invokeCallback(cb, 'leisure');
}
}
});
};
utils.isLocal = function(host)
{
const app = require('../pomelo').app;
if (!app)
{
return host === '127.0.0.1' || host === 'localhost' || host === '0.0.0.0' || inLocal(host);
}
return host === '127.0.0.1' || host === 'localhost' || host === '0.0.0.0' || inLocal(host) || host === app.master.host;
};
/**
* Load cluster server.
*
*/
utils.loadCluster = function(app, server, serverMap)
{
const increaseFields = {};
// const host = server.host;
const count = parseInt(server[Constants.RESERVED.CLUSTER_COUNT]);
let seq = app.clusterSeq[server.serverType];
if (!seq)
{
seq = 0;
app.clusterSeq[server.serverType] = count;
}
else
{
app.clusterSeq[server.serverType] = seq + count;
}
for (const key in server)
{
if (server.hasOwnProperty(key))
{
const value = server[key].toString();
if (value.indexOf(Constants.RESERVED.CLUSTER_SIGNAL) > 0)
{
increaseFields[key] = value.slice(0, -2);
}
}
}
const clone = function(src)
{
const rs = {};
for (const key in src)
{
rs[key] = src[key];
}
return rs;
};
for (let i = 0, l = seq; i < count; i++, l++)
{
const cserver = clone(server);
cserver.id = `${Constants.RESERVED.CLUSTER_PREFIX + server.serverType}-${l}`;
for (const k in increaseFields)
{
const v = parseInt(increaseFields[k]);
cserver[k] = v + i;
}
serverMap[cserver.id] = cserver;
}
};
utils.extends = function(origin, add)
{
if (!add || !utils.isObject(add)) return origin;
return Object.assign(origin, add);
};
utils.headHandler = function(headBuffer)
{
let len = 0;
for (let i = 1; i < 4; i++)
{
if (i > 1)
{
len <<= 8;
}
len += headBuffer.readUInt8(i);
}
return len;
};
const inLocal = function(host)
{
for (const index in localIps)
{
if (host === localIps[index])
{
return true;
}
}
return false;
};
const localIps = function()
{
const faces = os.networkInterfaces();
const ips = [];
const func = function(details)
{
if (details.family === 'IPv4')
{
ips.push(details.address);
}
};
for (const dev in faces)
{
faces[dev].forEach(func);
}
return ips;
}();
utils.isObject = function(arg)
{
return typeof arg === 'object' && arg !== null;
};