utils.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. var os = require('os');
  2. var util = require('util');
  3. var exec = require('child_process').exec;
  4. var logger = require('pomelo-logger').getLogger('pomelo', __filename);
  5. var Constants = require('./constants');
  6. var pomelo = require('../pomelo');
  7. var utils = module.exports;
  8. /**
  9. * Invoke callback with check
  10. */
  11. utils.invokeCallback = function(cb) {
  12. if ( !! cb && typeof cb === 'function') {
  13. cb.apply(null, Array.prototype.slice.call(arguments, 1));
  14. }
  15. };
  16. /**
  17. * Get the count of elements of object
  18. */
  19. utils.size = function(obj) {
  20. var count = 0;
  21. for (var i in obj) {
  22. if (obj.hasOwnProperty(i) && typeof obj[i] !== 'function') {
  23. count++;
  24. }
  25. }
  26. return count;
  27. };
  28. /**
  29. * Check a string whether ends with another string
  30. */
  31. utils.endsWith = function(str, suffix) {
  32. if (typeof str !== 'string' || typeof suffix !== 'string' ||
  33. suffix.length > str.length) {
  34. return false;
  35. }
  36. return str.indexOf(suffix, str.length - suffix.length) !== -1;
  37. };
  38. /**
  39. * Check a string whether starts with another string
  40. */
  41. utils.startsWith = function(str, prefix) {
  42. if (typeof str !== 'string' || typeof prefix !== 'string' ||
  43. prefix.length > str.length) {
  44. return false;
  45. }
  46. return str.indexOf(prefix) === 0;
  47. };
  48. /**
  49. * Compare the two arrays and return the difference.
  50. */
  51. utils.arrayDiff = function(array1, array2) {
  52. var o = {};
  53. for(var i = 0, len = array2.length; i < len; i++) {
  54. o[array2[i]] = true;
  55. }
  56. var result = [];
  57. for(i = 0, len = array1.length; i < len; i++) {
  58. var v = array1[i];
  59. if(o[v]) continue;
  60. result.push(v);
  61. }
  62. return result;
  63. };
  64. /*
  65. * Date format
  66. */
  67. utils.format = function(date, format) {
  68. format = format || 'MMddhhmm';
  69. var o = {
  70. "M+": date.getMonth() + 1, //month
  71. "d+": date.getDate(), //day
  72. "h+": date.getHours(), //hour
  73. "m+": date.getMinutes(), //minute
  74. "s+": date.getSeconds(), //second
  75. "q+": Math.floor((date.getMonth() + 3) / 3), //quarter
  76. "S": date.getMilliseconds() //millisecond
  77. };
  78. if (/(y+)/.test(format)) {
  79. format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  80. }
  81. for (var k in o) {
  82. if (new RegExp("(" + k + ")").test(format)) {
  83. format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] :
  84. ("00" + o[k]).substr(("" + o[k]).length));
  85. }
  86. }
  87. return format;
  88. };
  89. /**
  90. * check if has Chinese characters.
  91. */
  92. utils.hasChineseChar = function(str) {
  93. if (/.*[\u4e00-\u9fa5]+.*$/.test(str)) {
  94. return true;
  95. } else {
  96. return false;
  97. }
  98. };
  99. /**
  100. * transform unicode to utf8
  101. */
  102. utils.unicodeToUtf8 = function(str) {
  103. var i, len, ch;
  104. var utf8Str = "";
  105. len = str.length;
  106. for (i = 0; i < len; i++) {
  107. ch = str.charCodeAt(i);
  108. if ((ch >= 0x0) && (ch <= 0x7F)) {
  109. utf8Str += str.charAt(i);
  110. } else if ((ch >= 0x80) && (ch <= 0x7FF)) {
  111. utf8Str += String.fromCharCode(0xc0 | ((ch >> 6) & 0x1F));
  112. utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
  113. } else if ((ch >= 0x800) && (ch <= 0xFFFF)) {
  114. utf8Str += String.fromCharCode(0xe0 | ((ch >> 12) & 0xF));
  115. utf8Str += String.fromCharCode(0x80 | ((ch >> 6) & 0x3F));
  116. utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
  117. } else if ((ch >= 0x10000) && (ch <= 0x1FFFFF)) {
  118. utf8Str += String.fromCharCode(0xF0 | ((ch >> 18) & 0x7));
  119. utf8Str += String.fromCharCode(0x80 | ((ch >> 12) & 0x3F));
  120. utf8Str += String.fromCharCode(0x80 | ((ch >> 6) & 0x3F));
  121. utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
  122. } else if ((ch >= 0x200000) && (ch <= 0x3FFFFFF)) {
  123. utf8Str += String.fromCharCode(0xF8 | ((ch >> 24) & 0x3));
  124. utf8Str += String.fromCharCode(0x80 | ((ch >> 18) & 0x3F));
  125. utf8Str += String.fromCharCode(0x80 | ((ch >> 12) & 0x3F));
  126. utf8Str += String.fromCharCode(0x80 | ((ch >> 6) & 0x3F));
  127. utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
  128. } else if ((ch >= 0x4000000) && (ch <= 0x7FFFFFFF)) {
  129. utf8Str += String.fromCharCode(0xFC | ((ch >> 30) & 0x1));
  130. utf8Str += String.fromCharCode(0x80 | ((ch >> 24) & 0x3F));
  131. utf8Str += String.fromCharCode(0x80 | ((ch >> 18) & 0x3F));
  132. utf8Str += String.fromCharCode(0x80 | ((ch >> 12) & 0x3F));
  133. utf8Str += String.fromCharCode(0x80 | ((ch >> 6) & 0x3F));
  134. utf8Str += String.fromCharCode(0x80 | (ch & 0x3F));
  135. }
  136. }
  137. return utf8Str;
  138. };
  139. /**
  140. * Ping server to check if network is available
  141. *
  142. */
  143. utils.ping = function(host, cb) {
  144. if(!module.exports.isLocal(host)) {
  145. var cmd = 'ping -w 15 ' + host;
  146. exec(cmd, function(err, stdout, stderr) {
  147. if(!!err) {
  148. cb(false);
  149. return;
  150. }
  151. cb(true);
  152. });
  153. } else {
  154. cb(true);
  155. }
  156. };
  157. /**
  158. * Check if server is exsit.
  159. *
  160. */
  161. utils.checkPort = function(server, cb) {
  162. if (!server.port && !server.clientPort) {
  163. this.invokeCallback(cb, 'leisure');
  164. return;
  165. }
  166. var self = this;
  167. var port = server.port || server.clientPort;
  168. var host = server.host;
  169. var generateCommand = function(self, host, port) {
  170. var cmd;
  171. var ssh_params = pomelo.app.get(Constants.RESERVED.SSH_CONFIG_PARAMS);
  172. if(!!ssh_params && Array.isArray(ssh_params)) {
  173. ssh_params = ssh_params.join(' ');
  174. }
  175. else {
  176. ssh_params = "";
  177. }
  178. if (!self.isLocal(host)) {
  179. cmd = util.format('ssh %s %s "netstat -an|awk \'{print $4}\'|grep %s|wc -l"', host, ssh_params, port);
  180. } else {
  181. cmd = util.format('netstat -an|awk \'{print $4}\'|grep %s|wc -l', port);
  182. }
  183. return cmd;
  184. };
  185. var cmd1 = generateCommand(self, host, port);
  186. var child = exec(cmd1, function(err, stdout, stderr) {
  187. if(err) {
  188. logger.error('command %s execute with error: %j', cmd1, err.stack);
  189. self.invokeCallback(cb, 'error');
  190. } else if(stdout.trim() !== '0') {
  191. self.invokeCallback(cb, 'busy');
  192. } else {
  193. port = server.clientPort;
  194. var cmd2 = generateCommand(self, host, port);
  195. exec(cmd2, function(err, stdout, stderr) {
  196. if(err) {
  197. logger.error('command %s execute with error: %j', cmd2, err.stack);
  198. self.invokeCallback(cb, 'error');
  199. } else if (stdout.trim() !== '0') {
  200. self.invokeCallback(cb, 'busy');
  201. } else {
  202. self.invokeCallback(cb, 'leisure');
  203. }
  204. });
  205. }
  206. });
  207. };
  208. utils.isLocal = function(host) {
  209. var app = require('../pomelo').app;
  210. if(!app) {
  211. return host === '127.0.0.1' || host === 'localhost' || inLocal(host);
  212. } else {
  213. return host === '127.0.0.1' || host === 'localhost' || inLocal(host) || host === app.master.host;
  214. }
  215. };
  216. /**
  217. * Load cluster server.
  218. *
  219. */
  220. utils.loadCluster = function(app, server, serverMap) {
  221. var increaseFields = {};
  222. var host = server.host;
  223. var count = parseInt(server[Constants.RESERVED.CLUSTER_COUNT]);
  224. var seq = app.clusterSeq[server.serverType];
  225. if(!seq) {
  226. seq = 0;
  227. app.clusterSeq[server.serverType] = count;
  228. } else {
  229. app.clusterSeq[server.serverType] = seq + count;
  230. }
  231. for(var key in server) {
  232. var value = server[key].toString();
  233. if(value.indexOf(Constants.RESERVED.CLUSTER_SIGNAL) > 0) {
  234. var base = server[key].slice(0, -2);
  235. increaseFields[key] = base;
  236. }
  237. }
  238. var clone = function(src) {
  239. var rs = {};
  240. for(var key in src) {
  241. rs[key] = src[key];
  242. }
  243. return rs;
  244. };
  245. for(var i=0, l=seq; i<count; i++,l++) {
  246. var cserver = clone(server);
  247. cserver.id = Constants.RESERVED.CLUSTER_PREFIX + server.serverType + '-' + l;
  248. for(var k in increaseFields) {
  249. var v = parseInt(increaseFields[k]);
  250. cserver[k] = v + i;
  251. }
  252. serverMap[cserver.id] = cserver;
  253. }
  254. };
  255. utils.extends = function(origin, add) {
  256. if (!add || !isObject(add)) return origin;
  257. var keys = Object.keys(add);
  258. var i = keys.length;
  259. while (i--) {
  260. origin[keys[i]] = add[keys[i]];
  261. }
  262. return origin;
  263. };
  264. utils.headHandler = function(headBuffer) {
  265. var len = 0;
  266. for(var i=1; i<4; i++) {
  267. if(i > 1) {
  268. len <<= 8;
  269. }
  270. len += headBuffer.readUInt8(i);
  271. }
  272. return len;
  273. };
  274. var inLocal = function(host) {
  275. for (var index in localIps) {
  276. if (host === localIps[index]) {
  277. return true;
  278. }
  279. }
  280. return false;
  281. };
  282. var localIps = function() {
  283. var ifaces = os.networkInterfaces();
  284. var ips = [];
  285. var func = function(details) {
  286. if (details.family === 'IPv4') {
  287. ips.push(details.address);
  288. }
  289. };
  290. for (var dev in ifaces) {
  291. ifaces[dev].forEach(func);
  292. }
  293. return ips;
  294. }();
  295. var isObject = function(arg) {
  296. return typeof arg === 'object' && arg !== null;
  297. };