ERROR: [2012-10-22 13:52:59.256] 4202 EE "i am a bad boy" NetBlackHole listened at "10241" NetBlackHole listened at "10241" Coverage

Coverage

94%
776
731
45

build.js

100%
72
72
0
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51var fs = require('fs'), path = require('path');
6
71exports.setmode = function(path, mode) {
83 exports.fileset(path, function(file) {
93 fs.chmodSync(file, mode);
10 });
11};
12
131exports.parseProperties = function (file) {
144 var data = {};
15
164 try {
174 fs.readFileSync(file, 'utf8').trim().split('\n').forEach(function(line) {
1840 if (/^(#|!)/.test(line)) {
198 return;
20 }
2132 var match = line.match(/^\s*(.+?)\s*=\s*(.*)\s*$/);
2232 if (!match) {
238 return;
24 }
25
2624 data[match[1].trim()] = match[2].trim();
27 });
28 } catch (e) {
29 }
30
314 return data;
32};
33
341exports.fileset = function(dir, callback) {
3518 if (!fs.statSync(dir).isDirectory()) {
366 callback(dir);
376 return;
38 }
39
4011 fs.readdirSync(dir).forEach(function(file) {
4161 var who = path.normalize(dir + '/' + file);
4261 if (fs.statSync(who).isDirectory()) {
438 exports.fileset(who, callback);
44 } else {
4553 callback(who);
46 }
47 });
48};
49
501exports.init = function(file, root, force) {
51
52 /**
53 * @根路径
54 */
555 var _dirroot = path.normalize(root ? root : __dirname + '/../');
56
575 var _fixpath = function(dir) {
5832 if ('/' != dir.charAt(0)) {
597 dir = path.normalize(_dirroot + '/' + dir);
60 }
61
6232 return dir;
63 };
64
65 /**
66 * @默认属性
67 */
685 var _defaults = file ? exports.parseProperties(_fixpath(file)) : {};
695 for (var i in force) {
703 _defaults[i] = force[i];
71 }
72
73 /**
74 * @任务
75 */
765 var _task = [];
77
785 var _me = {};
79
80 /* {{{ public function property() */
815 _me.property = function() {
822 return _defaults;
83 };
84 /* }}} */
85
86 /* {{{ public function $() */
875 _me.$ = function (key, _def) {
8812 return (undefined === _defaults[key]) ? _def : _defaults[key];
89 };
90 /* }}} */
91
92 /* {{{ public function makeconf() */
93 /**
94 * 通过模版生成配置文件
95 *
96 * @access public
97 * @return void
98 */
995 _me.makeconf = function (source, target, values) {
1003 values = values || {};
1013 source = path.normalize(source);
102
1033 try {
1043 var isdir = fs.statSync(target).isDirectory();
105 } catch (e) {
1062 var isdir = false;
107 }
108
1093 exports.fileset(source, function (fname) {
1108 var _text = fs.readFileSync(_fixpath(fname), 'utf-8');
1118 var match = _text.match(/##(.+?)##/g);
1128 if (match) {
1135 match.forEach(function(item) {
11414 var i = item.slice(2, item.length - 2);
11514 if (undefined !== values[i]) {
1164 _text = _text.replace(item, values[i]);
117 } else {
11810 var v = _me.$(i);
11910 if (undefined !== v) {
1202 _text = _text.replace(item, v);
121 }
122 }
123 });
124 }
125
1268 var _save = '';
1278 if (!isdir && '/' !== target.charAt(target.length - 1)) {
1282 _save = _fixpath(target);
129 } else {
1306 _save = _fixpath(target + '/' + fname.replace(source, ''));
131 }
1328 _me.makedir(path.dirname(_save));
1338 fs.writeFileSync(_save, _text, 'utf-8');
134 });
135 };
136 /* }}} */
137
138 /* {{{ public function makedir() */
1395 _me.makedir = function(dir, mode) {
14012 dir = _fixpath(dir);
14112 if (!path.existsSync(dir)) {
1421 var p = path.dirname(dir);
1431 if (p && p != dir) {
1441 _me.makedir(p);
145 }
1461 fs.mkdirSync(dir, mode || 493/** 0755 */);
147 }
14812 return _me;
149 };
150 /* }}} */
151
1525 return _me;
153
154};
155

factory.js

86%
50
43
7
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31var Config = require(__dirname + '/config.js');
41var Log = require(__dirname + '/log.js');
51var Extend = require(__dirname + '/extend.js');
61var Mysql = require(__dirname + '/mysql.js');
7
8/**
9 * @存放对象的对象列表
10 */
111var __objects_list = {};
12
13/**
14 * @key归一化
15 */
161function _idx_normalize(idx) {
1719 return idx.trim().toLowerCase();
18}
19
20/* {{{ public function cleanAll() */
21/**
22 * Remove objects from the factory
23 */
241function cleanAll(/*key*/) {
2554 switch (arguments.length) {
26 case 0:
2753 __objects_list = {};
2853 break;
29
30 default:
311 delete __objects_list[_idx_normalize(arguments[0])];
321 break;
33 }
34
3554 return exports;
36}
371exports.cleanAll = cleanAll;
38/* }}} */
39
40/* {{{ public function setObject() */
41/**
42 * @param {String} key, indexName of the Object
43 * @param {Object} obj
44 * @return null
45 */
461function setObject(key, obj, _clone) {
476 if (obj) {
486 __objects_list[_idx_normalize(key)] = _clone ? Extend.clone(obj) : obj;
49 }
50}
511exports.setObject = setObject;
52/* }}} */
53
54/* {{{ public function getObject() */
55/**
56 * visit an object according by indexName (key)
57 */
581function getObject(key, _clone) {
5912 key = _idx_normalize(key);
6012 if (undefined === __objects_list[key]) {
613 return null;
62 }
63
649 return _clone ? Extend.clone(__objects_list[key]) : __objects_list[key];
65}
661exports.getObject = getObject;
67/* }}} */
68
69/* {{{ public function setMysql() */
701function setMysql(key, obj) {
711 if (!obj.query) {
720 obj = Mysql.create(obj);
73 }
741 return setObject('#mysql/' + key, obj, false);
75}
761exports.setMysql = setMysql;
77/* }}} */
78
79/* {{{ public function getMysql() */
801function getMysql(key) {
811 var mysql = getObject('#mysql/' + key, false);
821 return mysql ? mysql : require(__dirname + '/blackhole/mysql.js').create();
83}
841exports.getMysql = getMysql;
85/* }}} */
86
87/* {{{ public function setLog() */
881function setLog(key, obj) {
891 if (!obj.debug || 'function' != typeof(obj.debug)) {
900 obj = Log.create(obj);
91 }
921 return setObject('#log/' + key, obj, false);
93}
941exports.setLog = setLog;
95/* }}} */
96
97/* {{{ public function getLog() */
981function getLog(key) {
992 var _log = getObject('#log/' + key, false);
1002 return _log ? _log : require(__dirname + '/blackhole/log.js').create();
101}
1021exports.getLog = getLog;
103/* }}} */
104
105/* {{{ public function setConfig() */
1061exports.setConfig = function(key, obj) {
1070 if (!obj.get || 'function' !== typeof(obj.get)) {
1080 obj = Config.create(obj);
109 }
110
1110 return setObject('#config/' + key, obj, false);
112}
113/* }}} */
114
115/* {{{ public function getConfig() */
1161exports.getConfig = function(key) {
1170 var _conf = getObject('#config/' + key, false);
1180 return _conf ? _conf : require(__dirname + '/blackhole/config.js').create();
119};
120/* }}} */
121

config.js

100%
66
66
0
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51var fs = require('fs');
61var extend = require(__dirname + '/extend.js');
7
81exports.create = function(file) {
9
10 /* {{{ config file parse() */
118 var value = {};
128 var _call = null;
138 switch (file.split('.').pop().trim().toLowerCase()) {
14 case 'json':
151 _call = parse_json_file;
161 break;
17
18 case 'ini':
196 _call = parse_ini_file;
206 break;
21
22 default:
231 _call = parse_js_file;
241 break;
25 }
26
278 value = _call(file);
28 /* }}} */
29
308 var _me = {};
318 _me.get = function(key, _default) {
3215 return (undefined === value[key]) ? _default : extend.clone(value[key]);
33 };
34
358 _me.all = function() {
362 return value;
37 };
38
398 _me.find = function(prefix) {
402 var map = {};
412 if (!prefix) {
421 return map;
43 }
441 for (var i in value) {
457 if (0 === i.indexOf(prefix + ':')) {
461 map[i.slice(1 + prefix.length)] = extend.clone(value[i]);
47 }
48 }
491 return map;
50 };
51
528 return _me;
53};
54
55/* {{{ function parse_js_file() */
561function parse_js_file(fname) {
571 return require(fname);
58}
59/* }}} */
60
61/* {{{ function parse_json_file() */
621function parse_json_file(fname) {
631 var _text = fs.readFileSync(fname, 'utf8').trim().replace(/'/g, '"');
641 return JSON.parse(_text);
65}
66/* }}} */
67
68/* {{{ function parse_ini_file() */
691function parse_ini_file(fname) {
706 var data = {};
716 var sect = null;
72
736 var lines = fs.readFileSync(fname, 'utf8').trim().split('\n');
746 lines.forEach(function(line) {
7543 line = line.trim();
7643 if (!line.length || ';' == line.slice(0, 1)) {
7718 return;
78 }
79
8025 var match = line.match(/^\s*\[([^\]]+)\]\s*$/);
8125 if (match) {
827 sect = match[1];
837 data[sect] = {};
84 } else {
8518 var match = line.match(/^\s*([^=\s]+)\s*=\s*(.*)\s*$/);
8618 if (!match) {
871 return;
88 }
89
9017 var key = match[1];
9117 var tmp = _clean(match[2]);
9217 if (sect) {
935 data[sect][key] = tmp;
94 } else {
9512 data[key] = tmp;
96 }
97 }
98 });
996 return data;
100}
101/* }}} */
102
103/* {{{ function _clean() */
1041function _clean(val) {
105
10617 if (/^-?(\d|\.)+$/.test(val)) {
1075 return val - 0;
108 }
109
11012 var _me = [];
111
11212 val = val.replace(/^("|')+/, '').replace(/("|')+$/, '');
11312 for (var i = 0; i < val.length; i++) {
114160 var the = val.slice(i, i + 1);
115160 if ('\\' == the) {
1161 i++;
1171 _me.push(val.slice(i, i + 1));
118 } else {
119159 _me.push(the);
120 }
121 }
122
12312 return _me.join('');
124}
125/* }}} */
126

extend.js

100%
39
39
0
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
5/* {{{ public function clone() */
61var clone = exports.clone = function(obj) {
776 var _type = typeof(obj);
876 if ('object' == _type && null !== obj) {
922 var _me = Array.isArray(obj) ? [] : {};
1022 for (var i in obj) {
1139 _me[i] = clone(obj[i]);
12 }
1322 return _me;
14 }
15
1654 return obj;
17}
18/* }}} */
19
20/* {{{ public function concat() */
21/**
22 * buffer concat
23 */
241var concat = exports.concat = function() {
25
261 var chunk = [];
271 var total = 0;
28
291 var _me = {};
301 _me.push = function (data) {
314 if (data instanceof Buffer) {
323 chunk.push(data);
333 total += data.length;
34 }
35 };
36
371 _me.all = function () {
384 if (0 == chunk.length) {
391 return new Buffer(0);
40 }
41
423 if (1 == chunk.length) {
431 return chunk[0];
44 }
45
462 var data = new Buffer(total), pos = 0;
472 chunk.forEach(function(item) {
485 item.copy(data, pos);
495 pos += item.length;
50 });
51
522 return data;
53 };
54
551 return _me;
56}
57/* }}} */
58
59/* {{{ public function escape() */
60/**
61 * 对字符串进行安全转义
62 * @param {String} str
63 * @param {String} charset, default utf-8
64 * @return {String}
65 */
661var __escapemap = {
67 '\'' : '\\\'',
68 '"' : '\\\"',
69 '\\' : '\\\\',
70 '\0' : '\\0',
71 '\n' : '\\n',
72 '\r' : '\\r',
73 '\b' : '\\b',
74 '\t' : '\\t',
75 '\x1a': '\\Z', /**< EOF */
76};
771var escape = exports.escape = function(str) {
782 if ('number' === (typeof str)) {
791 return str;
80 }
81
821 var _char = [];
831 for (var i = 0, m = str.length; i < m; i++) {
8411 var _me = str.charAt(i);
8511 if (__escapemap[_me]) {
864 _me = __escapemap[_me];
87 }
8811 _char.push(_me);
89 }
90
911 return _char.join('');
92}
93/* }}} */
94

log.js

96%
92
89
3
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51var fs = require('fs');
61var moment = require('moment');
7
8/**
9 * @log level defination
10 */
111var DEBUG = exports.DEBUG = 0x01;
121var NOTICE = exports.NOTICE = 0x02;
131var WARN = exports.WARN = 0x04;
141var ERROR = exports.ERROR = 0x08;
151var ALL = exports.ALL = 0xff;
16
17/* {{{ private function _flush_time() */
181function _flush_time() {
193 return moment().format('YYYY-MM-DD HH:mm:ss.SSS');
20}
21
221var _timenow = _flush_time();
23
24/* }}} */
25
261function serialize(info) {
2711 return JSON.stringify(info);
28}
29
30/* {{{ private function _print() */
311function _print(msg, color) {
321 console.log(msg);
33}
34/* }}} */
35
361var _objects = [];
371var _timer = setInterval(function() {
382 _timenow = _flush_time();
392 _objects.forEach(function (log) {
400 if (log && log.flush) {
410 log.flush();
42 }
43 });
44}, 500);
451process.on('exit', function () {
462 _objects.forEach(function (log) {
476 if (log && log.close) {
486 log.close();
49 }
50 });
512 _objects = [];
52});
53
541var _exceptionLoger = null;
551exports.setExceptionLogger = function (options) {
561 _exceptionLoger = exports.create(options);
57};
58
591exports.exception = function (error, info) {
602 if (_exceptionLoger) {
612 _exceptionLoger._excep(error, info);
62 }
63};
64
651exports.create = function(options) {
66
676 var _options = {
68 'file' : '',
69 'level' : ALL & ~DEBUG,
70 'buffer': 16 * 1024,
71 };
72
736 for (var i in options) {
7411 _options[i] = options[i];
75 }
76
776 var _stream = null;
786 if (_options.file) {
796 try {
806 _stream = fs.createWriteStream(_options.file, {
81 'flags' : 'a+', 'encoding' : 'utf8', 'mode' : 420 /** 0644 */,
82 });
83 } catch (e) {
84 }
85 }
86
876 var _buffers = [];
886 var _bufsize = 0;
89
906 function _build(type, tag, info) {
919 return [type + ':', '[' + _timenow + ']', process.pid, tag.trim().toUpperCase(), serialize(info)].join("\t")
926 };
93
946 function _write(msg) {
9510 if (!_stream) {
961 _print(msg);
971 return;
98 }
99
1009 _buffers.push(msg);
1019 _bufsize += msg.length;
1029 if (_bufsize >= _options.buffer) {
1031 _flush_stream();
104 }
105 }
106
107 /* {{{ private function _flush_stream() */
1086 function _flush_stream() {
1097 if (_buffers.length < 1) {
1101 return;
111 }
1126 _stream.write(_buffers.join("\n") + "\n");
1136 _buffers = [];
1146 _bufsize = 0;
115 }
116
1176 var _self = {};
118
119 /* }}} */
120
121 /* {{{ public function debug() */
1226 _self.debug = function(tag, info) {
1233 if (DEBUG & _options.level) {
1241 _write(_build('DEBUG', tag, info));
125 }
126 };
127 /* }}} */
128
129 /* {{{ public function notice() */
1306 _self.notice = function(tag, info) {
1314 if (NOTICE & _options.level) {
1323 _write(_build('NOTICE', tag, info));
133 }
134 };
135 /* }}} */
136
137 /* {{{ public function warn() */
1386 _self.warn = function(tag, info) {
1391 if (WARN & _options.level) {
1401 _write(_build('WARN', tag, info));
141 }
142 };
143 /* }}} */
144
145 /* {{{ public function error() */
1466 _self.error = function(tag, info) {
1474 if (ERROR & _options.level) {
1484 _write(_build('ERROR', tag, info));
149 }
150 };
151 /* }}} */
152
153 /* {{{ public function close() */
1546 _self.close = function() {
1559 if (_stream) {
1566 _flush_stream();
1576 _stream.end();
1586 _stream = null;
159 }
160 };
161 /* }}} */
162
163 /* {{{ private function _excep() */
1646 _self._excep = function (error, info) {
1652 if (!(error instanceof Error)) {
1661 return;
167 }
168
1691 if (!error.name) {
1700 error.name = 'UnknownException';
1711 } else if (error.name.indexOf('Exception') < 0) {
1721 error.name = error.name + 'Exception';
173 }
174
1751 var msg = [_timenow + ' ' + error.stack];
1761 for (var key in info) {
1772 msg.push(key + ': ' + serialize(info[key]));
178 }
1791 msg.push(_timenow, '');
1801 _write(msg.join("\n"));
181 };
182 /* }}} */
183
1846 _self.flush = _flush_stream;
1856 _objects.push(_self);
186
1876 return _self;
188
189}
190

mysql.js

73%
83
61
22
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51var util = require('util');
61var events = require('events');
71var mysql = require('mysql');
8
91var READONLY = exports.READONLY = 1;
101var WRITABLE = exports.WRITABLE = 2;
11
12/* {{{ function _writable() */
13
141var _writable = function (c, f) {
153 c.query("SHOW VARIABLES LIKE 'READ_ONLY%'", function (error, res) {
163 f = f || function () {};
173 if (error) {
180 return f(error, false);
19 }
20
213 var r = {};
223 for (var i = 0; i < res.length; i++) {
233 r = res[i];
243 if (r && r.Variable_name && 'read_only' === r.Variable_name.toLowerCase()) {
253 return f(null, r.Value && r.Value.match(/^(off)$/i) ? true : false);
26 }
27 }
28
290 f(null, false);
30 });
31};
32
33/* }}} */
34
35/* {{{ function _heartbeat() */
36/**
37 * @ XXX: 用单独的一个连接处理心跳
38 */
391var _heartbeat = function (_self, next) {
403 _writable(_self._handle, function (error, yes) {
413 if (error) {
420 _self._status = 0;
43 } else {
443 _self._status = yes ? (READONLY | WRITABLE) : READONLY;
453 _self.emit('ready', _self._status);
46 }
47
483 next && setTimeout(next, 30000);
49 });
50};
51/* }}} */
52
53/* {{{ function errorHandle() */
541var errorHandle = function (_self) {
553 _self._handle.on('error', function (error) {
56
57 /**
58 * @ 准备断开连接
59 */
600 if (_self._status < 0) {
610 return;
62 }
63
640 _self._status = 0;
650 _self.emit('error', error);
66
67 /**
68 * @ 尝试重连
69 */
700 if (!error.fatal || 'PROTOCOL_CONNECTION_LOST' !== error.code) {
710 return;
72 }
73
740 _self._handle = mysql.createConnection(_self._handle.config);
750 errorHandle(_self);
76 });
77};
78/* }}} */
79
801var Agent = function (options) {
81
823 events.EventEmitter.call(this);
83
843 this._status = 0;
85
863 this._handle = mysql.createConnection(options);
87
883 errorHandle(this);
893 var _self = this;
903 _self._handle.connect(function (error) {
913 _heartbeat(_self);
92 });
93
94};
951util.inherits(Agent, events.EventEmitter);
96
971Agent.prototype.query = function (sql, options, callback) {
98
996 if ('function' === (typeof options)) {
1006 callback = options;
101 }
102
1036 var _self = this;
1046 _self._handle.query(sql, function (error, res) {
1056 callback(error, res);
1066 var p = _self._handle._protocol;
1076 if (p && p._queue && !p._queue.length) {
1080 _self.emit('ready', _self._status);
109 }
110 });
111};
112
1131Agent.prototype.close = function (callback) {
1140 var _self = this;
1150 _self._status = -1;
1160 _self._handle.end(function (error) {
1170 callback && callback(error);
1180 _self._handle = null;
119 });
120};
121
1221exports.create = function (options) {
1232 return new Agent(options);
124};
125
1261exports.createPool = function (options) {
127
1281 var _options = {
129 'poolsize' : 4,
130 };
1311 for (var i in options) {
1321 _options[i] = options[i];
133 }
134
1351 var r_queue = [];
136
1371 var w_queue = [];
138
1391 var r_stack = [];
140
1411 var w_stack = [];
142
1431 var conns = [];
144
1451 var _me = {};
146
147 /* {{{ public function addserver() */
148
1491 _me.addserver = function (config) {
150
1511 var m = new Agent(config);
1521 var i = conns.push(m);
153
1541 m.on('ready', function (flag) {
1551 if ((flag & WRITABLE) > 0) {
1561 w_stack.push(i);
1570 } else if ((flag & READONLY) > 0) {
1580 r_stack.push(i);
159 }
160 });
161 };
162
163 /* }}} */
164
165 /* {{{ public function query() */
166
1671 _me.query = function (sql, options, callback) {
1680 if (sql.match(/^(SELECT|SHOW|DESC|DESCRIBE|KILL)\s+/i)) {
1690 r_queue.push('a');
170 } else {
1710 w_queue.push('a');
172 }
173 };
174
175 /* }}} */
176
1771 return _me;
178};
179

redis.js

90%
60
54
6
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51var Redis = require('redis');
6
71exports.create = function(servers, options) {
8
9 /**
10 * @机器列表
11 */
125 var _servers = ['127.0.0.1:6379'];
135 if (servers) {
145 _servers = Array.isArray(servers) ? servers : servers.split(',');
15 }
16
17 /**
18 * @连接配置
19 */
205 var _options = {
21 'timeout' : 50,
22 };
235 for (var i in options) {
242 _options[i] = options[i];
25 }
265 if (!_options.connect_timeout) {
275 _options.connect_timeout = _options.timeout;
28 }
29
30 /**
31 * @连接对象
32 */
335 var _handles = {};
34
35 /**
36 * @对象key
37 */
385 var _handkey = [];
39
40 /**
41 * @连接计数器
42 */
435 var _connnum = 0;
44
45 /**
46 * @请求队列
47 */
485 var _queue = require(__dirname + '/queue.js').create(_options);
495 var _AfterRedisConnected = function (callback, onerr) {
5015 if (_handkey.length < 1) {
517 _queue.push(callback, onerr);
52 } else {
538 callback();
54 }
55 };
56
57 /**
58 * @连接函数
59 */
605 var _connect = function (item) {
6110 var _conn;
6210 var _me = item.split(':');
63
6410 if (_me.length > 1) {
6510 _conn = Redis.createClient(_me[1], _me[0], _options);
66 } else {
670 _conn = Redis.createClient(item, _options);
68 }
69
7010 _conn.removeAllListeners('error');
7110 _conn.on('error', function (error) {
720 require(__dirname + '/log.js').exception(error);
73 });
7410 _conn.once('ready', function () {
758 var p = (_connnum++);
768 _handles[p] = _conn;
778 _handkey = Object.keys(_handles);
78
798 _conn.on('error', function (error) {
800 delete _handles[p];
810 _handkey = Object.keys(_handles);
820 setTimeout(function () {
830 _connect(item);
84 }, 100);
85 });
86
878 var c;
888 while (c = _queue.shift()) {
896 c();
90 }
91 });
92 };
935 _servers.forEach(_connect);
94
95 /**
96 * @获取连接
97 */
985 var _getconn = function(key) {
99
10014 var idx = 5381;
10114 key = (key instanceof Buffer) ? key : new Buffer(key);
10214 for (var i = 0, len = key.length; i < len; i++) {
10378 idx = (idx << 5 + idx) + key[i];
104 }
10514 idx = _handkey[Math.abs(idx) % _handkey.length];
106
10714 return _handles[idx];
108 };
109
110 /**
111 * @redis对象
112 */
1135 var _me = {};
114
115 /* {{{ public function set() */
1165 _me.get = function(key, callback) {
1176 _AfterRedisConnected(function () {
1186 _getconn(key).get(key, function(error, result) {
1196 callback(error, result && result.length ? result : null);
120 })
121 }, callback);
122 };
123 /* }}} */
124
125 /* {{{ public function set() */
1265 _me.set = function(key, value, callback, expire) {
1279 _AfterRedisConnected(function () {
1288 _getconn(key).setex(key, expire || 86400, value, function(error, result) {
1298 callback(error);
130 })
131 }, callback);
132 };
133 /* }}} */
134
135 /* {{{ public function delete() */
1365 _me.delete = function(key, callback) {
1372 _me.set(key, '', callback);
138 };
139 /* }}} */
140
1415 return _me;
142};

pool.js

100%
55
55
0
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51exports.create = function(fn, options) {
6
7 /**
8 * @构造器
9 */
102 var _creator = fn;
11
12 /**
13 * @配置属性
14 */
15 /* {{{ _options */
162 var _options = {
17 'size' : 10, /**< 最大连接数 */
18 'idle' : 30000, /**< 空闲时间 */
19 };
202 for (var i in options) {
214 _options[i] = options[i];
22 }
23 /* }}} */
24
25 /**
26 * @对象列表
27 */
28 /* {{{ _objects */
29 /**
30 * @被占用的ID
31 */
322 var _stacks = [];
332 var _objects = [];
34
352 var _connect = function() {
367 _stacks.push(_objects.push({
37 '_up' : Date.now(),
38 '_me' : _creator(),
39 'use' : 0,
40 }) - 1);
41 };
42 /* }}} */
43
44 /**
45 * @调用请求
46 */
47 /* {{{ _execute() */
482 var _callback = [];
492 var _execute = function() {
50588 while (_callback.length && _stacks.length) {
512 var cb = _callback.shift();
522 var id = _stacks.pop();
532 cb(_objects[id]._me, id);
542 _objects[id].use = 1;
552 _objects[id]._up = Date.now();
56 //delete cb;
57 }
58588 if (_callback.length) {
59586 process.nextTick(_execute);
60 }
61 };
62 /* }}} */
63
64 /**
65 * @空闲检查定时器
66 */
67 /* {{{ _timer */
682 var _timer = setInterval(function() {
6920 var now = Date.now() - _options.idle;
7020 var ids = [];
7120 var obj = [];
7220 _objects.forEach(function(item) {
7353 if (item._up >= now || item.use > 0) {
7449 ids.push(obj.push(item) - 1);
7549 return;
76 }
77
784 if (item._me.close && 'function' === (typeof item._me.close)) {
794 item._me.close();
80 }
81 });
8220 _objects= obj;
8320 _stacks = ids;
84 }, Math.ceil(_options.idle / 10));
85 /* }}} */
86
872 var _me = {};
88
89 /* {{{ public function get() */
90 /**
91 * 获取一个资源
92 *
93 * @access public
94 * @param {Function} callback
95 * @param {Integer} timeout
96 */
972 _me.get = function(callback, timeout) {
9810 if (!_stacks.length && _objects.length < _options.size) {
997 _connect();
100 }
101
10210 if (_stacks.length) {
1038 var id = _stacks.pop();
1048 callback(_objects[id]._me, id);
1058 _objects[id].use = 1;
1068 _objects[id]._up = Date.now();
107 } else {
1082 _callback.push(callback);
1092 process.nextTick(_execute);
110 }
111 };
112 /* }}} */
113
114 /* {{{ public function free() */
115 /**
116 * 释放被锁定的资源
117 *
118 * @access public
119 */
1202 _me.free = function(id) {
12110 if (_objects[id] && _objects[id].use > -1) {
1229 _objects[id].use = 0;
1239 _stacks.push(id);
124 }
125 };
126 /* }}} */
127
128 /* {{{ public function remove() */
129 /**
130 * 从连接池中移除,用于连接出问题时调用
131 * @param {Integer} id
132 */
1332 _me.remove = function(id) {
1341 var obj = _objects[id];
1351 if (obj) {
1361 obj.use = -1;
1371 obj._up = 0;
138 }
139
1401 _stacks = _stacks.filter(function(item) {
1412 return id !== item;
142 });
143 };
144 /* }}} */
145
1462 return _me;
147
148};

mstack.js

100%
47
47
0
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51var extend = require(__dirname + '/extend.js');
6
71exports.create = function(size) {
8
94 var _size = parseInt(size, 10);
104 var _ceil = Math.ceil(_size * 1.4);
114 var _floo = Math.floor(_size * 0.8);
12
134 var _list = [];
14
154 var _stat = {
16 'q' : 0, /**< 查询次数(query) */
17 's' : 0, /**< 查询步长(steps) */
18 'm' : 0, /**< 未命中次数(miss) */
19 };
20
214 var _self = {};
22
23 /* {{{ private function _search() */
244 function _search(key) {
2527 var _is = false;
2627 _stat.q++;
2727 for (var i = 0, m = _list.length; i < m; i++) {
2833 if (_list[i].k === key) {
2915 _is = true;
3015 break;
31 }
32 }
3327 _stat.s += i;
3427 _stat.m ++;
35
3627 return _is ? i : -1;
37 }
38 /* }}} */
39
40 /* {{{ public function set() */
414 _self.set = function(key, value) {
429 var key = key.trim();
439 var pos = _search(key);
449 var itm = {'i':0,'k':key,'v':value};
45
469 if (pos >= 0) {
471 _list[pos] = itm;
48 } else {
498 if (_list.length >= _ceil) {
501 _list = _list.slice(0, _floo);
51 }
528 _list.push(itm);
53 }
54
559 return _self;
56 };
57 /* }}} */
58
59 /* {{{ public function get() */
604 _self.get = function(key) {
6118 var pos = _search(key.trim());
6218 if (pos < 0) {
634 return null;
64 }
6514 var itm = _list[pos];
6614 itm.i++;
6714 if (pos > 0) {
685 var i = Math.min(pos, itm.i * itm.i);
695 var t = _list[pos -i];
705 _list[pos - i] = itm;
715 _list[pos] = {
72 'i' : 0,
73 'k' : t.k,
74 'v' : t.v,
75 };
76 }
77
7814 return extend.clone(itm.v);
79 };
80 /* }}} */
81
82 /* {{{ public function clean() */
834 _self.clean = function() {
842 _list = [];
852 return _self;
86 };
87 /* }}} */
88
89 /* {{{ public function status() */
904 _self.status = function() {
913 return _stat;
92 };
93 /* }}} */
94
954 return _self;
96}
97

events.js

100%
19
19
0
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51exports.create = function (callback) {
6
7 /**
8 * @ 等待的事件列表
9 */
104 var waits = {};
11
12 /**
13 * @ 最先返回的错误
14 */
154 var error = null;
16
174 var _me = {};
18
194 _me.wait = function (evt, cb) {
208 waits[evt] = true;
218 cb && cb();
22 };
23
244 _me.emit = function (evt, e) {
2511 if (!waits[evt]) {
261 return;
27 }
28
2910 if (e && !error) {
301 error = e;
31 }
3210 process.nextTick(function () {
3310 delete waits[evt];
3410 for (var key in waits) {
356 return;
36 }
37
384 callback(error);
39 });
40 };
41
424 return _me;
43};
44

blackhole/log.js

100%
4
4
0
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
41function noop() {
5}
6
71exports.create = function() {
82 return {
9 'debug' : noop,
10 'notice' : noop,
11 'warn' : noop,
12 'error' : noop,
13 'close' : noop,
14 'flush' : noop,
15 };
16}

blackhole/config.js

100%
8
8
0
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
41exports.create = function() {
5
61 var _me = {};
7
81 _me.get = function(key, _default) {
91 return _default;
10 };
11
121 _me.all = function() {
131 return {};
14 };
15
161 return _me;
17};
18

blackhole/mysql.js

63%
11
7
4
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51var _mysql = {};
61_mysql.query = function (sql, callback) {
71 callback(new Error('MysqlBlackhole'));
8};
9
101exports.create = function () {
111 return _mysql;
12};
13
141exports.createPool = function () {
150 var _me = {};
160 _me.query = _mysql.query;
170 _me.addserver = function (mysql) {
18 };
19
200 return _me;
21};
22

cache.js

97%
104
101
3
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
5/* {{{ exports getkey() */
6/**
7 * 构造key
8 */
91var cacheindex = function(key) {
10
1130 key = (key instanceof Buffer) ? key : new Buffer(key);
12
1330 var hash1 = 5381;
1430 var hash2 = 0;
1530 for (var i = 0, len = key.length; i < len; i++) {
16369 hash1 = (hash1 << 5 + hash1) + key[i];
17369 hash2 = (hash2 << 4) ^ (hash2 >> 28) ^ key[i];
18 }
19
2030 return ([hash1, hash2, key.length]).join(':');
21};
221exports.getkey = cacheindex;
23/* }}} */
24
25/* {{{ function MemoryStore() */
26/**
27 * 数据存储在内存中
28 */
291var MemoryStore = function(size) {
30
311 var _pool = require(__dirname + '/mstack.js').create(size || 2000);
32
331 var _me = {};
34
351 _me.set = function(key, value, callback) {
361 _pool.set(key, value);
371 callback(null);
38 };
39
401 _me.get = function(key, callback) {
412 callback(null, _pool.get(key));
42 };
43
441 _me.delete = function(key, callback) {
451 _pool.clean();
461 callback(null);
47 };
48
491 return _me;
50};
51/* }}} */
52
531var __instances = {};
541exports.create = function(name, store, keeper, options) {
55
568 name = name.trim().toLowerCase();
578 if (undefined !== __instances[name]) {
582 return __instances[name];
59 }
60
61 /* {{{ private variable _conf */
626 var _conf = {
63 'tag_flush_interval' : 5000,
64 'tag_max_expire_time' : 7 * 86400000,
65 };
666 for (var key in options) {
672 _conf[key] = options[key];
68 }
69 /* }}} */
70
71 /* {{{ private variable _res */
72 /**
73 * @缓存存储引擎
74 */
756 var _res = store;
76
776 if (!_res || !_res.set || !_res.get || !_res.delete) {
781 _res = MemoryStore();
791 var serialize = function(value) {
801 return value;
81 };
821 var unserialize = function(value) {
832 return value;
84 };
85 } else {
865 var serialize = function(value) {
878 return JSON.stringify((value instanceof Buffer) ? value.toString() : value);
88 };
895 var unserialize = function(value) {
9014 try {
9114 return JSON.parse(value.toString());
92 } catch (e) {
930 return null;
94 }
95 };
96 }
97 /* }}} */
98
99 /* {{{ private variable _sync */
100 /**
101 * @Tag同步引擎
102 */
1036 var _sync = keeper;
104
105 /**
106 * @Tag数据更新时间
107 */
1086 var _tags = {};
109
110 /**
111 * @有更新的tag
112 */
1136 var _upds = {};
114
115 /**
116 * @数据同步时间
117 */
1186 var _time = Date.now() - _conf.tag_max_expire_time;
119
1206 var sync_tag_time = function() {
1211390 for (var key in _upds) {
122119 (function() {
123119 var t = _upds[key];
124119 _sync.write(key, t, function(error) {
125119 if (error && (!_upds[key] || t > _upds[key])) {
126119 _upds[key] = t;
127 }
128 });
129 })();
130119 delete _upds[key];
131 }
132
1331390 _sync.load(function(error, _data) {
1341390 if (error) {
1350 return;
136 }
137
1381390 for (var idx in _data) {
1392768 _tags[idx] = _tags[idx] ? Math.max(_data[idx], _tags[idx]) : _data[idx];
1402768 _time = Math.max(_time, _tags[idx]);
141 }
142 }, _time);
143 };
144 /* }}} */
145
146 /* {{{ private variable timer */
147 /**
148 * @tag数据同步定时器
149 */
1506 var timer = null;
1516 if (_sync) {
1522 timer = setInterval(sync_tag_time, _conf.tag_flush_interval);
153 }
154 /* }}} */
155
1566 var _me = __instances[name] = {};
157
158 /* {{{ public function set() */
159 /**
160 * Set cache value
161 *
162 * @param {String} key
163 * @param {Object} value
164 * @param {Function} callback
165 * @param {Integer} expire
166 * @param {Array} tags
167 */
1686 _me.set = function(key, value, callback, expire, tags) {
1699 var now = Date.now();
1709 expire = expire || 86400000;
1719 _res.set(cacheindex(name + '#' + key), serialize({
172 'i' : now, /**< 数据写入时间 */
173 'e' : now + expire, /**< 数据过期时间 */
174 'k' : key, /**< 数据key */
175 'v' : value, /**< 数据值 */
176 't' : tags ? (Array.isArray(tags) ? tags : [tags]) : [],
177 }), callback, Math.floor(expire / 1000));
178 };
179 /* }}} */
180
181 /* {{{ public function get() */
1826 _me.get = function(key, callback) {
18318 var now = Date.now();
18418 _res.get(cacheindex(name + '#' + key), function(error, value) {
18518 if (error || !value) {
1862 callback(error, null);
1872 return;
188 }
189
19016 value = unserialize(value);
19116 if (!value.i || !value.e || !value.k || undefined === value.v) {
1921 callback(new Error('UnExpectCacheValue'));
1931 return;
194 }
195
196 /**
197 * @time expire or key does not match
198 */
19915 if (value.e < now || value.k != key) {
2001 callback(null, null);
2011 return;
20214 };
203
204 /**
205 * @tag expire
206 */
20714 var _list = Array.isArray(value.t) ? value.t : [];
20814 var _len = _list.unshift('__global__');
20914 for (var i = 0; i < _len; i++) {
21031 var idx = _list[i];
21131 if (_tags[idx] && value.i <= _tags[idx]) {
2124 callback(null, null);
2134 return;
214 }
215 }
216
21710 callback(null, value.v, value.e - now);
218 });
219 };
220 /* }}} */
221
222 /* {{{ public function unset() */
2236 _me.unset = function(key, callback) {
2242 _res.delete(cacheindex(name + '#' + key), callback);
225 };
226 /* }}} */
227
228 /* {{{ public function tagrm() */
229 /**
230 * 根据tag删除缓存
231 *
232 * @param {String} tag
233 * @param {Integer} delay time (ms)
234 */
2356 _me.tagrm = function(tag, delay, flush) {
2364 var tag = tag ? tag.trim() : '__global__';
2374 var now = Date.now();
2384 if (delay) {
2391 delay = parseInt(delay, 10);
2401 now += delay ? delay : 0;
241 }
242
2434 _upds[tag] = now;
2444 _tags[tag] = now;
2454 if (flush && _sync) {
2460 _sync.write(tag, now, function(error){});
247 }
248 };
249 /* }}} */
250
2516 return _me;
252}

queue.js

100%
66
66
0
LineHitsSource
1/* vim: set expandtab tabstop=2 shiftwidth=2 foldmethod=marker: */
2
31"use strict";
4
51var _extend = function (a, b) {
611 for (var i in b) {
713 a[i] = b[i];
8 }
911 return a;
10};
11
121var _error = function (name, message) {
134 var o = new Error(message);
144 o.name = name;
154 return o;
16};
17
181exports.create = function (options) {
19
20 /**
21 * @队列属性
22 */
2311 var _options = _extend({
24 'timeout' : 0, /**< 超时时间(ms) */
25 'maxitem' : 0, /**< 最大记录数 */
26 }, options);
27
28
29 /**
30 * @对象栈
31 */
3211 var _queues = [];
33
3411 var _me = {};
35
3611 _me.size = function () {
3721 return _queues.length;
38 };
39
40 /* {{{ public function push() */
41 /**
42 * push an item to queue
43 *
44 * @access public
45 * @param {Object} o
46 * @param {Function} onerr
47 */
4811 _me.push = function (o, onerr) {
4919 var idx = _queues.length;
5019 if (_options.maxitem && idx >= _options.maxitem) {
512 onerr && onerr(_error('QueueIsFull', 'Already ' + idx + ' items in the queue.'), o);
522 return;
53 }
54
5517 _queues.push({
56 'o' : o,
57 's' : 0,
58 });
5917 if (_options.timeout && onerr) {
6010 (function () {
6110 var m = _queues[idx];
6210 m.t = setTimeout(function () {
633 m.s = 1;
643 var pos = _queues.indexOf(m);
653 if (pos >= 0) {
663 _queues.splice(pos, 1);
67 }
68
693 onerr(_error('QueuedTimeout', 'Item queued timeout after ' + _options.timeout + 'ms.'), o);
70 }, _options.timeout);
71 })();
72 }
73
7417 return _me;
75 };
76 /* }}} */
77
78 /* {{{ public function shift() */
79 /**
80 * to get an item from the head
81 *
82 * @access public
83 */
8411 _me.shift = function () {
8525 var obj;
8625 while (_queues.length) {
8714 obj = _queues.shift();
8814 obj.t && clearTimeout(obj.t);
8914 if (obj.s < 1) {
9014 return obj.o;
91 }
92 }
93
9411 return null;
95 };
96 /* }}} */
97
9811 return _me;
99};
100
1011exports.createPriorityQueue = function(options) {
102
103 /**
104 * @队列对象
105 */
1061 var slots = {};
107
108 /**
109 * @访问顺序
110 */
1111 var order = [];
112
1131 var _me = {};
114
1151 _me.size = function (p) {
1165 if (undefined !== p && null !== p) {
1171 return slots[p] ? slots[p].size() : 0;
118 }
119
1204 var n = 0;
1214 for (var i in slots) {
1227 n += slots[i].size();
123 }
124
1254 return n;
126 };
127
1281 _me.push = function (o, p, onerr) {
1294 p = Math.max(0, p && + p | 0 || 0);
1304 if (!slots[p]) {
1313 slots[p] = exports.create(options);
1323 order = Object.keys(slots).sort(function (a, b) {
1333 return a - b;
134 });
135 }
1364 slots[p].push(o, onerr);
137
1384 return _me;
139 };
140
1411 _me.shift = function () {
1426 for (var i = 0, m = order.length; i < m; i++) {
14310 var s = slots[order[i]];
14410 if (s.size()) {
1454 return s.shift();
146 }
147 }
1482 return null;
149 };
150
1511 return _me;
152
153}
154/* }}} */
155