You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ea...@apache.org on 2018/01/11 14:15:12 UTC

[1/3] qpid-dispatch git commit: removing rhea since it is incorporated in dispatch-management.js

Repository: qpid-dispatch
Updated Branches:
  refs/heads/master 33feac55c -> cabc6f075


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9b2b64ff/console/stand-alone/plugin/lib/rhea-min.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/lib/rhea-min.js b/console/stand-alone/plugin/lib/rhea-min.js
deleted file mode 100644
index 13d8344..0000000
--- a/console/stand-alone/plugin/lib/rhea-min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-require=function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){(function(process,Buffer){"use strict";var errors=require("./errors.js");var frames=require("./frames.js");var log=require("./log.js");var sasl=require("./sasl.js");var util=require("./util.js");var EndpointState=require("./endpoint.js");var Session=require("./session.js");var Transport=require("./transport.js");var net=require("net");var tls=require("tls");var EventEmitter=require("events").EventEmitter;var AMQP_PROTOCOL_ID=0;function get_socket_id(socket){if(socket.get_id_string)return socket.get_id_stri
 ng();return socket.localAddress+":"+socket.localPort+" -> "+socket.remoteAddress+":"+socket.remotePort}function session_per_connection(conn){var ssn=null;return{get_session:function(){if(!ssn){ssn=conn.create_session();ssn.begin()}return ssn}}}function restrict(count,f){if(count){var current=count;var reset;return function(successful_attempts){if(reset!==successful_attempts){current=count;reset=successful_attempts}if(current--)return f(successful_attempts);else return-1}}else{return f}}function backoff(initial,max){var delay=initial;var reset;return function(successful_attempts){if(reset!==successful_attempts){delay=initial;reset=successful_attempts}var current=delay;var next=delay*2;delay=max>next?next:max;return current}}function get_connect_fn(options){if(options.transport===undefined||options.transport==="tcp"){return net.connect}else if(options.transport==="tls"||options.transport==="ssl"){return tls.connect}else{throw Error("Unrecognised transport: "+options.transport)}}functi
 on connection_details(options){var details={};details.connect=options.connect?options.connect:get_connect_fn(options);details.host=options.host?options.host:"localhost";details.port=options.port?options.port:5672;details.options=options;return details}var aliases=["container_id","hostname","max_frame_size","channel_max","idle_time_out","outgoing_locales","incoming_locales","offered_capabilities","desired_capabilities","properties"];function remote_property_shortcut(name){return function(){return this.remote.open?this.remote.open[name]:undefined}}var conn_counter=1;var Connection=function(options,container){this.options={};if(options){for(var k in options){this.options[k]=options[k]}if((options.transport==="tls"||options.transport==="ssl")&&options.servername===undefined&&options.host!==undefined){this.options.servername=options.host}}this.container=container;if(!this.options.id){this.options.id="connection-"+conn_counter++}if(!this.options.container_id){this.options.container_id=con
 tainer?container.id:util.generate_uuid()}if(!this.options.connection_details){var self=this;this.options.connection_details=function(){return connection_details(self.options)}}var reconnect=this.get_option("reconnect",true);if(typeof reconnect==="boolean"&&reconnect){var initial=this.get_option("initial_reconnect_delay",100);var max=this.get_option("max_reconnect_delay",6e4);this.options.reconnect=restrict(this.get_option("reconnect_limit"),backoff(initial,max))}else if(typeof reconnect==="number"){var fixed=this.options.reconnect;this.options.reconnect=restrict(this.get_option("reconnect_limit"),function(){return fixed})}this.registered=false;this.state=new EndpointState;this.local_channel_map={};this.remote_channel_map={};this.local={};this.remote={};this.local.open=frames.open(this.options);this.local.close=frames.close({});this.session_policy=session_per_connection(this);this.amqp_transport=new Transport(this.options.id,AMQP_PROTOCOL_ID,frames.TYPE_AMQP,this);this.sasl_transport
 =undefined;this.transport=this.amqp_transport;this.conn_established_counter=0;this.heartbeat_out=undefined;this.heartbeat_in=undefined;this.abort_idle=false;this.socket_ready=false;this.scheduled_reconnect=undefined;this.default_sender=undefined;for(var i in aliases){var f=aliases[i];Object.defineProperty(this,f,{get:remote_property_shortcut(f)})}Object.defineProperty(this,"error",{get:function(){return this.remote.close?this.remote.close.error:undefined}})};Connection.prototype=Object.create(EventEmitter.prototype);Connection.prototype.constructor=Connection;Connection.prototype.dispatch=function(name){log.events("Connection got event: %s",name);if(this.listeners(name).length){EventEmitter.prototype.emit.apply(this,arguments);return true}else if(this.container){return this.container.dispatch.apply(this.container,arguments)}else{return false}};Connection.prototype.reset=function(){if(this.abort_idle){this.abort_idle=false;this.local.close.error=undefined;this.state=new EndpointState
 ;this.state.open()}this.amqp_transport=new Transport(this.options.id,AMQP_PROTOCOL_ID,frames.TYPE_AMQP,this);this.sasl_transport=undefined;this.transport=this.amqp_transport;this.state.disconnected();this.remote={};this.remote_channel_map={};for(var k in this.local_channel_map){this.local_channel_map[k].reset()}this.socket_ready=false};Connection.prototype.connect=function(){this.is_server=false;this._connect(this.options.connection_details(this.conn_established_counter));this.open();return this};Connection.prototype.reconnect=function(){this.scheduled_reconnect=undefined;log.reconnect("reconnecting...");this.reset();this._connect(this.options.connection_details(this.conn_established_counter));process.nextTick(this._process.bind(this));return this};Connection.prototype._connect=function(details){if(details.connect){this.init(details.connect(details.port,details.host,details.options,this.connected.bind(this)))}else{this.init(get_connect_fn(details)(details.port,details.host,details.o
 ptions,this.connected.bind(this)))}return this};Connection.prototype.accept=function(socket){this.is_server=true;log.io("[%s] client accepted: %s",this.id,get_socket_id(socket));this.socket_ready=true;return this.init(socket)};Connection.prototype.init=function(socket){this.socket=socket;if(this.get_option("tcp_no_delay",false)&&this.socket.setNoDelay){this.socket.setNoDelay(true)}this.socket.on("data",this.input.bind(this));this.socket.on("error",this.on_error.bind(this));this.socket.on("end",this.eof.bind(this));if(this.is_server){var mechs;if(this.container&&Object.getOwnPropertyNames(this.container.sasl_server_mechanisms).length){mechs=this.container.sasl_server_mechanisms}if(this.socket.encrypted&&this.socket.authorized&&this.get_option("enable_sasl_external",false)){mechs=sasl.server_add_external(mechs?util.clone(mechs):{})}if(mechs){if(mechs.ANONYMOUS!==undefined&&!this.get_option("require_sasl",false)){this.sasl_transport=new sasl.Selective(this,mechs)}else{this.sasl_transpo
 rt=new sasl.Server(this,mechs)}}else{if(!this.get_option("disable_sasl",false)){var anon=sasl.server_mechanisms();anon.enable_anonymous();this.sasl_transport=new sasl.Selective(this,anon)}}}else{var mechanisms=this.get_option("sasl_mechanisms");if(!mechanisms){var username=this.get_option("username");var password=this.get_option("password");if(username){mechanisms=sasl.client_mechanisms();if(password)mechanisms.enable_plain(username,password);else mechanisms.enable_anonymous(username)}}if(this.socket.encrypted&&this.options.cert&&this.get_option("enable_sasl_external",false)){if(!mechanisms)mechanisms=sasl.client_mechanisms();mechanisms.enable_external()}if(mechanisms){this.sasl_transport=new sasl.Client(this,mechanisms,this.options.sasl_init_hostname||this.options.servername||this.options.host)}}this.transport=this.sasl_transport?this.sasl_transport:this.amqp_transport;return this};Connection.prototype.attach_sender=function(options){return this.session_policy.get_session().attach_
 sender(options)};Connection.prototype.open_sender=Connection.prototype.attach_sender;Connection.prototype.attach_receiver=function(options){if(this.get_option("tcp_no_delay",true)&&this.socket.setNoDelay){this.socket.setNoDelay(true)}return this.session_policy.get_session().attach_receiver(options)};Connection.prototype.open_receiver=Connection.prototype.attach_receiver;Connection.prototype.get_option=function(name,default_value){if(this.options[name]!==undefined)return this.options[name];else if(this.container)return this.container.get_option(name,default_value);else return default_value};Connection.prototype.send=function(msg){if(this.default_sender===undefined){this.default_sender=this.open_sender({target:{}})}return this.default_sender.send(msg)};Connection.prototype.connected=function(){this.socket_ready=true;this.conn_established_counter++;log.io("[%s] connected %s",this.options.id,get_socket_id(this.socket));this.output()};Connection.prototype.sasl_failed=function(text){this.
 transport_error={condition:"amqp:unauthorized-access",description:text};this._handle_error()};Connection.prototype._is_fatal=function(error_condition){var non_fatal=this.get_option("non_fatal_errors",["amqp:connection:forced"]);return non_fatal.indexOf(error_condition)<0};Connection.prototype._handle_error=function(){var error=this.get_error();if(error){var handled=this.dispatch("connection_error",this._context());handled=this.dispatch("connection_close",this._context())||handled;if(!this._is_fatal(error.condition)){this.open()}else if(!handled){this.dispatch("error",new errors.ConnectionError(error.description,error.condition,this))}return true}else{return false}};Connection.prototype.get_error=function(){if(this.transport_error)return this.transport_error;if(this.remote.close&&this.remote.close.error)return this.remote.close.error;return undefined};Connection.prototype._get_peer_details=function(){var s="";if(this.remote.open&&this.remote.open.container){s+=this.remote.open.contai
 ner+" "}if(this.remote.open&&this.remote.open.properties){s+=JSON.stringify(this.remote.open.properties)}return s};Connection.prototype.output=function(){try{if(this.socket&&this.socket_ready){if(this.heartbeat_out)clearTimeout(this.heartbeat_out);this.transport.write(this.socket);if((this.is_closed()&&this.state.has_settled()||this.abort_idle||this.transport_error)&&!this.transport.has_writes_pending()){this.socket.end()}else if(this.is_open()&&this.remote.open.idle_time_out){this.heartbeat_out=setTimeout(this._write_frame.bind(this),this.remote.open.idle_time_out/2)}}}catch(e){if(e.name==="ProtocolError"){console.error("["+this.options.id+"] error on write: "+e+" "+this._get_peer_details()+" "+e.name);this.dispatch("protocol_error",e)||console.error("["+this.options.id+"] error on write: "+e+" "+this._get_peer_details())}else{this.dispatch("error",e)}this.socket.end()}};function byte_to_hex(value){if(value<16)return"0x0"+Number(value).toString(16);else return"0x"+Number(value).toS
 tring(16)}function buffer_to_hex(buffer){var bytes=[];for(var i=0;i<buffer.length;i++){bytes.push(byte_to_hex(buffer[i]))}return bytes.join(",")}Connection.prototype.input=function(buff){var buffer;try{if(this.heartbeat_in)clearTimeout(this.heartbeat_in);log.io("[%s] read %d bytes",this.options.id,buff.length);if(this.previous_input){buffer=Buffer.concat([this.previous_input,buff],this.previous_input.length+buff.length);this.previous_input=null}else{buffer=buff}var read=this.transport.read(buffer,this);if(read<buffer.length){this.previous_input=buffer.slice(read)}if(this.local.open.idle_time_out)this.heartbeat_in=setTimeout(this.idle.bind(this),this.local.open.idle_time_out);if(this.transport.has_writes_pending()){this.output()}else if(this.is_closed()&&this.state.has_settled()){this.socket.end()}else if(this.is_open()&&this.remote.open.idle_time_out&&!this.heartbeat_out){this.heartbeat_out=setTimeout(this._write_frame.bind(this),this.remote.open.idle_time_out/2)}}catch(e){if(e.name
 ==="ProtocolError"){this.dispatch("protocol_error",e)||console.error("["+this.options.id+"] error on read: "+e+" "+this._get_peer_details()+" (buffer:"+buffer_to_hex(buffer)+")")}else{this.dispatch("error",e)}this.socket.end()}};Connection.prototype.idle=function(){if(this.is_open()){this.abort_idle=true;this.local.close.error={condition:"amqp:resource-limit-exceeded",description:"max idle time exceeded"};this.close()}};Connection.prototype.on_error=function(e){console.warn("["+this.options.id+"] error: "+e);this._disconnected()};Connection.prototype.eof=function(){this._disconnected()};Connection.prototype._disconnected=function(){if(this.heartbeat_out)clearTimeout(this.heartbeat_out);if(this.heartbeat_in)clearTimeout(this.heartbeat_in);if(!this.is_closed()&&this.scheduled_reconnect===undefined){if(!this.dispatch("disconnected",this._context())){console.warn("["+this.options.id+"] disconnected ")}if(!this.is_server&&!this.transport_error&&this.options.reconnect){var delay=this.opti
 ons.reconnect(this.conn_established_counter);if(delay>=0){log.reconnect("Scheduled reconnect in "+delay+"ms");this.scheduled_reconnect=setTimeout(this.reconnect.bind(this),delay)}}}};Connection.prototype.open=function(){if(this.state.open()){this._register()}};Connection.prototype.close=function(error){if(error)this.local.close.error=error;if(this.state.close()){this._register()}};Connection.prototype.is_open=function(){return this.state.is_open()};Connection.prototype.is_closed=function(){return this.state.is_closed()};Connection.prototype.create_session=function(){var i=0;while(this.local_channel_map[i])i++;var session=new Session(this,i);this.local_channel_map[i]=session;return session};Connection.prototype.find_sender=function(filter){return this.find_link(util.sender_filter(filter))};Connection.prototype.find_receiver=function(filter){return this.find_link(util.receiver_filter(filter))};Connection.prototype.find_link=function(filter){for(var channel in this.local_channel_map){v
 ar session=this.local_channel_map[channel];var result=session.find_link(filter);if(result)return result}return undefined};Connection.prototype.each_receiver=function(action,filter){this.each_link(util.receiver_filter(filter))};Connection.prototype.each_sender=function(action,filter){this.each_link(util.sender_filter(filter))};Connection.prototype.each_link=function(action,filter){for(var channel in this.local_channel_map){var session=this.local_channel_map[channel];session.each_link(action,filter)}};Connection.prototype.on_open=function(frame){if(this.state.remote_opened()){this.remote.open=frame.performative;this.open();this.dispatch("connection_open",this._context())}else{throw new errors.ProtocolError("Open already received")}};Connection.prototype.on_close=function(frame){if(this.state.remote_closed()){this.remote.close=frame.performative;this.close();if(this.remote.close.error){this._handle_error()}else{this.dispatch("connection_close",this._context())}if(this.heartbeat_out)cle
 arTimeout(this.heartbeat_out)}else{throw new errors.ProtocolError("Close already received")}};Connection.prototype._register=function(){if(!this.registered){this.registered=true;process.nextTick(this._process.bind(this))}};Connection.prototype._process=function(){this.registered=false;do{if(this.state.need_open()){this._write_open()}for(var k in this.local_channel_map){this.local_channel_map[k]._process()}if(this.state.need_close()){this._write_close()}}while(!this.state.has_settled())};Connection.prototype._write_frame=function(channel,frame,payload){this.amqp_transport.encode(frames.amqp_frame(channel,frame,payload));this.output()};Connection.prototype._write_open=function(){this._write_frame(0,this.local.open.described())};Connection.prototype._write_close=function(){this._write_frame(0,this.local.close.described())};Connection.prototype.on_begin=function(frame){var session;if(frame.performative.remote_channel===null||frame.performative.remote_channel===undefined){session=this.cr
 eate_session();session.local.begin.remote_channel=frame.channel}else{session=this.local_channel_map[frame.performative.remote_channel];if(!session)throw new errors.ProtocolError("Invalid value for remote channel "+frame.performative.remote_channel)}session.on_begin(frame);this.remote_channel_map[frame.channel]=session};Connection.prototype.get_peer_certificate=function(){if(this.socket&&this.socket.getPeerCertificate){return this.socket.getPeerCertificate()}else{return undefined}};Connection.prototype.get_tls_socket=function(){if(this.socket&&(this.options.transport==="tls"||this.options.transport==="ssl")){return this.socket}else{return undefined}};Connection.prototype._context=function(c){var context=c?c:{};context.connection=this;if(this.container)context.container=this.container;return context};function delegate_to_session(name){Connection.prototype["on_"+name]=function(frame){var session=this.remote_channel_map[frame.channel];if(!session){throw new errors.ProtocolError(name+" r
 eceived on invalid channel "+frame.channel)}session["on_"+name](frame)}}delegate_to_session("end");delegate_to_session("attach");delegate_to_session("detach");delegate_to_session("transfer");delegate_to_session("disposition");delegate_to_session("flow");module.exports=Connection}).call(this,require("_process"),require("buffer").Buffer)},{"./endpoint.js":2,"./errors.js":3,"./frames.js":5,"./log.js":7,"./sasl.js":10,"./session.js":11,"./transport.js":13,"./util.js":15,_process:25,buffer:19,events:22,net:18,tls:18}],2:[function(require,module,exports){"use strict";var EndpointState=function(){this.init()};EndpointState.prototype.init=function(){this.local_open=false;this.remote_open=false;this.open_requests=0;this.close_requests=0;this.initialised=false};EndpointState.prototype.open=function(){this.initialised=true;if(!this.local_open){this.local_open=true;this.open_requests++;return true}else{return false}};EndpointState.prototype.close=function(){if(this.local_open){this.local_open=f
 alse;this.close_requests++;return true}else{return false}};EndpointState.prototype.disconnected=function(){var was_open=this.local_open;this.init();if(was_open){this.open()}else{this.close()}};EndpointState.prototype.remote_opened=function(){if(!this.remote_open){this.remote_open=true;return true}else{return false}};EndpointState.prototype.remote_closed=function(){if(this.remote_open){this.remote_open=false;return true}else{return false}};EndpointState.prototype.is_open=function(){return this.local_open&&this.remote_open};EndpointState.prototype.is_closed=function(){return this.initialised&&!this.local_open&&!this.remote_open};EndpointState.prototype.has_settled=function(){return this.open_requests===0&&this.close_requests===0};EndpointState.prototype.need_open=function(){if(this.open_requests>0){this.open_requests--;return true}else{return false}};EndpointState.prototype.need_close=function(){if(this.close_requests>0){this.close_requests--;return true}else{return false}};module.exp
 orts=EndpointState},{}],3:[function(require,module,exports){"use strict";var util=require("util");function ProtocolError(message){Error.call(this);this.message=message;this.name="ProtocolError"}util.inherits(ProtocolError,Error);function TypeError(message){ProtocolError.call(this,message);this.message=message;this.name="TypeError"}util.inherits(TypeError,ProtocolError);function ConnectionError(message,condition,connection){Error.call(this,message);this.message=message;this.name="ConnectionError";this.condition=condition;this.description=message;this.connection=connection}util.inherits(ConnectionError,Error);module.exports={ProtocolError:ProtocolError,TypeError:TypeError,ConnectionError:ConnectionError}},{util:34}],4:[function(require,module,exports){"use strict";var amqp_types=require("./types.js");module.exports={selector:function(s){return{"jms-selector":amqp_types.wrap_described(s,77567109365764)}}}},{"./types.js":14}],5:[function(require,module,exports){"use strict";var types=re
 quire("./types.js");var errors=require("./errors.js");var frames={};var by_descriptor={};frames.read_header=function(buffer){var offset=4;var header={};var name=buffer.toString("ascii",0,offset);if(name!=="AMQP"){throw new errors.ProtocolError("Invalid protocol header for AMQP "+name)}header.protocol_id=buffer.readUInt8(offset++);header.major=buffer.readUInt8(offset++);header.minor=buffer.readUInt8(offset++);header.revision=buffer.readUInt8(offset++);if(header.protocol_id===0&&header.major===0&&header.minor===9&&header.revision===1){throw new errors.ProtocolError("Unsupported AMQP version: 0-9-1")}if(header.protocol_id===1&&header.major===1&&header.minor===0&&header.revision===10){throw new errors.ProtocolError("Unsupported AMQP version: 0-10")}if(header.major!==1||header.minor!==0){throw new errors.ProtocolError("Unsupported AMQP version: "+JSON.stringify(header))}return header};frames.write_header=function(buffer,header){var offset=4;buffer.write("AMQP",0,offset,"ascii");buffer.wr
 iteUInt8(header.protocol_id,offset++);buffer.writeUInt8(header.major,offset++);buffer.writeUInt8(header.minor,offset++);buffer.writeUInt8(header.revision,offset++);return 8};frames.TYPE_AMQP=0;frames.TYPE_SASL=1;frames.read_frame=function(buffer){var reader=new types.Reader(buffer);var frame={};frame.size=reader.read_uint(4);if(reader.remaining<frame.size){return null}var doff=reader.read_uint(1);if(doff<2){throw new errors.ProtocolError("Invalid data offset, must be at least 2 was "+doff)}frame.type=reader.read_uint(1);if(frame.type===frames.TYPE_AMQP){frame.channel=reader.read_uint(2)}else if(frame.type===frames.TYPE_SASL){reader.skip(2)}else{throw new errors.ProtocolError("Unknown frame type "+frame.type)}if(doff>1){reader.skip(doff*4-8)}if(reader.remaining()){frame.performative=reader.read();var c=by_descriptor[frame.performative.descriptor.value];if(c){frame.performative=new c(frame.performative.value)}if(reader.remaining()){frame.payload=reader.read_bytes(reader.remaining())}}
 return frame};frames.write_frame=function(frame){var writer=new types.Writer;writer.skip(4);writer.write_uint(2,1);writer.write_uint(frame.type,1);if(frame.type===frames.TYPE_AMQP){writer.write_uint(frame.channel,2)}else if(frame.type===frames.TYPE_SASL){writer.write_uint(0,2)}else{throw new errors.ProtocolError("Unknown frame type "+frame.type)}if(frame.performative){writer.write(frame.performative);if(frame.payload){writer.write_bytes(frame.payload)}}var buffer=writer.toBuffer();buffer.writeUInt32BE(buffer.length,0);return buffer};frames.amqp_frame=function(channel,performative,payload){return{channel:channel||0,type:frames.TYPE_AMQP,performative:performative,payload:payload}};frames.sasl_frame=function(performative){return{channel:0,type:frames.TYPE_SASL,performative:performative}};function define_frame(type,def){var c=types.define_composite(def);frames[def.name]=c.create;by_descriptor[Number(c.descriptor.numeric).toString(10)]=c;by_descriptor[c.descriptor.symbolic]=c}var open={n
 ame:"open",code:16,fields:[{name:"container_id",type:"string",mandatory:true},{name:"hostname",type:"string"},{name:"max_frame_size",type:"uint",default_value:4294967295},{name:"channel_max",type:"ushort",default_value:65535},{name:"idle_time_out",type:"uint"},{name:"outgoing_locales",type:"symbol",multiple:true},{name:"incoming_locales",type:"symbol",multiple:true},{name:"offered_capabilities",type:"symbol",multiple:true},{name:"desired_capabilities",type:"symbol",multiple:true},{name:"properties",type:"symbolic_map"}]};var begin={name:"begin",code:17,fields:[{name:"remote_channel",type:"ushort"},{name:"next_outgoing_id",type:"uint",mandatory:true},{name:"incoming_window",type:"uint",mandatory:true},{name:"outgoing_window",type:"uint",mandatory:true},{name:"handle_max",type:"uint",default_value:"4294967295"},{name:"offered_capabilities",type:"symbol",multiple:true},{name:"desired_capabilities",type:"symbol",multiple:true},{name:"properties",type:"symbolic_map"}]};var attach={name:"
 attach",code:18,fields:[{name:"name",type:"string",mandatory:true},{name:"handle",type:"uint",mandatory:true},{name:"role",type:"boolean",mandatory:true},{name:"snd_settle_mode",type:"ubyte",default_value:2},{name:"rcv_settle_mode",type:"ubyte",default_value:0},{name:"source",type:"*"},{name:"target",type:"*"},{name:"unsettled",type:"map"},{name:"incomplete_unsettled",type:"boolean",default_value:false},{name:"initial_delivery_count",type:"uint"},{name:"max_message_size",type:"ulong"},{name:"offered_capabilities",type:"symbol",multiple:true},{name:"desired_capabilities",type:"symbol",multiple:true},{name:"properties",type:"symbolic_map"}]};var flow={name:"flow",code:19,fields:[{name:"next_incoming_id",type:"uint"},{name:"incoming_window",type:"uint",mandatory:true},{name:"next_outgoing_id",type:"uint",mandatory:true},{name:"outgoing_window",type:"uint",mandatory:true},{name:"handle",type:"uint"},{name:"delivery_count",type:"uint"},{name:"link_credit",type:"uint"},{name:"available",t
 ype:"uint"},{name:"drain",type:"boolean",default_value:false},{name:"echo",type:"boolean",default_value:false},{name:"properties",type:"symbolic_map"}]};var transfer={name:"transfer",code:20,fields:[{name:"handle",type:"uint",mandatory:true},{name:"delivery_id",type:"uint"},{name:"delivery_tag",type:"binary"},{name:"message_format",type:"uint"},{name:"settled",type:"boolean"},{name:"more",type:"boolean",default_value:false},{name:"rcv_settle_mode",type:"ubyte"},{name:"state",type:"delivery_state"},{name:"resume",type:"boolean",default_value:false},{name:"aborted",type:"boolean",default_value:false},{name:"batchable",type:"boolean",default_value:false}]};var disposition={name:"disposition",code:21,fields:[{name:"role",type:"boolean",mandatory:true},{name:"first",type:"uint",mandatory:true},{name:"last",type:"uint"},{name:"settled",type:"boolean",default_value:false},{name:"state",type:"*"},{name:"batchable",type:"boolean",default_value:false}]};var detach={name:"detach",code:22,field
 s:[{name:"handle",type:"uint",mandatory:true},{name:"closed",type:"boolean",default_value:false},{name:"error",type:"error"}]};var end={name:"end",code:23,fields:[{name:"error",type:"error"}]};var close={name:"close",code:24,fields:[{name:"error",type:"error"}]};define_frame(frames.TYPE_AMQP,open);define_frame(frames.TYPE_AMQP,begin);define_frame(frames.TYPE_AMQP,attach);define_frame(frames.TYPE_AMQP,flow);define_frame(frames.TYPE_AMQP,transfer);define_frame(frames.TYPE_AMQP,disposition);define_frame(frames.TYPE_AMQP,detach);define_frame(frames.TYPE_AMQP,end);define_frame(frames.TYPE_AMQP,close);var sasl_mechanisms={name:"sasl_mechanisms",code:64,fields:[{name:"sasl_server_mechanisms",type:"symbol",multiple:true,mandatory:true}]};var sasl_init={name:"sasl_init",code:65,fields:[{name:"mechanism",type:"symbol",mandatory:true},{name:"initial_response",type:"binary"},{name:"hostname",type:"string"}]};var sasl_challenge={name:"sasl_challenge",code:66,fields:[{name:"challenge",type:"binar
 y",mandatory:true}]};var sasl_response={name:"sasl_response",code:67,fields:[{name:"response",type:"binary",mandatory:true}]};var sasl_outcome={name:"sasl_outcome",code:68,fields:[{name:"code",type:"ubyte",mandatory:true},{name:"additional_data",type:"binary"}]};define_frame(frames.TYPE_SASL,sasl_mechanisms);define_frame(frames.TYPE_SASL,sasl_init);define_frame(frames.TYPE_SASL,sasl_challenge);define_frame(frames.TYPE_SASL,sasl_response);define_frame(frames.TYPE_SASL,sasl_outcome);module.exports=frames},{"./errors.js":3,"./types.js":14}],6:[function(require,module,exports){(function(Buffer){"use strict";var frames=require("./frames.js");var log=require("./log.js");var message=require("./message.js");var terminus=require("./terminus.js");var EndpointState=require("./endpoint.js");var FlowController=function(window){this.window=window};FlowController.prototype.update=function(context){var delta=this.window-context.receiver.credit;if(delta>=this.window/4){context.receiver.flow(delta)}}
 ;function auto_settle(context){context.delivery.settled=true}function auto_accept(context){context.delivery.update(undefined,message.accepted().described())}function LinkError(message,condition,link){Error.call(this);Error.captureStackTrace(this,this.constructor);this.message=message;this.condition=condition;this.description=message;this.link=link}require("util").inherits(LinkError,Error);var EventEmitter=require("events").EventEmitter;var link=Object.create(EventEmitter.prototype);link.dispatch=function(name){log.events("Link got event: %s",name);EventEmitter.prototype.emit.apply(this.observers,arguments);if(this.listeners(name).length){EventEmitter.prototype.emit.apply(this,arguments);return true}else{return this.session.dispatch.apply(this.session,arguments)}};link.set_source=function(fields){this.local.attach.source=terminus.source(fields).described()};link.set_target=function(fields){this.local.attach.target=terminus.target(fields).described()};link.attach=function(){if(this.st
 ate.open()){this.connection._register()}};link.open=link.attach;link.detach=function(){this.local.detach.closed=false;if(this.state.close()){this.connection._register()}};link.close=function(error){if(error)this.local.detach.error=error;this.local.detach.closed=true;if(this.state.close()){this.connection._register()}};link.is_open=function(){return this.session.is_open()&&this.state.is_open()};link.is_closed=function(){return this.session.is_closed()||this.state.is_closed()};link._process=function(){do{if(this.state.need_open()){this.session.output(this.local.attach.described())}if(this.issue_flow){this.session._write_flow(this);this.issue_flow=false}if(this.state.need_close()){this.session.output(this.local.detach.described())}}while(!this.state.has_settled())};link.on_attach=function(frame){if(this.state.remote_opened()){if(!this.remote.handle){this.remote.handle=frame.handle}frame.performative.source=terminus.unwrap(frame.performative.source);frame.performative.target=terminus.un
 wrap(frame.performative.target);this.remote.attach=frame.performative;this.open();this.dispatch(this.is_receiver()?"receiver_open":"sender_open",this._context())}else{throw Error("Attach already received")}};link.prefix_event=function(event){return(this.local.attach.role?"receiver_":"sender_")+event};link.on_detach=function(frame){if(this.state.remote_closed()){this.remote.detach=frame.performative;this.close();var error=this.remote.detach.error;if(error){var handled=this.dispatch(this.prefix_event("error"),this._context());handled=this.dispatch(this.prefix_event("close"),this._context())||handled;if(!handled){EventEmitter.prototype.emit.call(this.connection.container,"error",new LinkError(error.description,error.condition,this))}}else{this.dispatch(this.prefix_event("close"),this._context())}}else{throw Error("Detach already received")}};function is_internal(name){switch(name){case"name":case"handle":case"role":case"initial_delivery_count":return true;default:return false}}var alia
 ses=["snd_settle_mode","rcv_settle_mode","source","target","max_message_size","offered_capabilities","desired_capabilities","properties"];function remote_property_shortcut(name){return function(){return this.remote.attach?this.remote.attach[name]:undefined}}link.init=function(session,name,local_handle,opts,is_receiver){this.session=session;this.connection=session.connection;this.name=name;this.options=opts===undefined?{}:opts;this.state=new EndpointState;this.issue_flow=false;this.local={handle:local_handle};this.local.attach=frames.attach({handle:local_handle,name:name,role:is_receiver});for(var field in this.local.attach){if(!is_internal(field)&&this.options[field]!==undefined){this.local.attach[field]=this.options[field]}}this.local.detach=frames.detach({handle:local_handle,closed:true});this.remote={handle:undefined};this.delivery_count=0;this.credit=0;this.observers=new EventEmitter;for(var i in aliases){var alias=aliases[i];Object.defineProperty(this,alias,{get:remote_property
 _shortcut(alias)})}Object.defineProperty(this,"error",{get:function(){
-return this.remote.detach?this.remote.detach.error:undefined}})};link.reset=function(){this.state.disconnected();this.remote={handle:undefined};this.delivery_count=0;this.credit=0};link.has_credit=function(){return this.credit>0};link.is_receiver=function(){return this.local.attach.role};link.is_sender=function(){return!this.is_receiver()};link._context=function(c){var context=c?c:{};if(this.is_receiver()){context.receiver=this}else{context.sender=this}return this.session._context(context)};link.get_option=function(name,default_value){if(this.options[name]!==undefined)return this.options[name];else return this.session.get_option(name,default_value)};var Sender=function(session,name,local_handle,opts){this.init(session,name,local_handle,opts,false);this._draining=false;this._drained=false;this.local.attach.initial_delivery_count=0;this.tag=0;if(this.get_option("autosettle",true)){this.observers.on("settled",auto_settle)}var sender=this;if(this.get_option("treat_modified_as_released",
 true)){this.observers.on("modified",function(context){sender.dispatch("released",context)})}};Sender.prototype=Object.create(link);Sender.prototype.constructor=Sender;Sender.prototype._get_drain=function(){if(this._draining&&this._drained&&this.credit){while(this.credit){++this.delivery_count;--this.credit}return true}else{return false}};Sender.prototype.set_drained=function(drained){this._drained=drained;if(this._draining&&this._drained){this.issue_flow=true}};Sender.prototype.next_tag=function(){return new Buffer(new String(this.tag++))};Sender.prototype.sendable=function(){return this.credit&&this.session.outgoing.available()};Sender.prototype.on_flow=function(frame){var flow=frame.performative;this.credit=flow.delivery_count+flow.link_credit-this.delivery_count;this._draining=flow.drain;this._drained=this.credit>0;if(this.is_open()){this.dispatch("sender_flow",this._context());if(this._draining){this.dispatch("sender_draining",this._context())}if(this.sendable()){this.dispatch("
 sendable",this._context())}}};Sender.prototype.on_transfer=function(){throw Error("got transfer on sending link")};Sender.prototype.send=function(msg,tag){var delivery=this.session.send(this,tag?tag:this.next_tag(),message.encode(msg),0);if(this.local.attach.snd_settle_mode===1){delivery.settled=true}return delivery};var Receiver=function(session,name,local_handle,opts){this.init(session,name,local_handle,opts,true);this.drain=false;this.set_credit_window(this.get_option("credit_window",1e3));if(this.get_option("autoaccept",true)){this.observers.on("message",auto_accept)}};Receiver.prototype=Object.create(link);Receiver.prototype.constructor=Receiver;Receiver.prototype.on_flow=function(frame){this.dispatch("receiver_flow",this._context());if(frame.performative.drain){if(frame.performative.link_credit>0)console.error("ERROR: received flow with drain set, but non zero credit");else this.dispatch("receiver_drained",this._context())}};Receiver.prototype.flow=function(credit){if(credit>0
 ){this.credit+=credit;this.issue_flow=true;this.connection._register()}};Receiver.prototype.add_credit=Receiver.prototype.flow;Receiver.prototype._get_drain=function(){return this.drain};Receiver.prototype.set_credit_window=function(credit_window){if(credit_window>0){var flow_controller=new FlowController(credit_window);var listener=flow_controller.update.bind(flow_controller);this.observers.on("message",listener);this.observers.on("receiver_open",listener)}};module.exports={Sender:Sender,Receiver:Receiver}}).call(this,require("buffer").Buffer)},{"./endpoint.js":2,"./frames.js":5,"./log.js":7,"./message.js":8,"./terminus.js":12,buffer:19,events:22,util:34}],7:[function(require,module,exports){"use strict";var debug=require("debug");module.exports={frames:debug("rhea:frames"),raw:debug("rhea:raw"),reconnect:debug("rhea:reconnect"),events:debug("rhea:events"),message:debug("rhea:message"),flow:debug("rhea:flow"),io:debug("rhea:io")}},{debug:20}],8:[function(require,module,exports){"us
 e strict";var log=require("./log.js");var types=require("./types.js");var by_descriptor={};var unwrappers={};var wrappers=[];var message={};function define_section(descriptor,unwrap,wrap){unwrap.descriptor=descriptor;unwrappers[descriptor.symbolic]=unwrap;unwrappers[Number(descriptor.numeric).toString(10)]=unwrap;if(wrap){wrappers.push(wrap)}}function define_composite_section(def){var c=types.define_composite(def);message[def.name]=c.create;by_descriptor[Number(c.descriptor.numeric).toString(10)]=c;by_descriptor[c.descriptor.symbolic]=c;var unwrap=function(msg,section){var composite=new c(section.value);for(var i=0;i<def.fields.length;i++){var f=def.fields[i];var v=composite[f.name];if(v!==undefined&&v!==null){msg[f.name]=v}}};var wrap=function(sections,msg){sections.push(c.create(msg).described())};define_section(c.descriptor,unwrap,wrap)}function define_map_section(def){var descriptor={numeric:def.code};descriptor.symbolic="amqp:"+def.name.replace(/_/g,"-")+":map";var unwrap=funct
 ion(msg,section){msg[def.name]=types.unwrap_map_simple(section)};var wrap=function(sections,msg){if(msg[def.name]){sections.push(types.described_nc(types.wrap_ulong(descriptor.numeric),types.wrap_map(msg[def.name])))}};define_section(descriptor,unwrap,wrap)}function Section(typecode,content){this.typecode=typecode;this.content=content}Section.prototype.described=function(){return types.described(types.wrap_ulong(this.typecode),types.wrap(this.content))};define_composite_section({name:"header",code:112,fields:[{name:"durable",type:"boolean",default_value:false},{name:"priority",type:"ubyte",default_value:4},{name:"ttl",type:"uint"},{name:"first_acquirer",type:"boolean",default_value:false},{name:"delivery_count",type:"uint",default_value:0}]});define_map_section({name:"delivery_annotations",code:113});define_map_section({name:"message_annotations",code:114});define_composite_section({name:"properties",code:115,fields:[{name:"message_id",type:"message_id"},{name:"user_id",type:"binary
 "},{name:"to",type:"string"},{name:"subject",type:"string"},{name:"reply_to",type:"string"},{name:"correlation_id",type:"message_id"},{name:"content_type",type:"symbol"},{name:"content_encoding",type:"symbol"},{name:"absolute_expiry_time",type:"timestamp"},{name:"creation_time",type:"timestamp"},{name:"group_id",type:"string"},{name:"group_sequence",type:"uint"},{name:"reply_to_group_id",type:"string"}]});define_map_section({name:"application_properties",code:116});define_section({numeric:117,symbolic:"amqp:data:binary"},function(msg,section){msg.body=new Section(117,types.unwrap(section))});define_section({numeric:118,symbolic:"amqp:amqp-sequence:list"},function(msg,section){msg.body=new Section(118,types.unwrap(section))});define_section({numeric:119,symbolic:"amqp:value:*"},function(msg,section){msg.body=types.unwrap(section)});define_map_section({name:"footer",code:120});function wrap_body(sections,msg){if(msg.body&&msg.body.constructor===Section){sections.push(msg.body.describe
 d())}else{sections.push(types.described(types.wrap_ulong(119),types.wrap(msg.body)))}}wrappers.push(wrap_body);message.data_section=function(data){return new Section(117,data)};message.sequence_section=function(list){return new Section(118,list)};function copy(src,tgt){for(var k in src){var v=src[k];if(typeof v==="object"){copy(v,tgt[k])}else{tgt[k]=v}}}function Message(o){if(o){copy(o,this)}}Message.prototype.toJSON=function(){var o={};for(var key in this){if(typeof this[key]==="function")continue;o[key]=this[key]}return o};Message.prototype.inspect=function(){return JSON.stringify(this.toJSON())};Message.prototype.toString=function(){return JSON.stringify(this.toJSON())};message.encode=function(msg){var sections=[];wrappers.forEach(function(wrapper_fn){wrapper_fn(sections,msg)});var writer=new types.Writer;for(var i=0;i<sections.length;i++){log.message("Encoding section %d of %d: %o",i+1,sections.length,sections[i]);writer.write(sections[i])}var data=writer.toBuffer();log.message(
 "encoded %d bytes",data.length);return data};message.decode=function(buffer){var msg=new Message;var reader=new types.Reader(buffer);while(reader.remaining()){var s=reader.read();log.message("decoding section: %o of type: %o",s,s.descriptor);if(s.descriptor){var unwrap=unwrappers[s.descriptor.value];if(unwrap){unwrap(msg,s)}else{console.warn("WARNING: did not recognise message section with descriptor "+s.descriptor)}}else{console.warn("WARNING: expected described message section got "+JSON.stringify(s))}}return msg};var outcomes={};function define_outcome(def){var c=types.define_composite(def);c.composite_type=def.name;message[def.name]=c.create;outcomes[Number(c.descriptor.numeric).toString(10)]=c;outcomes[c.descriptor.symbolic]=c;message["is_"+def.name]=function(o){if(o&&o.descriptor){var c=outcomes[o.descriptor.value];if(c){return c.descriptor.numeric===def.code}}return false}}message.unwrap_outcome=function(outcome){if(outcome&&outcome.descriptor){var c=outcomes[outcome.descript
 or.value];if(c){return new c(outcome.value)}}console.error("unrecognised outcome: "+JSON.stringify(outcome));return outcome};message.are_outcomes_equivalent=function(a,b){if(a===undefined&&b===undefined)return true;else if(a===undefined||b===undefined)return false;else return a.descriptor.value===b.descriptor.value&&a.descriptor.value===36};define_outcome({name:"received",code:35,fields:[{name:"section_number",type:"uint",mandatory:true},{name:"section_offset",type:"ulong",mandatory:true}]});define_outcome({name:"accepted",code:36,fields:[]});define_outcome({name:"rejected",code:37,fields:[{name:"error",type:"error"}]});define_outcome({name:"released",code:38,fields:[]});define_outcome({name:"modified",code:39,fields:[{name:"delivery_failed",type:"boolean"},{name:"undeliverable_here",type:"boolean"},{name:"message_annotations",type:"map"}]});module.exports=message},{"./log.js":7,"./types.js":14}],9:[function(require,module,exports){"use strict";var url=require("url");var simple_id_g
 enerator={counter:1,next:function(){return this.counter++}};var Client=function(container,address){var u=url.parse(address);this.connection=container.connect({host:u.hostname,port:u.port});this.connection.on("message",this._response.bind(this));this.connection.on("receiver_open",this._ready.bind(this));this.sender=this.connection.attach_sender(u.path.substr(1));this.receiver=this.connection.attach_receiver({source:{dynamic:true}});this.id_generator=simple_id_generator;this.pending=[];this.outstanding={}};Client.prototype._request=function(id,name,args,callback){var request={};request.subject=name;request.body=args;request.message_id=id;request.reply_to=this.receiver.remote.attach.source.address;this.outstanding[id]=callback;this.sender.send(request)};Client.prototype._response=function(context){var id=context.message.correlation_id;var callback=this.outstanding[id];if(callback){if(context.message.subject==="ok"){callback(context.message.body)}else{callback(undefined,{name:context.me
 ssage.subject,description:context.message.body})}}else{console.error("no request pending for "+id+", ignoring response")}};Client.prototype._ready=function(){this._process_pending()};Client.prototype._process_pending=function(){for(var i=0;i<this.pending.length;i++){var r=this.pending[i];this._request(r.id,r.name,r.args,r.callback)}this.pending=[]};Client.prototype.call=function(name,args,callback){var id=this.id_generator.next();if(this.receiver.is_open()&&this.pending.length===0){this._request(id,name,args,callback)}else{this.pending.push({name:name,args:args,callback:callback,id:id})}};Client.prototype.close=function(){this.receiver.close();this.sender.close();this.connection.close()};Client.prototype.define=function(name){this[name]=function(args,callback){this.call(name,args,callback)}};var Cache=function(ttl,purged){this.ttl=ttl;this.purged=purged;this.entries={};this.timeout=undefined};Cache.prototype.clear=function(){if(this.timeout)clearTimeout(this.timeout);this.entries={}
 };Cache.prototype.put=function(key,value){this.entries[key]={value:value,last_accessed:Date.now()};if(!this.timeout)this.timeout=setTimeout(this.purge.bind(this),this.ttl)};Cache.prototype.get=function(key){var entry=this.entries[key];if(entry){entry.last_accessed=Date.now();return entry.value}else{return undefined}};Cache.prototype.purge=function(){var now=Date.now();var expired=[];var live=0;for(var k in this.entries){if(now-this.entries[k].last_accessed>=this.ttl){expired.push(k)}else{live++}}for(var i=0;i<expired.length;i++){var entry=this.entries[expired[i]];delete this.entries[expired[i]];this.purged(entry.value)}if(live&&!this.timeout){this.timeout=setTimeout(this.purge.bind(this),this.ttl)}};var LinkCache=function(factory,ttl){this.factory=factory;this.cache=new Cache(ttl,function(link){link.close()})};LinkCache.prototype.clear=function(){this.cache.clear()};LinkCache.prototype.get=function(address){var link=this.cache.get(address);if(link===undefined){link=this.factory(addr
 ess);this.cache.put(address,link)}return link};var Server=function(container,address,options){this.options=options||{};var u=url.parse(address);this.connection=container.connect({host:u.hostname,port:u.port});this.connection.on("connection_open",this._connection_open.bind(this));this.connection.on("message",this._request.bind(this));this.receiver=this.connection.attach_receiver(u.path.substr(1));this.callbacks={};this._send=undefined;this._clear=undefined};function match(desired,offered){if(offered){if(Array.isArray(offered)){return offered.indexOf(desired)>-1}else{return desired===offered}}else{return false}}Server.prototype._connection_open=function(){if(match("ANONYMOUS-RELAY",this.connection.remote.open.offered_capabilities)){var relay=this.connection.attach_sender({target:{}});this._send=function(msg){relay.send(msg)}}else{var cache=new LinkCache(this.connection.attach_sender.bind(this.connection),this.options.cache_ttl||6e4);this._send=function(msg){var s=cache.get(msg.to);if(
 s)s.send(msg)};this._clear=function(){cache.clear()}}};Server.prototype._respond=function(response){var server=this;return function(result,error){if(error){response.subject=error.name||"error";response.body=error.description||error}else{response.subject="ok";response.body=result}server._send(response)}};Server.prototype._request=function(context){var request=context.message;var response={};response.to=request.reply_to;response.correlation_id=request.message_id;var callback=this.callbacks[request.subject];if(callback){callback(request.body,this._respond(response))}else{response.subject="bad-method";response.body="Unrecognised method "+request.subject;this._send(response)}};Server.prototype.bind_sync=function(f,name){this.callbacks[name||f.name]=function(args,callback){var result=f(args);callback(result)}};Server.prototype.bind=function(f,name){this.callbacks[name||f.name]=f};Server.prototype.close=function(){if(this._clear)this._clear();this.receiver.close();this.connection.close()};
 module.exports={server:function(container,address,options){return new Server(container,address,options)},client:function(connection,address){return new Client(connection,address)}}},{url:30}],10:[function(require,module,exports){(function(Buffer){"use strict";var errors=require("./errors.js");var frames=require("./frames.js");var Transport=require("./transport.js");var sasl_codes={OK:0,AUTH:1,SYS:2,SYS_PERM:3,SYS_TEMP:4};var SASL_PROTOCOL_ID=3;function extract(buffer){var results=[];var start=0;var i=0;while(i<buffer.length){if(buffer[i]===0){if(i>start)results.push(buffer.toString("utf8",start,i));else results.push(null);start=++i}else{++i}}if(i>start)results.push(buffer.toString("utf8",start,i));else results.push(null);return results}var PlainServer=function(callback){this.callback=callback;this.outcome=undefined;this.username=undefined};PlainServer.prototype.start=function(response,hostname){var fields=extract(response);if(fields.length!==3){this.connection.sasl_failed("Unexpecte
 d response in PLAIN, got "+fields.length+" fields, expected 3")}if(this.callback(fields[1],fields[2],hostname)){this.outcome=true;this.username=fields[1]}else{this.outcome=false}};var PlainClient=function(username,password){this.username=username;this.password=password};PlainClient.prototype.start=function(){var response=new Buffer(1+this.username.length+1+this.password.length);response.writeUInt8(0,0);response.write(this.username,1);response.writeUInt8(0,1+this.username.length);response.write(this.password,1+this.username.length+1);return response};var AnonymousServer=function(){this.outcome=undefined;this.username=undefined};AnonymousServer.prototype.start=function(response){this.outcome=true;this.username=response?response.toString("utf8"):"anonymous"};var AnonymousClient=function(name){this.username=name?name:"anonymous"};AnonymousClient.prototype.start=function(){var response=new Buffer(1+this.username.length);response.writeUInt8(0,0);response.write(this.username,1);return resp
 onse};var ExternalServer=function(){this.outcome=undefined;this.username=undefined};ExternalServer.prototype.start=function(){this.outcome=true};var ExternalClient=function(){this.username=undefined};ExternalClient.prototype.start=function(){return""};ExternalClient.prototype.step=function(){return""};var SaslServer=function(connection,mechanisms){this.connection=connection;this.transport=new Transport(connection.amqp_transport.identifier,SASL_PROTOCOL_ID,frames.TYPE_SASL,this);this.next=connection.amqp_transport;this.mechanisms=mechanisms;this.mechanism=undefined;this.outcome=undefined;this.username=undefined;var mechlist=Object.getOwnPropertyNames(mechanisms);this.transport.encode(frames.sasl_frame(frames.sasl_mechanisms({sasl_server_mechanisms:mechlist}).described()))};SaslServer.prototype.do_step=function(challenge){if(this.mechanism.outcome===undefined){this.transport.encode(frames.sasl_frame(frames.sasl_challenge({challenge:challenge}).described()))}else{this.outcome=this.mech
 anism.outcome?sasl_codes.OK:sasl_codes.AUTH;this.transport.encode(frames.sasl_frame(frames.sasl_outcome({code:this.outcome}).described()));if(this.outcome===sasl_codes.OK){this.username=this.mechanism.username;this.transport.write_complete=true;this.transport.read_complete=true}}};SaslServer.prototype.on_sasl_init=function(frame){var f=this.mechanisms[frame.performative.mechanism];if(f){this.mechanism=f();var challenge=this.mechanism.start(frame.performative.initial_response,frame.performative.hostname);this.do_step(challenge)}else{this.outcome=sasl_codes.AUTH;this.transport.encode(frames.sasl_frame(frames.sasl_outcome({code:this.outcome}).described()))}};SaslServer.prototype.on_sasl_response=function(frame){this.do_step(this.mechanism.step(frame.performative.response))};SaslServer.prototype.has_writes_pending=function(){return this.transport.has_writes_pending()||this.next.has_writes_pending()};SaslServer.prototype.write=function(socket){if(this.transport.write_complete&&this.trans
 port.pending.length===0){return this.next.write(socket)}else{return this.transport.write(socket)}};SaslServer.prototype.read=function(buffer){if(this.transport.read_complete){return this.next.read(buffer)}else{return this.transport.read(buffer)}};var SaslClient=function(connection,mechanisms,hostname){this.connection=connection;this.transport=new Transport(connection.amqp_transport.identifier,SASL_PROTOCOL_ID,frames.TYPE_SASL,this);this.next=connection.amqp_transport;this.mechanisms=mechanisms;this.mechanism=undefined;this.mechanism_name=undefined;this.hostname=hostname;this.failed=false};SaslClient.prototype.on_sasl_mechanisms=function(frame){for(var i=0;this.mechanism===undefined&&i<frame.performative.sasl_server_mechanisms.length;i++){var mech=frame.performative.sasl_server_mechanisms[i];var f=this.mechanisms[mech];if(f){this.mechanism=f();this.mechanism_name=mech}}if(this.mechanism){var response=this.mechanism.start();var init={mechanism:this.mechanism_name,initial_response:resp
 onse};if(this.hostname){init.hostname=this.hostname}this.transport.encode(frames.sasl_frame(frames.sasl_init(init).described()))}else{this.failed=true;this.connection.sasl_failed("No suitable mechanism; server supports "+frame.performative.sasl_server_mechanisms)}};SaslClient.prototype.on_sasl_challenge=function(frame){var response=this.mechanism.step(frame.performative.challenge);this.transport.encode(frames.sasl_frame(frames.sasl_response({response:response}).described()))};SaslClient.prototype.on_sasl_outcome=function(frame){switch(frame.performative.code){case sasl_codes.OK:this.transport.read_complete=true;this.transport.write_complete=true;break;default:this.transport.write_complete=true;this.connection.sasl_failed("Failed to authenticate: "+frame.performative.code)}};SaslClient.prototype.has_writes_pending=function(){return this.transport.has_writes_pending()||this.next.has_writes_pending()};SaslClient.prototype.write=function(socket){if(this.transport.write_complete){return 
 this.next.write(socket)}else{return this.transport.write(socket)}};SaslClient.prototype.read=function(buffer){if(this.transport.read_complete){return this.next.read(buffer)}else{return this.transport.read(buffer)}};var SelectiveServer=function(connection,mechanisms){this.header_received=false;this.transports={0:connection.amqp_transport,3:new SaslServer(connection,mechanisms)};this.selected=undefined};SelectiveServer.prototype.has_writes_pending=function(){return this.header_received&&this.selected.has_writes_pending()};SelectiveServer.prototype.write=function(socket){if(this.selected){return this.selected.write(socket)}else{return 0}};SelectiveServer.prototype.read=function(buffer){if(!this.header_received){if(buffer.length<8){return 0}else{this.header_received=frames.read_header(buffer);this.selected=this.transports[this.header_received.protocol_id];if(this.selected===undefined){throw new errors.ProtocolError("Invalid AMQP protocol id "+this.header_received.protocol_id)}}}return t
 his.selected.read(buffer)};var default_server_mechanisms={enable_anonymous:function(){this["ANONYMOUS"]=function(){return new AnonymousServer}},enable_plain:function(callback){this["PLAIN"]=function(){return new PlainServer(callback)}}};var default_client_mechanisms={enable_anonymous:function(name){this["ANONYMOUS"]=function(){return new AnonymousClient(name)}},enable_plain:function(username,password){this["PLAIN"]=function(){return new PlainClient(username,password)}},enable_external:function(){this["EXTERNAL"]=function(){return new ExternalClient}}};module.exports={Client:SaslClient,Server:SaslServer,Selective:SelectiveServer,server_mechanisms:function(){return Object.create(default_server_mechanisms)},client_mechanisms:function(){return Object.create(default_client_mechanisms)},server_add_external:function(mechs){mechs["EXTERNAL"]=function(){return new ExternalServer};return mechs}}}).call(this,require("buffer").Buffer)},{"./errors.js":3,"./frames.js":5,"./transport.js":13,buffer
 :19}],11:[function(require,module,exports){(function(Buffer){"use strict";var frames=require("./frames.js");var link=require("./link.js");var log=require("./log.js");var message=require("./message.js");var types=require("./types.js");var util=require("./util.js");var EndpointState=require("./endpoint.js");var EventEmitter=require("events").EventEmitter;var CircularBuffer=function(capacity){this.capacity=capacity;this.size=0;this.head=0;this.tail=0;this.entries=[]};CircularBuffer.prototype.available=function(){return this.capacity-this.size};CircularBuffer.prototype.push=function(o){if(this.size<this.capacity){this.entries[this.tail]=o;this.tail=(this.tail+1)%this.capacity;this.size++}else{throw Error("circular buffer overflow: head="+this.head+" tail="+this.tail+" size="+this.size+" capacity="+this.capacity)}};CircularBuffer.prototype.pop_if=function(f){var count=0;while(this.size&&f(this.entries[this.head])){this.entries[this.head]=undefined;this.head=(this.head+1)%this.capacity;th
 is.size--;count++}return count};CircularBuffer.prototype.by_id=function(id){if(this.size>0){var gap=id-this.entries[this.head].id;if(gap<this.size){return this.entries[(this.head+gap)%this.capacity]}}return undefined};CircularBuffer.prototype.get_head=function(){return this.size>0?this.entries[this.head]:undefined};function write_dispositions(deliveries){var first,last,next_id,i,delivery;for(i=0;i<deliveries.length;i++){delivery=deliveries[i];if(first===undefined){first=delivery;last=delivery;next_id=delivery.id}if(!message.are_outcomes_equivalent(last.state,delivery.state)||last.settled!==delivery.settled||next_id!==delivery.id){first.link.session.output(frames.disposition({role:first.link.is_receiver(),first:first.id,last:last.id,state:first.state,settled:first.settled}).described());first=delivery;last=delivery;next_id=delivery.id}else{if(last.id!==delivery.id){last=delivery}next_id++}}if(first!==undefined&&last!==undefined){first.link.session.output(frames.disposition({role:firs
 t.link.is_receiver(),first:first.id,last:last.id,state:first.state,settled:first.settled}).described())}}var Outgoing=function(){this.deliveries=new CircularBuffer(2048);this.updated=[];this.pending_dispositions=[];this.next_delivery_id=0;this.next_pending_delivery=0;this.next_transfer_id=0;this.window=types.MAX_UINT;this.remote_next_transfer_id=undefined;this.remote_window=undefined};Outgoing.prototype.available=function(){return this.deliveries.available()};Outgoing.prototype.send=function(sender,tag,data,format){var d={id:this.next_delivery_id++,tag:tag,link:sender,data:data,format:format?format:0,sent:false,settled:false,state:undefined,remote_settled:false,remote_state:undefined};var self=this;d.update=function(settled,state){self.update(d,settled,state)};this.deliveries.push(d);return d};Outgoing.prototype.on_begin=function(fields){this.remote_window=fields.incoming_window};Outgoing.prototype.on_flow=function(fields){this.remote_next_transfer_id=fields.next_incoming_id;this.re
 mote_window=fields.incoming_window};Outgoing.prototype.on_disposition=function(fields){var last=fields.last?fields.last:fields.first;for(var i=fields.first;i<=last;i++){var d=this.deliveries.by_id(i);if(d&&!d.remote_settled){var updated=false;if(fields.settled){d.remote_settled=fields.settled;updated=true}if(fields.state&&fields.state!==d.remote_state){d.remote_state=message.unwrap_outcome(fields.state);updated=true}if(updated){this.updated.push(d)}}}};Outgoing.prototype.update=function(delivery,settled,state){if(delivery){delivery.settled=settled;if(state!==undefined)delivery.state=state;if(!delivery.remote_settled){this.pending_dispositions.push(delivery)}delivery.link.connection._register()}};Outgoing.prototype.transfer_window=function(){if(this.remote_window){return this.remote_window-(this.next_transfer_id-this.remote_next_transfer_id)}else{return 0}};Outgoing.prototype.process=function(){var d;while(this.next_pending_delivery<this.next_delivery_id){d=this.deliveries.by_id(this
 .next_pending_delivery);if(d){if(d.link.has_credit()){d.link.delivery_count++;d.transfers_required=1;if(this.transfer_window()>=d.transfers_required){this.next_transfer_id+=d.transfers_required;this.window-=d.transfers_required;d.link.session.output(frames.transfer({handle:d.link.local.handle,message_format:d.format,delivery_id:d.id,delivery_tag:d.tag,settled:d.settled}).described(),d.data);d.link.credit--;this.next_pending_delivery++}else{log.flow("Incoming window of peer preventing sending further transfers: remote_window=%d, remote_next_transfer_id=%d, next_transfer_id=%d",this.remote_window,this.remote_next_transfer_id,this.next_transfer_id);break}}else{log.flow("Link has no credit");break}}else{console.error("ERROR: Next pending delivery not found: "+this.next_pending_delivery);break}}for(var i=0;i<this.updated.length;i++){d=this.updated[i];if(d.remote_state&&d.remote_state.constructor.composite_type){d.link.dispatch(d.remote_state.constructor.composite_type,d.link._context({de
 livery:d}))}if(d.remote_settled)d.link.dispatch("settled",d.link._context({delivery:d}))}this.updated=[];if(this.pending_dispositions.length){write_dispositions(this.pending_dispositions);this.pending_dispositions=[]}this.deliveries.pop_if(function(d){return d.settled&&d.remote_settled})};var Incoming=function(){this.deliveries=new CircularBuffer(2048);this.updated=[];this.next_transfer_id=0;this.next_delivery_id=undefined;this.window=2048;this.remote_next_transfer_id=undefined;this.remote_window=undefined};Incoming.prototype.update=function(delivery,settled,state){if(delivery){delivery.settled=settled;if(state!==undefined)delivery.state=state;if(!delivery.remote_settled){this.updated.push(delivery)}delivery.link.connection._register()}};Incoming.prototype.on_transfer=function(frame,receiver){this.next_transfer_id++;if(receiver.is_open()){if(this.next_delivery_id===undefined){this.next_delivery_id=frame.performative.delivery_id}var current;var data;var last=this.deliveries.get_head(
 );if(last&&last.incomplete){if(frame.performative.delivery_id!==undefined&&this.next_delivery_id!==frame.performative.delivery_id){throw Error("frame sequence error: delivery "+this.next_delivery_id+" not complete, got "+frame.performative.delivery_id)}current=last;data=Buffer.concat([current.data,frame.payload],current.data.length+frame.payload.length)}else if(this.next_delivery_id===frame.performative.delivery_id){current={id:frame.performative.delivery_id,tag:frame.performative.delivery_tag,link:receiver,settled:false,state:undefined,remote_settled:frame.performative.settled===undefined?false:frame.performative.settled,remote_state:frame.performative.state};var self=this;current.update=function(settled,state){var settled_=settled;if(settled_===undefined){settled_=receiver.local.attach.rcv_settle_mode!==1}self.update(current,settled_,state)};current.accept=function(){this.update(undefined,message.accepted().described())};current.release=function(params){if(params){this.update(unde
 fined,message.modified(params).described())}else{this.update(undefined,message.released().described())}};current.reject=function(error){this.update(true,message.rejected({error:error}).described())};current.modified=function(params){this.update(true,message.modified(params).described())};this.deliveries.push(current);data=frame.payload}else{throw Error("frame sequence error: expected "+this.next_delivery_id+", got "+frame.performative.delivery_id)}current.incomplete=frame.performative.more;if(current.incomplete){current.data=data}else{receiver.credit--;receiver.delivery_count++;this.next_delivery_id++;receiver.dispatch("message",receiver._context({message:message.decode(data),delivery:current}))}}};Incoming.prototype.process=function(){if(this.updated.length>0){write_dispositions(this.updated);this.updated=[]}this.deliveries.pop_if(function(d){return d.settled})};Incoming.prototype.on_begin=function(fields){this.remote_window=fields.outgoing_window};Incoming.prototype.on_flow=functi
 on(fields){this.remote_next_transfer_id=fields.next_outgoing_id;this.remote_window=fields.outgoing_window};Incoming.prototype.on_disposition=function(fields){var last=fields.last?fields.last:fields.first;for(var i=fields.first;i<=last;i++){var d=this.deliveries.by_id(i);if(d&&!d.remote_settled){if(fields.settled){d.remote_settled=fields.settled;d.link.dispatch("settled",d.link._context({delivery:d}))}}}};var Session=function(connection,local_channel){this.connection=connection;this.outgoing=new Outgoing;this.incoming=new Incoming;this.state=new EndpointState;this.local={channel:local_channel,handles:{}};this.local.begin=frames.begin({next_outgoing_id:this.outgoing.next_transfer_id,incoming_window:this.incoming.window,outgoing_window:this.outgoing.window});this.local.end=frames.end();this.remote={handles:{}};this.links={};this.options={}};Session.prototype=Object.create(EventEmitter.prototype);Session.prototype.constructor=Session;Session.prototype.reset=function(){this.state.disconn
 ected();this.outgoing=new Outgoing;this.incoming=new Incoming;this.remote={handles:{}}
-;for(var l in this.links){this.links[l].reset()}};Session.prototype.dispatch=function(name){log.events("Session got event: %s",name);if(this.listeners(name).length){EventEmitter.prototype.emit.apply(this,arguments);return true}else{return this.connection.dispatch.apply(this.connection,arguments)}};Session.prototype.output=function(frame,payload){this.connection._write_frame(this.local.channel,frame,payload)};Session.prototype.create_sender=function(name,opts){return this.create_link(name,link.Sender,opts)};Session.prototype.create_receiver=function(name,opts){return this.create_link(name,link.Receiver,opts)};function attach(factory,args,remote_terminus){var opts=args?args:{};if(typeof args==="string"){opts={};opts[remote_terminus]=args}if(!opts.name)opts.name=util.generate_uuid();var l=factory(opts.name,opts);for(var t in{source:0,target:0}){if(opts[t]){if(typeof opts[t]==="string"){opts[t]={address:opts[t]}}l["set_"+t](opts[t])}}if(l.is_sender()&&opts.source===undefined){opts.sourc
 e=l.set_source({})}if(l.is_receiver()&&opts.target===undefined){opts.target=l.set_target({})}l.attach();return l}Session.prototype.get_option=function(name,default_value){if(this.options[name]!==undefined)return this.options[name];else return this.connection.get_option(name,default_value)};Session.prototype.attach_sender=function(args){return attach(this.create_sender.bind(this),args,"target")};Session.prototype.open_sender=Session.prototype.attach_sender;Session.prototype.attach_receiver=function(args){return attach(this.create_receiver.bind(this),args,"source")};Session.prototype.open_receiver=Session.prototype.attach_receiver;Session.prototype.find_sender=function(filter){return this.find_link(util.sender_filter(filter))};Session.prototype.find_receiver=function(filter){return this.find_link(util.receiver_filter(filter))};Session.prototype.find_link=function(filter){for(var name in this.links){var link=this.links[name];if(filter(link))return link}return undefined};Session.prototy
 pe.each_receiver=function(action,filter){this.each_link(util.receiver_filter(filter))};Session.prototype.each_sender=function(action,filter){this.each_link(util.sender_filter(filter))};Session.prototype.each_link=function(action,filter){for(var name in this.links){var link=this.links[name];if(filter===undefined||filter(link))action(link)}};Session.prototype.create_link=function(name,constructor,opts){var i=0;while(this.local.handles[i])i++;var l=new constructor(this,name,i,opts);this.links[name]=l;this.local.handles[i]=l;return l};Session.prototype.begin=function(){if(this.state.open()){this.connection._register()}};Session.prototype.open=Session.prototype.begin;Session.prototype.end=function(error){if(error)this.local.end.error=error;if(this.state.close()){this.connection._register()}};Session.prototype.close=Session.prototype.end;Session.prototype.is_open=function(){return this.connection.is_open()&&this.state.is_open()};Session.prototype.is_closed=function(){return this.connectio
 n.is_closed()||this.state.is_closed()};Session.prototype._process=function(){do{if(this.state.need_open()){this.output(this.local.begin.described())}this.outgoing.process();this.incoming.process();for(var k in this.links){this.links[k]._process()}if(this.state.need_close()){this.output(this.local.end.described())}}while(!this.state.has_settled())};Session.prototype.send=function(sender,tag,data,format){var d=this.outgoing.send(sender,tag,data,format);this.connection._register();return d};Session.prototype._write_flow=function(link){var fields={next_incoming_id:this.incoming.next_transfer_id,incoming_window:this.incoming.window,next_outgoing_id:this.outgoing.next_transfer_id,outgoing_window:this.outgoing.window};if(link){if(link._get_drain())fields.drain=true;fields.delivery_count=link.delivery_count;fields.handle=link.local.handle;fields.link_credit=link.credit}this.output(frames.flow(fields).described())};Session.prototype.on_begin=function(frame){if(this.state.remote_opened()){if(
 !this.remote.channel){this.remote.channel=frame.channel}this.remote.begin=frame.performative;this.outgoing.on_begin(frame.performative);this.incoming.on_begin(frame.performative);this.open();this.dispatch("session_open",this._context())}else{throw Error("Begin already received")}};Session.prototype.on_end=function(frame){if(this.state.remote_closed()){this.remote.end=frame.performative;this.close();this.dispatch("session_close",this._context())}else{throw Error("End already received")}};Session.prototype.on_attach=function(frame){var name=frame.performative.name;var link=this.links[name];if(!link){link=frame.performative.role?this.create_sender(name):this.create_receiver(name)}this.remote.handles[frame.performative.handle]=link;link.on_attach(frame);link.remote.attach=frame.performative};Session.prototype.on_disposition=function(frame){if(frame.performative.role){log.events("Received disposition for outgoing transfers");this.outgoing.on_disposition(frame.performative)}else{log.event
 s("Received disposition for incoming transfers");this.incoming.on_disposition(frame.performative)}this.connection._register()};Session.prototype.on_flow=function(frame){this.outgoing.on_flow(frame.performative);this.incoming.on_flow(frame.performative);if(frame.performative.handle!==undefined){this._get_link(frame).on_flow(frame)}this.connection._register()};Session.prototype._context=function(c){var context=c?c:{};context.session=this;return this.connection._context(context)};Session.prototype._get_link=function(frame){var handle=frame.performative.handle;var link=this.remote.handles[handle];if(!link){throw Error("Invalid handle "+handle)}return link};Session.prototype.on_detach=function(frame){this._get_link(frame).on_detach(frame);var handle=frame.performative.handle;var link=this.remote.handles[handle];delete this.remote.handles[handle];delete this.local.handles[link.local.handle];delete this.links[link.name]};Session.prototype.on_transfer=function(frame){this.incoming.on_transf
 er(frame,this._get_link(frame))};module.exports=Session}).call(this,require("buffer").Buffer)},{"./endpoint.js":2,"./frames.js":5,"./link.js":6,"./log.js":7,"./message.js":8,"./types.js":14,"./util.js":15,buffer:19,events:22}],12:[function(require,module,exports){"use strict";var types=require("./types.js");var terminus={};var by_descriptor={};function define_terminus(def){var c=types.define_composite(def);terminus[def.name]=c.create;by_descriptor[Number(c.descriptor.numeric).toString(10)]=c;by_descriptor[c.descriptor.symbolic]=c}terminus.unwrap=function(field){if(field&&field.descriptor){var c=by_descriptor[field.descriptor.value];if(c){return new c(field.value)}else{console.warn("Unknown terminus: "+field.descriptor)}}return null};define_terminus({name:"source",code:40,fields:[{name:"address",type:"string"},{name:"durable",type:"uint",default_value:0},{name:"expiry_policy",type:"symbol",default_value:"session-end"},{name:"timeout",type:"uint",default_value:0},{name:"dynamic",type:
 "boolean",default_value:false},{name:"dynamic_node_properties",type:"symbolic_map"},{name:"distribution_mode",type:"symbol"},{name:"filter",type:"symbolic_map"},{name:"default_outcome",type:"*"},{name:"outcomes",type:"symbol",multiple:true},{name:"capabilities",type:"symbol",multiple:true}]});define_terminus({name:"target",code:41,fields:[{name:"address",type:"string"},{name:"durable",type:"uint",default_value:0},{name:"expiry_policy",type:"symbol",default_value:"session-end"},{name:"timeout",type:"uint",default_value:0},{name:"dynamic",type:"boolean",default_value:false},{name:"dynamic_node_properties",type:"symbolic_map"},{name:"capabilities",type:"symbol",multiple:true}]});module.exports=terminus},{"./types.js":14}],13:[function(require,module,exports){(function(Buffer){"use strict";var errors=require("./errors.js");var frames=require("./frames.js");var log=require("./log.js");var Transport=function(identifier,protocol_id,frame_type,handler){this.identifier=identifier;this.protoc
 ol_id=protocol_id;this.frame_type=frame_type;this.handler=handler;this.pending=[];this.header_sent=undefined;this.header_received=undefined;this.write_complete=false;this.read_complete=false};Transport.prototype.has_writes_pending=function(){return this.pending.length>0};Transport.prototype.encode=function(frame){var buffer=frames.write_frame(frame);log.frames("[%s] PENDING: %o",this.identifier,JSON.stringify(frame));this.pending.push(buffer)};Transport.prototype.write=function(socket){if(!this.header_sent){var buffer=new Buffer(8);var header={protocol_id:this.protocol_id,major:1,minor:0,revision:0};frames.write_header(buffer,header);socket.write(buffer);this.header_sent=header}for(var i=0;i<this.pending.length;i++){socket.write(this.pending[i]);log.raw("[%s] SENT: %o",this.identifier,this.pending[i])}this.pending=[]};Transport.prototype.read=function(buffer){var offset=0;if(!this.header_received){if(buffer.length<8){return offset}else{this.header_received=frames.read_header(buffer)
 ;log.frames("[%s] RECV: %o",this.identifier,this.header_received);if(this.header_received.protocol_id!==this.protocol_id){if(this.protocol_id===3&&this.header_received.protocol_id===0){throw new errors.ProtocolError("Expecting SASL layer")}else if(this.protocol_id===0&&this.header_received.protocol_id===3){throw new errors.ProtocolError("SASL layer not enabled")}else{throw new errors.ProtocolError("Invalid AMQP protocol id "+this.header_received.protocol_id+" expecting: "+this.protocol_id)}}offset=8}}while(offset<buffer.length-4&&!this.read_complete){var frame_size=buffer.readUInt32BE(offset);log.io("[%s] got frame of size %d",this.identifier,frame_size);if(buffer.length<offset+frame_size){log.io("[%s] incomplete frame; have only %d of %d",this.identifier,buffer.length-offset,frame_size);break}else{var frame=frames.read_frame(buffer.slice(offset,offset+frame_size));log.frames("[%s] RECV: %o",this.identifier,JSON.stringify(frame));if(frame.type!==this.frame_type){throw new errors.Pro
 tocolError("Invalid frame type: "+frame.type)}offset+=frame_size;if(frame.performative){frame.performative.dispatch(this.handler,frame)}}}return offset};module.exports=Transport}).call(this,require("buffer").Buffer)},{"./errors.js":3,"./frames.js":5,"./log.js":7,buffer:19}],14:[function(require,module,exports){(function(Buffer){"use strict";var errors=require("./errors.js");var CAT_FIXED=1;var CAT_VARIABLE=2;var CAT_COMPOUND=3;var CAT_ARRAY=4;function Typed(type,value,code,descriptor){this.type=type;this.value=value;if(code){this.array_constructor={typecode:code};if(descriptor){this.array_constructor.descriptor=descriptor}}}Typed.prototype.toString=function(){return this.value?this.value.toString():null};Typed.prototype.toLocaleString=function(){return this.value?this.value.toLocaleString():null};Typed.prototype.valueOf=function(){return this.value};Typed.prototype.toJSON=function(){return this.value&&this.value.toJSON?this.value.toJSON():this.value};function TypeDesc(name,typecode,
 props,empty_value){this.name=name;this.typecode=typecode;var subcategory=typecode>>>4;switch(subcategory){case 4:this.width=0;this.category=CAT_FIXED;break;case 5:this.width=1;this.category=CAT_FIXED;break;case 6:this.width=2;this.category=CAT_FIXED;break;case 7:this.width=4;this.category=CAT_FIXED;break;case 8:this.width=8;this.category=CAT_FIXED;break;case 9:this.width=16;this.category=CAT_FIXED;break;case 10:this.width=1;this.category=CAT_VARIABLE;break;case 11:this.width=4;this.category=CAT_VARIABLE;break;case 12:this.width=1;this.category=CAT_COMPOUND;break;case 13:this.width=4;this.category=CAT_COMPOUND;break;case 14:this.width=1;this.category=CAT_ARRAY;break;case 15:this.width=4;this.category=CAT_ARRAY;break;default:break}if(props){if(props.read){this.read=props.read}if(props.write){this.write=props.write}if(props.encoding){this.encoding=props.encoding}}var t=this;if(subcategory===4){this.create=function(){return new Typed(t,empty_value)}}else if(subcategory===14||subcategory
 ===15){this.create=function(v,code,descriptor){return new Typed(t,v,code,descriptor)}}else{this.create=function(v){return new Typed(t,v)}}}TypeDesc.prototype.toString=function(){return this.name+"#"+hex(this.typecode)};function hex(i){return Number(i).toString(16)}var types={by_code:{}};Object.defineProperty(types,"MAX_UINT",{value:4294967295,writable:false,configurable:false});Object.defineProperty(types,"MAX_USHORT",{value:65535,writable:false,configurable:false});function define_type(name,typecode,annotations,empty_value){var t=new TypeDesc(name,typecode,annotations,empty_value);t.create.typecode=t.typecode;types.by_code[t.typecode]=t;types[name]=t.create}function buffer_uint8_ops(){return{read:function(buffer,offset){return buffer.readUInt8(offset)},write:function(buffer,value,offset){buffer.writeUInt8(value,offset)}}}function buffer_uint16be_ops(){return{read:function(buffer,offset){return buffer.readUInt16BE(offset)},write:function(buffer,value,offset){buffer.writeUInt16BE(val
 ue,offset)}}}function buffer_uint32be_ops(){return{read:function(buffer,offset){return buffer.readUInt32BE(offset)},write:function(buffer,value,offset){buffer.writeUInt32BE(value,offset)}}}function buffer_int8_ops(){return{read:function(buffer,offset){return buffer.readInt8(offset)},write:function(buffer,value,offset){buffer.writeInt8(value,offset)}}}function buffer_int16be_ops(){return{read:function(buffer,offset){return buffer.readInt16BE(offset)},write:function(buffer,value,offset){buffer.writeInt16BE(value,offset)}}}function buffer_int32be_ops(){return{read:function(buffer,offset){return buffer.readInt32BE(offset)},write:function(buffer,value,offset){buffer.writeInt32BE(value,offset)}}}function buffer_floatbe_ops(){return{read:function(buffer,offset){return buffer.readFloatBE(offset)},write:function(buffer,value,offset){buffer.writeFloatBE(value,offset)}}}function buffer_doublebe_ops(){return{read:function(buffer,offset){return buffer.readDoubleBE(offset)},write:function(buffer,
 value,offset){buffer.writeDoubleBE(value,offset)}}}var MAX_UINT=4294967296;var MIN_INT=-2147483647;function write_ulong(buffer,value,offset){if(typeof value==="number"||value instanceof Number){var hi=Math.floor(value/MAX_UINT);var lo=value%MAX_UINT;buffer.writeUInt32BE(hi,offset);buffer.writeUInt32BE(lo,offset+4)}else{value.copy(buffer,offset)}}function read_ulong(buffer,offset){var hi=buffer.readUInt32BE(offset);var lo=buffer.readUInt32BE(offset+4);if(hi<2097153){return hi*MAX_UINT+lo}else{return buffer.slice(offset,offset+8)}}function write_long(buffer,value,offset){if(typeof value==="number"||value instanceof Number){var abs=Math.abs(value);var hi=Math.floor(abs/MAX_UINT);var lo=abs%MAX_UINT;buffer.writeInt32BE(hi,offset);buffer.writeUInt32BE(lo,offset+4);if(value<0){var carry=1;for(var i=0;i<8;i++){var index=offset+(7-i);var v=(buffer[index]^255)+carry;buffer[index]=v&255;carry=v>>8}}}else{value.copy(buffer,offset)}}function read_long(buffer,offset){var hi=buffer.readInt32BE(of
 fset);var lo=buffer.readUInt32BE(offset+4);if(hi<2097153&&hi>-2097153){return hi*MAX_UINT+lo}else{return buffer.slice(offset,offset+8)}}define_type("Null",64,undefined,null);define_type("Boolean",86,buffer_uint8_ops());define_type("True",65,undefined,true);define_type("False",66,undefined,false);define_type("Ubyte",80,buffer_uint8_ops());define_type("Ushort",96,buffer_uint16be_ops());define_type("Uint",112,buffer_uint32be_ops());define_type("SmallUint",82,buffer_uint8_ops());define_type("Uint0",67,undefined,0);define_type("Ulong",128,{write:write_ulong,read:read_ulong});define_type("SmallUlong",83,buffer_uint8_ops());define_type("Ulong0",68,undefined,0);define_type("Byte",81,buffer_int8_ops());define_type("Short",97,buffer_int16be_ops());define_type("Int",113,buffer_int32be_ops());define_type("SmallInt",84,buffer_int8_ops());define_type("Long",129,{write:write_long,read:read_long});define_type("SmallLong",85,buffer_int8_ops());define_type("Float",114,buffer_floatbe_ops());define_typ
 e("Double",130,buffer_doublebe_ops());define_type("Decimal32",116);define_type("Decimal64",132);define_type("Decimal128",148);define_type("CharUTF32",115,buffer_uint32be_ops());define_type("Timestamp",131,{write:write_long,read:read_long});define_type("Uuid",152);define_type("Vbin8",160);define_type("Vbin32",176);define_type("Str8",161,{encoding:"utf8"});define_type("Str32",177,{encoding:"utf8"});define_type("Sym8",163,{encoding:"ascii"});define_type("Sym32",179,{encoding:"ascii"});define_type("List0",69,undefined,[]);define_type("List8",192);define_type("List32",208);define_type("Map8",193);define_type("Map32",209);define_type("Array8",224);define_type("Array32",240);function is_one_of(o,typelist){for(var i=0;i<typelist.length;i++){if(o.type.typecode===typelist[i].typecode)return true}return false}function buffer_zero(b,len,neg){for(var i=0;i<len&&i<b.length;i++){if(b[i]!==(neg?255:0))return false}return true}types.is_ulong=function(o){return is_one_of(o,[types.Ulong,types.Ulong0,t
 ypes.SmallUlong])};types.is_string=function(o){return is_one_of(o,[types.Str8,types.Str32])};types.is_symbol=function(o){return is_one_of(o,[types.Sym8,types.Sym32])};types.is_list=function(o){return is_one_of(o,[types.List0,types.List8,types.List32])};types.is_map=function(o){return is_one_of(o,[types.Map8,types.Map32])};types.wrap_boolean=function(v){return v?types.True():types.False()};types.wrap_ulong=function(l){if(Buffer.isBuffer(l)){if(buffer_zero(l,8,false))return types.Ulong0();return buffer_zero(l,7,false)?types.SmallUlong(l[7]):types.Ulong(l)}else{if(l===0)return types.Ulong0();else return l>255?types.Ulong(l):types.SmallUlong(l)}};types.wrap_uint=function(l){if(l===0)return types.Uint0();else return l>255?types.Uint(l):types.SmallUint(l)};types.wrap_ushort=function(l){return types.Ushort(l)};types.wrap_ubyte=function(l){return types.Ubyte(l)};types.wrap_long=function(l){if(Buffer.isBuffer(l)){var negFlag=(l[0]&128)!==0;if(buffer_zero(l,7,negFlag)&&(l[7]&128)===(negFlag?1
 28:0)){return types.SmallLong(negFlag?-((l[7]^255)+1):l[7])}return types.Long(l)}else{return l>127||l<-128?types.Long(l):types.SmallLong(l)}};types.wrap_int=function(l){return l>127||l<-128?types.Int(l):types.SmallInt(l)};types.wrap_short=function(l){return types.Short(l)};types.wrap_byte=function(l){return types.Byte(l)};types.wrap_float=function(l){return types.Float(l)};types.wrap_double=function(l){return types.Double(l)};types.wrap_timestamp=function(l){return types.Timestamp(l)};types.wrap_char=function(v){return types.CharUTF32(v)};types.wrap_uuid=function(v){return types.Uuid(v)};types.wrap_binary=function(s){return s.length>255?types.Vbin32(s):types.Vbin8(s)};types.wrap_string=function(s){return s.length>255?types.Str32(s):types.Str8(s)};types.wrap_symbol=function(s){return s.length>255?types.Sym32(s):types.Sym8(s)};types.wrap_list=function(l){if(l.length===0)return types.List0();var items=l.map(types.wrap);return types.List32(items)};types.wrap_map=function(m,key_wrapper){
 var items=[];for(var k in m){items.push(key_wrapper?key_wrapper(k):types.wrap(k));items.push(types.wrap(m[k]))}return types.Map32(items)};types.wrap_symbolic_map=function(m){return types.wrap_map(m,types.wrap_symbol)};types.wrap_array=function(l,code,descriptors){if(code){return types.Array32(l,code,descriptors)}else{console.trace("An array must specify a type for its elements");throw new errors.TypeError("An array must specify a type for its elements")}};types.wrap=function(o){var t=typeof o;if(t==="string"){return types.wrap_string(o)}else if(t==="boolean"){return o?types.True():types.False()}else if(t==="number"||o instanceof Number){if(isNaN(o)){throw new errors.TypeError("Cannot wrap NaN! "+o)}else if(Math.floor(o)-o!==0){return types.Double(o)}else if(o>0){if(o<MAX_UINT){return types.wrap_uint(o)}else{return types.wrap_ulong(o)}}else{if(o>MIN_INT){return types.wrap_int(o)}else{return types.wrap_long(o)}}}else if(o instanceof Date){return types.wrap_timestamp(o.getTime())}else 
 if(o instanceof Typed){return o}else if(o instanceof Buffer){return types.wrap_binary(o)}else if(t==="undefined"||o===null){return types.Null()}else if(Array.isArray(o)){return types.wrap_list(o)}else{return types.wrap_map(o)}};types.wrap_described=function(value,descriptor){var result=types.wrap(value);if(descriptor){if(typeof descriptor==="string"){result=types.described(types.wrap_string(descriptor),result)}else if(typeof descriptor==="number"||descriptor instanceof Number){result=types.described(types.wrap_ulong(descriptor),result)}}return result};types.wrap_message_id=function(o){var t=typeof o;if(t==="string"){return types.wrap_string(o)}else if(t==="number"||o instanceof Number){return types.wrap_ulong(o)}else{throw new errors.TypeError("invalid message id:"+o)}};function mapify(elements){var result={};for(var i=0;i+1<elements.length;){result[elements[i++]]=elements[i++]}return result}var by_descriptor={};types.unwrap_map_simple=function(o){return mapify(o.value.map(function(
 i){return types.unwrap(i,true)}))};types.unwrap=function(o,leave_described){if(o instanceof Typed){if(o.descriptor){var c=by_descriptor[o.descriptor.value];if(c){return new c(o.value)}else if(leave_described){return o}}var u=types.unwrap(o.value,true);return types.is_map(o)?mapify(u):u}else if(Array.isArray(o)){return o.map(function(i){return types.unwrap(i,true)})}else{return o}};types.described_nc=function(descriptor,o){if(descriptor.length){o.descriptor=descriptor.shift();return types.described(descriptor,o)}else{o.descriptor=descriptor;return o}};types.described=types.described_nc;function get_type(code){var type=types.by_code[code];if(!type){throw new errors.TypeError("Unrecognised typecode: "+hex(code))}return type}types.Reader=function(buffer){this.buffer=buffer;this.position=0};types.Reader.prototype.read_typecode=function(){return this.read_uint(1)};types.Reader.prototype.read_uint=function(width){var current=this.position;this.position+=width;if(width===1){return this.buff
 er.readUInt8(current)}else if(width===2){return this.buffer.readUInt16BE(current)}else if(width===4){return this.buffer.readUInt32BE(current)}else{throw new errors.TypeError("Unexpected width for uint "+width)}};types.Reader.prototype.read_fixed_width=function(type){var current=this.position;this.position+=type.width;if(type.read){return type.read(this.buffer,current)}else{return this.buffer.slice(current,this.position)}};types.Reader.prototype.read_variable_width=function(type){var size=this.read_uint(type.width);var slice=this.read_bytes(size);return type.encoding?slice.toString(type.encoding):slice};types.Reader.prototype.read=function(){var constructor=this.read_constructor();var value=this.read_value(get_type(constructor.typecode));return constructor.descriptor?types.described_nc(constructor.descriptor,value):value};types.Reader.prototype.read_constructor=function(){var code=this.read_typecode();if(code===0){var d=[];d.push(this.read());var c=this.read_constructor();while(c.des
 criptor){d.push(c.descriptor);c=this.read_constructor()}return{typecode:c.typecode,descriptor:d.length===1?d[0]:d}}else{return{typecode:code}}};types.Reader.prototype.read_value=function(type){if(type.width===0){return type.create()}else if(type.category===CAT_FIXED){return type.create(this.read_fixed_width(type))}else if(type.category===CAT_VARIABLE){return type.create(this.read_variable_width(type))}else if(type.category===CAT_COMPOUND){return this.read_compound(type)}else if(type.category===CAT_ARRAY){return this.read_array(type)}else{throw new errors.TypeError("Invalid category for type: "+type)}};types.Reader.prototype.read_array_items=function(n,type){var items=[];while(items.length<n){items.push(this.read_value(type))}return items};types.Reader.prototype.read_n=function(n){var items=new Array(n);for(var i=0;i<n;i++){items[i]=this.read()}return items};types.Reader.prototype.read_size_count=function(width){return{size:this.read_uint(width),count:this.read_uint(width)}};types.Re
 ader.prototype.read_compound=function(type){var limits=this.read_size_count(type.width);return type.create(this.read_n(limits.count))};types.Reader.prototype.read_array=function(type){var limits=this.read_size_count(type.width);var constructor=this.read_constructor();return type.create(this.read_array_items(limits.count,get_type(constructor.typecode)),constructor.typecode,constructor.descriptor)};types.Reader.prototype.toString=function(){var s="buffer@"+this.position;if(this.position)s+=": ";for(var i=this.position;i<this.buffer.length;i++){if(i>0)s+=",";s+="0x"+Number(this.buffer[i]).toString(16)}return s};types.Reader.prototype.reset=function(){this.position=0};types.Reader.prototype.skip=function(bytes){this.position+=bytes};types.Reader.prototype.read_bytes=function(bytes){var current=this.position;this.position+=bytes;return this.buffer.slice(current,this.position)};types.Reader.prototype.remaining=function(){return this.buffer.length-this.position};types.Writer=function(buffe
 r){this.buffer=buffer?buffer:new Buffer(1024);this.position=0};types.Writer.prototype.toBuffer=function(){return this.buffer.slice(0,this.position)};function max(a,b){return a>b?a:b}typ

<TRUNCATED>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[3/3] qpid-dispatch git commit: DISPATCH-903 Use c3 library for charts

Posted by ea...@apache.org.
DISPATCH-903 Use c3 library for charts


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/cabc6f07
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/cabc6f07
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/cabc6f07

Branch: refs/heads/master
Commit: cabc6f07552ee078046e01662fa81c9fa1ab56e3
Parents: 9b2b64f
Author: Ernest Allen <ea...@redhat.com>
Authored: Thu Jan 11 09:14:23 2018 -0500
Committer: Ernest Allen <ea...@redhat.com>
Committed: Thu Jan 11 09:14:23 2018 -0500

----------------------------------------------------------------------
 console/stand-alone/index.html                  |  11 +-
 console/stand-alone/package.json                |   3 +-
 console/stand-alone/plugin/css/dispatch.css     |  14 +-
 console/stand-alone/plugin/css/dispatchpf.css   |  43 ++
 console/stand-alone/plugin/css/plugin.css       |  13 +-
 console/stand-alone/plugin/html/qdrCharts.html  |   2 +-
 .../plugin/html/tmplChartConfig.html            |  11 +-
 .../stand-alone/plugin/html/tmplListChart.html  |   2 +-
 console/stand-alone/plugin/js/dispatchPlugin.js |  18 +-
 console/stand-alone/plugin/js/navbar.js         |  19 +-
 .../stand-alone/plugin/js/qdrChartService.js    | 764 +++++--------------
 console/stand-alone/plugin/js/qdrCharts.js      |  83 +-
 console/stand-alone/plugin/js/qdrList.js        | 152 ++--
 console/stand-alone/plugin/js/qdrListChart.js   |  16 +-
 console/stand-alone/plugin/js/qdrOverview.js    |   2 +-
 console/stand-alone/plugin/js/qdrService.js     |  45 ++
 console/stand-alone/plugin/js/qdrSettings.js    |  10 +-
 console/stand-alone/plugin/js/qdrTopology.js    |  51 +-
 18 files changed, 535 insertions(+), 724 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/index.html
----------------------------------------------------------------------
diff --git a/console/stand-alone/index.html b/console/stand-alone/index.html
index 20d1ecf..add2116 100644
--- a/console/stand-alone/index.html
+++ b/console/stand-alone/index.html
@@ -35,9 +35,11 @@ under the License.
     <link rel="stylesheet" href="node_modules/patternfly/dist/css/patternfly-additions.min.css" >
 
     <!-- jquery Styles -->
-    <link rel="stylesheet" href="node_modules/jquery.tipsy/src/jquery.tipsy.css" type="text/css"/>
     <link rel="stylesheet" href="node_modules/jquery.fancytree/dist/skin-bootstrap-n/ui.fancytree.css" type="text/css"/>
 
+    <!-- charting styles -->
+    <link rel="stylesheet" href="node_modules/c3/c3.css" type="text/css"/>
+
     <!-- angular Styles -->
     <link rel="stylesheet" href="node_modules/angular-ui-grid/ui-grid.css" type="text/css"/>
 
@@ -116,11 +118,16 @@ under the License.
 <!-- d3 -->
 <script src='node_modules/d3/d3.min.js'></script>
 <script src='node_modules/d3-queue/build/d3-queue.min.js'></script>
+<script src='node_modules/d3-time/build/d3-time.min.js'></script>
+<script src='node_modules/d3-time-format/build/d3-time-format.min.js'></script>
+
+<!-- c3 for charts -->
+<script src="node_modules/c3/c3.js"></script>
 
-<script src="node_modules/jquery.tipsy/src/jquery.tipsy.js"></script>
 <script src="node_modules/angular-ui-slider/src/slider.js"></script>
 <script src="node_modules/angular-ui-grid/ui-grid.js"></script>
 <script src="node_modules/notifyjs-browser/dist/notify.js"></script>
+<script src="node_modules/patternfly/dist/js/patternfly.min.js"></script>
 
 <script type="text/javascript" src="node_modules/dispatch-management/dist/dispatch-management.js"></script>
 <script type="text/javascript" src="plugin/js/dispatchPlugin.js"></script>

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/package.json
----------------------------------------------------------------------
diff --git a/console/stand-alone/package.json b/console/stand-alone/package.json
index c40057d..6b4df49 100644
--- a/console/stand-alone/package.json
+++ b/console/stand-alone/package.json
@@ -31,14 +31,15 @@
     "angular-ui-grid": "^4.0.8",
     "angular-ui-slider": "^0.4.0",
     "bluebird": "^3.5.1",
+    "c3": "^0.4.18",
     "d3": "^3.5.14",
     "d3-queue": "^3.0.7",
+    "d3-time-format": "^2.1.1",
     "dispatch-management": "^0.1.0",
     "html5shiv": "^3.7.3",
     "jquery": "^3.2.1",
     "jquery-ui-dist": "^1.12.1",
     "jquery.fancytree": "^2.26.0",
-    "jquery.tipsy": "^1.0.3",
     "notifyjs-browser": "^0.4.2",
     "patternfly": "^3.30.0"
   }

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/css/dispatch.css
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/css/dispatch.css b/console/stand-alone/plugin/css/dispatch.css
index 6af6b9d..670b158 100644
--- a/console/stand-alone/plugin/css/dispatch.css
+++ b/console/stand-alone/plugin/css/dispatch.css
@@ -35,7 +35,7 @@ svg:not(.active):not(.ctrl) {
 	fill: #33F;
 }
 path.link.selected {
-  stroke-dasharray: 10,2;
+  /* stroke-dasharray: 10,2; */
   stroke: #33F  !important;
 }
 
@@ -435,8 +435,8 @@ div.boolean {
 }
 
 .aggregate i {
-	float: right;
-    margin: 3px 3px 3px 8px;
+  float: right;
+  /*  margin: 3px 3px 3px 8px; */
 }
 
 .aggregate .hastip {
@@ -516,6 +516,14 @@ div.boolean {
     left: 600px;
 }
 
+.cross-rect {
+  /* fill: #cfe2f3; */
+}
+.cross-line {
+  stroke: black;
+  stroke-width: 4px;
+}
+
 .node circle {
 /*  fill: rgb(31, 119, 180);
   fill-opacity: .25; */

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/css/dispatchpf.css
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/css/dispatchpf.css b/console/stand-alone/plugin/css/dispatchpf.css
index fc6c2ac..c7e981f 100644
--- a/console/stand-alone/plugin/css/dispatchpf.css
+++ b/console/stand-alone/plugin/css/dispatchpf.css
@@ -249,4 +249,47 @@ span.fancytree-expander {
 
 
   display: none;
+}
+
+.dispatch-c3-tooltip {
+  border-collapse: collapse;
+  border-spacing: 0;
+  background-color: #fff;
+  empty-cells: show;
+  -webkit-box-shadow: 7px 7px 12px -9px #777777;
+  -moz-box-shadow: 7px 7px 12px -9px #777777;
+  box-shadow: 7px 7px 12px -9px #777777;
+  opacity: 0.9;
+
+}
+
+.dispatch-c3-tooltip tr {
+  border: 1px solid #CCC;
+}
+
+.dispatch-c3-tooltip th {
+  background-color: #aaa;
+  font-size: 13px;
+  padding: 2px 5px;
+  text-align: left;
+  color: #FFF;
+  font-weight: normal;
+}
+
+.dispatch-c3-tooltip td {
+  font-size: 13px;
+  padding: 3px 6px;
+  background-color: #fff;
+  border-left: 1px dotted #999;
+}
+
+.chart-tip-legend {
+  width: 10px;
+  height: 10px;
+  display: inline-block;
+  margin-right: 4px;
+}
+
+th.text-center {
+  text-align: center;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/css/plugin.css
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/css/plugin.css b/console/stand-alone/plugin/css/plugin.css
index e903c79..fc0fa60 100644
--- a/console/stand-alone/plugin/css/plugin.css
+++ b/console/stand-alone/plugin/css/plugin.css
@@ -63,6 +63,10 @@ div.listAttrName button {
     margin: 3px 5px;
 }
 
+div.listAggrValue button {
+    margin: 3px 5px;
+}
+
 @-moz-document url-prefix() {
   div.listAttrName button {
     top: -24px;
@@ -156,7 +160,7 @@ div.chartContainer {
 /* the line surrounding the area chart */
 div.d3Chart path {
 /*    stroke: black; */
-    stroke-width: 0;
+/*    stroke-width: 0; */
 /*	opacity: 0.5; */
 }
 
@@ -222,8 +226,8 @@ div.d3Chart .title {
 }
 
 div.d3Chart {
-    padding: 1em 0;
-    border: 1px solid #C0C0C0;
+    /* padding: 1em 0; */
+    /* border: 1px solid #C0C0C0; */
     margin-bottom: 2em;
 }
 div.d3Chart.hDash {
@@ -233,8 +237,9 @@ div.d3Chart.hDash {
 div.d3Chart .axis path {
 	display: inherit;
 }
+
 .c3-circle {
-	display: none;
+	/* display: none; */
 }
 
 .fo-table {

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/html/qdrCharts.html
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/html/qdrCharts.html b/console/stand-alone/plugin/html/qdrCharts.html
index 583a407..d2bd38c 100644
--- a/console/stand-alone/plugin/html/qdrCharts.html
+++ b/console/stand-alone/plugin/html/qdrCharts.html
@@ -24,7 +24,7 @@ under the License.
                 <button ng-click="editChart(chart)" title="Configure"><span class="fa-edit"></span></button>
 <!--                <button ng-click="zoomChart(chart)" title="Zoom {{chart.zoomed ? 'in' : 'out'}}" ng-if="!chart.chart.request().nodeList"><i ng-class="chart.zoomed ? 'fa-zoom-in' : 'icon-zoom-out'"></i></button> -->
             </p><div style="clear:both"></div>
-            <div id="{{chart.chart.id()}}" class="aChart d3Chart"></div>
+            <div id="{{chart.chart.id()}}" class="line-chart-pf aChart d3Chart"></div>
         </div>
         <div ng-init="chartsLoaded()"></div>
     </div>

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/html/tmplChartConfig.html
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/html/tmplChartConfig.html b/console/stand-alone/plugin/html/tmplChartConfig.html
index ac5363b..2e2cb8c 100644
--- a/console/stand-alone/plugin/html/tmplChartConfig.html
+++ b/console/stand-alone/plugin/html/tmplChartConfig.html
@@ -26,7 +26,7 @@
         <h3 class="modal-title">Chart {{chart.attr() | humanify}}</h3>
     </div>
     <div class="modal-body">
-        <div id="{{svgDivId}}" class="d3Chart"></div>
+        <div id="{{svgDivId}}" class="line-chart-pf"></div>
 
         <uib-tabset>
             <uib-tab heading="Type">
@@ -34,25 +34,26 @@
                 <div>
                     <label><input type="radio" ng-model="dialogChart.type" value="value" /> Value Chart</label>
                     <label><input type="radio" ng-model="dialogChart.type" value="rate" /> Rate Chart</label>
+<!--
                     <div class="dlg-slider" ng-show="dialogChart.type=='rate'">
                         <span>Rate Window: {{rateWindow}} second{{rateWindow > 1 ? "s" : ""}}</span>
                         <div id="rateSlider"></div>
                     </div>
+-->
                 </div>
                 <div style="clear:both;"> </div>
             </uib-tab>
+<!--
             <uib-tab ng-hide="$parent.chart.aggregate()" heading="Colors">
                 <legend>Chart colors</legend>
                 <div>
                     <div class="colorPicker">
-                        <label>Line: <input id="lineColor" name="lineColor" type="color" /></label>
-                    </div>
-                    <div class="colorPicker">
                         <label>Area: <input id="areaColor" name="areaColor" type="color" /></label>
                     </div>
                 </div>
                 <div style="clear:both;"> </div>
             </uib-tab>
+-->
             <uib-tab heading="Duration">
                 <legend>Chart duration</legend>
                 <div>
@@ -77,7 +78,7 @@
                 <button class="btn btn-success" type="button" ng-click="addChartsPage()"><i class="icon-bar-chart"></i> Add</button> this chart to the Charts page.
             </span>
             <span ng-show="isOnChartsPage()">
-                <button class="btn btn-danger" type="button" ng-click="delChartsPage()">Remove</button> this chart from the <button class="btn btn-success" type="button" ng-click="showChartsPage()"><i class="icon-bar-chart"></i> Charts</button> page.
+                View the <button class="btn btn-success" type="button" ng-click="showChartsPage()"><i class="icon-bar-chart"></i> Charts</button> page.
             </span>
             <button class="btn btn-primary" type="button" ng-click="okClick()">Close</button>
         </div>

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/html/tmplListChart.html
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/html/tmplListChart.html b/console/stand-alone/plugin/html/tmplListChart.html
index 4884984..3214187 100644
--- a/console/stand-alone/plugin/html/tmplListChart.html
+++ b/console/stand-alone/plugin/html/tmplListChart.html
@@ -27,7 +27,7 @@
     <p class="newChart">
         <button ng-click="editChart()" title="Configure"><span class="fa-edit"></span></button>
     </p><div style="clear:both"></div>
-    <div id="{{svgDivId}}" class="d3Chart"></div>
+    <div id="pfDialogChart" class="line-chart-pf"></div>
 </div>
 <div class="modal-footer">
         <span ng-hide="isOnChartsPage()">

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/dispatchPlugin.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/dispatchPlugin.js b/console/stand-alone/plugin/js/dispatchPlugin.js
index d897425..81d716c 100644
--- a/console/stand-alone/plugin/js/dispatchPlugin.js
+++ b/console/stand-alone/plugin/js/dispatchPlugin.js
@@ -184,10 +184,6 @@ var QDR = (function(QDR) {
     }
     QDR.queue = d3.queue;
 
-    QDRService.management.topology.addUpdatedAction("initChartService", function() {
-      QDRService.management.topology.delUpdatedAction("initChartService")
-      QDRChartService.init(); // initialize charting service after we are connected
-    });
     if (!QDRService.management.connection.is_connected()) {
       // attempt to connect to the host:port that served this page
       var protocol = $location.protocol()
@@ -202,11 +198,23 @@ var QDR = (function(QDR) {
       QDR.log.info("Attempting AMQP over websockets connection using address:port of browser ("+host+':'+port+")")
       QDRService.management.connection.testConnect(connectOptions)
         .then( function (r) {
+          // We didn't connect with reconnect: true flag.
+          // The reason being that if we used reconnect:true and the connection failed, rhea would keep trying. There
+          // doesn't appear to be a way to tell it to stop trying to reconnect.
           QDRService.disconnect()
           QDR.log.info("Connect succeeded. Using address:port of browser")
           connectOptions.reconnect = true
           // complete the connection (create the sender/receiver)
-          QDRService.connect(connectOptions) // since the testConnect succeeded, we don't need to handle the success/failure return of the promise
+          QDRService.connect(connectOptions)
+            .then( function (r) {
+              // register a callback for when the node list is available (needed for loading saved charts)
+              QDRService.management.topology.addUpdatedAction("initChartService", function() {
+                QDRService.management.topology.delUpdatedAction("initChartService")
+                QDRChartService.init(); // initialize charting service after we are connected
+              });
+              // get the list of nodes
+              QDRService.management.topology.startUpdating(false);
+            })
       }, function (e) {
           QDR.log.info("failed to auto-connect to " + host + ":" + port)
           QDR.log.info("redirecting to connect page")

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/navbar.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/navbar.js b/console/stand-alone/plugin/js/navbar.js
index e562a7e..7cb129a 100644
--- a/console/stand-alone/plugin/js/navbar.js
+++ b/console/stand-alone/plugin/js/navbar.js
@@ -158,6 +158,9 @@ var QDR = (function (QDR) {
     $scope.addChartsPage = function () {
       QDRChartService.addDashboard(dialogSvgChart.chart);
     };
+    $scope.delChartsPage = function () {
+      QDRChartService.delDashboard($scope.chart);
+    }
 
     $scope.showChartsPage = function () {
       cleanup();
@@ -197,7 +200,7 @@ var QDR = (function (QDR) {
         setTimeout(initRateSlider, 100)
       }
     }
-    initRateSlider();
+    //initRateSlider();
 
     var initDurationSlider = function () {
       if (document.getElementById('durationSlider')) {
@@ -224,8 +227,9 @@ var QDR = (function (QDR) {
     }
 
     $scope.isOnChartsPage = function () {
+      var chart = $scope.chart
       if (adding)
-        return dialogSvgChart ? dialogSvgChart.chart.dashboard : false;
+        return QDRChartService.isAttrCharted(chart.nodeId(), chart.entity(), chart.name(), chart.attr(), chart.aggregate())
       else
         return $scope.chart.dashboard
     }
@@ -260,7 +264,7 @@ var QDR = (function (QDR) {
           dialogSvgChart.tick($scope.svgDivId);
 
       // draw the chart again in 1 second
-      var updateRate = localStorage['updateRate'] ? localStorage['updateRate'] : 5000;
+      var updateRate = localStorage['updateRate'] ? localStorage['updateRate'] : 1000;
       if (updateTimer)
       clearTimeout(updateTimer);
         updateTimer = setTimeout(updateDialogChart, updateRate);
@@ -273,17 +277,14 @@ var QDR = (function (QDR) {
         setTimeout(showChart, 100);
         return;
       }
-      dialogSvgChart = new QDRChartService.AreaChart($scope.dialogChart);
-      $('input[name=lineColor]').val($scope.dialogChart.lineColor);
+      dialogSvgChart = new QDRChartService.pfAreaChart($scope.dialogChart, $scope.svgDivId)
+/*
       $('input[name=areaColor]').val($scope.dialogChart.areaColor);
       $('input[name=areaColor]').on('input', function (e) {
         $scope.dialogChart.areaColor = $(this).val();
         updateDialogChart()
       })
-      $('input[name=lineColor]').on('input', function (e) {
-        $scope.dialogChart.lineColor = $(this).val();
-        updateDialogChart()
-      })
+*/
       if (updateTimer)
         clearTimeout(updateTimer);
           updateDialogChart();

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/qdrChartService.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrChartService.js b/console/stand-alone/plugin/js/qdrChartService.js
index 418b597..ed96fd4 100644
--- a/console/stand-alone/plugin/js/qdrChartService.js
+++ b/console/stand-alone/plugin/js/qdrChartService.js
@@ -70,9 +70,9 @@ var QDR = (function(QDR) {
         this.hreq = false; // has this hdash chart been requested
         this.type = opts.type ? opts.type : "value"; // value or rate
         this.rateWindow = opts.rateWindow ? opts.rateWindow : 1000; // calculate the rate of change over this time interval. higher == smother graph
-        this.areaColor = "#cbe7f3"; // the chart's area color when not an empty string
+        this.areaColor = "#32b9f3"; // the chart's area color when not an empty string
         this.lineColor = "#058dc7"; // the chart's line color when not an empty string
-        this.visibleDuration = opts.visibleDuration ? opts.visibleDuration : 10; // number of minutes of data to show (<= base.duration)
+        this.visibleDuration = opts.visibleDuration ? opts.visibleDuration : 1; // number of minutes of data to show (<= base.duration)
         this.userTitle = null; // user title overrides title()
 
         // generate a unique id for this chart
@@ -141,6 +141,9 @@ var QDR = (function(QDR) {
           this.base.request.duration = _;
           return this;
         }
+        this.router = function () {
+          return QDRService.management.topology.nameFromId(this.nodeId())
+        }
         this.title = function(_) {
           var name = this.request().aggregate ? 'Aggregate' : QDRService.management.topology.nameFromId(this.nodeId());
           var computed = name +
@@ -338,6 +341,7 @@ var QDR = (function(QDR) {
             request = new ChartRequest(opts); //nodeId, entity, name, attr, interval, aggregate);
             self.chartRequests.push(request);
             self.startCollecting(request);
+            self.sendChartRequest(request, true)
           }
           var charts = self.findCharts(opts); //name, attr, nodeId, entity, hdash);
           var chart;
@@ -479,7 +483,7 @@ var QDR = (function(QDR) {
           //return self.charts.length;
         },
 
-        isAttrCharted: function(nodeId, entity, name, attr) {
+        isAttrCharted: function(nodeId, entity, name, attr, aggregate) {
           var charts = self.findCharts({
               name: name,
               attr: attr,
@@ -488,7 +492,7 @@ var QDR = (function(QDR) {
             })
             // if any of the matching charts are on the dashboard page, return true
           return charts.some(function(chart) {
-            return (chart.dashboard)
+            return (chart.dashboard && (aggregate ? chart.aggregate() : !chart.aggregate()))
           });
         },
 
@@ -527,9 +531,7 @@ var QDR = (function(QDR) {
           var charts = angular.fromJson(localStorage["QDRCharts"]);
           if (charts) {
             // get array of known ids
-            var nodeList = QDRService.management.topology.nodeList().map(function(node) {
-              return node.id;
-            })
+            var nodeList = QDRService.management.topology.nodeIdList()
             charts.forEach(function(chart) {
               // if this chart is not in the current list of nodes, skip
               if (nodeList.indexOf(chart.nodeId) >= 0) {
@@ -539,7 +541,7 @@ var QDR = (function(QDR) {
                 if (chart.instance >= instance)
                   instance = chart.instance + 1;
                 if (!chart.duration)
-                  chart.duration = 10;
+                  chart.duration = 1;
                 if (chart.nodeList)
                   chart.aggregate = true;
                 if (!chart.hdash)
@@ -558,10 +560,10 @@ var QDR = (function(QDR) {
                 newChart.hreq = false;
                 newChart.type = chart.type;
                 newChart.rateWindow = chart.rateWindow;
-                newChart.areaColor = chart.areaColor ? chart.areaColor : "#cbe7f3";
+                newChart.areaColor = chart.areaColor ? chart.areaColor : "#32b9f3";
                 newChart.lineColor = chart.lineColor ? chart.lineColor : "#058dc7";
                 newChart.duration(chart.duration);
-                newChart.visibleDuration = chart.visibleDuration ? chart.visibleDuration : 10;
+                newChart.visibleDuration = chart.visibleDuration ? chart.visibleDuration : 1;
                 if (chart.userTitle)
                   newChart.title(chart.userTitle);
               }
@@ -569,583 +571,223 @@ var QDR = (function(QDR) {
           }
         },
 
-        AreaChart: function(chart) {
+        // constructor for a c3 area chart
+        pfAreaChart: function (chart, chartId, defer) {
           if (!chart)
             return;
 
+          // reference to underlying chart
+          this.chart = chart;
+
           // if this is an aggregate chart, show it stacked
-          var stacked = chart.request().aggregate;
-          this.chart = chart; // reference to underlying chart
-          this.svgchart = null;
-          this.url = $location.absUrl();
+          this.stacked = chart.request().aggregate;
 
-          // callback function. called by svgchart when binding data
-          // the variable 'this' refers to the svg and not the AreaChart,
-          // but since we are still in the scope of the AreaChart we have access to the passed in chart argument
-          this.chartData = function() {
+          // the id of the html element that is bound to the chart. The svg will be a child of this
+          this.htmlId = chartId
 
-            var now = new Date();
-            var visibleDate = new Date(now.getTime() - chart.visibleDuration * 60 * 1000);
-            var data = chart.data();
-            var nodeList = QDRService.management.topology.nodeIdList();
-
-            if (chart.type == "rate") {
-              var rateData = [];
-              var datalen = data.length;
-              k = 0; // inner loop optimization
-              for (var i = 0; i < datalen; ++i) {
-                var d = data[i];
-                if (d[0] >= visibleDate) {
-                  for (var j = k + 1; j < datalen; ++j) {
-                    var d1 = data[j];
-                    if (d1[0] - d[0] >= chart.rateWindow) { // rateWindow is the timespan to calculate rates
-                      var elapsed = Math.max((d1[0] - d[0]) / 1000, 1); // number of seconds that elapsed
-                      var rd = [d1[0], (d1[1] - d[1]) / elapsed]
-                      k = j; // start here next time
-                      // this is a stacked (aggregate) chart
-                      if (stacked) {
-                        var detail = [];
-                        nodeList.forEach(function(node, nodeIndex) {
-                          if (d1[2][nodeIndex] && d[2][nodeIndex])
-                            detail.push({
-                              node: QDRService.management.topology.nameFromId(node),
-                              val: (d1[2][nodeIndex].val - d[2][nodeIndex].val) / elapsed
-                            })
-                        })
-                        rd.push(detail)
-                      }
-                      rateData.push(rd);
-                      break;
-                    }
-                  }
+          // an array of 20 colors
+          this.colors = d3.scale.category10().range();
+
+          if (!defer)
+            this.generate()
+        },
+      }
+
+      // create the svg and bind it to the given div.id
+      self.pfAreaChart.prototype.generate = function () {
+        var chart = this.chart  // for access during chart callbacks
+        var self = this
+
+        // list of router names. used to get the color index
+        var nameList = QDRService.management.topology.nodeNameList();
+
+        var c3ChartDefaults = $().c3ChartDefaults();
+        var singleAreaChartConfig = c3ChartDefaults.getDefaultSingleAreaConfig();
+        singleAreaChartConfig.bindto = '#' + this.htmlId;
+        singleAreaChartConfig.data = {
+            x: 'x',           // x-axis is named x
+            columns: [[]],
+            type: 'area-spline'
+        }
+        singleAreaChartConfig.axis = {
+          x: {
+            type: 'timeseries',
+            tick: {
+              format: (function (d) {
+                var data = this.singleAreaChart.data.shown()
+                var first = data[0]['values'][0].x
+
+                if (d - first == 0) {
+                  return d3.timeFormat("%I:%M:%S")(d)
                 }
-              }
-              // we need at least a point to chart
-              if (rateData.length == 0) {
-                rateData[0] = [chart.data()[0][0], 0, [{
-                  node: '',
-                  val: 0
-                }]];
-              }
-              return rateData;
+                return d3.timeFormat("%M:%S")(d)
+              }).bind(this),
+              culling: {max: 4}
+            },
+            label: {
+              text: chart.name()
             }
-            if (chart.visibleDuration != chart.duration()) {
-              return data.filter(function(d) {
-                return d[0] >= visibleDate
-              });
-            } else
-              return data;
-          }
-
-          this.zoom = function(id, zoom) {
-            if (this.svgchart) {
-              this.svgchart.attr("zoom", zoom)
-              d3.select('#' + id)
-                .data([this.chartData()])
-                .call(this.svgchart)
+          },
+          y: {
+            tick: {
+              format: function (d) { return d<1 ? d3.format(".2f")(d) : d3.format(".2s")(d) },
+              count: 5
             }
           }
+        }
+        singleAreaChartConfig.transition = {
+          duration: 0
+        }
 
-          // called by the controller on the page that displays the chart
-          // called whenever the controller wants to redraw the chart
-          // note: the data is collected independently of how often the chart is redrawn
-          this.tick = function(id) {
-
-            // can't draw charts that don't have data yet
-            if (this.chart.data().length == 0) {
-              return;
-            }
+        singleAreaChartConfig.area = {
+          zerobased: false
+        }
 
-            // if we haven't created the svg yet
-            if (!this.svgchart) {
-
-              // make sure the dom element exists on the page
-              var div = angular.element('#' + id);
-              if (!div)
-                return;
-
-              var width = div.width();
-              var height = div.height();
-
-              // make sure the dom element has a size. otherwise we wouldn't see anything anyway
-              if (!width)
-                return;
-
-              var tooltipGenerator;
-              // stacked charts have a different tooltip
-              if (stacked) {
-                tooltipGenerator = function(d, color, format) {
-                  var html = "<table class='fo-table'><tbody><tr class='fo-title'>" +
-                    "<td align='center' colspan='2' nowrap>Time: " + d[0].toTimeString().substring(0, 8) + "</td></tr>"
-                  d[2].forEach(function(detail) {
-                    html += "<tr class='detail'><td align='right' nowrap>" + detail.node + "<div class='fo-table-legend' style='background-color: " + color(detail.node) + "'></div>" + "</td><td>" + format(detail.val) + "</td></tr>"
-                  })
-                  html += "</tbody></table>"
-                  return html;
-                }
-              } else {
-                tooltipGenerator = function(d, color, format) {
-                  var html = "<table class='fo-table'><tbody><tr class='fo-title'>" +
-                    "<td align='center'>Time</td><td align='center'>Value</td></tr><tr><td>" +
-                    d[0].toTimeString().substring(0, 8) +
-                    "</td><td>" +
-                    format(d[1]) +
-                    "</td></tr></tbody></table>"
-                  return html;
-                }
+        singleAreaChartConfig.tooltip = {
+          contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
+            var d3f = ","
+            if (chart.type === 'rate')
+              d3f = ",.2f"
+            var zPre = function (i) {
+              if (i < 10) {
+                i = "0" + i;
               }
-              // create and initialize the chart
-              this.svgchart = self.timeSeriesStackedChart(id, width, height,
-                  QDRService.utilities.humanify(this.chart.attr()),
-                  this.chart.name(),
-                  QDRService.management.topology.nameFromId(this.chart.nodeId()),
-                  this.chart.entity(),
-                  stacked,
-                  this.chart.visibleDuration)
-                .tooltipGenerator(tooltipGenerator);
-
+              return i;
             }
-            // in case the chart properties have changed, set the new props
-            this.svgchart
-              .attr("type", this.chart.type)
-              .attr("areaColor", this.chart.areaColor)
-              .attr("lineColor", this.chart.lineColor)
-              .attr("url", this.url)
-              .attr("title", this.chart.userTitle);
-
-            // bind the new data and update the chart
-            d3.select('#' + id) // the div id on the page/dialog
-              .data([this.chartData()])
-              .call(this.svgchart); // the charting function
-          }
-        },
-
-        timeSeriesStackedChart: function(id, width, height, attrName, name, node, entity, stacked, visibleDuration) {
-          var margin = {
-              top: 20,
-              right: 18,
-              bottom: 10,
-              left: 15
+            var h = zPre(d[0].x.getHours())
+            var m = zPre(d[0].x.getMinutes())
+            var s = zPre(d[0].x.getSeconds())
+            var table = "<table class='dispatch-c3-tooltip'>  <tr><th colspan='2' class='text-center'><strong>"+h+':'+m+':'+s+"</strong></th></tr> <tbody>"
+            for (var i=0; i<d.length; i++) {
+              var colorIndex = nameList.indexOf(d[i].id) % 10
+              var span = "<span class='chart-tip-legend' style='background-color: "+self.colors[colorIndex]+";'> </span>" + d[i].id
+              table += ("<tr><td>"+span+"<td>"+d3.format(d3f)(d[i].value)+"</td></tr>")
             }
-            // attrs that can be changed after the chart is created by using
-            // chart.attr(<attrname>, <attrvalue>);
-          var attrs = {
-            attrName: attrName, // like Deliveries to Container. Put at top of chart
-            name: name, // like router.address/qdrhello  Put at bottom of chart with node
-            node: node, // put at bottom of chart with name
-            entity: entity, // like .router.address  Not used atm
-            title: "", // user title overrides the node and name at the bottom of the chart
-            url: "", // needed to reference filters and clip because of angular's location service
-            type: "value", // value or rate
-            areaColor: "", // can be set for non-stacked charts
-            lineColor: "", // can be set for non-stacked charts
-            zoom: false, // should the y-axis range start at 0 or the min data value
-            visibleDuration: visibleDuration
-          }
-          var width = width - margin.left - margin.right,
-            height = height - margin.top - margin.bottom,
-            yAxisTransitionDuration = 0
-
-          var x = d3.time.scale()
-          var y = d3.scale.linear()
-            .rangeRound([height, 0]);
-          // The x-accessor for the path generator; xScale * xValue.
-          var X = function(d) {
-              return x(d[0])
-            }
-            // The x-accessor for the path generator; yScale * yValue.
-          var Y = function Y(d) {
-            return y(d[1])
+            table += "</tbody></table>"
+            return table
           }
+        }
 
-          var xAxis = d3.svg.axis().scale(x).orient("bottom")
-            .outerTickSize(6)
-            .innerTickSize(-(height - margin.top - margin.bottom))
-            .tickPadding(2)
-            .ticks(d3.time.minutes, 2)
-          var yAxis = d3.svg.axis().scale(y).orient("right")
-            .outerTickSize(8)
-            .innerTickSize(-(width - margin.left - margin.right))
-            .tickPadding(10)
-            .ticks(3)
-            .tickFormat(function(d) {
-              return formatValue(d)
-            })
+        singleAreaChartConfig.title = {
+          text: QDRService.utilities.humanify(this.chart.attr())
+        }
 
-          var tooltipGenerator = function(d, color, format) {
-            return ""
-          }; // should be overridden to set an appropriate tooltip
-          var formatValue = d3.format(".2s");
-          var formatPrecise = d3.format(",");
-          var bisectDate = d3.bisector(function(d) {
-            return d[0];
-          }).left;
-          var line = d3.svg.line();
-
-          var stack = d3.layout.stack()
-            .offset("zero")
-            .values(function(d) {
-              return d.values;
-            })
-            .x(function(d) {
-              return x(d.date);
-            })
-            .y(function(d) {
-              return d.value;
-            });
-
-          var area = d3.svg.area()
-          if (stacked) {
-            area.interpolate("cardinal")
-              .x(function(d) {
-                return x(d.date);
-              })
-              .y0(function(d) {
-                return y(d.y0);
-              })
-              .y1(function(d) {
-                return y(d.y0 + d.y);
-              });
-          } else {
-            area.interpolate("basis").x(X).y1(Y)
-            line.x(X).y(Y)
-          }
-          var color = d3.scale.category20();
-
-          var sv = d3.select("#" + id).append("svg")
-            .attr("width", width + margin.left + margin.right)
-            .attr("height", height + margin.top + margin.bottom)
-          var svg = sv
-            .append("g")
-            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-          sv.append("linearGradient")
-            .attr("id", id) //"temperature-gradient")
-            .attr("gradientUnits", "userSpaceOnUse")
-            .attr("x1", 0).attr("y1", height * .5)
-            .attr("x2", 0).attr("y2", height * 1.2)
-            .selectAll("stop")
-            .data([{
-              offset: "0%",
-              opacity: 1
-            }, {
-              offset: "100%",
-              opacity: 0
-            }])
-            .enter().append("stop")
-            .attr("offset", function(d) {
-              return d.offset;
-            })
-            .attr("stop-opacity", function(d) {
-              return d.opacity;
-            })
-            .attr("stop-color", function(d) {
-              return "#cbe7f3"
-            });
-          /*
-                      var clip = svg.append("defs").append("svg:clipPath")
-                        .attr("id", "clip")
-                        .append("svg:rect")
-                        .attr("id", "clip-rect")
-                        .attr("x", "0")
-                        .attr("y", "0")
-                        .attr("width", width)
-                        .attr("height", height);
-          */
-          // we want all our areas to appear before the axiis
-          svg.append("g")
-            .attr("class", "section-container")
-
-          svg.append("g")
-            .attr("class", "x axis")
-
-          svg.append("g")
-            .attr("class", "y axis")
-
-          svg.append("text").attr("class", "title")
-            .attr("x", (width / 2) - (margin.left + margin.right) / 2)
-            .attr("y", 0 - (margin.top / 2))
-            .attr("text-anchor", "middle")
-            .text(attrs.attrName);
-
-          svg.append("text").attr("class", "legend")
-            .attr("x", (width / 2) - (margin.left + margin.right) / 2)
-            .attr("y", height + (margin.bottom / 2))
-            .attr("text-anchor", "middle")
-            .text(!stacked ? attrs.node + " " + attrs.name : attrs.name);
-
-          var focus = sv.append("g")
-            .attr("class", "focus")
-            .style("display", "none");
-
-          focus.append("circle")
-            .attr("r", 4.5);
-
-          var focusg = focus.append("g");
-          focusg.append("rect")
-            .attr("class", "mo-guide y")
-            .attr("width", 1)
-            .attr("height", height - (margin.top + margin.bottom));
-          focusg.append("rect")
-            .attr("class", "mo-guide x")
-            .attr("width", width - (margin.left + margin.right))
-            .attr("height", 1);
-          focus.append("foreignObject")
-            .attr('class', 'svg-tooltip')
-            .append("xhtml:span");
-          /*
-                  var transition = d3.select({}).transition()
-                      .duration(2000)
-                      .ease("linear");
-          */
-          function chart(selection) {
-            selection.each(function(data) {
-
-              var seriesArr = []
-              if (stacked) {
-                var detailNames = data[0][2].map(function(detail) {
-                  return detail.node
-                })
-                var revNames = angular.copy(detailNames).reverse();
-                color.domain(revNames);
-
-                var series = {};
-                detailNames.forEach(function(name) {
-                  series[name] = {
-                    name: name,
-                    values: []
-                  };
-                  seriesArr.unshift(series[name]); // insert at beginning
-                });
-
-                data.forEach(function(d) {
-                  detailNames.map(function(name, i) {
-                    series[name].values.push({
-                      date: d[0],
-                      value: d[2][i] ? d[2][i].val : 0
-                    });
-                  });
-                });
-
-                // this decorates seriesArr with x,y,and y0 properties
-                stack(seriesArr);
-              }
+        singleAreaChartConfig.data.colors = {}
+        nameList.forEach( (function (r, i) {
+          singleAreaChartConfig.data.colors[r] = this.colors[i % 10]
+        }).bind(this))
 
-              var extent = d3.extent(data, function(d) {
-                return d[0];
-              });
-              //var points = data.length;
-              //var futureDate = new Date(data[points-1][0].getTime() - attrs.visibleDuration * 60 * 1000);
-              //extent = [futureDate, data[points-1][0]]
-              x.domain(extent)
-                .range([0, width - margin.left - margin.right]);
-
-              // Update the y-scale.
-              var min = attrs.zoom ? 0 : d3.min(data, function(d) {
-                return d[1]
-              }) * .99;
-              var max = d3.max(data, function(d) {
-                return d[1]
-              }) * 1.01;
-              var mean = d3.mean(data, function(d) {
-                return d[1]
-              });
-              //max = max * 1.01;
-              var diff = (max - min);
-              if (diff == 0) {
-                max = max + 1;
-                diff = 1;
-              }
-              var ratio = mean != 0 ? diff / mean : 1;
-              if (ratio < .05)
-                formatValue = d3.format(".3s")
+        singleAreaChartConfig.data.color = (function (color, d) {
+          var i = nameList.indexOf(d)
+          return i >= 0 ? this.colors[i % 10] : color
+        }).bind(this)
 
-              if (stacked) {
-                y.domain([min, max])
-                  .range([height - margin.top - margin.bottom, 0]);
-              } else {
-                y
-                  .domain([min, max])
-                  .range([height - margin.top - margin.bottom, 0]);
-              }
-              if (attrs.type == "rate") {
-                area.interpolate("linear"); // rate charts look better smoothed, but the tooltop is in the wrong place
-                line.interpolate("linear");
-//                area.interpolate("basis"); // rate charts look better smoothed
-//                line.interpolate("basis");
-              } else {
-                area.interpolate("linear"); // don't smooth value charts
-                line.interpolate("linear");
-              }
+        singleAreaChartConfig.legend = {show: true}
 
-              // adjust the xaxis based on the range of x values (domain)
-              var timeSpan = (extent[1] - extent[0]) / (1000 * 60); // number of minutes
-              if (timeSpan < 1.5)
-                xAxis.ticks(d3.time.seconds, 10);
-              else if (timeSpan < 3)
-                xAxis.ticks(d3.time.seconds, 30);
-              else if (timeSpan < 8)
-                xAxis.ticks(d3.time.minutes, 1);
-              else
-                xAxis.ticks(d3.time.minutes, 2);
-
-              // adjust the number of yaxis ticks based on the range of y values
-              if (formatValue(min) === formatValue(max))
-                yAxis.ticks(2);
-
-              var container = svg.select('.section-container');
-              container.selectAll('.series').remove();
-              if (stacked) {
-                y.domain([Math.min(min, 0), d3.max(seriesArr, function(c) {
-                  return d3.max(c.values, function(d) {
-                    return d.y0 + d.y;
-                  });
-                })]);
-
-                // creates a .series g path for each section in the detail
-                // since we don't get more sections this selection is only run once
-                var series = container.selectAll(".series")
-                  .data(seriesArr)
-
-                series.enter().append("g")
-                  .attr("class", "series")
-                  .append("path")
-                  .attr("class", "streamPath")
-                  .style("fill", function(d) {
-                    return color(d.name);
-                  })
-                  .style("stroke", "grey");
-
-                series.exit().remove()
-
-                // each time the data is updated, update each section
-                container.selectAll(".series .streamPath").data(seriesArr)
-                  .attr("d", function(d) {
-                    return area(d.values);
-                  })
-              } else {
-                var series = container.selectAll(".series")
-                  .data([data], function(d) {
-                    return d;
-                  })
-
-                var g = series.enter().append("g")
-                  .attr("class", "series")
-
-                g.append("path")
-                  .attr("class", "area")
-                  .style("fill", "url(" + attrs.url + "#" + id + ") " + attrs.areaColor) //temperature-gradient)")
-                  .attr("d", area.y0(y.range()[0]))
-                  .attr("transform", null);
-
-                g.append("path")
-                  .attr("class", "line")
-                  .style("stroke", attrs.lineColor)
-                  .attr("d", line)
-                  /*
-                  debugger;
-                              g.transition()
-                                .duration(2000)
-                                              .attr("transform", "translate(-4)");
-                  */
-                series.exit().remove()
-
-                sv.selectAll("stop")
-                  .attr("stop-color", attrs.areaColor)
+        this.singleAreaChart = c3.generate(singleAreaChartConfig);
+      }
 
+      // filter/modify the chart.data into data points for the svg
+      /* the collected data looks like:
+         [[date, val, [v1,v2,...]], [date, val, [v1,v2,...]],...]
+         with date being the timestamp of the sample
+              val being the total value
+              and the [v1,v2,...] array being the component values for each router for stacked charts
+
+         for stacked charts, the returned data looks like:
+         [['x', date, date,...},
+          ['R1', v1, v1,...},
+          ['R2', v2, v2,...],
+          ...]
+
+         for non-stacked charts, the returned data looks like:
+         ['x', date, date,...],
+         ['R1', val, val,...]]
+
+         for rate charts, all the values returned are the change per second between adjacent values
+      */
+      self.pfAreaChart.prototype.chartData = function() {
+        var data = this.chart.data();
+        var nodeList = QDRService.management.topology.nodeIdList();
+
+        // oldest data point that should be visible
+        var now = new Date();
+        var visibleDate = new Date(now.getTime() - this.chart.visibleDuration * 60 * 1000);
+
+        var accessorSingle = function (d, d1, elapsed) {
+          return this.chart.type === 'rate' ? (d1[1] - d[1]) / elapsed : d[1]
+        }
+        var accessorStacked = function (d, d1, elapsed, i) {
+          return this.chart.type === 'rate' ? (d1[2][i].val - d[2][i].val) / elapsed : d[2][i].val
+        }
+        var accessor = this.stacked ? accessorStacked : accessorSingle
+
+        var dx = ['x']
+        var dlines = []
+        if (this.stacked) {
+          // for stacked, there is a line per router
+          nodeList.forEach( function (node) {
+            dlines.push([QDRService.management.topology.nameFromId(node)])
+          })
+        } else {
+          // for non-stacked, there is only one line
+          dlines.push([this.chart.router()])
+        }
+        for (var i=0; i<data.length; i++) {
+          var d = data[i], elapsed = 1, d1
+          if (d[0] >= visibleDate) {
+            if (this.chart.type === 'rate' && i < data.length-1) {
+              d1 = data[i+1]
+              elapsed = Math.max((d1[0] - d[0]) / 1000, 0.001); // number of seconds that elapsed
+            }
+            // don't push the last data point for a rate chart
+            if (this.chart.type !== 'rate' || i < data.length-1) {
+              dx.push(d[0])
+              if (this.stacked) {
+                nodeList.forEach( (function (node, nodeIndex) {
+                  dlines[nodeIndex].push(accessor.call(this, d, d1, elapsed, nodeIndex))
+                }).bind(this))
+              } else {
+                dlines[0].push(accessor.call(this, d, d1, elapsed))
               }
-              // Update the x-axis.
-              svg.select(".x.axis")
-                .attr("transform", "translate(0," + (height - margin.top - margin.bottom + 1) + ")")
-                .call(xAxis);
-
-              svg.select(".y.axis")
-                .transition().duration(yAxisTransitionDuration) // animate the y axis
-                .attr("transform", "translate(" + (width - margin.right - margin.left) + ",0)")
-                .call(yAxis);
-              yAxisTransitionDuration = 1000 // only do a transition after the chart is 1st drawn
-
-              // TODO: fix this
-              // need to recreate this every update... not sure why
-              var overlay = sv.select(".overlay");
-              if (!overlay.empty())
-                overlay.remove();
-              sv.append("rect")
-                .attr("class", "overlay")
-                .attr("width", width)
-                .attr("height", height)
-                .on("mouseover", function() {
-                  focus.style("display", null)
-                })
-                .on("mouseout", function() {
-                  focus.style("display", "none")
-                })
-                .on("mousemove", mousemove)
-
-              function mousemove() {
-                var x0 = x.invert(d3.mouse(this)[0] - margin.left);
-                var i = bisectDate(data, x0, 1);
-                if (i < data.length && i > 0) {
-                  var d0 = data[i - 1];
-                  var d1 = data[i];
-                  // set d to the data that is closest to the mouse position
-                  var d = x0 - d0[0] > d1[0] - x0 ? d1 : d0;
-                  focus.attr("transform", "translate(" + (x(d[0]) + margin.left) + "," + (y(d[1]) + margin.top) + ")");
-
-                  var tipFormat = formatPrecise;
-                  if (attrs.type === "rate")
-                    tipFormat = d3.format(".2n")
-                    // set the tooltip html and position it
-                  focus.select('.svg-tooltip span')
-                    .html(tooltipGenerator(d, color, tipFormat))
-
-                  var foBounds = focus.select('table')[0][0].getBoundingClientRect();
-                  var mx = x(d[0]); // mouse x
-                  var my = y(d[1]); // mouse y
-
-                  // perfer to put the tooltip in the nw corner relative to the focus circle
-                  var foy = -foBounds.height;
-                  var fox = -foBounds.width;
-                  // off the left side
-                  if (mx - foBounds.width - margin.left < 0)
-                    fox = 0;
-                  // above the top
-                  if (my - foBounds.height - margin.top < 0)
-                    foy = 0;
-                  // won't fit above or below, just put it at bottom
-                  if (my + foBounds.height > height)
-                    foy = -(foBounds.height - (height - my));
-
-                  focus.select('.svg-tooltip')
-                    .attr('x', fox).attr('y', foy);
-
-                  // position the guide lines
-                  focus.select(".mo-guide.y")
-                    .attr("y", -my);
-                  focus.select(".mo-guide.x")
-                    .attr("x", -mx);
-
-                } else {
-                  focus.attr("transform", "translate(-10,-10)");
-                }
-              }
-
-            })
-          }
-          chart.attr = function(attrName, value) {
-            if (arguments.length < 2)
-              return arguments.length == 1 ? attrs[attrName] : chart;
-            if (angular.isDefined(attrs[attrName]))
-              attrs[attrName] = value;
-            return chart;
-          }
-          chart.tooltipGenerator = function(_) {
-            tooltipGenerator = _;
-            return chart;
+            }
           }
-          return chart;
         }
+        var columns = [dx]
+        dlines.forEach( function (line) {
+          columns.push(line)
+        })
+        return columns
       }
+
+      // get the data for the chart and update it
+      self.pfAreaChart.prototype.tick = function() {
+        // can't draw charts that don't have data yet
+        if (this.chart.data().length == 0 || !this.singleAreaChart) {
+          return;
+        }
+
+        // update the chart title
+        // since there is no c3 api to get or set the chart title, we change the title directly using d3
+        var rate = ''
+        if (this.chart.type === 'rate')
+          rate = ' per second'
+        d3.select("#"+this.htmlId+" svg text.c3-title").text(QDRService.utilities.humanify(this.chart.attr()) + rate);
+
+/*
+        var type='area'
+        if (this.chart.type === 'rate')
+          type = 'area-spline'
+        this.singleAreaChart.transform(type);
+*/
+        var d = this.chartData()
+        // load the new data
+        // using the c3.flow api causes the x-axis labels to jump around
+        this.singleAreaChart.load({
+          columns: d
+        })
+      }
+
       return self;
     }
   ]);

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/qdrCharts.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrCharts.js b/console/stand-alone/plugin/js/qdrCharts.js
index 3cec385..5724a1d 100644
--- a/console/stand-alone/plugin/js/qdrCharts.js
+++ b/console/stand-alone/plugin/js/qdrCharts.js
@@ -26,46 +26,54 @@ var QDR = (function (QDR) {
    *
    * Controller that handles the QDR charts page
    */
-  QDR.module.controller("QDR.ChartsController", function($scope, QDRService, QDRChartService, $uibModal, $location, $routeParams) {
+  QDR.module.controller("QDR.ChartsController", function($scope, QDRService, QDRChartService, $uibModal, $location, $routeParams, $timeout) {
 
-  var updateTimer = null;
+    var updateTimer = null;
 
-  if (!QDRService.management.connection.is_connected()) {
-    // we are not connected. we probably got here from a bookmark or manual page reload
-    QDR.redirectWhenConnected($location, "charts");
-    return;
-  }
+    if (!QDRService.management.connection.is_connected()) {
+      // we are not connected. we probably got here from a bookmark or manual page reload
+      QDR.redirectWhenConnected($location, "charts");
+      return;
+    }
+
+    $scope.svgCharts = [];
+    // create an svg object for each chart
+    QDRChartService.charts.filter(function (chart) {return chart.dashboard}).forEach(function (chart) {
+      var svgChart = new QDRChartService.pfAreaChart(chart, chart.id(), true)
+      svgChart.zoomed = false;
+      $scope.svgCharts.push(svgChart);
+    })
 
-  $scope.svgCharts = [];
-  // create an svg object for each chart
-  QDRChartService.charts.filter(function (chart) {return chart.dashboard}).forEach(function (chart) {
-    var svgChart = new QDRChartService.AreaChart(chart)
-    svgChart.zoomed = false;
-    $scope.svgCharts.push(svgChart);
-  })
 
     // redraw the chart every update period
-  // this is a $scope function because it is called from the dialog
     var updateCharts = function () {
       $scope.svgCharts.forEach(function (svgChart) {
         svgChart.tick(svgChart.chart.id()); // on this page we are using the chart.id() as the div id in which to render the chart
       })
-      var updateRate = localStorage['updateRate'] ?  localStorage['updateRate'] : 5000;
+      var updateRate = localStorage['updateRate'] ?  localStorage['updateRate'] : 1000;
       if (updateTimer) {
         clearTimeout(updateTimer)
       }
       updateTimer = setTimeout(updateCharts, updateRate);
     }
 
-        // called by ng-init in the html when the page is loaded
-  $scope.chartsLoaded = function () {
-      $scope.svgCharts.forEach(function (svgChart) {
-                QDRChartService.sendChartRequest(svgChart.chart.request(), true);
-            })
-            if (updateTimer)
-                clearTimeout(updateTimer)
-      setTimeout(updateCharts, 0);
-  }
+    // called by ng-init in the html when the page is loaded
+    $scope.chartsLoaded = function () {
+      // ensure the div for our chart is loaded in the dom
+      var div = angular.element(".chartContainer");
+      if (!div.width()) {
+        setTimeout($scope.chartsLoaded, 100);
+        return;
+      }
+      // create an svg object for each chart
+      $scope.svgCharts.forEach ( function (c) {
+        c.generate()
+        QDRChartService.sendChartRequest(c.chart.request(), true);
+      })
+      if (updateTimer)
+        clearTimeout(updateTimer)
+      setTimeout(updateCharts);
+    }
 
   $scope.zoomChart = function (chart) {
     chart.zoomed = !chart.zoomed;
@@ -80,23 +88,28 @@ var QDR = (function (QDR) {
     };
 
     $scope.editChart = function (chart) {
-        doDialog("tmplChartConfig.html", chart.chart);
+      doDialog("tmplChartConfig.html", chart.chart);
     };
 
     $scope.delChart = function (chart) {
-        QDRChartService.unRegisterChart(chart.chart);
-        // remove from svgCharts
-        $scope.svgCharts.forEach(function (svgChart, i) {
-            if (svgChart === chart) {
-                delete $scope.svgCharts.splice(i, 1);
-            }
-        })
-    };
+      QDRChartService.unRegisterChart(chart.chart);
+      // remove from svgCharts
+      $scope.svgCharts.forEach(function (svgChart, i) {
+        if (svgChart === chart) {
+          delete $scope.svgCharts.splice(i, 1);
+        }
+      })
+    }
 
     // called from dialog when we want to clone the dialog chart
     // the chart argument here is a QDRChartService chart
     $scope.addChart = function (chart) {
-      $scope.svgCharts.push(new QDRChartService.AreaChart(chart));
+      var nchart = new QDRChartService.pfAreaChart(chart, chart.id(), true)
+      $scope.svgCharts.push(nchart);
+      $timeout( function () {
+        nchart.generate()
+        QDRChartService.sendChartRequest(chart.request(), true);
+      })
     };
 
     $scope.$on("$destroy", function( event ) {

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/qdrList.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrList.js b/console/stand-alone/plugin/js/qdrList.js
index 9f60e5c..7263da8 100644
--- a/console/stand-alone/plugin/js/qdrList.js
+++ b/console/stand-alone/plugin/js/qdrList.js
@@ -24,8 +24,8 @@ var QDR = (function(QDR) {
   /**
    * Controller for the main interface
    */
-  QDR.module.controller("QDR.ListController", ['$scope', '$location', '$uibModal', '$filter', '$timeout', 'QDRService', 'QDRChartService', 'uiGridConstants',
-    function ($scope, $location, $uibModal, $filter, $timeout, QDRService, QDRChartService, uiGridConstants) {
+  QDR.module.controller("QDR.ListController", ['$scope', '$location', '$uibModal', '$filter', '$timeout', 'QDRService', 'QDRChartService', 'uiGridConstants', '$sce',
+    function ($scope, $location, $uibModal, $filter, $timeout, QDRService, QDRChartService, uiGridConstants, $sce) {
 
     QDR.log.debug("QDR.ListControll started with location of " + $location.path() + " and connection of  " + QDRService.management.connection.is_connected());
     var updateIntervalHandle = undefined;
@@ -147,6 +147,7 @@ var QDR = (function(QDR) {
     $scope.nodes = []
     var excludedEntities = ["management", "org.amqp.management", "operationalEntity", "entity", "configurationEntity", "dummy", "console"];
     var aggregateEntities = ["router.address"];
+
     var classOverrides = {
       "connection": function (row, nodeId) {
         var isConsole = QDRService.utilities.isAConsole (row.properties.value, row.identity.value, row.role.value, nodeId)
@@ -429,25 +430,6 @@ var QDR = (function(QDR) {
           return (old.name === attr) ? old.graph && old.rawValue != row[attr].value : false;
         })
         var schemaEntity = schemaProps($scope.selectedEntity, attr, $scope.currentNode)
-/*
-[{
-  "type": "value",
-  "rateWindow": 1000,
-  "areaColor": "#cbe7f3",
-  "lineColor": "#058dc7",
-  "visibleDuration": 10,
-  "userTitle": null,
-  "dashboard": true,
-  "hdash": false,
-  "instance": 1,
-  "name": "Lqdhello",
-  "attr": "deliveriesFromContainer",
-  "nodeId": "amqp:/_topo/0/QDR.A/$management",
-  "entity": "router.address",
-  "interval": 1000,
-  "duration": 10
-}]
-*/
         details.push( {
           attributeName:  QDRService.utilities.humanify(attr),
           attributeValue: attr === 'port' ? row[attr].value : QDRService.utilities.pretty(row[attr].value),
@@ -456,8 +438,8 @@ var QDR = (function(QDR) {
           rawValue:       row[attr].value,
           graph:          row[attr].graph,
           title:          row[attr].title,
-          chartExists:    (QDRChartService.findCharts({name: row.name.value, attr: attr, nodeId: $scope.currentNode.id, entity: $scope.selectedEntity}).length > 0),
-          //chartExists:    QDRChartService.findChartRequest($scope.currentNode.id, $scope.selectedEntity) !== null,
+          chartExists:    (QDRChartService.isAttrCharted($scope.currentNode.id, $scope.selectedEntity, row.name.value, attr)),
+          aggchartExists: (QDRChartService.isAttrCharted($scope.currentNode.id, $scope.selectedEntity, row.name.value, attr, true)),
           aggregateValue: QDRService.utilities.pretty(row[attr].aggregate),
           aggregateTip:   row[attr].aggregateTip,
 
@@ -629,43 +611,8 @@ var QDR = (function(QDR) {
     // tableRows are the records that were returned, this populates the left hand tree on the page
     var selectRow = function (info) {
       updateTreeChildren(info.entity, info.rows, info.expand);
-      fixTooltips();
-    }
-
-    var titleFromAlt = function (alt) {
-      if (alt && alt.length) {
-        var data = angular.fromJson(alt);
-        var table = "<table class='tiptable'><tbody>";
-        data.forEach (function (row) {
-          table += "<tr>";
-          table += "<td>" + row.node + "</td><td align='right'>" + QDRService.utilities.pretty(row.val) + "</td>";
-          table += "</tr>"
-        })
-        table += "</tbody></table>"
-        return table;
-      }
-      return '';
+      //fixTooltips();
     }
-
-    var fixTooltips = function () {
-      if ($('.hastip').length == 0) {
-        setTimeout(fixTooltips, 100);
-        return;
-      }
-      $('.hastip').each( function (i, tip) {
-        var tipset = tip.getAttribute('tipset')
-        if (!tipset) {
-          $(tip).tipsy({html: true, className: 'subTip', opacity: 1, title: function () {
-            return titleFromAlt(this.getAttribute('alt'))
-          } });
-          tip.setAttribute('tipset', true)
-        } else {
-          var title = titleFromAlt(tip.getAttribute('alt'))
-          tip.setAttribute('original-title', title)
-        }
-      })
-    }
-
     $scope.detailFields = [];
 
     $scope.addToGraph = function(rowEntity) {
@@ -675,7 +622,8 @@ var QDR = (function(QDR) {
          name:   $scope.selectedRecordName,
          attr:    rowEntity.name,
          forceCreate: true});
-      doDialog('tmplListChart.html', chart);
+
+      doDialog('tmplChartConfig.html', chart);
     }
 
     $scope.addAllToGraph = function(rowEntity) {
@@ -689,9 +637,31 @@ var QDR = (function(QDR) {
         visibleDuration: 1,
         forceCreate: true,
         aggregate:   true});
-      doDialog('tmplListChart.html', chart);
+      doDialog('tmplChartConfig.html', chart);
     }
 
+    // The ui-popover dynamic html
+    $scope.aggregateTip = ''
+    // disable popover tips for non-integer cells
+    $scope.aggregateTipEnabled = function (row) {
+      var tip = row.entity.aggregateTip
+      return (tip && tip.length) ? "true" : "false"
+    }
+    // convert the aggregate data into a table for the popover tip
+    $scope.genAggregateTip = function (row) {
+      var tip = row.entity.aggregateTip
+      if (tip && tip.length) {
+        var data = angular.fromJson(tip);
+        var table = "<table class='tiptable'><tbody>";
+        data.forEach (function (row) {
+          table += "<tr>";
+          table += "<td>" + row.node + "</td><td align='right'>" + QDRService.utilities.pretty(row.val) + "</td>";
+          table += "</tr>"
+        })
+        table += "</tbody></table>"
+        $scope.aggregateTip = $sce.trustAsHtml(table)
+      }
+    }
     var aggregateColumn = function () {
       if ((aggregateEntities.indexOf($scope.selectedEntity) > -1 && $scope.detailCols.length != 3) ||
         (aggregateEntities.indexOf($scope.selectedEntity) == -1 && $scope.detailCols.length != 2)) {
@@ -710,13 +680,13 @@ var QDR = (function(QDR) {
         ]
         if (aggregateEntities.indexOf($scope.selectedEntity) > -1) {
           $scope.detailCols.push(
-          {
-            width: '10%',
-            field: 'aggregateValue',
-            displayName: 'Aggregate',
-            cellTemplate: '<div class="hastip ui-grid-cell-contents" alt="{{row.entity.aggregateTip}}" ng-class="{\'changed\': row.entity.changed == 1}">{{COL_FIELD CUSTOM_FILTERS}} <button title="Click to view/add a graph" ng-if="row.entity.graph" ng-click="grid.appScope.addAllToGraph(row.entity)" ng-class="{\'btn-success\': row.entity.chartExists}" class="btn"><i ng-class="{\'icon-bar-chart\': row.entity.graph == true }"></i></button></div>',
-            cellClass: 'aggregate'
-          }
+            {
+              width: '10%',
+              field: 'aggregateValue',
+              displayName: 'Aggregate',
+              cellTemplate: '<div popover-enable="{{grid.appScope.aggregateTipEnabled(row)}}" uib-popover-html="grid.appScope.aggregateTip" popover-append-to-body="true" ng-mouseover="grid.appScope.genAggregateTip(row)" popover-trigger="\'mouseenter\'" class="listAggrValue ui-grid-cell-contents" ng-class="{\'changed\': row.entity.changed == 1}">{{COL_FIELD CUSTOM_FILTERS}} <button title="Click to view/add a graph" ng-if="row.entity.graph" ng-click="grid.appScope.addAllToGraph(row.entity)" ng-class="{\'btn-success\': row.entity.aggchartExists}" class="btn"><i ng-class="{\'icon-bar-chart\': row.entity.graph == true }"></i></button></div>',
+              cellClass: 'aggregate'
+            }
           )
         }
       }
@@ -802,27 +772,32 @@ var QDR = (function(QDR) {
        .then(function (response) {gotMethodResponse($scope.selectedEntity, response.context)})
     }
 
-    function doDialog(tmpl, chart) {
-        var d = $uibModal.open({
-          backdrop: true,
-          keyboard: true,
-          backdropClick: true,
-          templateUrl: QDR.templatePath + tmpl,
-          controller: "QDR.ListChartController",
-          resolve: {
-                 chart: function() {
-                   return chart
-                 },
-                 nodeName: function () {
-                    return $scope.selectedNode
-                 }
-              }
-        });
-
-        d.result.then(function(result) { QDR.log.debug("d.open().then"); });
+    function doDialog(template, chart) {
 
+      var d = $uibModal.open({
+      backdrop: true,
+      keyboard: true,
+      backdropClick: true,
+      templateUrl: QDR.templatePath + template,
+      controller: "QDR.ChartDialogController",
+      resolve: {
+        chart: function() {
+          return chart;
+        },
+        updateTick: function () {
+          return function () {};
+        },
+        dashboard: function () {
+          return $scope;
+        },
+        adding: function () {
+          return true
+        }
+      }
+      }).result.then(function(result) {
+        QDRChartService.unRegisterChart(chart)
+      });
     };
-
     var setCurrentNode = function () {
       $scope.nodes.some( function (node, i) {
         if (node.name === $scope.selectedNode) {
@@ -835,6 +810,9 @@ var QDR = (function(QDR) {
     var treeReady = false;
     var serviceReady = false;
     $scope.largeNetwork = QDRService.management.topology.isLargeNetwork()
+    if ($scope.largeNetwork)
+      aggregateEntities = [];
+
     // called after we know for sure the schema is fetched and the routers are all ready
     QDRService.management.topology.addUpdatedAction("initList", function () {
       QDRService.management.topology.stopUpdating();

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/qdrListChart.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrListChart.js b/console/stand-alone/plugin/js/qdrListChart.js
index 3c14ebf..af281ad 100644
--- a/console/stand-alone/plugin/js/qdrListChart.js
+++ b/console/stand-alone/plugin/js/qdrListChart.js
@@ -19,9 +19,11 @@ under the License.
 /**
  * @module QDR
  */
+
 var QDR = (function(QDR) {
 
-  QDR.module.controller('QDR.ListChartController', function ($scope, $uibModalInstance, $uibModal, $location, QDRChartService, chart, nodeName) {
+  QDR.module.controller('QDR.ListChartController', function ($scope, $uibModalInstance, $uibModal, $location, QDRService, QDRChartService, chart, nodeName) {
+
     $scope.chart = chart;
     $scope.dialogSvgChart = null;
     var updateTimer = null;
@@ -69,21 +71,21 @@ var QDR = (function(QDR) {
     }
 
     var showChart = function () {
-      // the chart divs are generated by angular and aren't available immediately
-      var div = angular.element("#" + $scope.svgDivId);
+      // we need a width and height before generating the chart
+      var div = angular.element("#pfDialogChart");
       if (!div.width()) {
         setTimeout(showChart, 100);
         return;
       }
-      dialogSvgChart = new QDRChartService.AreaChart($scope.chart);
-      $scope.dialogSvgChart = dialogSvgChart;
+      $scope.pfDialogSvgChart = new QDRChartService.pfAreaChart($scope.chart, 'pfDialogChart')
       updateDialogChart();
     }
     showChart();
 
     var updateDialogChart = function () {
-      if ($scope.dialogSvgChart)
-        $scope.dialogSvgChart.tick($scope.svgDivId);
+      if ($scope.pfDialogSvgChart) {
+        $scope.pfDialogSvgChart.tick();
+      }
       if (updateTimer)
         clearTimeout(updateTimer)
       updateTimer = setTimeout(updateDialogChart, 1000);

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/qdrOverview.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrOverview.js b/console/stand-alone/plugin/js/qdrOverview.js
index 7167250..9c2ae0a 100644
--- a/console/stand-alone/plugin/js/qdrOverview.js
+++ b/console/stand-alone/plugin/js/qdrOverview.js
@@ -1442,7 +1442,7 @@ return;
     }
 
     var setTemplate = function (node) {
-      var type = node.data.type;
+      var type = node.type;
       var template = $scope.templates.filter( function (tpl) {
         return tpl.name == type;
       })

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/qdrService.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrService.js b/console/stand-alone/plugin/js/qdrService.js
index d49a4e1..f5acb89 100644
--- a/console/stand-alone/plugin/js/qdrService.js
+++ b/console/stand-alone/plugin/js/qdrService.js
@@ -176,3 +176,48 @@ if (!Array.prototype.findIndex) {
     }
   });
 }
+
+// https://tc39.github.io/ecma262/#sec-array.prototype.find
+if (!Array.prototype.find) {
+  Object.defineProperty(Array.prototype, 'find', {
+    value: function(predicate) {
+     // 1. Let O be ? ToObject(this value).
+      if (this == null) {
+        throw new TypeError('"this" is null or not defined');
+      }
+
+      var o = Object(this);
+
+      // 2. Let len be ? ToLength(? Get(O, "length")).
+      var len = o.length >>> 0;
+
+      // 3. If IsCallable(predicate) is false, throw a TypeError exception.
+      if (typeof predicate !== 'function') {
+        throw new TypeError('predicate must be a function');
+      }
+
+      // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
+      var thisArg = arguments[1];
+
+      // 5. Let k be 0.
+      var k = 0;
+
+      // 6. Repeat, while k < len
+      while (k < len) {
+        // a. Let Pk be ! ToString(k).
+        // b. Let kValue be ? Get(O, Pk).
+        // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
+        // d. If testResult is true, return kValue.
+        var kValue = o[k];
+        if (predicate.call(thisArg, kValue, k, o)) {
+          return kValue;
+        }
+        // e. Increase k by 1.
+        k++;
+      }
+
+      // 7. Return undefined.
+      return undefined;
+    }
+  });
+}

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/qdrSettings.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrSettings.js b/console/stand-alone/plugin/js/qdrSettings.js
index 3edaffc..2af529a 100644
--- a/console/stand-alone/plugin/js/qdrSettings.js
+++ b/console/stand-alone/plugin/js/qdrSettings.js
@@ -29,7 +29,7 @@ var QDR = (function(QDR) {
    * Controller that handles the QDR settings page
    */
 
-  QDR.module.controller("QDR.SettingsController", ['$scope', 'QDRService', '$timeout', '$location', function($scope, QDRService, $timeout, $location) {
+  QDR.module.controller("QDR.SettingsController", ['$scope', 'QDRService', 'QDRChartService', '$timeout', '$location', function($scope, QDRService, QDRChartService, $timeout, $location) {
 
     $scope.connecting = false;
     $scope.connectionError = false;
@@ -58,6 +58,7 @@ var QDR = (function(QDR) {
       }
     };
 
+    // connect/disconnect button clicked
     $scope.connect = function() {
       if (QDRService.management.connection.is_connected()) {
         $timeout( function () {
@@ -93,6 +94,13 @@ var QDR = (function(QDR) {
       var options = {address: $scope.formEntity.address, port: $scope.formEntity.port, reconnect: true}
       QDRService.connect(options)
         .then( function (r) {
+          // register a callback for when the node list is available (needed for loading saved charts)
+          QDRService.management.topology.addUpdatedAction("initChartService", function() {
+            QDRService.management.topology.delUpdatedAction("initChartService")
+            QDRChartService.init(); // initialize charting service after we are connected
+          });
+          // get the list of nodes
+          QDRService.management.topology.startUpdating(false);
           // will have redirected to last known page or /overview
         }, function (e) {
           failed(e)

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/cabc6f07/console/stand-alone/plugin/js/qdrTopology.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrTopology.js b/console/stand-alone/plugin/js/qdrTopology.js
index e3d986b..e67059f 100644
--- a/console/stand-alone/plugin/js/qdrTopology.js
+++ b/console/stand-alone/plugin/js/qdrTopology.js
@@ -1227,13 +1227,62 @@ console.log("showEntityForm " + args.entity)
                   .value(function(d) { return d.size; });
 
               d3.select("#crosssection svg").remove();
-              //var svg = d3.select(document.createElement('div'))
               var svg = d3.select("#crosssection").append("svg")
                   .attr("width", diameter)
                   .attr("height", diameter)
+
+              var rg = svg.append('svg:defs')
+                .append('radialGradient')
+                .attr("id", "cross-gradient")
+                .attr("gradientTransform", "scale(2.0) translate(-0.5,-0.5)")
+
+              rg
+                .append('stop')
+                .attr("offset", "0%")
+                .attr("stop-color", "#feffff")
+              rg
+                .append('stop')
+                .attr("offset", "40%")
+                .attr("stop-color", "#cfe2f3")
+
               var svgg = svg.append("g")
                   .attr("transform", "translate(2,2)");
 
+              svgg
+                .append("rect")
+                .attr("x", 0)
+                .attr("y", 0)
+                .attr("width", 200)
+                .attr("height", 200)
+                .attr("class", "cross-rect")
+                .attr("fill", "url("+urlPrefix+"#cross-gradient)")
+
+              svgg
+                .append("line")
+                .attr("class", "cross-line")
+                .attr({x1: 2, y1: 0, x2: 200, y2: 0})
+              svgg
+                .append("line")
+                .attr("class", "cross-line")
+                .attr({x1: 2, y1: 0, x2: 0, y2: 200})
+
+/*
+              var simpleLine = d3.svg.line();
+              svgg
+                .append('path')
+                .attr({
+                  d: simpleLine([[0,0],[0,200]]),
+                  stroke: '#000',
+                  'stroke-width': '4px'
+                });
+              svgg
+                .append('path')
+                .attr({
+                  d: simpleLine([[0,0],[200,0]]),
+                  stroke: '#000',
+                  'stroke-width': '4px'
+                });
+*/
               var root = {
                 name: " Links between " + d.source.name + " and " + d.target.name,
                 children: []


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[2/3] qpid-dispatch git commit: removing rhea since it is incorporated in dispatch-management.js

Posted by ea...@apache.org.
removing rhea since it is incorporated in dispatch-management.js


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/9b2b64ff
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/9b2b64ff
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/9b2b64ff

Branch: refs/heads/master
Commit: 9b2b64ff913a959db7bcfb749864e5ce3b8ebb94
Parents: 33feac5
Author: Ernest Allen <ea...@redhat.com>
Authored: Thu Jan 11 09:10:11 2018 -0500
Committer: Ernest Allen <ea...@redhat.com>
Committed: Thu Jan 11 09:10:11 2018 -0500

----------------------------------------------------------------------
 console/stand-alone/plugin/lib/rhea-min.js | 6 ------
 1 file changed, 6 deletions(-)
----------------------------------------------------------------------



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org