2045 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			2045 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								head	1.5;
							 | 
						||
| 
								 | 
							
								access;
							 | 
						||
| 
								 | 
							
								symbols;
							 | 
						||
| 
								 | 
							
								locks
							 | 
						||
| 
								 | 
							
									sbosse:1.5; strict;
							 | 
						||
| 
								 | 
							
								comment	@# @;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.5
							 | 
						||
| 
								 | 
							
								date	2020.02.03.09.45.01;	author sbosse;	state Exp;
							 | 
						||
| 
								 | 
							
								branches;
							 | 
						||
| 
								 | 
							
								next	1.4;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.4
							 | 
						||
| 
								 | 
							
								date	2017.06.19.17.18.39;	author sbosse;	state Exp;
							 | 
						||
| 
								 | 
							
								branches;
							 | 
						||
| 
								 | 
							
								next	1.3;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.3
							 | 
						||
| 
								 | 
							
								date	2017.06.06.14.53.57;	author sbosse;	state Exp;
							 | 
						||
| 
								 | 
							
								branches;
							 | 
						||
| 
								 | 
							
								next	1.2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.2
							 | 
						||
| 
								 | 
							
								date	2017.05.27.18.20.44;	author sbosse;	state Exp;
							 | 
						||
| 
								 | 
							
								branches;
							 | 
						||
| 
								 | 
							
								next	1.1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.1
							 | 
						||
| 
								 | 
							
								date	2017.05.23.07.00.54;	author sbosse;	state Exp;
							 | 
						||
| 
								 | 
							
								branches;
							 | 
						||
| 
								 | 
							
								next	;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								desc
							 | 
						||
| 
								 | 
							
								@@
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.5
							 | 
						||
| 
								 | 
							
								log
							 | 
						||
| 
								 | 
							
								@.
							 | 
						||
| 
								 | 
							
								@
							 | 
						||
| 
								 | 
							
								text
							 | 
						||
| 
								 | 
							
								@/**
							 | 
						||
| 
								 | 
							
								 **      ==============================
							 | 
						||
| 
								 | 
							
								 **       O           O      O   OOOO
							 | 
						||
| 
								 | 
							
								 **       O           O     O O  O   O
							 | 
						||
| 
								 | 
							
								 **       O           O     O O  O   O
							 | 
						||
| 
								 | 
							
								 **       OOOO   OOOO O     OOO  OOOO
							 | 
						||
| 
								 | 
							
								 **       O   O       O    O   O O   O
							 | 
						||
| 
								 | 
							
								 **       O   O       O    O   O O   O
							 | 
						||
| 
								 | 
							
								 **       OOOO        OOOO O   O OOOO
							 | 
						||
| 
								 | 
							
								 **      ==============================
							 | 
						||
| 
								 | 
							
								 **      Dr. Stefan Bosse http://www.bsslab.de
							 | 
						||
| 
								 | 
							
								 **
							 | 
						||
| 
								 | 
							
								 **      COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED
							 | 
						||
| 
								 | 
							
								 **                 BY THE AUTHOR(S).
							 | 
						||
| 
								 | 
							
								 **                 THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
							 | 
						||
| 
								 | 
							
								 **                 MODIFIED, OR OTHERWISE USED IN A CONTEXT
							 | 
						||
| 
								 | 
							
								 **                 OUTSIDE OF THE SOFTWARE SYSTEM.
							 | 
						||
| 
								 | 
							
								 **
							 | 
						||
| 
								 | 
							
								 **    $AUTHORS:     Stefan Bosse
							 | 
						||
| 
								 | 
							
								 **    $INITIAL:     (C) 2006-2019 bLAB
							 | 
						||
| 
								 | 
							
								 **    $CREATED:     25-12-16 by sbosse.
							 | 
						||
| 
								 | 
							
								 **    $RCS:         $Id: jamlib.js,v 1.4 2017/06/19 17:18:39 sbosse Exp sbosse $
							 | 
						||
| 
								 | 
							
								 **    $VERSION:     1.32.1
							 | 
						||
| 
								 | 
							
								 **
							 | 
						||
| 
								 | 
							
								 **    $INFO:
							 | 
						||
| 
								 | 
							
								 **
							 | 
						||
| 
								 | 
							
								 **  JAM library API that can be embedded in any host application.
							 | 
						||
| 
								 | 
							
								 **
							 | 
						||
| 
								 | 
							
								 **
							 | 
						||
| 
								 | 
							
								 ** New: Embedded auto setup (e.g., for clusters) using command line arguments
							 | 
						||
| 
								 | 
							
								 ** 
							 | 
						||
| 
								 | 
							
								 **      jamlib autosetup:"{options}"
							 | 
						||
| 
								 | 
							
								 **
							 | 
						||
| 
								 | 
							
								 **
							 | 
						||
| 
								 | 
							
								 **    $ENDOFINFO
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								var onexit=false;
							 | 
						||
| 
								 | 
							
								var start=false;
							 | 
						||
| 
								 | 
							
								var options = {
							 | 
						||
| 
								 | 
							
								  geo:undefined,
							 | 
						||
| 
								 | 
							
								  verbose:0,
							 | 
						||
| 
								 | 
							
								  version:'1.32.1'  // public version
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								global.config={simulation:false,nonetwork:false};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var Io = Require('com/io');
							 | 
						||
| 
								 | 
							
								var Comp = Require('com/compat');
							 | 
						||
| 
								 | 
							
								var Aios = Require('jam/aios');
							 | 
						||
| 
								 | 
							
								var Esprima = Require('parser/esprima');
							 | 
						||
| 
								 | 
							
								var Json = Require('jam/jsonfn');
							 | 
						||
| 
								 | 
							
								var fs = Require('fs');
							 | 
						||
| 
								 | 
							
								var Sat = Require('dos/ext/satelize');
							 | 
						||
| 
								 | 
							
								var CBL = Require('com/cbl');
							 | 
						||
| 
								 | 
							
								var platform = Require('os/platform');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var DIR = Aios.DIR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Parse command line arguments; extract a:v attributes
							 | 
						||
| 
								 | 
							
								var environment = process.env; process.argv.slice(2).forEach(function (arg) { 
							 | 
						||
| 
								 | 
							
								  var tokens=arg.match(/([a-zA-Z]+):(['"0-9a-zA-Z_:\->\.\{\},;]+)/);
							 | 
						||
| 
								 | 
							
								  if (tokens && tokens.length==3) environment[tokens[1]]=tokens[2];
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function locationEvalError(e) {
							 | 
						||
| 
								 | 
							
								  return (e.lineNumber?(' at line '+e.lineNumber+
							 | 
						||
| 
								 | 
							
								                       (e.columnNumber?(' column '+e.columnNumber):'')):'')
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (typeof setImmediate == 'undefined') {
							 | 
						||
| 
								 | 
							
								  function setImmediate(callback) {return setTimeout(callback,0)};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Extend DIR with IP capabilities of NORTH, ..
							 | 
						||
| 
								 | 
							
								DIR.North= function (ip) { return {tag:DIR.NORTH,ip:ip}}
							 | 
						||
| 
								 | 
							
								DIR.South= function (ip) { return {tag:DIR.SOUTH,ip:ip}}
							 | 
						||
| 
								 | 
							
								DIR.West = function (ip) { return {tag:DIR.WEST ,ip:ip}}
							 | 
						||
| 
								 | 
							
								DIR.East = function (ip) { return {tag:DIR.EAST ,ip:ip}}
							 | 
						||
| 
								 | 
							
								DIR.Up   = function (ip) { return {tag:DIR.UP ,ip:ip}}
							 | 
						||
| 
								 | 
							
								DIR.Down = function (ip) { return {tag:DIR.DOWN ,ip:ip}}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 *  typeof options = { 
							 | 
						||
| 
								 | 
							
								 *                     connections?, 
							 | 
						||
| 
								 | 
							
								 *                     print? is agent and control message output function,
							 | 
						||
| 
								 | 
							
								 *                     printAgent? is agent message only output function,
							 | 
						||
| 
								 | 
							
								 *                     fork?,
							 | 
						||
| 
								 | 
							
								 *                     provider?, consumer?, 
							 | 
						||
| 
								 | 
							
								 *                     classes?, 
							 | 
						||
| 
								 | 
							
								 *                     id?:string is JAM and JAM root node id,
							 | 
						||
| 
								 | 
							
								 *                     world?:string is JAM world id,
							 | 
						||
| 
								 | 
							
								 *                     position?:{x,y}, 
							 | 
						||
| 
								 | 
							
								 *                     cluster?:boolean|[] is an attached cluster node,
							 | 
						||
| 
								 | 
							
								 *                     nowatch:boolean is a disable flag for agent watchdog checking,
							 | 
						||
| 
								 | 
							
								 *                     checkpoint:boolean is a flag forcing code checkpointing (even if watchdog is available),
							 | 
						||
| 
								 | 
							
								 *                     nolimits:boolean is a disable flag for agent resource monitoring,
							 | 
						||
| 
								 | 
							
								 *                     log?:{class?:boolean,node?,agent?,parent?,host?,time?,Time?,pid?},
							 | 
						||
| 
								 | 
							
								 *                     logJam?:{host?,time?,pid?,node?,world?},
							 | 
						||
| 
								 | 
							
								 *                     scheduler?:scheduler is an external scheduler, singlestep?,
							 | 
						||
| 
								 | 
							
								 *                     network?:{cluster?,rows,columns,connect?:function},
							 | 
						||
| 
								 | 
							
								 *                     verbose?, TMO? }
							 | 
						||
| 
								 | 
							
								 *  with typeof connections = { 
							 | 
						||
| 
								 | 
							
								 *    @@kind : {from:string,to?:string,proto:string='udp'|'tcp'|'http'|'stream',num?:number,on?,range?:number[]},
							 | 
						||
| 
								 | 
							
								 *    @@kind : {send:function, status:function, register?:function(@@link)} , 
							 | 
						||
| 
								 | 
							
								 *    @@kind : .. }
							 | 
						||
| 
								 | 
							
								 *  with @@kind = {north,south,west,east,ip, ..}
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Connecting JAM nodes (IP)
							 | 
						||
| 
								 | 
							
								 * -------------------------
							 | 
						||
| 
								 | 
							
								 *   
							 | 
						||
| 
								 | 
							
								 *  .. Jam({
							 | 
						||
| 
								 | 
							
								 *    connections: {
							 | 
						||
| 
								 | 
							
								 *      // Generic, P2PN
							 | 
						||
| 
								 | 
							
								 *      ip?: {from:string,to?:string,proto:string='udp'|'tcp'|'http',num?:number} // AMP link (UDP) or set of AMP links (num>1)
							 | 
						||
| 
								 | 
							
								 *      // Assigned to a logical direction, P2P
							 | 
						||
| 
								 | 
							
								 *      north?: {                                                             
							 | 
						||
| 
								 | 
							
								 *        from:string,to?:string,proto?='udp'|'tcp'|'http'|'device',device?:string // device is a hardware P2P stream device 
							 | 
						||
| 
								 | 
							
								 *      }, ..
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Integration of host program streams
							 | 
						||
| 
								 | 
							
								 * ------------------------------------
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  var chan = Some Stream Channel Object;
							 | 
						||
| 
								 | 
							
								 *  
							 | 
						||
| 
								 | 
							
								 *  .. Jam({
							 | 
						||
| 
								 | 
							
								 *    connections: {
							 | 
						||
| 
								 | 
							
								 *      north?: {
							 | 
						||
| 
								 | 
							
								 *        register: function (link) {
							 | 
						||
| 
								 | 
							
								 *          // register channel data handler with link handler 
							 | 
						||
| 
								 | 
							
								 *          chan.on('data',function (data) {
							 | 
						||
| 
								 | 
							
								 *            // process raw data, extract msg={agent:string,to?,from?,..} or {signal:string,to?,from?,..}
							 | 
						||
| 
								 | 
							
								 *            if (msg.agent) link.emit('agent',msg.agent);
							 | 
						||
| 
								 | 
							
								 *            if (msg.signal) link.emit('signal',msg.signal);
							 | 
						||
| 
								 | 
							
								 *          });
							 | 
						||
| 
								 | 
							
								 *        }
							 | 
						||
| 
								 | 
							
								 *        send: function (msg) {
							 | 
						||
| 
								 | 
							
								 *          chan.send(msg);
							 | 
						||
| 
								 | 
							
								 *        },
							 | 
						||
| 
								 | 
							
								 *        status: function (to) {
							 | 
						||
| 
								 | 
							
								 *          return true;
							 | 
						||
| 
								 | 
							
								 *        }
							 | 
						||
| 
								 | 
							
								 *      }
							 | 
						||
| 
								 | 
							
								 *    }, ..
							 | 
						||
| 
								 | 
							
								 *  } 
							 | 
						||
| 
								 | 
							
								 *  
							 | 
						||
| 
								 | 
							
								 * Cluster
							 | 
						||
| 
								 | 
							
								 * --------
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * A forked cluster consists of a master node (0) and up to 8 child ndoes connected around the root node
							 | 
						||
| 
								 | 
							
								 * by streams in directions {E,S,SE,W,SW,N,NW,NE}. Each node is executed physically in a different JAM process. 
							 | 
						||
| 
								 | 
							
								 * Ex. network: {cluster:true, rows:2, columns:2},
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								var jam = function (options) {
							 | 
						||
| 
								 | 
							
								  var self=this,
							 | 
						||
| 
								 | 
							
								      p,conn,node;
							 | 
						||
| 
								 | 
							
								  this.options = options||{};
							 | 
						||
| 
								 | 
							
								  this.environment=environment;
							 | 
						||
| 
								 | 
							
								  if (this.setup)           this.setup(); // overwrite options
							 | 
						||
| 
								 | 
							
								  if (this.options.world && !this.options.id) this.options.id=this.options.world;
							 | 
						||
| 
								 | 
							
								  if (!this.options.id)     this.options.id=Aios.aidgen();
							 | 
						||
| 
								 | 
							
								  if (!this.options.log)    this.options.log={};
							 | 
						||
| 
								 | 
							
								  if (!this.options.logJam) this.options.logJam={pid:false,host:false,time:false};
							 | 
						||
| 
								 | 
							
								  this.verbose =  this.options.verbose || 0;
							 | 
						||
| 
								 | 
							
								  this.Aios =     Aios;
							 | 
						||
| 
								 | 
							
								  this.DIR =      Aios.aios.DIR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Aios.options.verbose=this.verbose;
							 | 
						||
| 
								 | 
							
								  if (options.scheduler) Aios.current.scheduler=scheduler;
							 | 
						||
| 
								 | 
							
								  if (options.nolimits||options.nowatch||options.checkpoint) 
							 | 
						||
| 
								 | 
							
								    Aios.config({nolimits:options.nolimits,nowatch:options.nowatch,checkpoint:options.checkpoint});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // out=function (msg) { Io.print('[JAM '+self.options.id+'] '+msg)};
							 | 
						||
| 
								 | 
							
								  if (this.options.print)  Aios.print=Aios.printAgent=this.options.print;
							 | 
						||
| 
								 | 
							
								  if (this.options.print2) Aios.printAgent=this.options.print2;
							 | 
						||
| 
								 | 
							
								  if (this.options.printAgent) Aios.printAgent=this.options.printAgent;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  // JAM messages
							 | 
						||
| 
								 | 
							
								  this.log=function (msg) { 
							 | 
						||
| 
								 | 
							
								    var s='[JAM',sep=' ';
							 | 
						||
| 
								 | 
							
								    if (self.options.logJam.pid && process) s += (' '+process.pid),sep=':';
							 | 
						||
| 
								 | 
							
								    if (self.options.logJam.world && Aios.current.world) s += (sep+Aios.current.world.id),sep=':';
							 | 
						||
| 
								 | 
							
								    if (self.options.logJam.node && Aios.current.node) s += (sep+Aios.current.node.id),sep=':';
							 | 
						||
| 
								 | 
							
								    if (self.options.logJam.time) s += (sep+Aios.time());
							 | 
						||
| 
								 | 
							
								    Aios.print(s+'] '+msg);
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  this.err=function (msg,err) {
							 | 
						||
| 
								 | 
							
								    self.log('Error: '+msg);
							 | 
						||
| 
								 | 
							
								    throw (err||'JAMLIB');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  this.warn=function (msg) {
							 | 
						||
| 
								 | 
							
								    self.log('Warning: '+msg);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  this.error=undefined;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  // Create a world
							 | 
						||
| 
								 | 
							
								  this.world = Aios.World.World([],{
							 | 
						||
| 
								 | 
							
								    id:this.options.world||this.options.id.toUpperCase(),
							 | 
						||
| 
								 | 
							
								    classes:options.classes||[],
							 | 
						||
| 
								 | 
							
								    scheduler:options.scheduler,
							 | 
						||
| 
								 | 
							
								    verbose:options.verbose
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  if (this.verbose) this.log('Created world '+this.world.id+'.');
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  this.node=none;
							 | 
						||
| 
								 | 
							
								  this.run=false;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  // Service loop executing the AIOS scheduler
							 | 
						||
| 
								 | 
							
								  // NOT USED if there is an external scheduler supplied (world will create JAM scheduling loop)
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.ticks=0;       // schedule loop execution counter!
							 | 
						||
| 
								 | 
							
								  this.steps=0;       // Number of schedule loop execution steps
							 | 
						||
| 
								 | 
							
								  this.loop=none;     // Schedule loop function
							 | 
						||
| 
								 | 
							
								  this.looping=none;  // Current schedule loop run (or none); can be waiting for a timeout
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								  Aios.config({fastcopy:this.options.fastcopy,
							 | 
						||
| 
								 | 
							
								               verbose:this.options.verbose});
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  if (this.options.log) 
							 | 
						||
| 
								 | 
							
								    for(p in this.options.log) Aios.config(this.options.log[p]?{"log+":p}:{"log-":p});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.process = Aios.Proc.Proc();
							 | 
						||
| 
								 | 
							
								  this.process.agent={id:'jamlib'};
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								  this.events={};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Import analyzer class...
							 | 
						||
| 
								 | 
							
								var JamAnal = Require('jam/analyzer');
							 | 
						||
| 
								 | 
							
								JamAnal.current(Aios);
							 | 
						||
| 
								 | 
							
								jam.prototype.analyzeSyntax=JamAnal.jamc.prototype.analyze;
							 | 
						||
| 
								 | 
							
								jam.prototype.syntax=JamAnal.jamc.prototype.syntax;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Add agent class to the JAM world and create sandboxed constructors.
							 | 
						||
| 
								 | 
							
								 *  type constructor = function|string
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.addClass = function (name,constructor,env) {
							 | 
						||
| 
								 | 
							
								  this.world.addClass(name,constructor,env);
							 | 
						||
| 
								 | 
							
								  if (this.verbose) this.log('Agent class '+name+' added to world library.');
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Add a new node to the world.
							 | 
						||
| 
								 | 
							
								 *  Assumption: 2d meshgrid network with (x,y) coordinates.
							 | 
						||
| 
								 | 
							
								 *  The root node has position {x=0,y=0}.
							 | 
						||
| 
								 | 
							
								 *  type of nodeDesc = {x:number,y:number,id?}
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.addNode = function (nodeDesc) {
							 | 
						||
| 
								 | 
							
								  var node,x,y;
							 | 
						||
| 
								 | 
							
								  x=nodeDesc.x;
							 | 
						||
| 
								 | 
							
								  y=nodeDesc.y;
							 | 
						||
| 
								 | 
							
								  if (Comp.array.find(this.world.nodes,function (node) {
							 | 
						||
| 
								 | 
							
								    return node.position.x==x && node.position.y==y;
							 | 
						||
| 
								 | 
							
								  })) {
							 | 
						||
| 
								 | 
							
								    this.err('addNodes: Node at positition ('+x+','+y+') exists already.');
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  node=Aios.Node.Node({id:nodeDesc.id||Aios.aidgen(),position:{x:x,y:y}},true);
							 | 
						||
| 
								 | 
							
								  if (this.verbose) this.log('Created node '+node.id+' ('+x+','+y+').');
							 | 
						||
| 
								 | 
							
								  // Add node to world
							 | 
						||
| 
								 | 
							
								  this.world.addNode(node);    
							 | 
						||
| 
								 | 
							
								  return node.id;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Add logical nodes.
							 | 
						||
| 
								 | 
							
								 *  The root node has position {x=0,y=0}.
							 | 
						||
| 
								 | 
							
								 *  type of nodes = [{x:number,y:number,id?},..]
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.addNodes = function (nodes) {  
							 | 
						||
| 
								 | 
							
								  var n,node,x,y,nodeids=[];
							 | 
						||
| 
								 | 
							
								  for(n in nodes) {
							 | 
						||
| 
								 | 
							
								    nodeids.push(this.addNode(nodes[n]));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return nodeids;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Analyze agent class template in text or object form
							 | 
						||
| 
								 | 
							
								 ** typeof @@options = {..,classname?:string}
							 | 
						||
| 
								 | 
							
								 *  Returns {report:string,interface}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.analyze = function (ac,options) {
							 | 
						||
| 
								 | 
							
								  var source,name,syntax,content,report,interface;
							 | 
						||
| 
								 | 
							
								  if (Comp.obj.isString(ac)) {
							 | 
						||
| 
								 | 
							
								    // TODO
							 | 
						||
| 
								 | 
							
								  } else if (Comp.obj.isObject(ac)) {
							 | 
						||
| 
								 | 
							
								    // TODO
							 | 
						||
| 
								 | 
							
								  } else if (Comp.obj.isFunction(ac)) {
							 | 
						||
| 
								 | 
							
								    source = ac.toString();
							 | 
						||
| 
								 | 
							
								    if (!options.classname) { 
							 | 
						||
| 
								 | 
							
								      name=source.match(/^ *function *([^\s\(]*)\(/);
							 | 
						||
| 
								 | 
							
								      if (name && name[1]!='') options.classname=name[1];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    content = 'var ac ='+source;
							 | 
						||
| 
								 | 
							
								    syntax = Esprima.parse(content, { tolerant: true, loc:true });
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      interface=this.analyzeSyntax(syntax,{
							 | 
						||
| 
								 | 
							
								        classname:options.classname||'anonymous',
							 | 
						||
| 
								 | 
							
								        level:options.level==undefined?2:options.level,
							 | 
						||
| 
								 | 
							
								        verbose:options.verbose,
							 | 
						||
| 
								 | 
							
								        err:function (msg){throw msg},
							 | 
						||
| 
								 | 
							
								        out:function (msg){if (!report) report=msg; else report=report+'\n'+msg;},
							 | 
						||
| 
								 | 
							
								        warn:function (msg){if (!report) report=msg; else report=report+'\n'+msg;}
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      return {report:report||'OK',interface:interface};
							 | 
						||
| 
								 | 
							
								    } catch (e) {
							 | 
						||
| 
								 | 
							
								      return {report:e,interface:interface};
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								jam.prototype.clock = Aios.clock;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Compile (analyze) an agent class constructor function and add it to the world class library.
							 | 
						||
| 
								 | 
							
								 ** Can be used after an open statement.
							 | 
						||
| 
								 | 
							
								 ** Usage: compileClass(name,constructor,options?)
							 | 
						||
| 
								 | 
							
								 **        compileClass(constructor,options?)
							 | 
						||
| 
								 | 
							
								 **
							 | 
						||
| 
								 | 
							
								 **  typeof @@name=string|undefined
							 | 
						||
| 
								 | 
							
								 **  typeof @@constructor=function|string
							 | 
						||
| 
								 | 
							
								 **  typeof @@options={verbose:number|boolean)|verbose:number|undefined
							 | 
						||
| 
								 | 
							
								*/ 
							 | 
						||
| 
								 | 
							
								jam.prototype.compileClass = function (name,constructor,options) {
							 | 
						||
| 
								 | 
							
								  var ac,p,verbose,content,syntax,report,text,env={ac:undefined},self=this,ac;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (typeof name == 'function') constructor=name,name=undefined,options=constructor;
							 | 
						||
| 
								 | 
							
								  if (typeof options == 'object') verbose=options.verbose||0; 
							 | 
						||
| 
								 | 
							
								  else if (options!=undefined) verbose=options; else verbose=this.verbose;
							 | 
						||
| 
								 | 
							
								  // if (typeof constructor != 'function') throw 'compileClass: second constructor argument not a function';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (typeof constructor == 'function') text = constructor.toString();
							 | 
						||
| 
								 | 
							
								  else text = constructor;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  if (!name) {
							 | 
						||
| 
								 | 
							
								    // try to find name in function definition
							 | 
						||
| 
								 | 
							
								    name=text.match(/[\s]*function[\s]*([A-Za-z0-9_]+)[\s]*\(/);
							 | 
						||
| 
								 | 
							
								    if (!name) throw ('compileClass: No class name provided and no name found in constructor '+
							 | 
						||
| 
								 | 
							
								                      text.substring(0,80));
							 | 
						||
| 
								 | 
							
								    name=name[1];
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  content = 'var ac = '+text;
							 | 
						||
| 
								 | 
							
								  try { syntax = Esprima.parse(content, { tolerant: true, loc:true }) }
							 | 
						||
| 
								 | 
							
								  catch (e) { throw 'compileClass('+name+'): Parsing failed with '+e }
							 | 
						||
| 
								 | 
							
								  report = this.analyzeSyntax(syntax,
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      classname:name,
							 | 
						||
| 
								 | 
							
								      level:2,
							 | 
						||
| 
								 | 
							
								      verbose:verbose||0,
							 | 
						||
| 
								 | 
							
								      err:  function (msg){self.log(msg)},
							 | 
						||
| 
								 | 
							
								      out:  function (msg){self.log(msg)},
							 | 
						||
| 
								 | 
							
								      warn: function (msg){self.log(msg)}
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  if (report.errors.length) { throw 'compileClass('+name+'): failed with '+report.errors.join('; ')};
							 | 
						||
| 
								 | 
							
								  for (p in report.activities) env[p]=p;
							 | 
						||
| 
								 | 
							
								  try { with (env) { eval(content) } }
							 | 
						||
| 
								 | 
							
								  catch (e) { throw ('compileClass('+name+'): failed with '+e+locationEvalError(e)) };
							 | 
						||
| 
								 | 
							
								  ac=env.ac; env.ac=undefined;
							 | 
						||
| 
								 | 
							
								  this.addClass(name,ac,env);
							 | 
						||
| 
								 | 
							
								  return name;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Connect logical nodes (virtual link).
							 | 
						||
| 
								 | 
							
								 *  The root node has position {x=0,y=0}.
							 | 
						||
| 
								 | 
							
								 *  type of links = [{x1:number,y1:number,x2:number,x2:number},..]|[{x,y},{x,y}]
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.connectNodes = function (connections) {  
							 | 
						||
| 
								 | 
							
								  var c,node1,node2,x1,y1,x2,y2,dir;
							 | 
						||
| 
								 | 
							
								  if (connections[0].x != undefined && connections[0].y != undefined) {
							 | 
						||
| 
								 | 
							
								    if (connections.length!=2) throw 'INVALID'; // invalid
							 | 
						||
| 
								 | 
							
								    // simple style
							 | 
						||
| 
								 | 
							
								    connections=[{x1:connections[0].x,x2:connections[1].x,
							 | 
						||
| 
								 | 
							
								                  y1:connections[0].y,y2:connections[0].y}];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  for(c in connections) {
							 | 
						||
| 
								 | 
							
								    x1=connections[c].x1;
							 | 
						||
| 
								 | 
							
								    y1=connections[c].y1;
							 | 
						||
| 
								 | 
							
								    x2=connections[c].x2;
							 | 
						||
| 
								 | 
							
								    y2=connections[c].y2;
							 | 
						||
| 
								 | 
							
								    if (this.verbose) this.log('Connecting ('+x1+','+y1+') -> ('+x2+','+y2+')');
							 | 
						||
| 
								 | 
							
								    node1=Comp.array.find(this.world.nodes,function (node) {
							 | 
						||
| 
								 | 
							
								      return node.position.x==x1 && node.position.y==y1;
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    node2=Comp.array.find(this.world.nodes,function (node) {
							 | 
						||
| 
								 | 
							
								      return node.position.x==x2 && node.position.y==y2;
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    if (!node1) this.err('connectNodes: Node at positition ('+x1+','+y1+') does not exist.');
							 | 
						||
| 
								 | 
							
								    if (!node2) this.err('connectNodes: Node at positition ('+x2+','+y2+') does not exist.');
							 | 
						||
| 
								 | 
							
								    if ((x2-x1)==0) {
							 | 
						||
| 
								 | 
							
								      if ((y2-y1) > 0) dir=Aios.DIR.SOUTH;
							 | 
						||
| 
								 | 
							
								      else dir=Aios.DIR.NORTH;
							 | 
						||
| 
								 | 
							
								    } else if ((x2-x1)>0) dir=Aios.DIR.EAST;
							 | 
						||
| 
								 | 
							
								    else dir=Aios.DIR.WEST;
							 | 
						||
| 
								 | 
							
								    this.world.connect(dir,node1,node2);
							 | 
						||
| 
								 | 
							
								    this.world.connect(Aios.DIR.opposite(dir),node2,node1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Dynamically connect remote endpoint at run-time
							 | 
						||
| 
								 | 
							
								  * typeof @@to = string <dir->url>|<url>
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								jam.prototype.connectTo = function (to,nodeid) {
							 | 
						||
| 
								 | 
							
								  var node=this.getNode(nodeid),
							 | 
						||
| 
								 | 
							
								      tokens=(typeof to=='string')?to.split('->'):null,
							 | 
						||
| 
								 | 
							
								      dir;
							 | 
						||
| 
								 | 
							
								  // console.log(tokens)
							 | 
						||
| 
								 | 
							
								  if (!node) return;
							 | 
						||
| 
								 | 
							
								  if (to.tag) dir=to;
							 | 
						||
| 
								 | 
							
								  else if (tokens.length==2) {
							 | 
						||
| 
								 | 
							
								    dir=Aios.DIR.from(tokens[0]);
							 | 
						||
| 
								 | 
							
								    if (dir) dir.ip=tokens[1];
							 | 
						||
| 
								 | 
							
								  } else dir={tag:'DIR.IP',ip:to};
							 | 
						||
| 
								 | 
							
								  if (dir) this.world.connectTo(dir,node);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Check connection status of a link
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.connected = function (dir,nodeid) {
							 | 
						||
| 
								 | 
							
								  var node=this.getNode(nodeid);
							 | 
						||
| 
								 | 
							
								  if (!node) return;
							 | 
						||
| 
								 | 
							
								  return this.world.connected(dir,node);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Create and start an agent from class ac with arguments. 
							 | 
						||
| 
								 | 
							
								 *  Ac is either already loaded (i.e., ac specifies the class name) or 
							 | 
						||
| 
								 | 
							
								 *  AC is supplied as a constructor function (ac), a class name, or a sandboxed constructor
							 | 
						||
| 
								 | 
							
								 *  {fun:function,mask:{}} object for a specific level.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  type of ac = string|object|function
							 | 
						||
| 
								 | 
							
								 *  type of args = * []
							 | 
						||
| 
								 | 
							
								 *  level = {0,1,2,3}
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.createAgent = function (ac,args,level,className,parent) {
							 | 
						||
| 
								 | 
							
								  var node=this.world.nodes[this.node],
							 | 
						||
| 
								 | 
							
								      process=none,sac;
							 | 
						||
| 
								 | 
							
								  if (level==undefined) level=1;
							 | 
						||
| 
								 | 
							
								  if (!className && typeof ac == 'string') className=ac;
							 | 
						||
| 
								 | 
							
								  if (!className && typeof ac == 'function') className=Aios.Code.className(ac);
							 | 
						||
| 
								 | 
							
								  if (Comp.obj.isFunction(ac) || Comp.obj.isObject(ac)) {
							 | 
						||
| 
								 | 
							
								    // Create an agent process from a constructor function or sandboxed constructor object
							 | 
						||
| 
								 | 
							
								    process = Aios.Code.createOn(node,ac,args,level,className);
							 | 
						||
| 
								 | 
							
								    if (process && !process.agent.parent) process.agent.parent=parent;
							 | 
						||
| 
								 | 
							
								    if (process) return process.agent.id;   
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    // It is a class name. Find an already sandboxed constructor from world classes pool
							 | 
						||
| 
								 | 
							
								    if (this.world.classes[ac])
							 | 
						||
| 
								 | 
							
								      process = Aios.Code.createOn(node,this.world.classes[ac][level],args,level,className);
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								      this.error='createAgent: Cannot find agent class '+ac;
							 | 
						||
| 
								 | 
							
								      this.log(this.error);
							 | 
						||
| 
								 | 
							
								      return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (process) {
							 | 
						||
| 
								 | 
							
								      if (!process.agent.parent) process.agent.parent=parent;
							 | 
						||
| 
								 | 
							
								      process.agent.ac=ac;
							 | 
						||
| 
								 | 
							
								      return process.agent.id; 
							 | 
						||
| 
								 | 
							
								    } else return none;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Create agent on specified (logical or physical) node.
							 | 
						||
| 
								 | 
							
								 *  typeof node = number|string|{x,y}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.createAgentOn = function (node,ac,args,level,className,parent) {
							 | 
						||
| 
								 | 
							
								  var res,_currentNode=this.node,found=this.getNode(node);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (found) {
							 | 
						||
| 
								 | 
							
								    this.setCurrentNode();
							 | 
						||
| 
								 | 
							
								    res=this.createAgent(ac,args,level,className,parent);
							 | 
						||
| 
								 | 
							
								    this.setCurrentNode(_currentNode);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return res;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Create a physical communication port
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.createPort = function (dir,options,nodeid) {
							 | 
						||
| 
								 | 
							
								  if (!options) options={};
							 | 
						||
| 
								 | 
							
								  var multicast=options.multicast;
							 | 
						||
| 
								 | 
							
								  switch (dir.tag) { 
							 | 
						||
| 
								 | 
							
								    case Aios.DIR.NORTH: 
							 | 
						||
| 
								 | 
							
								    case Aios.DIR.SOUTH: 
							 | 
						||
| 
								 | 
							
								    case Aios.DIR.WEST: 
							 | 
						||
| 
								 | 
							
								    case Aios.DIR.EAST: 
							 | 
						||
| 
								 | 
							
								    case Aios.DIR.UP: 
							 | 
						||
| 
								 | 
							
								    case Aios.DIR.DOWN: 
							 | 
						||
| 
								 | 
							
								      multicast=false;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (dir.ip && typeof dir.ip == 'string' && dir.ip.indexOf('//')>0) {
							 | 
						||
| 
								 | 
							
								        // extract proto from url
							 | 
						||
| 
								 | 
							
								        var addr = Aios.Amp.url2addr(dir.ip);
							 | 
						||
| 
								 | 
							
								        if (!options.proto && addr.proto) options.proto=addr.proto;
							 | 
						||
| 
								 | 
							
								        dir.ip=Aios.Amp.addr2url(addr);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (options.from==undefined && dir.ip) options.from=dir.ip.toString();
							 | 
						||
| 
								 | 
							
								  var  chan=this.world.connectPhy(
							 | 
						||
| 
								 | 
							
								            dir,
							 | 
						||
| 
								 | 
							
								            this.getNode(nodeid),
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              broker  :   options.broker,
							 | 
						||
| 
								 | 
							
								              multicast : multicast,
							 | 
						||
| 
								 | 
							
								              name  :     options.name,
							 | 
						||
| 
								 | 
							
								              on    :     options.on,
							 | 
						||
| 
								 | 
							
								              oneway  :   options.oneway,
							 | 
						||
| 
								 | 
							
								              proto :     options.proto||'udp',
							 | 
						||
| 
								 | 
							
								              rcv   :     options.from,
							 | 
						||
| 
								 | 
							
								              secure :    options.secure,
							 | 
						||
| 
								 | 
							
								              snd   :     options.to,
							 | 
						||
| 
								 | 
							
								              verbose:(options.verbose!=undefined?options.verbose:this.verbose)
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								  chan.init();
							 | 
						||
| 
								 | 
							
								  chan.start();
							 | 
						||
| 
								 | 
							
								  return chan;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/** Dynamically disconnect remote endpoint at run-time
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.disconnect = function (to,nodeid) {
							 | 
						||
| 
								 | 
							
								  var node=this.getNode(nodeid);
							 | 
						||
| 
								 | 
							
								  if (node) {
							 | 
						||
| 
								 | 
							
								    this.world.disconnect(to,node);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Emit an event
							 | 
						||
| 
								 | 
							
								 ** function emit(@@event,@@arg1,..)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.emit = function () {
							 | 
						||
| 
								 | 
							
								  Aios.emit.apply(this,arguments);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Execute an agent snapshot on current node delivered in JSON+ text format or read from a file. 
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.execute = function (data,file) {
							 | 
						||
| 
								 | 
							
								  if (!data && file && fs) 
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      data=fs.readFileSync(file,'utf8');
							 | 
						||
| 
								 | 
							
								    } catch (e) {
							 | 
						||
| 
								 | 
							
								      this.log('Error: Reading file '+file+' failed: '+e);
							 | 
						||
| 
								 | 
							
								      return undefined;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  if (data) return this.world.nodes[this.node].receive(data,true);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Execute an agent snapshot on node @@node delivered in JSON+ text format or read from a file.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.executeOn = function (data,node,file) {
							 | 
						||
| 
								 | 
							
								  node=this.getNode(node);
							 | 
						||
| 
								 | 
							
								  if (!node) return;
							 | 
						||
| 
								 | 
							
								  if (!data && file && fs) 
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      data=fs.readFileSync(file,'utf8');
							 | 
						||
| 
								 | 
							
								    } catch (e) {
							 | 
						||
| 
								 | 
							
								      this.log('Error: Reading file '+file+' failed: '+e);
							 | 
						||
| 
								 | 
							
								      return undefined;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  if (data) return node.receive(data,true);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Extend AIOS of specific privilege level. The added functions can be accessed by agents.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * function extend(level:number [],name:string,func:function,argn?:number|number []);
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.extend = function (level,name,func,argn) {
							 | 
						||
| 
								 | 
							
								  var self=this;
							 | 
						||
| 
								 | 
							
								  if (Comp.obj.isArray(level)) {
							 | 
						||
| 
								 | 
							
								    Comp.array.iter(level,function (l) {self.extend(l,name,func,argn)});
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  switch (level) {
							 | 
						||
| 
								 | 
							
								    case 0: 
							 | 
						||
| 
								 | 
							
								      if (Aios.aios0[name]) throw Error('JAM: Cannot extend AIOS(0) with '+name+', existst already!');
							 | 
						||
| 
								 | 
							
								      Aios.aios0[name]=func; break;
							 | 
						||
| 
								 | 
							
								    case 1: 
							 | 
						||
| 
								 | 
							
								      if (Aios.aios1[name]) throw Error('JAM: Cannot extend AIOS(1) with '+name+', existst already!');
							 | 
						||
| 
								 | 
							
								      Aios.aios1[name]=func; break;
							 | 
						||
| 
								 | 
							
								    case 2: 
							 | 
						||
| 
								 | 
							
								      if (Aios.aios2[name]) throw Error('JAM: Cannot extend AIOS(2) with '+name+', existst already!');
							 | 
						||
| 
								 | 
							
								      Aios.aios2[name]=func; break;
							 | 
						||
| 
								 | 
							
								    case 3: 
							 | 
						||
| 
								 | 
							
								      if (Aios.aios3[name]) throw Error('JAM: Cannot extend AIOS(3) with '+name+', existst already!');
							 | 
						||
| 
								 | 
							
								      Aios.aios3[name]=func; break;
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      throw Error('JAM: Extend: Invalid privilige level argument ([0,1,2,3])');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (!JamAnal.corefuncs[name]) JamAnal.corefuncs[name]={argn:argn||func.length}; 
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return node object referenced by logical node number, position, or name
							 | 
						||
| 
								 | 
							
								 *  If @@id is undefined return current node object.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.getNode = function (id) {
							 | 
						||
| 
								 | 
							
								  var node;
							 | 
						||
| 
								 | 
							
								  if (id==undefined) return this.world.nodes[this.node];
							 | 
						||
| 
								 | 
							
								  if (typeof id == 'number') 
							 | 
						||
| 
								 | 
							
								    node=this.world.nodes[id];
							 | 
						||
| 
								 | 
							
								  else if (typeof id == 'string') {
							 | 
						||
| 
								 | 
							
								    // Search node identifier or position;
							 | 
						||
| 
								 | 
							
								    loop: for(var i in this.world.nodes) {
							 | 
						||
| 
								 | 
							
								      if (this.world.nodes[i] && this.world.nodes[i].id==id) {
							 | 
						||
| 
								 | 
							
								        node = this.world.nodes[i];
							 | 
						||
| 
								 | 
							
								        break loop;
							 | 
						||
| 
								 | 
							
								      } 
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } else if (id.x != undefined && 
							 | 
						||
| 
								 | 
							
								             id.y != undefined) {
							 | 
						||
| 
								 | 
							
								    // Search node position;
							 | 
						||
| 
								 | 
							
								    loop: for(var i in this.world.nodes) {
							 | 
						||
| 
								 | 
							
								      if (this.world.nodes[i] && Comp.obj.equal(this.world.nodes[i].position,id)) {
							 | 
						||
| 
								 | 
							
								        node = this.world.nodes[i];
							 | 
						||
| 
								 | 
							
								        break loop;
							 | 
						||
| 
								 | 
							
								      } 
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  return node;
							 | 
						||
| 
								 | 
							
								} 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return node name from logical node number or position
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.getNodeName = function (nodeNumberorPosition) {
							 | 
						||
| 
								 | 
							
								  var node=this.getNode(nodeNumberorPosition);  
							 | 
						||
| 
								 | 
							
								  if (node) return node.id;
							 | 
						||
| 
								 | 
							
								} 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Get current agent process or search for agent process
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.getProcess = function (agent) {
							 | 
						||
| 
								 | 
							
								  if (!agent)
							 | 
						||
| 
								 | 
							
								    return Aios.current.process;
							 | 
						||
| 
								 | 
							
								  else {
							 | 
						||
| 
								 | 
							
								    var node = this.getNode();  // current node
							 | 
						||
| 
								 | 
							
								    if (node) return node.getAgentProcess(agent);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Return node name from logical node number or position
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.getWorldName = function () {
							 | 
						||
| 
								 | 
							
								  return this.world.id;
							 | 
						||
| 
								 | 
							
								} 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Get info about node, agents, plattform
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.info = function (kind,id) {
							 | 
						||
| 
								 | 
							
								  switch (kind) {
							 | 
						||
| 
								 | 
							
								    case 'node':
							 | 
						||
| 
								 | 
							
								      var node=this.getNode(id);
							 | 
						||
| 
								 | 
							
								      if (!node) return;
							 | 
						||
| 
								 | 
							
								      return { 
							 | 
						||
| 
								 | 
							
								        id:node.id, 
							 | 
						||
| 
								 | 
							
								        position: node.position, 
							 | 
						||
| 
								 | 
							
								        location:node.location,
							 | 
						||
| 
								 | 
							
								        type:node.type 
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case 'agent':
							 | 
						||
| 
								 | 
							
								      var agent = this.getProcess(id);
							 | 
						||
| 
								 | 
							
								      if (!agent) return;
							 | 
						||
| 
								 | 
							
								      var code = Aios.Code.print(agent.agent,true);
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        id:id,
							 | 
						||
| 
								 | 
							
								        pid:agent.pid,
							 | 
						||
| 
								 | 
							
								        level:agent.level,
							 | 
						||
| 
								 | 
							
								        blocked:agent.blocked,
							 | 
						||
| 
								 | 
							
								        suspended:agent.suspended,
							 | 
						||
| 
								 | 
							
								        resources:agent.resources,
							 | 
						||
| 
								 | 
							
								        code:code
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case 'agent-data':
							 | 
						||
| 
								 | 
							
								      var agent = this.getProcess(id);
							 | 
						||
| 
								 | 
							
								      if (!agent) return;
							 | 
						||
| 
								 | 
							
								      else return agent.agent;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case 'version': return Aios.options.version;
							 | 
						||
| 
								 | 
							
								    case 'host': return { 
							 | 
						||
| 
								 | 
							
								      type:global.TARGET,
							 | 
						||
| 
								 | 
							
								      watchdog:Aios.watchdog?true:false,
							 | 
						||
| 
								 | 
							
								      protect: Aios.watchdog&&Aios.watchdog.protect?true:false,
							 | 
						||
| 
								 | 
							
								      jsonify:Aios.options.json,
							 | 
						||
| 
								 | 
							
								      minify:!Aios.Code.options.compactit,
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    case 'platform': return platform;     
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** INITIALIZE
							 | 
						||
| 
								 | 
							
								 *  1. Create and initialize node(s)/world
							 | 
						||
| 
								 | 
							
								 *  2. Add optional TS provider/consumer
							 | 
						||
| 
								 | 
							
								 *  3. Create physical network conenctions
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.init = function (callback) {
							 | 
						||
| 
								 | 
							
								  var i=0,j=0, n, p, id, node, connect=[], chan, dir, dirs, pos,
							 | 
						||
| 
								 | 
							
								      self=this;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  // Current node == root node
							 | 
						||
| 
								 | 
							
								  this.node=0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ///////////// CREATE NODES /////////
							 | 
						||
| 
								 | 
							
								  if (!this.options.network) {
							 | 
						||
| 
								 | 
							
								    if (this.options.position) i=this.options.position.x,j=this.options.position.y;
							 | 
						||
| 
								 | 
							
								    // Create one (root) node if not already existing
							 | 
						||
| 
								 | 
							
								    if (!this.getNode({x:i,y:j})) {
							 | 
						||
| 
								 | 
							
								      node = Aios.Node.Node({
							 | 
						||
| 
								 | 
							
								          id:this.options.id,
							 | 
						||
| 
								 | 
							
								          position:{x:i,y:j},
							 | 
						||
| 
								 | 
							
								          TMO:this.options.TMO,
							 | 
						||
| 
								 | 
							
								          type:this.options.type
							 | 
						||
| 
								 | 
							
								        },true);
							 | 
						||
| 
								 | 
							
								      // Add node to world
							 | 
						||
| 
								 | 
							
								      if (this.verbose) this.log('Created '+(i==0&&j==0?'root ':'')+'node '+node.id+' ('+i+','+j+').');
							 | 
						||
| 
								 | 
							
								      this.world.addNode(node);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    // Register jamlib event handler for the root node
							 | 
						||
| 
								 | 
							
								    this.register(node);
							 | 
						||
| 
								 | 
							
								  } else if (!this.options.network.cluster) {
							 | 
						||
| 
								 | 
							
								    // Create a virtual network of logical nodes. Default: grid
							 | 
						||
| 
								 | 
							
								    if (this.options.network.rows && this.options.network.columns) {
							 | 
						||
| 
								 | 
							
								      for(j=0;j<this.options.network.rows;j++) 
							 | 
						||
| 
								 | 
							
								        for(i=0;i<this.options.network.columns;i++) {
							 | 
						||
| 
								 | 
							
								          node = Aios.Node.Node({id:Aios.aidgen(),position:{x:i,y:j},TMO:this.options.TMO},true);
							 | 
						||
| 
								 | 
							
								          if (this.verbose) this.log('Created node '+node.id+' at ('+i+','+j+').');
							 | 
						||
| 
								 | 
							
								          if (i==0&&j==0) {
							 | 
						||
| 
								 | 
							
								            // Register jamlib event handler for the root node
							 | 
						||
| 
								 | 
							
								            this.register(node);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          this.world.addNode(node);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      // Connect nodes with virtual links
							 | 
						||
| 
								 | 
							
								      for(j=0;j<this.options.network.rows;j++) 
							 | 
						||
| 
								 | 
							
								        for(i=0;i<this.options.network.columns;i++) {
							 | 
						||
| 
								 | 
							
								          if (i+1<this.options.network.columns)  connect.push({x1:i,y1:j,x2:i+1,y2:j});
							 | 
						||
| 
								 | 
							
								          if (j+1<this.options.network.rows)  connect.push({x1:i,y1:j,x2:i,y2:j+1});
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      if (this.options.network.connect) connect=connect.filter(this.options.network.connect);
							 | 
						||
| 
								 | 
							
								      this.connectNodes(connect);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } else if (this.options.network.cluster && this.options.fork) {
							 | 
						||
| 
								 | 
							
								      // Physical network cluster; each node is executed in a process on this host
							 | 
						||
| 
								 | 
							
								      dirs=[DIR.ORIGIN,DIR.EAST,DIR.SOUTH,DIR.SE,DIR.WEST,DIR.SW,DIR.NORTH,DIR.NW,DIR.NE];
							 | 
						||
| 
								 | 
							
								      pos={x:[0,1,0,1,-1,-1,0,-1,1],
							 | 
						||
| 
								 | 
							
								           y:[0,0,1,1,0,1,-1,-1,-1]};
							 | 
						||
| 
								 | 
							
								      // Create a physical network of nodes. Here create only the root node (0,0)
							 | 
						||
| 
								 | 
							
								      this.cluster=[]; this.master=true;
							 | 
						||
| 
								 | 
							
								      for(j=0;j<this.options.network.rows;j++) 
							 | 
						||
| 
								 | 
							
								        for(i=0;i<this.options.network.columns;i++) {
							 | 
						||
| 
								 | 
							
								          id=Aios.aidgen();
							 | 
						||
| 
								 | 
							
								          if (i==0 && j==0) {
							 | 
						||
| 
								 | 
							
								            dir=undefined;
							 | 
						||
| 
								 | 
							
								            node = Aios.Node.Node({id:id,position:{x:i,y:j},TMO:this.options.TMO},true);
							 | 
						||
| 
								 | 
							
								            if (this.verbose) this.log('Created root node '+node.id+' at ('+i+','+j+').');
							 | 
						||
| 
								 | 
							
								            // Register jamlib event handler for the root node
							 | 
						||
| 
								 | 
							
								            this.register(node);
							 | 
						||
| 
								 | 
							
								            this.world.addNode(node); 
							 | 
						||
| 
								 | 
							
								          } else {
							 | 
						||
| 
								 | 
							
								            n=i+j*this.options.network.columns;
							 | 
						||
| 
								 | 
							
								            dir=dirs[n];
							 | 
						||
| 
								 | 
							
								            if (this.verbose) this.log('Started cluster node '+id+' at ('+i+','+j+'). with link '+DIR.print(dir));
							 | 
						||
| 
								 | 
							
								            this.cluster[id]=this.options.fork(process.argv[1],['autosetup:'+JSON.stringify({
							 | 
						||
| 
								 | 
							
								              id:id,
							 | 
						||
| 
								 | 
							
								              world:this.world.id,
							 | 
						||
| 
								 | 
							
								              cluster:true,
							 | 
						||
| 
								 | 
							
								              network:null,
							 | 
						||
| 
								 | 
							
								              position:{x:pos.x[n],y:pos.y[n]},
							 | 
						||
| 
								 | 
							
								              dir:dir,
							 | 
						||
| 
								 | 
							
								              connections:{
							 | 
						||
| 
								 | 
							
								                stream:{
							 | 
						||
| 
								 | 
							
								                  dir:DIR.opposite(dir)
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            })]);
							 | 
						||
| 
								 | 
							
								            this.cluster[id].dir=dir;
							 | 
						||
| 
								 | 
							
								            // Clustered forked nodes communicate via process.send, receive message via process.on('message') handler
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      // Create physical stream links to all child nodes
							 | 
						||
| 
								 | 
							
								      for(p in this.cluster) {
							 | 
						||
| 
								 | 
							
								        chan=this.world.connectPhy(
							 | 
						||
| 
								 | 
							
								            this.cluster[p].dir,
							 | 
						||
| 
								 | 
							
								            this.getNode(),
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              proto:'stream',
							 | 
						||
| 
								 | 
							
								              sock:this.cluster[p],
							 | 
						||
| 
								 | 
							
								              mode:'object',
							 | 
						||
| 
								 | 
							
								              verbose:this.verbose
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								        chan.init();                
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //////////// Install host platform tuple provider and consumer //////////
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  /*
							 | 
						||
| 
								 | 
							
								  ** Each time a tuple of a specific dimension is requested by an agent (rd) 
							 | 
						||
| 
								 | 
							
								  ** the provider function can return (provide) a mathcing tuple (returning the tuple).
							 | 
						||
| 
								 | 
							
								  ** IO gate between agents/JAM and host application.
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								  if (this.options.provider) this.world.nodes[this.node].ts.register(function (pat) {
							 | 
						||
| 
								 | 
							
								    // Caching?
							 | 
						||
| 
								 | 
							
								    return self.options.provider(pat);
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /*
							 | 
						||
| 
								 | 
							
								  ** Each time a tuple of a specific dimension is stored by an agent (out) 
							 | 
						||
| 
								 | 
							
								  ** the consumer function can return consume the tuple (returning true).
							 | 
						||
| 
								 | 
							
								  ** IO gate between agents/JAM and host application.
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								  if (this.options.consumer) this.world.nodes[this.node].ts.register(function (tuple) {
							 | 
						||
| 
								 | 
							
								    // Caching?
							 | 
						||
| 
								 | 
							
								    return self.options.consumer(tuple);
							 | 
						||
| 
								 | 
							
								  },true);
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  ///////////// CREATE NETWORK CONNECTIVITY /////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Register host application connections {send,status,count,register?} using host app. streams or
							 | 
						||
| 
								 | 
							
								  // create physical conenction ports (using the AMP P2P protocol over IP/RS232) {from:*,proto:'udp'|..}
							 | 
						||
| 
								 | 
							
								  if (this.options.connections) {
							 | 
						||
| 
								 | 
							
								    for (p in this.options.connections) {
							 | 
						||
| 
								 | 
							
								      conn=this.options.connections[p];
							 | 
						||
| 
								 | 
							
								      if (!conn) continue;
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      if (p=='ip' || conn.proto) {
							 | 
						||
| 
								 | 
							
								        // 1. IP
							 | 
						||
| 
								 | 
							
								        // Attach AMP port to root node, actually not linked with endpoint
							 | 
						||
| 
								 | 
							
								        n=1;
							 | 
						||
| 
								 | 
							
								        switch (p) {
							 | 
						||
| 
								 | 
							
								          case 'ip': 
							 | 
						||
| 
								 | 
							
								            dir=this.DIR.IP(this.options.connections.ip.from||'*');
							 | 
						||
| 
								 | 
							
								                                                        // actually not linked with endpoint
							 | 
						||
| 
								 | 
							
								            n = (conn.range && conn.range.length==2 && (conn.range[1]-conn.range[0]+1))||
							 | 
						||
| 
								 | 
							
								                conn.num||
							 | 
						||
| 
								 | 
							
								                1; // multiple interface are allowed
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								          case 'north': dir=this.DIR.NORTH; break;
							 | 
						||
| 
								 | 
							
								          case 'south': dir=this.DIR.SOUTH; break;
							 | 
						||
| 
								 | 
							
								          case 'west': dir=this.DIR.WEST; break;
							 | 
						||
| 
								 | 
							
								          case 'east': dir=this.DIR.EAST; break;
							 | 
						||
| 
								 | 
							
								          case 'up': dir=this.DIR.UP; break;
							 | 
						||
| 
								 | 
							
								          case 'down': dir=this.DIR.DOWN; break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        function makeAddr(ip,i) {
							 | 
						||
| 
								 | 
							
								          if (!conn.range) return ip;
							 | 
						||
| 
								 | 
							
								          else return ip+':'+(conn.range[0]+i);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        for(i=0;i<n;i++) {
							 | 
						||
| 
								 | 
							
								          chan=this.world.connectPhy(
							 | 
						||
| 
								 | 
							
								            dir,
							 | 
						||
| 
								 | 
							
								            this.getNode(),
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              broker:conn.broker,
							 | 
						||
| 
								 | 
							
								              multicast:conn.multicast,
							 | 
						||
| 
								 | 
							
								              name:conn.name,
							 | 
						||
| 
								 | 
							
								              on:conn.on,
							 | 
						||
| 
								 | 
							
								              oneway:conn.oneway,
							 | 
						||
| 
								 | 
							
								              proto:conn.proto||'udp',
							 | 
						||
| 
								 | 
							
								              rcv:makeAddr(conn.from,i),
							 | 
						||
| 
								 | 
							
								              snd:conn.to,
							 | 
						||
| 
								 | 
							
								              verbose:this.verbose
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								          chan.init();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } else if (conn.send) {
							 | 
						||
| 
								 | 
							
								        // 2. Host stream interface
							 | 
						||
| 
								 | 
							
								        node=this.world.nodes[this.node]; // TODO: connections.node -> world node#
							 | 
						||
| 
								 | 
							
								        function makeconn (p,conn) {
							 | 
						||
| 
								 | 
							
								          var link = { 
							 | 
						||
| 
								 | 
							
								            _handler:[],
							 | 
						||
| 
								 | 
							
								            emit: function (event,msg) {
							 | 
						||
| 
								 | 
							
								              if (link._handler[event]) link._handler[event](msg);
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            on: function (event,callback) {
							 | 
						||
| 
								 | 
							
								              link._handler[event]=callback;
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            send: function (data,dest,context) {
							 | 
						||
| 
								 | 
							
								              var res;
							 | 
						||
| 
								 | 
							
								              self.world.nodes[self.node].connections[p]._count += data.length;
							 | 
						||
| 
								 | 
							
								              res=conn.send(data,dest);
							 | 
						||
| 
								 | 
							
								              if (!res) {
							 | 
						||
| 
								 | 
							
								                context.error='Migration to destination '+dest+' failed';
							 | 
						||
| 
								 | 
							
								                // We're still in the agent process context! Throw an error for this agent ..
							 | 
						||
| 
								 | 
							
								                throw 'MOVE';              
							 | 
						||
| 
								 | 
							
								              };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              // kill ghost agent
							 | 
						||
| 
								 | 
							
								              context.process.finalize();
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            status : conn.status?conn.status:(function () {return true}),
							 | 
						||
| 
								 | 
							
								            count: conn.count?conn.count:function () {return link._count},
							 | 
						||
| 
								 | 
							
								            _count:0
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								          if (conn.register) conn.register(link);
							 | 
						||
| 
								 | 
							
								          return link;       
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        node.connections[p] = makeconn(p,conn);
							 | 
						||
| 
								 | 
							
								        // register agent receiver and signal handler
							 | 
						||
| 
								 | 
							
								        node.connections[p].on('agent',node.receive.bind(node));
							 | 
						||
| 
								 | 
							
								        node.connections[p].on('signal',node.handle.bind(node));
							 | 
						||
| 
								 | 
							
								      } else if (p=='stream') {
							 | 
						||
| 
								 | 
							
								        // 3. Physical process stream interface (cluster); child->parent proecss connection
							 | 
						||
| 
								 | 
							
								        chan=this.world.connectPhy(
							 | 
						||
| 
								 | 
							
								            conn.dir,
							 | 
						||
| 
								 | 
							
								            this.getNode(),
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              proto:'stream',
							 | 
						||
| 
								 | 
							
								              sock:process,
							 | 
						||
| 
								 | 
							
								              mode:'object',
							 | 
						||
| 
								 | 
							
								              verbose:this.verbose
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								        chan.init();
							 | 
						||
| 
								 | 
							
								      }    
							 | 
						||
| 
								 | 
							
								    } 
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (callback) callback();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Tuple space input operation - non blocking, i.e., equiv. to inp(pat,_,0)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.inp = function (pat,all) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.inp(pat,all);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Kill agent with specified id ('*': kill all agents on node or current node)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.kill = function (id,node) {
							 | 
						||
| 
								 | 
							
								  if (id=='*') {
							 | 
						||
| 
								 | 
							
								    this.world.nodes[this.node].processes.table.forEach(function (p) {
							 | 
						||
| 
								 | 
							
								      if (p) Aios.kill(p.agent.id);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else
							 | 
						||
| 
								 | 
							
								    return Aios.kill(id);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Try to locate this node (based on network connectivity)
							 | 
						||
| 
								 | 
							
								 *  Any geospatial information is attached to current (node=undefined) or specific node
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								jam.prototype.locate = function (nodeid,cb) {
							 | 
						||
| 
								 | 
							
								  var node=this.getNode(nodeid);
							 | 
						||
| 
								 | 
							
								  if (!node) return;
							 | 
						||
| 
								 | 
							
								  Sat.satelize({},function (err,info) {
							 | 
						||
| 
								 | 
							
								        if (err) {
							 | 
						||
| 
								 | 
							
								          return cb?cb(undefined,err):console.log(err.toString());
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          var location = {
							 | 
						||
| 
								 | 
							
								            ip:info.query,
							 | 
						||
| 
								 | 
							
								            gps:{lat:info.lat,lon:info.lon},
							 | 
						||
| 
								 | 
							
								            geo:{city:info.city,country:info.country,countryCode:info.countryCode,region:info.region,zip:info.zip}
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          node.location=location;
							 | 
						||
| 
								 | 
							
								          if (cb) cb(location);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								   })
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/** Lookup nodes and get connection info (more general as connected and broker support)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.lookup = function (dir,callback,nodeid) {
							 | 
						||
| 
								 | 
							
								  var node=this.getNode(nodeid);
							 | 
						||
| 
								 | 
							
								  if (!node) return;
							 | 
						||
| 
								 | 
							
								  return this.world.lookup(dir,callback,node);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Tuple space output operation with timeout 
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.mark = function (tuple,tmo) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.mark(tuple,tmo);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Execute an agent snapshot in JSON+ text form after migration provided from host application
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.migrate = function (data) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].receive(data,false);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Install event handler
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								*   typeof @@event = {'agent','agent+','agent-','signal+','signal','link+','link-',..}
							 | 
						||
| 
								 | 
							
								*   agent+/agent-: Agent creation and destruction event
							 | 
						||
| 
								 | 
							
								*   agent: Agent receive event
							 | 
						||
| 
								 | 
							
								*   signal+: Signal raise event
							 | 
						||
| 
								 | 
							
								*   signal: Signal receive (handle) event
							 | 
						||
| 
								 | 
							
								*   route+: A new link was established
							 | 
						||
| 
								 | 
							
								*   route-: A link is broken
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								jam.prototype.on = function (event,handler) {
							 | 
						||
| 
								 | 
							
								  Aios.on(event,handler);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Remove event handler
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.off = function (ev) {
							 | 
						||
| 
								 | 
							
								  Aios.off(event); 
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Read and parse one agent class from file. Can contain nested open statements.
							 | 
						||
| 
								 | 
							
								 *  Browser (no fs module): @@file parameter contains source text.
							 | 
						||
| 
								 | 
							
								 *  File/source text format: function [ac] (p1,p2,..) { this.x; .. ; this.act = {..}; ..}
							 | 
						||
| 
								 | 
							
								 *  open(file:string,options?:{verbose?:number|boolean,classname?:string}) -> function | object
							 | 
						||
| 
								 | 
							
								 *  
							 | 
						||
| 
								 | 
							
								 *  Output can be processed by method compileClass
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.open = function (file,options) {
							 | 
						||
| 
								 | 
							
								  var self=this,
							 | 
						||
| 
								 | 
							
								      res,
							 | 
						||
| 
								 | 
							
								      text,
							 | 
						||
| 
								 | 
							
								      name,
							 | 
						||
| 
								 | 
							
								      ast=null;
							 | 
						||
| 
								 | 
							
								  if (!options) options={};
							 | 
						||
| 
								 | 
							
								  name=options.classname||'<unknown>';
							 | 
						||
| 
								 | 
							
								  if (options.verbose>0) this.log('Reading agent class template '+name+' from '+file);
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  function parseModel (text) {
							 | 
						||
| 
								 | 
							
								    var modu={},more,module={exports:{}},name=text.match(/[\s]*function[\s]*([a-z0-9]+)[\s]*\(/);
							 | 
						||
| 
								 | 
							
								    if (name) name=name[1];
							 | 
						||
| 
								 | 
							
								    function open(filename) {
							 | 
						||
| 
								 | 
							
								      var text;
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        text=fs?fs.readFileSync(filename,'utf8'):null;
							 | 
						||
| 
								 | 
							
								        return parseModel(text);
							 | 
						||
| 
								 | 
							
								      } catch (e) {
							 | 
						||
| 
								 | 
							
								        self.log('Error: Opening of '+(fs?file:'text')+' failed: '+e); 
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      with (module) {eval('res = '+text)};
							 | 
						||
| 
								 | 
							
								      if (name) { modu[name]=res; return modu} 
							 | 
						||
| 
								 | 
							
								      else if (module.exports) return module.exports; 
							 | 
						||
| 
								 | 
							
								      else return res;
							 | 
						||
| 
								 | 
							
								    } catch (e) {
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        ast = Esprima.parse(text, { tolerant: true, loc:true });
							 | 
						||
| 
								 | 
							
								        if (ast.errors && ast.errors.length>0) more = ', '+ast.errors[0];
							 | 
						||
| 
								 | 
							
								      } catch (e) {
							 | 
						||
| 
								 | 
							
								        if (e.lineNumber) more = ', in line '+e.lineNumber; 
							 | 
						||
| 
								 | 
							
								      } 
							 | 
						||
| 
								 | 
							
								      self.log(e.name+(e.message?': '+e.message:'')+(more?more:''));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    text=fs?fs.readFileSync(file,'utf8'):file;    // Browser: file parameter contains already source text
							 | 
						||
| 
								 | 
							
								    return parseModel(text);
							 | 
						||
| 
								 | 
							
								  } catch (e) {
							 | 
						||
| 
								 | 
							
								    this.log('Error: Opening of '+(fs?file:'text')+' failed: '+e); 
							 | 
						||
| 
								 | 
							
								  }  
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Tuple space output operation 
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.out = function (tuple) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.out(tuple);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Tuple space read operation - non blocking, i.e., equiv. to rd(pat,_,0)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.rd = function (pat,all) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.rd(pat,all);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** 1. Read agent template classes from file and compile (analyze) agent constructor functions.
							 | 
						||
| 
								 | 
							
								 *     Expected file format: module.exports = { ac1: function (p1,p2,..) {}, ac2:.. }
							 | 
						||
| 
								 | 
							
								 *  2. Read single agent constructor function from file
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * typeof @@options={verbose,error:function}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								// TODO: clean up, split fs interface, no require caching ..
							 | 
						||
| 
								 | 
							
								if (fs) jam.prototype.readClass = function (file,options) {
							 | 
						||
| 
								 | 
							
								  var self=this,
							 | 
						||
| 
								 | 
							
								      ac,
							 | 
						||
| 
								 | 
							
								      name,
							 | 
						||
| 
								 | 
							
								      env,
							 | 
						||
| 
								 | 
							
								      interface,
							 | 
						||
| 
								 | 
							
								      text,
							 | 
						||
| 
								 | 
							
								      modu,
							 | 
						||
| 
								 | 
							
								      path,
							 | 
						||
| 
								 | 
							
								      p,m,
							 | 
						||
| 
								 | 
							
								      regex1,
							 | 
						||
| 
								 | 
							
								      ast=null,
							 | 
						||
| 
								 | 
							
								      fileText=null,
							 | 
						||
| 
								 | 
							
								      off=null;
							 | 
						||
| 
								 | 
							
								  this.error=_;
							 | 
						||
| 
								 | 
							
								  function errLoc(ast) {
							 | 
						||
| 
								 | 
							
								    var err;
							 | 
						||
| 
								 | 
							
								    if (ast && ast.errors && ast.errors.length) {
							 | 
						||
| 
								 | 
							
								      err=ast.errors[0];
							 | 
						||
| 
								 | 
							
								      if (err.lineNumber != undefined) return 'line '+err.lineNumber;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return 'unknown'
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    if (!options) options={};
							 | 
						||
| 
								 | 
							
								    if (options.verbose>0) this.log('Looking up agent class template(s) from '+file);
							 | 
						||
| 
								 | 
							
								    //modu=Require(file);
							 | 
						||
| 
								 | 
							
								    if (Comp.obj.isEmpty(modu)) {
							 | 
						||
| 
								 | 
							
								      if (options.verbose>0) this.log('Reading agent class template(s) from file '+file);
							 | 
						||
| 
								 | 
							
								      if (Comp.string.get(file,0)!='/') 
							 | 
						||
| 
								 | 
							
								        path = (process.cwd?process.cwd()+'/':'./')+file;
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        path = file;
							 | 
						||
| 
								 | 
							
								      fileText=fs.readFileSync(path,'utf8');
							 | 
						||
| 
								 | 
							
								      ast=Esprima.parse(fileText, { tolerant: true, loc:true });
							 | 
						||
| 
								 | 
							
								      if (require.cache) delete require.cache[file]; // force reload of file by require
							 | 
						||
| 
								 | 
							
								      modu=require(path);
							 | 
						||
| 
								 | 
							
								      if(Comp.obj.isEmpty(modu)) {
							 | 
						||
| 
								 | 
							
								        modu={};
							 | 
						||
| 
								 | 
							
								        // Try evaluation of fileText containing one single function definition
							 | 
						||
| 
								 | 
							
								        if (!fileText) throw 'No such file!';
							 | 
						||
| 
								 | 
							
								        name=fileText.match(/[\s]*function[\s]*([a-z0-9]+)[\s]*\(/);
							 | 
						||
| 
								 | 
							
								        if (!name) throw ('Export interface of module is empty and file contains no valid function definition!');
							 | 
						||
| 
								 | 
							
								        name=name[1];
							 | 
						||
| 
								 | 
							
								        eval('(function () {'+fileText+' modu["'+name+'"]='+name+'})()');        
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (!modu || Comp.obj.isEmpty(modu)) throw 'Empty module.';
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    for (m in modu) {
							 | 
						||
| 
								 | 
							
								      ac=modu[m];
							 | 
						||
| 
								 | 
							
								      env={};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (fileText)       off=this.syntax.find(fileText,'VariableDeclarator',m);
							 | 
						||
| 
								 | 
							
								      if (off && off.loc) this.syntax.offset=off.loc.start.line-1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      content = 'var ac = '+ac;
							 | 
						||
| 
								 | 
							
								      syntax = Esprima.parse(content, { tolerant: true, loc:true });
							 | 
						||
| 
								 | 
							
								      interface = this.analyzeSyntax(syntax,
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          classname:m,
							 | 
						||
| 
								 | 
							
								          level:2,
							 | 
						||
| 
								 | 
							
								          verbose:  options.verbose||0,
							 | 
						||
| 
								 | 
							
								          err:      options.error||function (msg){throw(msg)},
							 | 
						||
| 
								 | 
							
								          out:      function (msg){self.log(msg)},
							 | 
						||
| 
								 | 
							
								          warn:     function (msg){self.log(msg)}
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      // text=Json.stringify(ac);
							 | 
						||
| 
								 | 
							
								      for (var p in interface.activities) env[p]=p;
							 | 
						||
| 
								 | 
							
								      with (env) { eval(content) };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (options.verbose>0) this.log('Adding agent class constructor '+m+' ('+(typeof ac)+').');
							 | 
						||
| 
								 | 
							
								      this.addClass(m,ac,env);
							 | 
						||
| 
								 | 
							
								      this.syntax.offset=0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    this.error=undefined;
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								  } catch (e) {
							 | 
						||
| 
								 | 
							
								    this.error='Compiling agent class file "'+file+'" failed: '+e+
							 | 
						||
| 
								 | 
							
								               (ast && ast.errors.length?', in '+errLoc(ast):'');
							 | 
						||
| 
								 | 
							
								    if (options.error) 
							 | 
						||
| 
								 | 
							
								      options.error(e+(ast && ast.errors.length?', in '+errLoc(ast):''));
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								      this.log(this.error);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Register jamlib event handler for the (root) node
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								jam.prototype.register = function (node) {
							 | 
						||
| 
								 | 
							
								  this.on('agent', function (msg) { node.receive(msg) });
							 | 
						||
| 
								 | 
							
								  this.on('signal', function (msg) { node.handle(msg) });
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Disconnect and remove a virtual node from the world
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.removeNode = function (nodeid) {
							 | 
						||
| 
								 | 
							
								  this.world.removeNode(nodeid);  
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Tuple space remove operation 
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.rm = function (pat,all) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.rm(pat,all);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Take an agent process snapshot executed currently on given node @@node:number|string|undefined.
							 | 
						||
| 
								 | 
							
								 *  If @@file:string is not specified, a string containing the snapshot is
							 | 
						||
| 
								 | 
							
								 *  returned, otehrwise it is saved to the file (text format. JSON+).
							 | 
						||
| 
								 | 
							
								 *  If @@node is undefined, the current node is used.
							 | 
						||
| 
								 | 
							
								 *  If @@kill is set, the agent is killed after taken the snapshot.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.saveSnapshotOn = function (aid,node,file,kill) {
							 | 
						||
| 
								 | 
							
								  var snapshot,pro;
							 | 
						||
| 
								 | 
							
								  node=this.getNode(node);
							 | 
						||
| 
								 | 
							
								  if (!node) return;
							 | 
						||
| 
								 | 
							
								  // Look-up agent process ..
							 | 
						||
| 
								 | 
							
								  pro=node.getAgentProcess(aid);
							 | 
						||
| 
								 | 
							
								  if (!pro) return;
							 | 
						||
| 
								 | 
							
								  // Take snapshot od the process ..
							 | 
						||
| 
								 | 
							
								  snapshot=Aios.Code.ofCode(pro,false);
							 | 
						||
| 
								 | 
							
								  if (kill) Aios.killOn(aid,node);
							 | 
						||
| 
								 | 
							
								  // Save it ..
							 | 
						||
| 
								 | 
							
								  if (!file) return snapshot;
							 | 
						||
| 
								 | 
							
								  else if (fs) return fs.writeFileSync(file, snapshot, 'utf8');
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								jam.prototype.saveSnapshot = function (aid,file,kill) {
							 | 
						||
| 
								 | 
							
								  return this.saveSnapshotOn(aid,_,file,kill);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Force a scheduler run immediately normally executed by the
							 | 
						||
| 
								 | 
							
								 *  jam service loop. Required if there were externeal agent 
							 | 
						||
| 
								 | 
							
								 *  management, e.g., by sending signals.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.schedule = function () {
							 | 
						||
| 
								 | 
							
								  if (this.loop) {
							 | 
						||
| 
								 | 
							
								    clearTimeout(this.loop);
							 | 
						||
| 
								 | 
							
								    setImmediate(this.looping);
							 | 
						||
| 
								 | 
							
								  } else if (!this.run) setImmediate(this.looping);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Access to JAM security module
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.security = Aios.Sec;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Set current node
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.setCurrentNode=function (n) {
							 | 
						||
| 
								 | 
							
								  if (n>=0 && n < this.world.nodes.length) this.node=n;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Send a signal to a specific agent 'to'.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.signal=function (to,sig,arg,broadcast) {
							 | 
						||
| 
								 | 
							
								  var node=this.getNode(),
							 | 
						||
| 
								 | 
							
								      _process=Aios.current.process;
							 | 
						||
| 
								 | 
							
								  Aios.current.process=this.process;
							 | 
						||
| 
								 | 
							
								  if (!broadcast)
							 | 
						||
| 
								 | 
							
								    Aios.aios.send(to,sig,arg);
							 | 
						||
| 
								 | 
							
								  else  
							 | 
						||
| 
								 | 
							
								    Aios.aios.broadcast(to,sig,arg);    
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								  Aios.current.process=_process;
							 | 
						||
| 
								 | 
							
								  this.schedule();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Start the JAM scheduler
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.start=function (callback) {
							 | 
						||
| 
								 | 
							
								  var self=this,cbl=CBL(callback);
							 | 
						||
| 
								 | 
							
								  // Start all connections if not already done
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  this.world.nodes.forEach(function (node) {
							 | 
						||
| 
								 | 
							
								    node.connections.forEach(function (chan,kind) {
							 | 
						||
| 
								 | 
							
								      if (!chan) return;
							 | 
						||
| 
								 | 
							
								      if (chan.start) cbl.push(function (next) {chan.start(next)});
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  cbl.start();
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  Aios.on('schedule',function () {
							 | 
						||
| 
								 | 
							
								    self.schedule();
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function loop() {
							 | 
						||
| 
								 | 
							
								    var loop = function () {
							 | 
						||
| 
								 | 
							
								      var nexttime,curtime;
							 | 
						||
| 
								 | 
							
								      if (self.verbose>3) self.log('loop: Entering scheduler #'+self.ticks);
							 | 
						||
| 
								 | 
							
								      self.ticks++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      nexttime=Aios.scheduler();
							 | 
						||
| 
								 | 
							
								      curtime=Aios.time();
							 | 
						||
| 
								 | 
							
								      if (self.verbose>3) self.log('loop: Scheduler returned nexttime='+nexttime+
							 | 
						||
| 
								 | 
							
								                                           ' ('+(nexttime>0?nexttime-curtime:0)+')');
							 | 
						||
| 
								 | 
							
								      if (!self.run) return;
							 | 
						||
| 
								 | 
							
								      if (nexttime>0) 
							 | 
						||
| 
								 | 
							
								        self.loop=setTimeout(loop,nexttime-curtime);
							 | 
						||
| 
								 | 
							
								      else if (nexttime==0) 
							 | 
						||
| 
								 | 
							
								        self.loop=setTimeout(loop,1000);
							 | 
						||
| 
								 | 
							
								      else setImmediate(loop);
							 | 
						||
| 
								 | 
							
								      // else setTimeout(loop,10);
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    self.loop = setTimeout(loop,1);
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								  this.looping=loop;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  Aios.config({iterations:100});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.run=true;
							 | 
						||
| 
								 | 
							
								  this.world.start();
							 | 
						||
| 
								 | 
							
								  if (this.verbose) this.log('Starting JAM loop .. ');
							 | 
						||
| 
								 | 
							
								  if (!this.options.scheduler) this.loop = setTimeout(loop,1); // Start internal scheduling loop
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Get agent process table info and other statistics
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  type kind = 'process'|'agent'|'node'|'vm'|'conn'
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								jam.prototype.stats = function (kind,id) {
							 | 
						||
| 
								 | 
							
								  var p,n,sys,conn,pro,agent,state,stats,allstats={},signals,node;
							 | 
						||
| 
								 | 
							
								  switch (kind) {
							 | 
						||
| 
								 | 
							
								    case 'process':      
							 | 
						||
| 
								 | 
							
								    case 'agent':      
							 | 
						||
| 
								 | 
							
								      for(n in this.world.nodes) {        
							 | 
						||
| 
								 | 
							
								        stats={};
							 | 
						||
| 
								 | 
							
								        node=this.world.nodes[n];
							 | 
						||
| 
								 | 
							
								        for (p in node.processes.table) {
							 | 
						||
| 
								 | 
							
								          if (node.processes.table[p]) {
							 | 
						||
| 
								 | 
							
								            pro=node.processes.table[p];
							 | 
						||
| 
								 | 
							
								            if (pro.signals.length == 0) signals=[];
							 | 
						||
| 
								 | 
							
								            else signals = pro.signals.map(function (sig)  {return sig[0] });
							 | 
						||
| 
								 | 
							
								            agent=pro.agent;
							 | 
						||
| 
								 | 
							
								            if (pro.suspended) state='SUSPENDED';
							 | 
						||
| 
								 | 
							
								            else if (pro.blocked) state='BLOCKED';
							 | 
						||
| 
								 | 
							
								            else if (pro.dead) state='DEAD';
							 | 
						||
| 
								 | 
							
								            else if (pro.kill) state='KILL';
							 | 
						||
| 
								 | 
							
								            else if (pro.move) state='MOVE';
							 | 
						||
| 
								 | 
							
								            else state='READY';
							 | 
						||
| 
								 | 
							
								            stats[agent.id]={
							 | 
						||
| 
								 | 
							
								              pid:pro.pid,
							 | 
						||
| 
								 | 
							
								              gid:pro.gid,
							 | 
						||
| 
								 | 
							
								              state:state,
							 | 
						||
| 
								 | 
							
								              parent:pro.agent.parent,
							 | 
						||
| 
								 | 
							
								              class:pro.agent.ac,
							 | 
						||
| 
								 | 
							
								              next:agent.next,
							 | 
						||
| 
								 | 
							
								              resources:Comp.obj.copy(pro.resources)
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								            if (signals.length) stats[agent.id].signals=signals;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        allstats[node.id]=stats;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								    case 'node':
							 | 
						||
| 
								 | 
							
								      return Comp.obj.copy(this.getNode(id).stats);
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								    case 'conn':
							 | 
						||
| 
								 | 
							
								      for(n in this.world.nodes) {        
							 | 
						||
| 
								 | 
							
								        stats={};
							 | 
						||
| 
								 | 
							
								        node=this.world.nodes[n];
							 | 
						||
| 
								 | 
							
								        for (p in node.connections) {
							 | 
						||
| 
								 | 
							
								          conn=node.connections[p];
							 | 
						||
| 
								 | 
							
								          if (conn) {
							 | 
						||
| 
								 | 
							
								            stats[p]={count:conn.count(),conn:conn.status('%')};
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        allstats[node.id]=stats;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								    case 'vm':
							 | 
						||
| 
								 | 
							
								      // Return VM memory usage in kB units and VM system information
							 | 
						||
| 
								 | 
							
								      if (process && process.memoryUsage) {
							 | 
						||
| 
								 | 
							
								        sys=process.memoryUsage();
							 | 
						||
| 
								 | 
							
								        for ( p in sys) sys[p] = (sys[p]/1024)|0;
							 | 
						||
| 
								 | 
							
								        sys.v8 = process.versions && process.versions.v8;
							 | 
						||
| 
								 | 
							
								        sys.node = process.versions && process.versions.node;
							 | 
						||
| 
								 | 
							
								        sys.arch = process.arch;
							 | 
						||
| 
								 | 
							
								        sys.platform = process.platform;
							 | 
						||
| 
								 | 
							
								        sys.watchdog = Aios.watchdog?(Aios.watchdog.checkPoint?'semi':'full'):'none'; 
							 | 
						||
| 
								 | 
							
								        return sys;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (this.world.nodes.length==1) return stats;
							 | 
						||
| 
								 | 
							
								  else return allstats;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Stepping the scheduler loop 
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.step = function (steps,callback) {
							 | 
						||
| 
								 | 
							
								  // TODO: accurate timing
							 | 
						||
| 
								 | 
							
								  var self=this,
							 | 
						||
| 
								 | 
							
								      milliTime=function () {return Math.ceil(Date.now())},
							 | 
						||
| 
								 | 
							
								      curtime=Aios.time(),// Aios.time();
							 | 
						||
| 
								 | 
							
								      lasttime=curtime;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								  function loop () {
							 | 
						||
| 
								 | 
							
								    var loop = function () {
							 | 
						||
| 
								 | 
							
								      var nexttime,curtime;
							 | 
						||
| 
								 | 
							
								      if (self.verbose>1) self.log('loop: Entering scheduler #'+self.ticks);
							 | 
						||
| 
								 | 
							
								      self.ticks++,self.steps--;
							 | 
						||
| 
								 | 
							
								      self.time=curtime=Aios.time();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // Execute scheduler loop
							 | 
						||
| 
								 | 
							
								      nexttime=Aios.scheduler();
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      curtime=Aios.time();
							 | 
						||
| 
								 | 
							
								      if (self.verbose>3) self.log('loop: Scheduler returned nexttime='+nexttime+
							 | 
						||
| 
								 | 
							
								                                           ' ('+(nexttime>0?nexttime-curtime:0)+')');
							 | 
						||
| 
								 | 
							
								      if (self.steps==0 || !self.run) {
							 | 
						||
| 
								 | 
							
								        self.loop=none;
							 | 
						||
| 
								 | 
							
								        self.run=false;
							 | 
						||
| 
								 | 
							
								        self.time=curtime;
							 | 
						||
| 
								 | 
							
								        if (callback) callback();
							 | 
						||
| 
								 | 
							
								        return;              
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (nexttime>0) 
							 | 
						||
| 
								 | 
							
								        self.loop=setTimeout(loop,nexttime-curtime);
							 | 
						||
| 
								 | 
							
								      else if (nexttime < 0) self.loop=setImmediate(loop);
							 | 
						||
| 
								 | 
							
								      else {
							 | 
						||
| 
								 | 
							
								        self.loop=none;
							 | 
						||
| 
								 | 
							
								        self.run=false;
							 | 
						||
| 
								 | 
							
								        self.time=curtime;
							 | 
						||
| 
								 | 
							
								        if (callback) callback();        
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    self.loop = setTimeout(loop,1);
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								  this.looping=loop;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  Aios.config({iterations:1});
							 | 
						||
| 
								 | 
							
								  this.steps=steps;
							 | 
						||
| 
								 | 
							
								  this.run=true;
							 | 
						||
| 
								 | 
							
								  if (this.time>0) current.world.lag=current.world.lag+(curtime-this.time);
							 | 
						||
| 
								 | 
							
								  this.time=curtime;
							 | 
						||
| 
								 | 
							
								  if (!this.options.scheduler) this.loop = setTimeout(loop,0); // Start internal scheduling loop
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Stop the JAM scheduler and all network connections
							 | 
						||
| 
								 | 
							
								 * 
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.stop=function (callback) {
							 | 
						||
| 
								 | 
							
								  this.run=false,cbl=CBL(callback);
							 | 
						||
| 
								 | 
							
								  this.log('Stopping JAM ..');
							 | 
						||
| 
								 | 
							
								  Aios.off('schedule');
							 | 
						||
| 
								 | 
							
								  if (this.loop)
							 | 
						||
| 
								 | 
							
								    clearTimeout(this.loop);
							 | 
						||
| 
								 | 
							
								  this.world.nodes.forEach(function (node) {
							 | 
						||
| 
								 | 
							
								    node.connections.forEach(function (chan,kind) {
							 | 
						||
| 
								 | 
							
								      if (!chan) return;
							 | 
						||
| 
								 | 
							
								      if (chan.stop) cbl.push(function (next) {chan.stop(next)});
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  cbl.start();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/** Tuple space test operation - non blocking
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.test = function (pat) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.exists(pat);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Tuple space testandset operation 
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.ts = function (pat,callback) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.ts(pat,callback);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Get JAM time
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.time=function () {
							 | 
						||
| 
								 | 
							
								  return Aios.time();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Get JAMLIB version
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								jam.prototype.version=function () {
							 | 
						||
| 
								 | 
							
								  return options.version;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var Jam = function(options) {
							 | 
						||
| 
								 | 
							
								  var obj = new jam(options);
							 | 
						||
| 
								 | 
							
								  return obj;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Embedded cluster setup and start; 
							 | 
						||
| 
								 | 
							
								 * Provided by process arguments
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								if (environment.autosetup) {
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    var _options=JSON.parse(environment.autosetup);
							 | 
						||
| 
								 | 
							
								    // console.log('['+process.pid+'] JAM cluster setup with options:',process.argv[_index+1]);
							 | 
						||
| 
								 | 
							
								    jam.prototype.setup=function () {
							 | 
						||
| 
								 | 
							
								      for(var p in _options) this.options[p]=_options[p];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } catch (e) {
							 | 
						||
| 
								 | 
							
								    console.log('['+process.pid+'] JAM auto setup failed: '+e);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								  Aios:Aios,
							 | 
						||
| 
								 | 
							
								  Comp:Comp,
							 | 
						||
| 
								 | 
							
								  Esprima:Esprima,
							 | 
						||
| 
								 | 
							
								  Io:Io,
							 | 
						||
| 
								 | 
							
								  Jam:Jam,
							 | 
						||
| 
								 | 
							
								  Json:Json,
							 | 
						||
| 
								 | 
							
								  environment:environment,
							 | 
						||
| 
								 | 
							
								  options:options
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								@
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.4
							 | 
						||
| 
								 | 
							
								log
							 | 
						||
| 
								 | 
							
								@.
							 | 
						||
| 
								 | 
							
								@
							 | 
						||
| 
								 | 
							
								text
							 | 
						||
| 
								 | 
							
								@d20 1
							 | 
						||
| 
								 | 
							
								a20 1
							 | 
						||
| 
								 | 
							
								 **    $INITIAL:     (C) 2006-2017 BSSLAB
							 | 
						||
| 
								 | 
							
								d22 2
							 | 
						||
| 
								 | 
							
								a23 2
							 | 
						||
| 
								 | 
							
								 **    $RCS:         $Id: jamlib.js,v 1.3 2017/06/06 14:53:57 sbosse Exp $
							 | 
						||
| 
								 | 
							
								 **    $VERSION:     1.3.3
							 | 
						||
| 
								 | 
							
								d29 5
							 | 
						||
| 
								 | 
							
								a33 2
							 | 
						||
| 
								 | 
							
								 **  Should a virtual agent process be created for the host application?
							 | 
						||
| 
								 | 
							
								 **  This would enable direct access of tuple spaces with callbacks but w/o blocking ...
							 | 
						||
| 
								 | 
							
								d42 1
							 | 
						||
| 
								 | 
							
								a42 1
							 | 
						||
| 
								 | 
							
								  version:'1.3.2'
							 | 
						||
| 
								 | 
							
								d45 1
							 | 
						||
| 
								 | 
							
								a45 1
							 | 
						||
| 
								 | 
							
								global.config={simulation:false,nonetwork:true};
							 | 
						||
| 
								 | 
							
								a48 1
							 | 
						||
| 
								 | 
							
								var Db = Require('db/db');
							 | 
						||
| 
								 | 
							
								d53 28
							 | 
						||
| 
								 | 
							
								a80 4
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//if (typeof setImmediate == 'undefined') {
							 | 
						||
| 
								 | 
							
								//  function setImmediate(callback) = {return setTimeout(callback,0)};
							 | 
						||
| 
								 | 
							
								//}
							 | 
						||
| 
								 | 
							
								d83 70
							 | 
						||
| 
								 | 
							
								a152 3
							 | 
						||
| 
								 | 
							
								 *  typeof options = { connections?, print?, provider?, consumer?, classes?, id?, verbose?, TMO? }
							 | 
						||
| 
								 | 
							
								 *  with typeof connections = { 'kind : {send:function, link?:function} , 'kind : .. }
							 | 
						||
| 
								 | 
							
								 *  with 'kind = {north,south,west,east,path,..}
							 | 
						||
| 
								 | 
							
								d156 2
							 | 
						||
| 
								 | 
							
								a157 1
							 | 
						||
| 
								 | 
							
								  var self=this;
							 | 
						||
| 
								 | 
							
								d159 9
							 | 
						||
| 
								 | 
							
								a167 4
							 | 
						||
| 
								 | 
							
								  if (!this.options.id) this.options.id=Aios.aidgen();
							 | 
						||
| 
								 | 
							
								  this.verbose = this.options.verbose || 0;
							 | 
						||
| 
								 | 
							
								  this.Aios = Aios;
							 | 
						||
| 
								 | 
							
								  this.DIR = Aios.aios.DIR;
							 | 
						||
| 
								 | 
							
								d170 3
							 | 
						||
| 
								 | 
							
								d175 13
							 | 
						||
| 
								 | 
							
								a187 1
							 | 
						||
| 
								 | 
							
								  this.print=function (msg) { if (self.options.print) self.options.print('[JAM] '+msg)};
							 | 
						||
| 
								 | 
							
								a188 1
							 | 
						||
| 
								 | 
							
								  this.log=this.print;
							 | 
						||
| 
								 | 
							
								d191 1
							 | 
						||
| 
								 | 
							
								a191 1
							 | 
						||
| 
								 | 
							
								    self.print('Error: '+msg);
							 | 
						||
| 
								 | 
							
								d195 1
							 | 
						||
| 
								 | 
							
								a195 1
							 | 
						||
| 
								 | 
							
								    self.print('Warning: '+msg);
							 | 
						||
| 
								 | 
							
								d198 2
							 | 
						||
| 
								 | 
							
								d201 6
							 | 
						||
| 
								 | 
							
								a206 1
							 | 
						||
| 
								 | 
							
								  this.world = Aios.World.World([],{id:this.options.id.toUpperCase(),classes:options.classes||[]});
							 | 
						||
| 
								 | 
							
								a207 8
							 | 
						||
| 
								 | 
							
								  // Create one (root) node
							 | 
						||
| 
								 | 
							
								  var node = Aios.Node.Node({id:this.options.id,position:{x:0,y:0},TMO:this.options.TMO},true);
							 | 
						||
| 
								 | 
							
								  // Add node to world
							 | 
						||
| 
								 | 
							
								  if (this.verbose) this.log('Created root node '+node.id+' (0,0).');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.world.addNode(node);
							 | 
						||
| 
								 | 
							
								  // Current node == root node
							 | 
						||
| 
								 | 
							
								  this.node=0;
							 | 
						||
| 
								 | 
							
								d209 1
							 | 
						||
| 
								 | 
							
								d212 1
							 | 
						||
| 
								 | 
							
								d214 2
							 | 
						||
| 
								 | 
							
								a215 18
							 | 
						||
| 
								 | 
							
								  this.looprun=0;
							 | 
						||
| 
								 | 
							
								  this.loopnext=none;
							 | 
						||
| 
								 | 
							
								  this.loop = function () {
							 | 
						||
| 
								 | 
							
								    var loop = function () {
							 | 
						||
| 
								 | 
							
								      self.looprun++;
							 | 
						||
| 
								 | 
							
								      if (self.options.verbose>1) self.print('loop: Entering scheduler run #'+self.looprun);
							 | 
						||
| 
								 | 
							
								      var nexttime=Aios.scheduler();
							 | 
						||
| 
								 | 
							
								      var curtime=Aios.time();
							 | 
						||
| 
								 | 
							
								      if (self.options.verbose>1) self.print('loop: Scheduler returned nexttime='+nexttime+
							 | 
						||
| 
								 | 
							
								                                           ' ('+(nexttime>0?nexttime-curtime:0)+')');
							 | 
						||
| 
								 | 
							
								      if (nexttime>0) 
							 | 
						||
| 
								 | 
							
								        self.loopnext=setTimeout(loop,nexttime-curtime);
							 | 
						||
| 
								 | 
							
								      else if (nexttime==0) 
							 | 
						||
| 
								 | 
							
								        self.loopnext=setTimeout(loop,1000);
							 | 
						||
| 
								 | 
							
								      else setImmediate(loop);
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    self.loopnext = setTimeout(loop,1);
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								d217 6
							 | 
						||
| 
								 | 
							
								a222 2
							 | 
						||
| 
								 | 
							
								  Aios.config({iterations:100,
							 | 
						||
| 
								 | 
							
								               fastcopy:this.options.fastcopy,
							 | 
						||
| 
								 | 
							
								d225 2
							 | 
						||
| 
								 | 
							
								a226 13
							 | 
						||
| 
								 | 
							
								  /* Install host platform tuple provider and consumer
							 | 
						||
| 
								 | 
							
								  **
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  /*
							 | 
						||
| 
								 | 
							
								  ** Each time a tuple of a specific dimension is requested by an agent (rd) 
							 | 
						||
| 
								 | 
							
								  ** the provider function can return (provide) a mathcing tuple (returning the tuple).
							 | 
						||
| 
								 | 
							
								  ** IO gate between agents/JAM and host application.
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								  if (this.options.provider) this.world.nodes[this.node].ts.register(function (pat) {
							 | 
						||
| 
								 | 
							
								    // Caching?
							 | 
						||
| 
								 | 
							
								    return self.options.provider(pat);
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								a227 38
							 | 
						||
| 
								 | 
							
								  /*
							 | 
						||
| 
								 | 
							
								  ** Each time a tuple of a specific dimension is stored by an agent (out) 
							 | 
						||
| 
								 | 
							
								  ** the consumer function can return consume the tuple (returning true).
							 | 
						||
| 
								 | 
							
								  ** IO gate between agents/JAM and host application.
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								  if (this.options.consumer) this.world.nodes[this.node].ts.register(function (tuple) {
							 | 
						||
| 
								 | 
							
								    // Caching?
							 | 
						||
| 
								 | 
							
								    return self.options.consumer(tuple);
							 | 
						||
| 
								 | 
							
								  },true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Register a connection {send,status] for Aios.Mobi ...
							 | 
						||
| 
								 | 
							
								  if (this.options.connections) {
							 | 
						||
| 
								 | 
							
								    for (p in this.options.connections) {
							 | 
						||
| 
								 | 
							
								      conn=this.options.connections[p];
							 | 
						||
| 
								 | 
							
								      function makeconn (p,conn) {
							 | 
						||
| 
								 | 
							
								        return { 
							 | 
						||
| 
								 | 
							
								          send: function (data,dest,context) {
							 | 
						||
| 
								 | 
							
								            var res;
							 | 
						||
| 
								 | 
							
								            self.world.nodes[self.node].connections[p].count += data.length;
							 | 
						||
| 
								 | 
							
								            res=conn.send(data,dest);
							 | 
						||
| 
								 | 
							
								            if (!res) {
							 | 
						||
| 
								 | 
							
								              // context???
							 | 
						||
| 
								 | 
							
								              context.error='Migration to destination '+dest+' failed';
							 | 
						||
| 
								 | 
							
								              // We're still in the agent process context! Throw an error for this agent ..
							 | 
						||
| 
								 | 
							
								              throw 'MOVE';              
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // kill ghost agent
							 | 
						||
| 
								 | 
							
								            context.process.finalize();
							 | 
						||
| 
								 | 
							
								          },
							 | 
						||
| 
								 | 
							
								          status : conn.link?conn.link:(function () {return true}),
							 | 
						||
| 
								 | 
							
								          count:0
							 | 
						||
| 
								 | 
							
								        }       
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      this.world.nodes[this.node].connections[p] = makeconn(p,conn);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								d230 2
							 | 
						||
| 
								 | 
							
								a231 2
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  if (this.verbose) this.Aios.options.log.node=true;
							 | 
						||
| 
								 | 
							
								d242 2
							 | 
						||
| 
								 | 
							
								a243 2
							 | 
						||
| 
								 | 
							
								/** Add agent class templates to the JAM world and create sandboxed constructors.
							 | 
						||
| 
								 | 
							
								 *  type templates = {<ac name>:function|{fun:function,mask:{}}},..} 
							 | 
						||
| 
								 | 
							
								d245 20
							 | 
						||
| 
								 | 
							
								a264 9
							 | 
						||
| 
								 | 
							
								jam.prototype.addClass = function (templates) {
							 | 
						||
| 
								 | 
							
								  for (var p in templates) {
							 | 
						||
| 
								 | 
							
								    if (this.verbose) this.log('Added agent class '+p);
							 | 
						||
| 
								 | 
							
								    this.world.classes[p]=[
							 | 
						||
| 
								 | 
							
								      this.Aios.Code.makeSandbox(templates[p],0),
							 | 
						||
| 
								 | 
							
								      this.Aios.Code.makeSandbox(templates[p],1),
							 | 
						||
| 
								 | 
							
								      this.Aios.Code.makeSandbox(templates[p],2),
							 | 
						||
| 
								 | 
							
								      this.Aios.Code.makeSandbox(templates[p],3)      
							 | 
						||
| 
								 | 
							
								    ]
							 | 
						||
| 
								 | 
							
								d266 6
							 | 
						||
| 
								 | 
							
								a271 1
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								d278 1
							 | 
						||
| 
								 | 
							
								a278 1
							 | 
						||
| 
								 | 
							
								  var n,node,x,y;
							 | 
						||
| 
								 | 
							
								d280 1
							 | 
						||
| 
								 | 
							
								a280 12
							 | 
						||
| 
								 | 
							
								    x=nodes[n].x;
							 | 
						||
| 
								 | 
							
								    y=nodes[n].y;
							 | 
						||
| 
								 | 
							
								    if (Comp.array.find(this.world.nodes,function (node) {
							 | 
						||
| 
								 | 
							
								      return node.position.x==x && node.position.y==y;
							 | 
						||
| 
								 | 
							
								    })) {
							 | 
						||
| 
								 | 
							
								      this.err('addNodes: Node at positition ('+x+','+y+') exists already.');
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    node=Aios.Node.Node({id:nodes[n].id||Aios.aidgen(),position:{x:x,y:y}},true);
							 | 
						||
| 
								 | 
							
								    if (this.verbose) this.log('Created node '+node.id+' ('+x+','+y+').');
							 | 
						||
| 
								 | 
							
								    // Add node to world
							 | 
						||
| 
								 | 
							
								    this.world.addNode(node);    
							 | 
						||
| 
								 | 
							
								d282 1
							 | 
						||
| 
								 | 
							
								d286 1
							 | 
						||
| 
								 | 
							
								d290 3
							 | 
						||
| 
								 | 
							
								a292 3
							 | 
						||
| 
								 | 
							
								  var syntax,content,report,interface;
							 | 
						||
| 
								 | 
							
								  if (Comp.obj.is_String) {
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								d294 1
							 | 
						||
| 
								 | 
							
								a294 1
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								d296 6
							 | 
						||
| 
								 | 
							
								a301 1
							 | 
						||
| 
								 | 
							
								    content = 'var ac ='+ac;
							 | 
						||
| 
								 | 
							
								d318 50
							 | 
						||
| 
								 | 
							
								d371 1
							 | 
						||
| 
								 | 
							
								a371 1
							 | 
						||
| 
								 | 
							
								 *  type of links = [{x1:number,y1:number,x2:number,x2:number},..]
							 | 
						||
| 
								 | 
							
								d375 6
							 | 
						||
| 
								 | 
							
								d405 26
							 | 
						||
| 
								 | 
							
								d441 1
							 | 
						||
| 
								 | 
							
								a441 1
							 | 
						||
| 
								 | 
							
								jam.prototype.createAgent = function (ac,args,level,className) {
							 | 
						||
| 
								 | 
							
								d445 2
							 | 
						||
| 
								 | 
							
								a446 1
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								d450 1
							 | 
						||
| 
								 | 
							
								d455 6
							 | 
						||
| 
								 | 
							
								a460 2
							 | 
						||
| 
								 | 
							
								      process = Aios.Code.createOn(node,this.world.classes[ac][level],args);
							 | 
						||
| 
								 | 
							
								    else this.print('create: Cannot find agent class '+ac);
							 | 
						||
| 
								 | 
							
								d462 1
							 | 
						||
| 
								 | 
							
								d469 100
							 | 
						||
| 
								 | 
							
								a568 4
							 | 
						||
| 
								 | 
							
								/** Execute an agent snapshot delivered in JSON+ text format 
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								jam.prototype.execute = function (data) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].receive(data,true);
							 | 
						||
| 
								 | 
							
								d571 1
							 | 
						||
| 
								 | 
							
								a571 1
							 | 
						||
| 
								 | 
							
								/** Extend AIOS of pseicifc privilege level. The added functions can be accessed by agents.
							 | 
						||
| 
								 | 
							
								d573 1
							 | 
						||
| 
								 | 
							
								d575 1
							 | 
						||
| 
								 | 
							
								a575 1
							 | 
						||
| 
								 | 
							
								jam.prototype.extend = function (level,name,func) {
							 | 
						||
| 
								 | 
							
								d578 1
							 | 
						||
| 
								 | 
							
								a578 1
							 | 
						||
| 
								 | 
							
								    Comp.array.iter(level,function (l) {self.extend(l,name,func)});
							 | 
						||
| 
								 | 
							
								d583 1
							 | 
						||
| 
								 | 
							
								a583 1
							 | 
						||
| 
								 | 
							
								      if (Aios.aios0[name]) throw Error('JAM: Cannot extend AIOS(0) with'+name+', existst already!');
							 | 
						||
| 
								 | 
							
								d586 1
							 | 
						||
| 
								 | 
							
								a586 1
							 | 
						||
| 
								 | 
							
								      if (Aios.aios1[name]) throw Error('JAM: Cannot extend AIOS(1) with'+name+', existst already!');
							 | 
						||
| 
								 | 
							
								d589 1
							 | 
						||
| 
								 | 
							
								a589 1
							 | 
						||
| 
								 | 
							
								      if (Aios.aios2[name]) throw Error('JAM: Cannot extend AIOS(2) with'+name+', existst already!');
							 | 
						||
| 
								 | 
							
								d592 1
							 | 
						||
| 
								 | 
							
								a592 1
							 | 
						||
| 
								 | 
							
								      if (Aios.aios3[name]) throw Error('JAM: Cannot extend AIOS(3) with'+name+', existst already!');
							 | 
						||
| 
								 | 
							
								d597 1
							 | 
						||
| 
								 | 
							
								d599 335
							 | 
						||
| 
								 | 
							
								a933 1
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								d937 2
							 | 
						||
| 
								 | 
							
								a938 2
							 | 
						||
| 
								 | 
							
								jam.prototype.inp = function (pat) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.inp(pat);
							 | 
						||
| 
								 | 
							
								d942 1
							 | 
						||
| 
								 | 
							
								a942 1
							 | 
						||
| 
								 | 
							
								/** Kill agent with specified id
							 | 
						||
| 
								 | 
							
								d944 7
							 | 
						||
| 
								 | 
							
								a950 2
							 | 
						||
| 
								 | 
							
								jam.prototype.kill = function (id) {
							 | 
						||
| 
								 | 
							
								  return Aios.kill(id);
							 | 
						||
| 
								 | 
							
								d953 39
							 | 
						||
| 
								 | 
							
								a991 2
							 | 
						||
| 
								 | 
							
								/** Execute an agent snapshot in JSON+ text form after migration
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								d996 16
							 | 
						||
| 
								 | 
							
								a1011 2
							 | 
						||
| 
								 | 
							
								/** Read and parse one agent class from file.
							 | 
						||
| 
								 | 
							
								 *  Format: function (p1,p2,..) { this.x; .. ; this.act = {..}; ..}
							 | 
						||
| 
								 | 
							
								d1013 14
							 | 
						||
| 
								 | 
							
								a1026 1
							 | 
						||
| 
								 | 
							
								if (fs) jam.prototype.open = function (file,options) {
							 | 
						||
| 
								 | 
							
								d1033 2
							 | 
						||
| 
								 | 
							
								a1034 2
							 | 
						||
| 
								 | 
							
								  name=options.classname||'<anonymous>';
							 | 
						||
| 
								 | 
							
								  if (options.verbose>0) this.print('Reading agent class template '+name+' from '+file);
							 | 
						||
| 
								 | 
							
								d1037 2
							 | 
						||
| 
								 | 
							
								d1040 7
							 | 
						||
| 
								 | 
							
								a1046 4
							 | 
						||
| 
								 | 
							
								      var text=Io.read_file(filename);
							 | 
						||
| 
								 | 
							
								      if (text==undefined) 
							 | 
						||
| 
								 | 
							
								         self.print('Error: Opening of file '+filename+' failed!'); 
							 | 
						||
| 
								 | 
							
								      else return parseModel(text);
							 | 
						||
| 
								 | 
							
								d1049 4
							 | 
						||
| 
								 | 
							
								a1052 2
							 | 
						||
| 
								 | 
							
								      eval('res = '+text);
							 | 
						||
| 
								 | 
							
								      return res;
							 | 
						||
| 
								 | 
							
								d1060 1
							 | 
						||
| 
								 | 
							
								a1060 1
							 | 
						||
| 
								 | 
							
								      self.print(e.name+(e.message?': '+e.message:'')+(more?more:''));
							 | 
						||
| 
								 | 
							
								d1063 6
							 | 
						||
| 
								 | 
							
								a1068 5
							 | 
						||
| 
								 | 
							
								  var text=Io.read_file(file);
							 | 
						||
| 
								 | 
							
								  if (text==undefined) {
							 | 
						||
| 
								 | 
							
								    self.print('Error: Opening of file '+file+' failed!'); 
							 | 
						||
| 
								 | 
							
								    return undefined;
							 | 
						||
| 
								 | 
							
								  } else return parseModel(text);
							 | 
						||
| 
								 | 
							
								d1079 2
							 | 
						||
| 
								 | 
							
								a1080 2
							 | 
						||
| 
								 | 
							
								jam.prototype.rd = function (pat) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.rd(pat);
							 | 
						||
| 
								 | 
							
								d1083 3
							 | 
						||
| 
								 | 
							
								a1085 2
							 | 
						||
| 
								 | 
							
								/** Read and compile agent class templates from file
							 | 
						||
| 
								 | 
							
								 *  Expected file format: module.exports = { ac1: function (p1,p2,..) {}, ac2:.. }
							 | 
						||
| 
								 | 
							
								d1087 1
							 | 
						||
| 
								 | 
							
								d1089 1
							 | 
						||
| 
								 | 
							
								d1093 3
							 | 
						||
| 
								 | 
							
								d1098 2
							 | 
						||
| 
								 | 
							
								a1099 1
							 | 
						||
| 
								 | 
							
								      p,
							 | 
						||
| 
								 | 
							
								d1102 1
							 | 
						||
| 
								 | 
							
								a1102 1
							 | 
						||
| 
								 | 
							
								      all=null,
							 | 
						||
| 
								 | 
							
								d1104 72
							 | 
						||
| 
								 | 
							
								a1175 37
							 | 
						||
| 
								 | 
							
								  if (!options) options={};
							 | 
						||
| 
								 | 
							
								  if (options.verbose>0) this.print('Looking up agent class template(s) from '+file);
							 | 
						||
| 
								 | 
							
								  modu=Require(file);
							 | 
						||
| 
								 | 
							
								  if (Comp.obj.isEmpty(modu)) {
							 | 
						||
| 
								 | 
							
								    if (options.verbose>0) this.print('Importing agent class template(s) from file '+file);
							 | 
						||
| 
								 | 
							
								    if (Comp.string.get(file,0)!='/') file = './'+file;
							 | 
						||
| 
								 | 
							
								    modu=require(file);
							 | 
						||
| 
								 | 
							
								    all=Io.read_file(file);
							 | 
						||
| 
								 | 
							
								    ast=Esprima.parse(all, { tolerant: true, loc:true });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (!modu) this.print('Importing of agent class template(s) from '+file+' failed (empty).');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (p in modu) {
							 | 
						||
| 
								 | 
							
								    ac={};
							 | 
						||
| 
								 | 
							
								    ac[p]=modu[p];
							 | 
						||
| 
								 | 
							
								    if (all) off=this.syntax.find(ast,'VariableDeclarator',p);
							 | 
						||
| 
								 | 
							
								    if (off && off.loc) this.syntax.offset=off.loc.start.line-1;
							 | 
						||
| 
								 | 
							
								    content = 'var ac = '+modu[p];
							 | 
						||
| 
								 | 
							
								    syntax = Esprima.parse(content, { tolerant: true, loc:true });
							 | 
						||
| 
								 | 
							
								    this.analyzeSyntax(syntax,
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        classname:p,
							 | 
						||
| 
								 | 
							
								        level:2,
							 | 
						||
| 
								 | 
							
								        verbose:options.verbose,
							 | 
						||
| 
								 | 
							
								        err:function (msg){self.print(msg)},
							 | 
						||
| 
								 | 
							
								        out:function (msg){self.print(msg)},
							 | 
						||
| 
								 | 
							
								        warn:function (msg){self.print(msg)}
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								    text=Json.stringify(ac);
							 | 
						||
| 
								 | 
							
								    regex1= /this\.next=([a-zA-Z0-9_]+)/;
							 | 
						||
| 
								 | 
							
								    text=text.replace(regex1,"this.next='$1'");
							 | 
						||
| 
								 | 
							
								    // console.log(text);
							 | 
						||
| 
								 | 
							
								    ac=Json.parse(text,{});    
							 | 
						||
| 
								 | 
							
								    if (options.verbose>0) this.print('Adding agent class constructor '+p+'.');
							 | 
						||
| 
								 | 
							
								    this.addClass(ac);
							 | 
						||
| 
								 | 
							
								    this.syntax.offset=0;
							 | 
						||
| 
								 | 
							
								d1179 14
							 | 
						||
| 
								 | 
							
								d1195 28
							 | 
						||
| 
								 | 
							
								a1222 2
							 | 
						||
| 
								 | 
							
								jam.prototype.rm = function (pat) {
							 | 
						||
| 
								 | 
							
								  return this.world.nodes[this.node].ts.extern.rm(pat);
							 | 
						||
| 
								 | 
							
								d1230 4
							 | 
						||
| 
								 | 
							
								a1233 2
							 | 
						||
| 
								 | 
							
								  if (this.loopnext) clearTimeout(this.loopnext);
							 | 
						||
| 
								 | 
							
								  this.loop();
							 | 
						||
| 
								 | 
							
								d1236 6
							 | 
						||
| 
								 | 
							
								d1253 2
							 | 
						||
| 
								 | 
							
								a1254 1
							 | 
						||
| 
								 | 
							
								  var _process=Aios.current.process;
							 | 
						||
| 
								 | 
							
								d1262 1
							 | 
						||
| 
								 | 
							
								d1265 1
							 | 
						||
| 
								 | 
							
								d1269 40
							 | 
						||
| 
								 | 
							
								a1308 1
							 | 
						||
| 
								 | 
							
								jam.prototype.start=function () {
							 | 
						||
| 
								 | 
							
								d1311 2
							 | 
						||
| 
								 | 
							
								a1312 2
							 | 
						||
| 
								 | 
							
								  this.print('Starting ..');
							 | 
						||
| 
								 | 
							
								  this.loop();
							 | 
						||
| 
								 | 
							
								d1317 1
							 | 
						||
| 
								 | 
							
								a1317 1
							 | 
						||
| 
								 | 
							
								 *  type kind = {'process'}
							 | 
						||
| 
								 | 
							
								d1321 2
							 | 
						||
| 
								 | 
							
								a1322 2
							 | 
						||
| 
								 | 
							
								jam.prototype.stats = function (kind) {
							 | 
						||
| 
								 | 
							
								  var p,n,pro,agent,state,stats,allstats={},node;
							 | 
						||
| 
								 | 
							
								d1325 1
							 | 
						||
| 
								 | 
							
								d1332 2
							 | 
						||
| 
								 | 
							
								d1335 2
							 | 
						||
| 
								 | 
							
								a1336 1
							 | 
						||
| 
								 | 
							
								            if (pro.blocked||pro.suspended) state='BLOCKED';
							 | 
						||
| 
								 | 
							
								d1345 4
							 | 
						||
| 
								 | 
							
								a1348 1
							 | 
						||
| 
								 | 
							
								              next:agent.next
							 | 
						||
| 
								 | 
							
								d1350 17
							 | 
						||
| 
								 | 
							
								d1372 13
							 | 
						||
| 
								 | 
							
								d1390 54
							 | 
						||
| 
								 | 
							
								a1443 1
							 | 
						||
| 
								 | 
							
								/** Stop the JAM scheduler
							 | 
						||
| 
								 | 
							
								d1446 30
							 | 
						||
| 
								 | 
							
								a1475 5
							 | 
						||
| 
								 | 
							
								jam.prototype.stop=function () {
							 | 
						||
| 
								 | 
							
								  this.run=false;
							 | 
						||
| 
								 | 
							
								  this.print('Stopping ..');
							 | 
						||
| 
								 | 
							
								  if (this.loopnext)
							 | 
						||
| 
								 | 
							
								    clearTimeout(this.loopnext);
							 | 
						||
| 
								 | 
							
								d1478 2
							 | 
						||
| 
								 | 
							
								d1483 3
							 | 
						||
| 
								 | 
							
								d1491 16
							 | 
						||
| 
								 | 
							
								d1508 8
							 | 
						||
| 
								 | 
							
								a1515 1
							 | 
						||
| 
								 | 
							
								  Jam:Jam
							 | 
						||
| 
								 | 
							
								@
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.3
							 | 
						||
| 
								 | 
							
								log
							 | 
						||
| 
								 | 
							
								@.
							 | 
						||
| 
								 | 
							
								@
							 | 
						||
| 
								 | 
							
								text
							 | 
						||
| 
								 | 
							
								@d22 2
							 | 
						||
| 
								 | 
							
								a23 2
							 | 
						||
| 
								 | 
							
								 **    $RCS:         $Id: jamlib.js,v 1.2 2017/05/27 18:20:44 sbosse Exp $
							 | 
						||
| 
								 | 
							
								 **    $VERSION:     1.3.2
							 | 
						||
| 
								 | 
							
								@
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.2
							 | 
						||
| 
								 | 
							
								log
							 | 
						||
| 
								 | 
							
								@*** empty log message ***
							 | 
						||
| 
								 | 
							
								@
							 | 
						||
| 
								 | 
							
								text
							 | 
						||
| 
								 | 
							
								@d22 2
							 | 
						||
| 
								 | 
							
								a23 2
							 | 
						||
| 
								 | 
							
								 **    $RCS:         $Id: jamlib.js,v 1.1 2017/05/23 07:00:54 sbosse Exp sbosse $
							 | 
						||
| 
								 | 
							
								 **    $VERSION:     1.3.1
							 | 
						||
| 
								 | 
							
								d39 1
							 | 
						||
| 
								 | 
							
								a39 1
							 | 
						||
| 
								 | 
							
								  version:'1.3.1'
							 | 
						||
| 
								 | 
							
								d57 2
							 | 
						||
| 
								 | 
							
								a58 2
							 | 
						||
| 
								 | 
							
								 *  type options = { connections?, print?, provider?, consumer?, classes?, id?, verbose? }
							 | 
						||
| 
								 | 
							
								 *  with type of connections = { 'kind : {send:function, link?:function} , 'kind : .. }
							 | 
						||
| 
								 | 
							
								d89 1
							 | 
						||
| 
								 | 
							
								a89 1
							 | 
						||
| 
								 | 
							
								  var node = Aios.Node.Node({id:this.options.id,position:{x:0,y:0}},true);
							 | 
						||
| 
								 | 
							
								@
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1.1
							 | 
						||
| 
								 | 
							
								log
							 | 
						||
| 
								 | 
							
								@Initial revision
							 | 
						||
| 
								 | 
							
								@
							 | 
						||
| 
								 | 
							
								text
							 | 
						||
| 
								 | 
							
								@d22 2
							 | 
						||
| 
								 | 
							
								a23 2
							 | 
						||
| 
								 | 
							
								 **    $RCS:         $Id: aios.js,v 1.2 2017/05/19 05:13:27 sbosse Exp $
							 | 
						||
| 
								 | 
							
								 **    $VERSION:     1.2.9
							 | 
						||
| 
								 | 
							
								d27 1
							 | 
						||
| 
								 | 
							
								a27 1
							 | 
						||
| 
								 | 
							
								 **  JAM library API taht can be embedded in any host application.
							 | 
						||
| 
								 | 
							
								d39 1
							 | 
						||
| 
								 | 
							
								a39 1
							 | 
						||
| 
								 | 
							
								  version:'1.2.8'
							 | 
						||
| 
								 | 
							
								d120 1
							 | 
						||
| 
								 | 
							
								a120 1
							 | 
						||
| 
								 | 
							
								               drity:this.options.dirty,
							 | 
						||
| 
								 | 
							
								d227 1
							 | 
						||
| 
								 | 
							
								d230 1
							 | 
						||
| 
								 | 
							
								a230 1
							 | 
						||
| 
								 | 
							
								  var syntax,content,result;
							 | 
						||
| 
								 | 
							
								d239 1
							 | 
						||
| 
								 | 
							
								a239 1
							 | 
						||
| 
								 | 
							
								      this.analyzeSyntax(syntax,{
							 | 
						||
| 
								 | 
							
								d244 2
							 | 
						||
| 
								 | 
							
								a245 2
							 | 
						||
| 
								 | 
							
								        out:function (msg){if (!result) result=msg; else result=result+'\n'+msg;},
							 | 
						||
| 
								 | 
							
								        warn:function (msg){if (!result) result=msg; else result=result+'\n'+msg;}
							 | 
						||
| 
								 | 
							
								d247 1
							 | 
						||
| 
								 | 
							
								a247 1
							 | 
						||
| 
								 | 
							
								      return result||'OK';
							 | 
						||
| 
								 | 
							
								d249 1
							 | 
						||
| 
								 | 
							
								a249 1
							 | 
						||
| 
								 | 
							
								      return e;
							 | 
						||
| 
								 | 
							
								@
							 |