Browse Source

Revamped events system, now supports variable storage between bundles

Luis Figueiredo 10 năm trước cách đây
mục cha
commit
1347b2a97e
34 tập tin đã thay đổi với 860 bổ sung và 3836 xóa
  1. 6 3
      bundles/core-installer/index.js
  2. 5 3
      bundles/core-loader/index.js
  3. 13 2
      bundles/core-monitor/index.js
  4. 5 0
      doc/eventual/ideas.md
  5. 21 33
      lib/bundle-context.js
  6. 0 3
      lib/bundle-manager.js
  7. 1 0
      lib/eventual-old/index.js
  8. 93 0
      lib/eventual-old/lib/channel.js
  9. 9 9
      lib/eventual/eventual-context.js
  10. 18 0
      lib/eventual-old/lib/event-param.js
  11. 105 0
      lib/eventual-old/lib/eventual.js
  12. 0 171
      lib/eventual/eventual-channel.js
  13. 0 31
      lib/eventual/eventual.js
  14. 1 1
      lib/eventual/index.js
  15. 46 0
      lib/eventual/lib/context-flat-list/context.js
  16. 1 0
      lib/eventual/lib/context-flat-list/index.js
  17. 15 0
      lib/eventual/lib/context-flat-map/channel.js
  18. 71 0
      lib/eventual/lib/context-flat-map/context.js
  19. 1 0
      lib/eventual/lib/context-flat-map/index.js
  20. 92 0
      lib/eventual/lib/context-recursive-objects/channel.js
  21. 47 0
      lib/eventual/lib/context-recursive-objects/context.js
  22. 1 0
      lib/eventual/lib/context-recursive-objects/index.js
  23. 18 0
      lib/eventual/lib/event-param.js
  24. 128 0
      lib/eventual/lib/eventual.js
  25. 0 227
      lib/utils/xevents.js
  26. 142 0
      test/eventual-test/benchmark.js
  27. 0 128
      test/eventual-test/index.js
  28. 0 128
      test/eventual-test/lib/eventual-context.js
  29. 0 19
      test/eventual-test/lib/eventual.js
  30. 17 0
      test/eventual-test/watcher.js
  31. 0 1
      test/hci-usecase/bundles/hci-http/index.js
  32. 4 2
      test/hci-usecase/bundles/stress-test/index.js
  33. 0 3
      test/hci-usecase/siege.err.txt
  34. 0 3072
      test/hci-usecase/siege.out.txt

+ 6 - 3
bundles/core-installer/index.js

@@ -16,14 +16,14 @@ var installerActivator = {
 		this.runPath = context.manager.config.runPath;
 		if(this.deployPath == undefined) {
 			log.warn("There is no deploy path configured");
-			context.state("installed");
+			context.set("installed",true);
 			//context.emit('installed');
 			return;
 		}
 		if(this.runPath == undefined) {
 			log.warn("There is no bundlePath configured");
 			this.installed = true;
-			context.state("installed");
+			context.state("installed",true);
 			return;
 		}
 
@@ -35,7 +35,7 @@ var installerActivator = {
 		var hitCounter = new HitCounter(mods.length, () => {
 			log.info("Emitting installed");
 			this.installed = true;
-			context.state('installed');	
+			context.state('installed',true);	
 		});
 
 		for(var v of mods) {
@@ -47,6 +47,9 @@ var installerActivator = {
 			this.installPlugin(path.resolve( path.join(this.deployPath,v)), hitCounter.hit.bind(hitCounter));
 		}
 	},
+	stop(context) {
+		context.unset('installed');	
+	},
 	installPlugin(fullPath,cb) {
 		log.info("Intalling: " + fullPath);
 		var basename = path.basename(fullPath,".zip");

+ 5 - 3
bundles/core-loader/index.js

@@ -13,13 +13,15 @@ var loaderActivator = {
 
 		this.registerShell(context);
 
-
 		if(!this.runPath ) {
 			log.warn("There is no runPath configured in manager");
 			return;
 		}
-		context.on('core-installer:installed',() => {
-				this.loadBundles();	
+		context.watch('core-installer:installed',(value) => {
+			console.log("core-installer:installed is:",value);
+			if(value == true) {
+				process.nextTick(() => { this.loadBundles()});
+			}
 		});
 		//this.loadBundles();	
 		// Check this out its wrong!?

+ 13 - 2
bundles/core-monitor/index.js

@@ -12,9 +12,8 @@ function ntokb(n) {
 	return n.toFixed(2) + " " +suffix[si];
 }
 
-
 var monitor = {
-
+	
 	bundleStart(context) {
 		this.context = context;
 		log.info("Bundle monitor started");
@@ -25,12 +24,17 @@ var monitor = {
 			});	
 		});
 	},
+
 	registerCommands(context) {
 		context
 			.channel('core-shell:cmd')
 			.on('stat',(req,res,e) => {
 				this.showStat(res); // Should pass stdout
+			})
+			.on('gc',(req,res,e) => {
+				gc();
 			});
+		
 		// listen from command from ourselves
 		/*context.on('core-shell:cmd:stat',(req,res,e) => {
 				this.showStat(res); // Should pass stdout
@@ -49,6 +53,13 @@ var monitor = {
 				 +" Total: " + ntokb(obj.heapTotal)
 				 +" Used: " + ntokb(obj.heapUsed) +"\n");
 
+		// Sum events
+		var nevents = 0;
+		context.manager.eventual._events.ctx.forEach((c) => {
+			nevents += Object.keys(c.listeners).length;
+		});
+		res.write("Events: " + nevents + "\n");
+
 		// Weird?
 		/*res.write("Modules registered: " + context.manager.stat.modulesRegistered
 						+" Modules UnRegistered: " + context.manager.stat.modulesUnRegistered

+ 5 - 0
doc/eventual/ideas.md

@@ -0,0 +1,5 @@
+
+Object storage can be simplified as in
+
+disable channel complexity?
+

+ 21 - 33
lib/bundle-context.js

@@ -90,16 +90,13 @@ class BundleContext /*extends XEventEmitter*/ {
 			log.warn("Instance is turned on trying to turn off first");
 			this.stop();
 		}
-		//process.nextTick(() => {
-			try {
-				this._bundleContext.instanceStart(this);
-			} catch(e) {
-				log.error("Bundle start error: " + this.name + "\n",e);
-			}
-			//this.manager.events.toggleOn(this.name,this.instance);
-			this.info.state = 1;
-			this.info.startDate = new Date();
-		//});
+		try {
+			this._bundleContext.instanceStart(this);
+		} catch(e) {
+			log.error("Bundle start error: " + this.name + "\n",e);
+		}
+		this.info.state = 1;
+		this.info.startDate = new Date();
 	}
 
 	stop() {
@@ -120,27 +117,10 @@ class BundleContext /*extends XEventEmitter*/ {
 		this.info.state = 0;
 	}
 
-	/* Event wrappers */
-	/*removeListener(ename) {
-		this.manager.events.removeListener(this,ename);
-	}*/
-	
 	emit(name,...args) {
-		return this.events.broadcast( this.name + ":" +name,...args);
-	}
-	state(name,...args) {
-		this.events.state( this.name + ":"+ name,...args);
-		return this;
-	}
-	/*emit(ename,...args) {
-		return this.manager.events.emit(this.name+":"+ename,...args);
-	}*/
-	/*toggleOn(ename,arg) {
-		this.manager.events.toggleOn(this.name+":"+ename,arg);
+		return this.events.emit(this.name + ":" +name,...args);
 	}
-	toggleOff(ename) {
-		this.manager.events.toggleOff(this.name+":"+ename);
-	}*/
+
 	channel(name) {
 		return this.events.channel(name);
 	}
@@ -150,6 +130,18 @@ class BundleContext /*extends XEventEmitter*/ {
 		return this;
 	}
 
+
+	// Watcher
+	watch(name,cb) {
+		this.events.watch(name,cb);
+	}
+	set(name,value) {
+		this.events.set(this.name + ":" + name, value);
+	}
+	unset(name) {
+		this.events.unset(this.name + ":" + name);
+	}
+
 	/*on(...args) {
 		var cb = args.pop();
 		var evtName = args.join(":");
@@ -160,10 +152,6 @@ class BundleContext /*extends XEventEmitter*/ {
 		this.events.on(name,cb,1000);
 		return this;
 	}
-	// Channel
-	prefix(name) {
-		return this.manager.events.prefix(this,name);
-	}
 	// Wrappers
 	
 	/**

+ 0 - 3
lib/bundle-manager.js

@@ -1,6 +1,5 @@
 var path 						= require('path'),
 		fs 							= require('fs'),
-		XEventEmitter 	= require('./utils/xevents'),
 		clearRequire 		= require('./utils/clear-require'),
 		readPackageJson = require('./utils/read-packagejson');
 
@@ -11,7 +10,6 @@ var Eventual = require('./eventual');
 var	BundleContext = require('./bundle-context');
 var log = require('hlogger').createLogger('bundle-manager');
 
-
 function solveBundleName(inpath) {
 	var name = path.basename(inpath);
 	if(name == "index.js") {
@@ -34,7 +32,6 @@ class BundleManager {
 		//this.events = new XEventEmitter();   // Force for now
 		
 		// Global channel
-		this.globalEvents = new XEventEmitter();
 
 		this.stat = {
 			modulesRegistered:0,

+ 1 - 0
lib/eventual-old/index.js

@@ -0,0 +1 @@
+module.exports = require('./lib/eventual');

+ 93 - 0
lib/eventual-old/lib/channel.js

@@ -0,0 +1,93 @@
+/** Concept each channel can have child channels ??**/
+
+const chs = ':'; // Channel separator
+
+class EventualChannel {
+
+	constructor(eventual, name,parent) {
+		// We could fetch eventual from parent
+		this.eventual = eventual;
+		this.name = name;
+		this.parent = parent; //?? we need
+		
+		this.childs = {}
+		this.listeners = [];
+	}
+	// createChannel based on name
+	//
+	fullName() {
+		var name = this.name;
+		for(var cur = this;cur = cur.parent;cur.parent) {
+			if(this.parent.parent) { // if not root
+				name = this.parent.name +":" + name;
+			}
+		}
+		return  name;
+	}
+
+	// Recursive
+	get2(name,create) {
+		if(name == undefined) return this;
+
+		var cur = this;	
+		var [childName,...sub] = name.split(chs);
+		
+		if(cur.child[childName] == undefined) {
+			if(!create) return null;
+			cur.child[name] = new EventualChannel(this.eventual,name,this);
+		}
+		return this.get2(sub.join(chs),create);
+	};
+
+	// Should be private function
+	get(name,create) {
+		var nodes = name.split(chs);
+		var cur = this;
+		var ok = 1;
+
+		nodes.some((v) => {
+			if( cur.childs[v] == undefined) {
+				if(create == undefined) { cur = null; return true; }
+				cur.childs[v] = new EventualChannel(this.eventual,name,this);
+			}
+			cur = cur.childs[v]; // next;
+		});
+
+		return cur;
+	}
+
+	channel(name) { // Will create channel and return new child channel
+		return this.get(name,true);
+	}
+	
+	// Get listeners
+/*	search(name,create) {
+		var channel	= this.get(name,create);
+		if(channel) return channel.listeners;
+		return [];
+	}*/
+
+	// Maybe this should be in context?
+	// Registers 
+	// new listener
+	on (name,cb,order) {
+		var channel = this.channel(name);
+		var listener = { name:name, callback:cb, order: order || 0 };
+		channel.listeners.push(listener)
+
+		// Check for state call // Disable this flavouring watch
+		var cname = channel.fullName();
+		if(this.eventual._events.state[cname]!=undefined) {
+			this.eventual.process([listener],this.eventual._events.state[cname]);
+		}
+		return this;
+	}
+	
+	// Emit is wrong here since it will only call same context
+	/*emit(name,args) {
+		var tocall = this.search(name);
+		return this.eventual.process(tocall,args);
+	}*/
+}
+
+module.exports = EventualChannel;

+ 9 - 9
lib/eventual/eventual-context.js

@@ -1,19 +1,19 @@
 
 /** Concept each channel can have child channels ??**/
-var EventualChannel = require('./eventual-channel');
+var EventualChannel = require('./channel');
 
 class EventualContext2 extends EventualChannel {
 	constructor(eventual) {
 		super(eventual);
 	}
-	broadcast(name,...args) {
-		// Special send to all eventual contexts
-		var tocall = [];		
-		this.eventual._events.ctx.forEach((c) => {
-			tocall.push(...c.search(name));
-		});
-		return this.process(tocall,args)
-	}
+	// Seems something to eventual and not context
+	
+	
+	// Alias
+	emit(name,...args) {
+		return this.eventual.emit(name,...args);
+	}	
+
 	state(name,...args) {
 		this.eventual.state(name,args);
 	}

+ 18 - 0
lib/eventual-old/lib/event-param.js

@@ -0,0 +1,18 @@
+// Create event .js
+class Event {
+	constructor(donecb,args) {
+		this.count = 0;
+		this.dowait = 0;
+		
+		this.done= donecb; // Callback
+		this.errors = [];
+		this.params = args;
+	}
+	wait() {
+		this.dowait = 1;
+	}
+}
+
+
+module.exports = Event;
+

+ 105 - 0
lib/eventual-old/lib/eventual.js

@@ -0,0 +1,105 @@
+/** 
+ * Substitute for xeventx
+ * */
+
+const EventualContext = require('./context');
+const EventParam = require('./event-param');
+
+
+class Eventual {
+	constructor() {
+		this._events = {
+			ctx: [],
+			state: {},
+			store: {}
+		};
+	}
+
+	emit(name,...args) {
+		// Special send to all eventual contexts
+		var tocall = [];		
+		this._events.ctx.forEach((c) => {
+			var channel = c.get(name);
+			if(channel)tocall.push(...channel.listeners);
+		});
+		return this.process(tocall,args)
+	}
+
+	// process should be handled here
+	process(tocall,nargs) {
+		var args = nargs || [];	 // or empty
+		var evt = new EventParam(next,args);
+		
+		var callback,dotrigger = 0;
+		//Inner trigger	
+		// Finish	
+		function triggerDone() {
+			if(callback) callback(evt);
+			dotrigger = 1;
+		}
+		var ret = {
+			done: function(cb) {
+				if(dotrigger) { cb(evt); }
+				callback = cb;
+			}
+		}
+		tocall = tocall.sort((a,b) => {
+			return (a.order - b.order) 
+		});	
+		// Get iter and setup evt
+		var iter = tocall[Symbol.iterator]();
+		
+		function next() {
+			process.nextTick(() => chain(iter));
+		}
+
+		// Internal thing
+		function chain(iter) { 
+			// Stack overflow risk? maybe put this in process.tick();
+			var v = iter.next();
+			if(v.done) {
+				triggerDone(); // Done callback with evt only
+				return;
+			}
+			// Create evt here with some global event chaining iteraction	
+			try {
+				// Setup entry info
+				var entry = v.value;
+				evt.args = args;
+				evt.name = entry.name;
+				entry.callback(...args,evt);
+				evt.count++;
+			}catch(e) {
+				console.log(e);
+				evt.errors.push(e);
+				// Should we stop??
+			}
+			if(!evt.dowait) next();
+			evt.dowait=0; // reset wait?
+		}
+		next();
+
+		return ret;
+	}
+
+
+	createContext() {
+		var ret = new EventualContext(this);
+		this._events.ctx.push(ret);
+		return ret;
+	}
+	destroyContext(ctx) {
+		var i = this._events.ctx.indexOf(ctx);
+		if(i!=-1) this._events.ctx.splice(i,1);
+	}
+	state(name,args) {
+		// Should do this per context
+		this._events.state[name] = args;
+	}
+
+
+	
+}
+
+module.exports = Eventual;
+

+ 0 - 171
lib/eventual/eventual-channel.js

@@ -1,171 +0,0 @@
-/** Concept each channel can have child channels ??**/
-const chs = ':'; // Channel separator
-
-class XEvent {
-	constructor(donecb,args) {
-		this.count = 0;
-		this.dowait = 0;
-		
-		this.done= donecb; // Callback
-		this.errors = [];
-		this.params = args;
-	}
-	wait() {
-		this.dowait = 1;
-	}
-}
-
-class EventualChannel {
-
-	constructor(eventual, name,parent) {
-		this.eventual = eventual;
-		this.name = name;
-		this.parent = parent; //?? we need
-		
-		this.childs = {}
-		this.listeners = [];
-	}
-
-	// createChannel based on name
-	//
-	fullName() {
-		var name = this.name;
-		for(var cur = this;cur = cur.parent;cur.parent) {
-			if(this.parent.parent) { // if not root
-				name = this.parent.name +":" + name;
-			}
-		}
-		return  name;
-	}
-
-	get2(name,create) {
-		if(name == undefined) return this;
-
-		var cur = this;	
-		var [childName,...sub] = name.split(chs);
-		
-		if(cur.child[childName] == undefined) {
-			if(!create) return null;
-			cur.child[name] = new EventualChannel(this.eventual,name,this);
-		}
-		return this.get2(sub.join(chs),create);
-	};
-
-	// Should be private function
-	get(name,create) {
-		// How it should work?
-		// Recursivelly get a listener why? because of match
-		var nodes = name.split(chs);
-		var cur = this;
-		var ok = 1;
-
-		nodes.forEach((v) => {
-			if( cur.childs[v] == undefined) {
-				if(create == undefined) { ok = false; return null; }
-				cur.childs[v] = new EventualChannel(this.eventual,name,this);
-			}
-			cur = cur.childs[v]; // next;
-		});
-
-		if(!ok) return null;
-		return cur;
-	}
-	channel(name) { // Will create channel and return new child channel
-		return this.get(name,true);
-	}
-	// Get listeners
-	search(name,create) {
-		var channel	= this.get(name,create);
-		if(channel) return channel.listeners;
-		return [];
-	}
-	// Registers 
-	// new listener
-	on (name,cb,order) {
-		var channel = this.channel(name);
-		var listener = { name:name, callback:cb, order: order || 0 };
-		channel.listeners.push(listener)
-
-		// Check for state call
-		var cname = channel.fullName();
-		if(this.eventual._events.state[cname]!=undefined) {
-			this.process([listener],this.eventual._events.state[cname]);
-		}
-		return this;
-	}
-	emit(name,args) {
-		var tocall = this.search(name);
-		return this.process(tocall,args);
-	}
-
-	//TODO: CLEAN THIS
-	/*
-	 * Basically process a list of functions and calls done in end
-	 * */
-	process(tocall,nargs) {
-		var self=this;
-	
-		var args = nargs || [];	 // or empty
-		// Common for all for now	
-		var evt = new XEvent(next,args);
-
-		var callback,dotrigger = 0;
-		//Inner trigger	
-		// Finish	
-		function triggerDone() {
-			if(callback) callback(evt);
-			dotrigger = 1;
-		}
-		// Mem leak???
-		var ret = {
-			done: function(cb) {
-				if(dotrigger) { cb(evt); }
-				callback = cb;
-			}
-		}
-
-		//this.stat.emitted++;
-		// Sort
-		tocall = tocall.sort((a,b) => {
-			return (a.order - b.order) 
-		});	
-		// Get iter and setup evt
-		var iter = tocall[Symbol.iterator]();
-		
-		function next() {
-			process.nextTick(() => chain(iter));
-		}
-
-		// Internal thing
-		function chain(iter) { 
-			// Stack overflow risk? maybe put this in process.tick();
-			var v = iter.next();
-			if(v.done) {
-				triggerDone(); // Done callback with evt only
-				return;
-			}
-			// Create evt here with some global event chaining iteraction	
-			try {
-				var entry = v.value;
-				evt.args = args;
-				evt.name = entry.name;
-				//self.stat.called++;
-				entry.callback(...args,evt);
-				evt.count++;
-			}catch(e) {
-				console.log(e);
-				evt.errors.push(e);
-				// Should we stop??
-			}
-			if(!evt.dowait) next();
-			evt.dowait=0; // reset wait?
-		}
-		next();
-
-		return ret;
-	}
-
-
-}
-
-module.exports = EventualChannel;

+ 0 - 31
lib/eventual/eventual.js

@@ -1,31 +0,0 @@
-/** 
- * Substitute for xeventx
- * */
-
-const EventualContext = require('./eventual-context');
-
-
-class Eventual {
-	constructor() {
-		this._events = {
-			ctx: [],
-			state: {} 
-		};
-	}
-	createContext() {
-		var ret = new EventualContext(this);
-		this._events.ctx.push(ret);
-		return ret;
-	}
-	destroyContext(ctx) {
-		var i = this._events.ctx.indexOf(ctx);
-		if(i!=-1) this._events.ctx.splice(i,1);
-	}
-	state(name,args) {
-		// Should do this per context
-		this._events.state[name] = args;
-	}
-}
-
-module.exports = Eventual;
-

+ 1 - 1
lib/eventual/index.js

@@ -1 +1 @@
-module.exports = require('./eventual');
+module.exports = require('./lib/eventual');

+ 46 - 0
lib/eventual/lib/context-flat-list/context.js

@@ -0,0 +1,46 @@
+/** Old and deprecated **/
+class EventualContext {
+
+	constructor(eventual) {
+		this.version = "Context FLAT model";
+		this.eventual = eventual;
+		// Contextual listeners, it will invalidate regexp?
+		this.listeners = [];
+	}
+
+	/** flat model **/
+	on(name,cb) {
+		// Any listener will be placed here
+		this.listeners.push({
+			name: name,
+			callback:cb
+		});
+		return this;
+	}
+	getCallbacks(name) {
+		var ret = [];
+		this.listeners.forEach((l) =>  {
+			if(l.name == name) { ret.push(l); }
+		})
+		return ret;
+	}
+	emit(name,...args) {
+		this.eventual.emit(name,...args);
+	}
+	/*emit(name,...args) {
+		// We need to go trought all contexts in Eventual
+		var tocall = [];
+		this.eventual._events.ctx.forEach((c) => {
+			c.listeners.forEach((l) =>  {
+				if(l.name == name) { tocall.push(l); }
+			})
+		});
+		this.eventual.process(tocall,name,args);
+	}/**/
+	destroy() {
+		this.eventual.destroyContext(this);
+		this.listeners = null;
+	}
+}
+
+module.exports = EventualContext;

+ 1 - 0
lib/eventual/lib/context-flat-list/index.js

@@ -0,0 +1 @@
+module.exports = require('./context');

+ 15 - 0
lib/eventual/lib/context-flat-map/channel.js

@@ -0,0 +1,15 @@
+class Channel {
+	constructor(context,name) {
+		this.context = context;
+		this.name = name; // Full name
+	}
+	channel(name) {
+		return new Channel(this.context,this.name + ":" + name);
+	}
+	on(name,cb,order) {
+		this.context.on(this.name + ":" + name,cb,order);
+		return this;
+	}
+}
+
+module.exports = Channel;

+ 71 - 0
lib/eventual/lib/context-flat-map/context.js

@@ -0,0 +1,71 @@
+var Channel = require("./channel");
+
+const chs = ":"; // Channel separator
+
+class EventualContext {
+
+	constructor(eventual) {
+		this.version = "Context MAP version";
+		this.eventual = eventual;
+		//this.listeners = new Map();
+		this.listeners = {}; // Flat map
+		this.watchers = {};
+	}
+	destroy() {
+		this.eventual.destroyContext(this);
+	}
+	channel(name) {
+		return new Channel(this,name);
+	}
+	get(name,create) {
+		if(!this.listeners[name] && create) {
+			var o = {listeners:{},callbacks:[]};
+			this.listeners[name]= o;
+			return o;
+		}
+		return this.listeners[name];
+
+		/*var nodes = name.split(chs);
+		var cur = this;
+		for(var v of nodes ) {
+			if(cur.listeners[v] == undefined) {
+				if(create == undefined) { return null; }
+				cur.listeners[v] = {listeners:{},callbacks:[]}
+			}
+			cur = cur.listeners[v]; // next;
+		};
+		return cur;*/
+	}
+	getCallbacks(name) {
+		var listener = this.get(name);
+		if(listener==null) return [];	
+		return listener.callbacks;
+	}
+
+	getWatchers(name) {
+		return this.watchers[name] || [];
+	}
+		on(name,callback,order = 0) {
+		var listener = this.get(name,true);
+		listener.callbacks.push({name,callback:callback,order});
+	}
+	emit(name,...args) {
+		return this.eventual.emit(name,...args);
+	}
+	// Watcher features
+	watch(name,callback) {
+		if(this.watchers[name]== undefined) this.watchers[name]= [];
+		this.watchers[name].push(callback);
+
+		callback(this.eventual._events.store[name]);
+	}
+	set(name,value) {
+		this.eventual.set(name,value);
+	}
+	unset(name) {
+		this.eventual.unset(name);
+	}
+
+}
+
+module.exports = EventualContext;

+ 1 - 0
lib/eventual/lib/context-flat-map/index.js

@@ -0,0 +1 @@
+module.exports = require('./context');

+ 92 - 0
lib/eventual/lib/context-recursive-objects/channel.js

@@ -0,0 +1,92 @@
+/** Concept each channel can have child channels ??**/
+
+const chs = ':'; // Channel separator
+
+class EventualChannel {
+
+	constructor(eventual, name,parent) {
+		// We could fetch eventual from parent
+		this.eventual = eventual;
+		this.name = name;
+		this.parent = parent; //?? we need
+		
+		this.childs = {}
+		this.listeners = [];
+	}
+	// createChannel based on name
+	//
+	fullName() {
+		var name = this.name;
+		for(var cur = this;cur = cur.parent;cur.parent) {
+			if(this.parent.parent) { // if not root
+				name = this.parent.name +":" + name;
+			}
+		}
+		return  name;
+	}
+
+	// Recursive
+	get2(name,create) {
+		if(name == undefined) return this;
+
+		var cur = this;	
+		var [childName,...sub] = name.split(chs);
+		
+		if(cur.child[childName] == undefined) {
+			if(!create) return null;
+			cur.child[name] = new EventualChannel(this.eventual,name,this);
+		}
+		return this.get2(sub.join(chs),create);
+	};
+
+	// Should be private function
+	get(name,create) {
+		var nodes = name.split(chs);
+		var cur = this;
+		var ok = 1;
+
+		nodes.some((v) => {
+			if( cur.childs[v] == undefined) {
+				if(create == undefined) { cur = null; return true; }
+				cur.childs[v] = new EventualChannel(this.eventual,name,this);
+			}
+			cur = cur.childs[v]; // next;
+		});
+		return cur;
+	}
+
+	channel(name) { // Will create channel and return new child channel
+		return this.get(name,true);
+	}
+	
+	// Get listeners
+	getCallbacks(name) {
+		var channel	= this.get(name);
+		if(channel) return channel.listeners;
+		return [];
+	}
+
+	// Maybe this should be in context?
+	// Registers 
+	// new listener
+	on (name,cb,order) {
+		var channel = this.channel(name);
+		var listener = { name:name, callback:cb, order: order || 0 };
+		channel.listeners.push(listener)
+
+		// Check for state call // Disable this flavouring watch
+		var cname = channel.fullName();
+		if(this.eventual._events.state[cname]!=undefined) {
+			this.eventual.process([listener],this.eventual._events.state[cname]);
+		}
+		return this;
+	}
+	
+	// Emit is wrong here since it will only call same context
+	/*emit(name,args) {
+		var tocall = this.search(name);
+		return this.eventual.process(tocall,args);
+	}*/
+}
+
+module.exports = EventualChannel;

+ 47 - 0
lib/eventual/lib/context-recursive-objects/context.js

@@ -0,0 +1,47 @@
+
+/** Concept each channel can have child channels ??**/
+var EventualChannel = require('./channel');
+
+class Context extends EventualChannel {
+	constructor(eventual) {
+		super(eventual);
+		this.version = "Context Channel recursion";
+		// Listener childs here
+	}
+	// Seems something to eventual and not context
+	
+	// Alias
+	emit(name,...args) {
+		return this.eventual.emit(name,...args);
+	}	
+
+	state(name,...args) {
+		this.eventual.state(name,args);
+	}
+	destroy() {
+		this.childs = null;
+		this.listeners = null;
+		this.eventual.destroyContext(this);
+	}
+	toString() {
+		var out = [];
+		this.eventual._events.ctx.forEach((c) => {	
+			var cur = c;
+			// First level
+			function listChild(cur,prefix) {
+				for( var c in cur.childs) {
+					var name = (prefix)?prefix + ":" + c:c;
+				out.push(name);
+				listChild(cur.childs[c], name);
+				}
+			}
+			listChild(cur,"");
+		});
+
+		return out.join("\n");
+	}
+
+
+}
+
+module.exports = Context;

+ 1 - 0
lib/eventual/lib/context-recursive-objects/index.js

@@ -0,0 +1 @@
+module.exports = require('./context');

+ 18 - 0
lib/eventual/lib/event-param.js

@@ -0,0 +1,18 @@
+// Create event .js
+class Event {
+	constructor(donecb,args) {
+		this.count = 0;
+		this.dowait = 0;
+		
+		this.done= donecb; // Callback
+		this.errors = [];
+		this.params = args;
+	}
+	wait() {
+		this.dowait = 1;
+	}
+}
+
+
+module.exports = Event;
+

+ 128 - 0
lib/eventual/lib/eventual.js

@@ -0,0 +1,128 @@
+/** 
+ * Substitute for xeventx
+ * */
+
+const EventualContext = require('./context-flat-map');
+const EventParam = require('./event-param');
+
+class Eventual {
+	constructor() {
+		this._events = {
+			ctx: new Set(),
+			store: {}
+		};
+	}
+
+	set(name,value) {
+		if(value == undefined) {
+			delete this._events.store[name];
+		}else {
+			this._events.store[name] = value;
+		}
+		var tocall = [];	
+		// Trigger value separatedaly
+		this._events.ctx.forEach((c) => {
+			var watchers = c.getWatchers(name);
+			watchers.forEach((w) => {
+				tocall.push(w);
+			});
+		});
+		tocall.forEach((tc) => {
+			tc(value);
+		});
+	}
+	unset(name) {
+		this.set(name,undefined);
+	}
+	emit(name,...args) {
+		// Special send to all eventual contexts
+		var tocall = [];		
+		this._events.ctx.forEach((c) => {
+			var callbacks = c.getCallbacks(name);
+			//tocall.push(...callbacks); // Oh too many will break
+			callbacks.forEach((l) => { tocall.push(l); });
+		});
+		return this.process(tocall,args)
+	}
+
+	processsimple(tocall,nargs) {
+		tocall.forEach((l) => {
+			l.callback(...nargs);
+		});
+	}
+	// process should be handled here
+	process(tocall,nargs) {
+		var args = nargs || [];	 // or empty
+		var evt = new EventParam(next,args);
+		var callback,dotrigger = 0;
+		//Inner trigger	
+		// Finish	
+		function triggerDone() {
+			if(callback) callback(evt);
+			dotrigger = 1;
+		}
+		var ret = {
+			done: function(cb) {
+				if(dotrigger) { cb(evt); }
+				callback = cb;
+			}
+		}
+		tocall = tocall.sort((a,b) => {
+			return (a.order - b.order) 
+		});	
+		// Get iter and setup evt
+		var iter = tocall[Symbol.iterator]();
+		
+		function next() {
+			process.nextTick(() => chain(iter));
+		}
+
+		// Internal thing
+		function chain(iter) { 
+			// Stack overflow risk? maybe put this in process.tick();
+			var v = iter.next();
+			if(v.done) {
+				triggerDone(); // Done callback with evt only
+				return;
+			}
+			// Create evt here with some global event chaining iteraction	
+			try {
+				// Setup entry info
+				var entry = v.value;
+				evt.args = args;
+				evt.name = entry.name;
+				entry.callback(...args,evt);
+				evt.count++;
+			}catch(e) {
+				console.log(e);
+				evt.errors.push(e);
+				// Should we stop??
+			}
+			if(!evt.dowait) next();
+			evt.dowait=0; // reset wait?
+		}
+		next();
+
+		return ret;
+	}
+
+
+	createContext() {
+		var ret = new EventualContext(this);
+		this._events.ctx.add(ret);
+		return ret;
+	}
+	destroyContext(ctx) {
+		this._events.ctx.delete(ctx);
+	}
+	state(name,args) {
+		// Should do this per context
+		this._events.state[name] = args;
+	}
+
+
+	
+}
+
+module.exports = Eventual;
+

+ 0 - 227
lib/utils/xevents.js

@@ -1,227 +0,0 @@
-var log = require('hlogger').createLogger('xevents');
-
-
-class XPrefix {
-	constructor(ctx,event,prefix) {
-		this.ctx = ctx;
-		this.event = event;
-		this.prefix = prefix || ""; 
-	}
-	on(name,cb) {
-		this.event.on(this.ctx,this.prefix + ":" + name, cb);
-		return this;
-	}
-}
-
-
-
-class XEvent {
-	constructor(donecb,args) {
-		this.count = 0;
-		this.dowait = 0;
-		
-		this.done= donecb; // Callback
-		this.errors = [];
-		this.params = args;
-	}
-	wait() {
-		this.dowait = 1;
-	}
-}
-
-class XEventListener {
-	constructor(ctx,name,cb,order) {
-		this.ctx = ctx;
-		this.name = name;
-		this.callback = cb;
-		this.order = order || 0; // Late call
-	}
-}
-
-
-// Smarter event system?
-class XEventEmitter {
-	
-	constructor() {
-		// Prepare this in a single context
-
-		//this.listeners = new Map();
-		this.listeners = [];
-
-		this.auto = {};
-		this.stat = {
-			emitted:0,
-			tried:0,
-			called:0
-		}
-	}
-
-	addListener(...args) {
-		var ctx = this,evtName,cb,order;
-		if(typeof(args[0]) == "string") {
-			[evtName,cb,order] = args;
-		} else {
-			[ctx,evtName,cb,order] = args;
-		}
-		var listener = new XEventListener(ctx,evtName,cb,order);
-		this.listeners.push(listener);
-		//this.listeners.push(entry);
-	
-		// Process the autos
-		var re = new RegExp(evtName);
-		Object.keys(this.auto).map((v) => {
-			var match = v.match(re);
-			if(v.match(re)) {
-				var tocall = [{match:match,listener:listener}];
-				this.process(tocall,this.auto[v]); // No callback
-			}
-		});
-	
-			/*	try {
-					cb(this.auto[v], new XEvent());
-				} catch(e) {
-					console.log(e);
-				}
-			}
-		});*/
-	}
-	// Remove listeners by ctx
-	removeListener(ctx,name) {
-		this.listeners = this.listeners.filter((v) => {
-			if(v == ctx || v.ctx == ctx) {
-			} else {
-				return v;
-			}
-		});
-	}
-	
-	// 1 arg only
-	toggleOn(name,...args) {
-		// Should be contextual if we remove context toggle will remain
-		this.auto[name] = args; // should store array
-		this.emit(name,...args);
-	}
-
-	toggleOff(name) {
-		delete this.auto[name];
-	}
-
-	process(tocall,nargs,cb) {
-		var self=this;
-	
-		var args = nargs || [];	 // or empty
-		// Common for all for now	
-		var evt = new XEvent(next,args);
-
-		this.stat.emitted++;
-		// Sort
-		tocall = tocall.sort((a,b) => {
-			return (a.listener.order - b.listener.order) 
-		});	
-		// Get iter and setup evt
-		var iter = tocall[Symbol.iterator]();
-		
-		function next() {
-			process.nextTick(() => chain(iter));
-		}
-
-		// Internal thing
-		function chain(iter) { 
-			// Stack overflow risk? maybe put this in process.tick();
-			var v = iter.next();
-			if(v.done) {
-				if(cb != undefined) cb(evt); // Done callback with evt only
-				return;
-			}
-			// Create evt here with some global event chaining iteraction	
-			try {
-				var entry = v.value;
-				evt.match = entry.match;
-				evt.args = args;
-				self.stat.called++;
-				entry.listener.callback(...args,evt);
-				evt.count++;
-			}catch(e) {
-				console.log(e);
-				evt.errors.push(e);
-				// Should we stop??
-			}
-			if(!evt.dowait) next();
-			evt.dowait=0; // reset wait?
-		}
-		next();
-	}
-
-	search(name,ctx) {
-		var ret = [];
-		this.listeners.forEach((v) => {
-			var re = new RegExp( "^" + v.name+ "$" );
-			//var re = v.name;
-			var matchres = name.match(re);
-			if(matchres && (ctx == undefined || ctx == v.ctx) ) {
-				ret.push({
-					match: matchres,
-					listener:v
-				});
-			}
-		});
-		return ret;
-	}
-
-	// Multiple argument
-	// Should work like emit("event",1,2,3,4,5);
-	emit(name,...args) {
-		this.stat.tried++;
-		var tocall = this.search(name);
-
-		var evt,callback,dotrigger = 0;
-		function trigger(ievt) {
-			evt = ievt; // Will call
-			if(callback)callback(evt);
-		}
-		// Mem leak???
-		var ret = {
-			done: function(cb) {
-				if(evt) { cb(evt); }
-				callback = cb;
-			}
-		}
-		// Test
-		this.process(tocall,args, trigger );
-		return ret ;
-	}
-	// Why?
-	/*emitTo(ctx,name,args) {
-		var tocall = this.search(name,ctx)
-		this.process(tocall,arg,cb);
-	}*/
-	// Alias
-	on(ctx,match,cb) {
-		this.addListener(ctx,match,cb);
-		return this;
-	}
-	after(ctx,match,cb) {
-		this.addListener(ctx,match,cb,1000);
-		return this;
-	}
-	prefix(ctx,prefix) {
-		return new XPrefix(ctx,this,prefix);
-	}
-	/*when(ctx,match,cb) {
-		this.addListener(ctx,match,cb);
-	}*/
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-module.exports=XEventEmitter;

+ 142 - 0
test/eventual-test/benchmark.js

@@ -0,0 +1,142 @@
+const Eventual = require('../../lib/eventual');
+const Benchmark = require('../../lib/utils/benchmark');
+
+var events = new Eventual();
+
+
+function ntokb(n) {
+	var suffix = ["B","KB","MB","GB"];
+	var si = 0;
+	while( n> 1024 && si< suffix.length) {
+		n/=1024;
+		si++;
+	}
+	return n.toFixed(2) + " " +suffix[si];
+}
+
+
+
+var test = new Set();
+
+test.add("hello:world");
+
+if(test.has("hello:world")) {
+	console.log("True is not reference");
+};
+
+
+
+function makeid()
+{
+    var text = "";
+    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+    for( var i=0; i < 5; i++ )
+        text += possible.charAt(Math.floor(Math.random() * possible.length));
+
+    return text;
+}
+
+
+
+var g = events.createContext();
+console.log("Context MODEL: " + g.version);
+
+function createContexts() {
+	var ncount = 1000000;
+	var r= [];
+	console.log("Adding",ncount,"contexts");
+	for(var i = 0;i<ncount;i++) {
+		r.push(events.createContext());
+	}
+	return r;
+}
+
+function stressEvents() {
+	var ctx = events.createContext();
+	var ctx2 = events.createContext();
+	
+	// 1 million
+	var ncount = 100;
+	console.log("Adding",ncount * ncount*ncount,"events in 2 contexts");
+	for(var i = 0;i<ncount;i++) {
+		// Create random contexts too
+		var evtName = makeid();
+		for(var j = 0;j<ncount;j++) {
+			var n2 = evtName + ":" + makeid();
+			for(var k = 0;k<ncount;k++) {
+				var n3 = n2+":"+k;
+				ctx.on(evtName,(a,b,c,evt) => {
+						console.log("evt: " , evt);
+						console.log("Args: " + a,b,c);	
+				});
+			}
+		}
+	}
+	// Second context
+	console.log("Adding events to second context");
+	for(var i = 0;i<ncount;i++) {
+		ctx2.on('test:test',(a,b,c) => { });
+	};
+	return [ctx,ctx2];
+}
+
+function pinger() {
+	var pingbm = new Benchmark();
+	var pctx = events.createContext();
+	
+	pctx.on('c1:ping',(e) => {
+		console.log("Pong: " + pingbm.mark(), "Contexts:",events._events.ctx.size,"Memory:",ntokb(process.memoryUsage().heapTotal));
+	})
+	setInterval(() => {
+		pingbm.start();
+		pctx.emit('c1:ping');
+	},500);
+}
+
+
+function sequential() {
+	// Testing done
+	var cc = events.createContext();	
+	var cc2 = events.createContext();
+	cc.on('hello',(e) => {
+		e.wait();
+		console.log("CC1 Hello will wait 1s");
+		setTimeout(() => {
+			e.done()
+		},1000);
+	});
+	cc2.on('hello',(e) => {
+		e.wait();
+		console.log("cc2 Hello");
+		setTimeout(() => {
+			e.done();
+		},2000);
+	});
+
+console.log("Broadcasting hello");
+	cc.emit('hello').done(() => {
+		console.log("Hello called");
+	});
+}
+
+
+pinger();
+console.log("Turning on stress in 10s");
+
+var contextList;
+setTimeout(() => {
+	console.log("Stressing events");
+	contextList = stressEvents();
+},10000);
+setTimeout(() => {
+	console.log("Clearing events context");
+	contextList.forEach(c => c.destroy())
+	contextList = null;
+},20000);
+
+setTimeout(() =>  { 
+	contextList = createContexts(); 
+},30000);
+setTimeout(() => stressEvents(),40000);
+

+ 0 - 128
test/eventual-test/index.js

@@ -1,128 +0,0 @@
-const Eventual = require('../../lib/eventual');
-const Benchmark = require('../../lib/utils/benchmark');
-
-
-
-function makeid()
-{
-    var text = "";
-    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-
-    for( var i=0; i < 5; i++ )
-        text += possible.charAt(Math.floor(Math.random() * possible.length));
-
-    return text;
-}
-
-
-var events = new Eventual();
-var cevt= events.createContext();
-var ctx2 = events.createContext();
-
-function stressEvents() {
-	// 1 million
-	var ncount = 1000000;
-	console.log("Adding",ncount,"events");
-	for(var i = 0;i<ncount;i++) {
-		// Create random contexts too
-		var evtName = makeid() + ":test";
-		cevt.on(evtName,(a,b,c,evt) => {
-			console.log("evt: " , evt);
-			console.log("Args: " + a,b,c);	
-		});
-	}
-	// Second context
-	console.log("Adding events to second context");
-	for(var i = 0;i<ncount;i++) {
-		ctx2.on('test:test',(a,b,c) => { });
-	};
-}
-
-
-
-
-
-function pinger() {
-
-	ctx2.on('c1:ping',() => {
-		console.log("Pong from ctx2");
-	});
-
-	var pingbm = new Benchmark();
-	var pctx = events.createContext();
-	pctx .on('c1:ping',(e) => {
-		console.log("Pong: " + pingbm.mark(), "Contexts:",events._events.ctx.length);
-	})
-
-	var test = 0;
-	setInterval(() => {
-		pingbm.start();
-		console.log("Sending ping");
-		pctx.emit('c1:ping').done((e) => {
-			console.log("executed");	
-		});
-		if( test > 10) { // 10 second
-			cevt.destroy();
-			ctx2.destroy();
-		}
-		test++;
-	},1000);
-}
-function sequential() {
-	// Testing done
-	var cc = events.createContext();	
-	var cc2 = events.createContext();
-
-	cc.on('hello',(e) => {
-		e.wait();
-		console.log("CC1 Hello will wait 1s");
-		setTimeout(() => {
-
-			e.done()
-		},1000);
-	});
-	cc2.on('hello',(e) => {
-		e.wait();
-		console.log("cc2 Hello");
-		setTimeout(() => {
-			e.done();
-		},2000);
-	});
-
-console.log("Broadcasting hello");
-	cc.broadcast('hello').done(() => {
-		console.log("Hello called");
-	});
-}
-
-
-//stressEvents();
-//pinger();
-//sequential();
-//
-
-// State changes
-
-var cc = events.createContext();
-var cc2 = events.createContext();
-//cc.emit('test');
-//cc.state('test',1);
-
-// call this
-cc2.on('test:test2',() => { // Should be calling it self
-	console.log("Ok2");
-});
-cc.on('test:test2:test3',() => { // Should be calling it self
-	console.log("ok3");
-});
-cc.onMatch('test.*',() => {
-	console.log("Event matched");
-});
-
-cc2.broadcast('test:test2:test3');
-
-
-
-
-
-

+ 0 - 128
test/eventual-test/lib/eventual-context.js

@@ -1,128 +0,0 @@
-
-/** Concept each channel can have child channels ??**/
-const chs = ':';
-
-
-class EventualChannel {
-
-	constructor(name,parent) {
-		this.name = name;
-		this.parent = parent;
-		
-		this.callbacks = [], // Local callbacks
-		this.childs = {}
-		this.listeners = [];
-	}
-
-	// createChannel based on name
-	//
-	getChannel(name,create) { // Should return listeners to mess up
-		var [child, ...sub]= name.split(chs);
-		if(this.childs[child] == undefined) {
-			if(create==undefined) return []; // Maybe empty?
-			this.childs[child] = new EventualChannel(this);
-		}
-		if(sub.length != 0) {	 // We could do this without recursion
-			return this.childs[child].getChannel(sub.join(chs),create);
-		}
-		return this.childs[child].listeners;
-	}
-	getChannel2(name,create) {
-		var nodes = name.split(chs);
-		var cur = this;
-		nodes.forEach((v) => {
-			if( cur.childs[v] == undefined) {
-				if(create == undefined) return []; // Empty
-				cur.childs[v] = new EventualChannel(name,this);
-			}
-			cur = cur.childs[v]; // next;
-		});
-
-		return cur.listeners;
-	}
-	search(name) {
-		return this.getChannel2(name);
-	}
-	// Registers
-	on(name,cb) {
-		var listeners = this.getChannel2(name,true);
-		listeners.push(cb);
-	}
-	emit(name,args) {
-		var listeners = this.search(name);
-		listeners.forEach((l) => {
-			l(args);
-		});
-
-		// Something to process callback as the xevents
-	}
-
-}
-
-class EventualContext2 extends EventualChannel {
-		constructor(eventual) {
-			super();
-			this.eventual = eventual;
-		}
-		broadcast(name,...args) {
-			this.eventual._events.ctx.forEach((c) => {
-				c.emit(name,...args);
-			});
-		}
-
-		destroy() {
-			this.childs = null;
-			this.listeners = null;
-			var i = this.eventual._events.ctx.indexOf(this);
-			if(i!=-1) this.eventual._events.ctx.splice(i,1);
-		}
-}
-
-
-class EventualContext extends EventualChannel {
-	constructor(eventual) {
-		super();
-		this.eventual = eventual;
-		// Contextual listeners, it will invalidate regexp?
-		this.listeners = [];
-	}
-	process(tocall,args,donecb) {
-		tocall.forEach((l) => {
-			l.callback(...args);
-		});
-	}
-	broadcast(name,...args) {
-		this.eventual._events.ctx.forEach((c) => {
-			c.emit(name,...args);
-		});
-	}
-	/** flat model **/
-	on(name,cb) {
-		// Any listener will be placed here
-		this.listeners.push({
-			name: name,
-			callback:cb
-		});
-		return this;
-	}
-	emit(name,...args) {
-		// We need to go trought all contexts in Eventual
-		var tocall = [];
-		this.eventual._events.ctx.forEach((c) => {
-			c.listeners.forEach((l) =>  {
-				if(l.name == name) {
-					tocall.push(l);
-				}
-			})
-		});
-		this.process(tocall,name,args);
-	}/**/
-
-	destroy() {
-		var i = this.eventual._events.ctx.indexOf(this);
-		if(i!=-1) this.eventual._events.ctx.splice(i,1);
-		this.listeners = null;
-	}
-}
-
-module.exports = EventualContext;

+ 0 - 19
test/eventual-test/lib/eventual.js

@@ -1,19 +0,0 @@
-const EventualContext = require('./eventual-context');
-
-
-class Eventual {
-	constructor() {
-		this._events = {
-			ctx: []
-		};
-	}
-
-	createContext() {
-		var ret = new EventualContext(this);
-		this._events.ctx.push(ret);
-		return ret;
-	}
-}
-
-module.exports = Eventual;
-

+ 17 - 0
test/eventual-test/watcher.js

@@ -0,0 +1,17 @@
+var Eventual = require('../../lib/eventual');
+
+
+var events = new Eventual();
+
+var ctx = events.createContext();
+
+
+ctx.watch('core-installer:installed',(value) => {
+	console.log("value changed:" , value);
+});
+
+
+ctx.set('core-installer:installed',2);
+
+
+

+ 0 - 1
test/hci-usecase/bundles/hci-http/index.js

@@ -36,7 +36,6 @@ var activator = {
 				this.clients[k].destroy();
 			};
 		});
-		context.state('serverStart',this);
 	},
 
 	stop(context) {

+ 4 - 2
test/hci-usecase/bundles/stress-test/index.js

@@ -47,9 +47,10 @@ module.exports.bundleActivator = {
 		this.context.emit('ping',e);
 	},
 	events(req,res,e) {
-		var count = 1000000;
+		res.write("Adding 1 million events\n");
+		var count = 1000000; 
 		for(;count;count--) {
-			this.context.on('stress-test:test:event',() => { var arr = new Array(5);	});
+			this.context.on('stress-test:'+Math.random().toString(36).substring(7) + ':test:event',() => { var arr = new Array(5);	});
 		}
 	},
 
@@ -73,6 +74,7 @@ module.exports.bundleActivator = {
 		//
 		var toggle = false;
 		this.ci = context.setInterval(() => {
+			res.write("Toggling module\n");
 			if(toggle) {
 				this.context.manager.load(__dirname + "/memory-test-unit");
 			}else {

+ 0 - 3
test/hci-usecase/siege.err.txt

@@ -1,3 +0,0 @@
-** SIEGE 4.0.2
-** Preparing 25 concurrent users for battle.
-The server is now under siege...

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 3072
test/hci-usecase/siege.out.txt