You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by fa...@apache.org on 2014/09/01 20:32:04 UTC
svn commit: r1621865 - in /qpid/proton/branches/fadams-javascript-binding:
examples/messenger/javascript/ proton-c/bindings/javascript/
tests/javascript/
Author: fadams
Date: Mon Sep 1 18:32:04 2014
New Revision: 1621865
URL: http://svn.apache.org/r1621865
Log:
The qpid-config port is largely complete except for xml binding support, it also needs a bit of tidying up. Added a simple soak test to send and receive messages from a broker ad-infinitum and a simple html send message example
Added:
qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.html (with props)
qpid/proton/branches/fadams-javascript-binding/tests/javascript/soak.js (with props)
Removed:
qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/my-library.js
Modified:
qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/qpid-config.js
qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.js
qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/CMakeLists.txt
qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/binding.js
Modified: qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/qpid-config.js
URL: http://svn.apache.org/viewvc/qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/qpid-config.js?rev=1621865&r1=1621864&r2=1621865&view=diff
==============================================================================
--- qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/qpid-config.js (original)
+++ qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/qpid-config.js Mon Sep 1 18:32:04 2014
@@ -41,7 +41,11 @@ if (typeof exports !== "undefined" && ex
proton = require("qpid-proton");
}
-var address = 'amqp://0.0.0.0:5673/qmf.default.direct';
+var addr = 'guest:guest@localhost:5673';
+//var addr = 'localhost:5673';
+var address = 'amqp://' + addr + '/qmf.default.direct';
+console.log(address);
+
var replyTo = '';
var subscription;
var subscribed = false;
@@ -52,13 +56,14 @@ var messenger = new proton.Messenger();
/**
* The correlator object is a mechanism used to correlate requests with their
* aynchronous responses. It might possible be better to make use of Promises
- * to implement part of this behaviour but a mechanism would still be meeded to
+ * to implement part of this behaviour but a mechanism would still be needed to
* correlate a request with its response callback in order to wrap things up in
* a Promise, so much of the behaviour of this object would still be required.
* In addition it seemed to make sense to make this QMF2 implementation fairly
* free of dependencies and using Promises would require external libraries.
- * Instead the correlator implements Promise-like semantics, you might call it
+ * Instead the correlator implements "Promise-like" semantics, you might call it
* a broken Promise :-)
+ * <p>
* in particular the request method behaves a *bit* like Promise.all() though it
* is mostly fake and takes an array of functions that call the add() method
* which is really the method used to associate response objects by correlationID.
@@ -155,6 +160,7 @@ var getObjects = function(packageName, c
message.setReplyTo(replyTo);
message.setCorrelationID(className);
message.properties = {
+ "routing-key": "broker", // Added for Java Broker
"x-amqp-0-10.app-id": "qmf2",
"method": "request",
"qmf.opcode": "_query_request",
@@ -178,6 +184,7 @@ var invokeMethod = function(object, meth
message.setReplyTo(replyTo);
message.setCorrelationID(correlationID);
message.properties = {
+ "routing-key": "broker", // Added for Java Broker
"x-amqp-0-10.app-id": "qmf2",
"method": "request",
"qmf.opcode": "_method_request",
@@ -197,7 +204,7 @@ messenger.on('work', pumpData);
messenger.setOutgoingWindow(1024);
messenger.start();
-subscription = messenger.subscribe('amqp://0.0.0.0:5673/#');
+subscription = messenger.subscribe('amqp://' + addr + '/#');
messenger.recv(); // Receive as many messages as messenger can buffer.
@@ -358,11 +365,24 @@ var _options =
' output\n';
var REPLICATE_LEVELS = {"none" : true, "configuration": true, "all": true};
-var DEFAULT_PROPERTIES = {"exchange":["name", "type", "durable"], "queue":["name", "durable", "autoDelete"]};
+var DEFAULT_PROPERTIES = {"exchange": {"name": true, "type": true, "durable": true},
+ "queue": {"name": true, "durable": true, "autoDelete": true}};
+
+var getValue = function(r) {
+ var value = null;
+ if (r.length === 2) {
+ value = r[1];
+ if (!isNaN(value)) {
+ value = parseInt(value);
+ }
+ }
+
+ return value;
+};
var config = {
_recursive : false,
- _host : 'localhost',
+ _host : 'localhost:5673', // Note 5673 not 5672 as we use WebSocket transport.
_connTimeout : 10,
_ignoreDefault : false,
_altern_ex : null,
@@ -389,17 +409,13 @@ var config = {
_extra_arguments: [],
_start_replica : null,
_returnCode : 0,
- _list_properties: [],
+ _list_properties: null,
getOptions: function() {
var options = {};
for (var a = 0; a < this._extra_arguments.length; a++) {
var r = this._extra_arguments[a].split('=');
- var value = null;
- if (r.length === 2) {
- value = r[1];
- }
- options[r[0]] = value;
+ options[r[0]] = getValue(r);
}
return options;
}
@@ -471,7 +487,7 @@ var idMap = function(list) {
return map;
};
-var renderArguments = function(obj, list) {
+var renderObject = function(obj, list) {
if (!obj) {
return '';
}
@@ -493,7 +509,7 @@ var renderArguments = function(obj, list
}
if (addComma) {
- return ' {' + string + '}';
+ return '{' + string + '}';
} else {
if (list) {
return string;
@@ -645,7 +661,7 @@ var exchangeListRecurse = function(filte
var queue = queues[oid(bind.queueRef)];
var queueName = queue ? queue._values.name : "<unknown>";
console.log(" bind [" + bind.bindingKey + "] => " + queueName +
- renderArguments(bind.arguments));
+ " " + renderObject(bind.arguments));
}
}
}
@@ -743,7 +759,7 @@ var queueList = function(filter) {
if (args[SHARED_MSG_GROUP] === 1) {
string += ' --shared-groups';
}
- string += renderArguments(args, true);
+ string += ' ' + renderObject(args, true);
console.log(string);
}
}
@@ -785,7 +801,7 @@ var queueListRecurse = function(filter)
}
console.log(" bind [" + bind.bindingKey + "] => " + exchangeName +
- renderArguments(bind.arguments));
+ " " + renderObject(bind.arguments));
}
}
}
@@ -824,10 +840,10 @@ console.log("Method result");
if (response._arguments) {
//console.log(response._arguments);
} if (response._values) {
- console.error("Exception from Agent: " + renderArguments(response._values));
+ console.error("Exception from Agent: " + renderObject(response._values));
}
// Mostly we want to stop the Messenger Event loop and exit when a QMF method
- // call returns, but sometimes we don't.
+ // returns, but sometimes we don't, the dontStop flag prevents this behaviour.
if (!dontStop) {
messenger.stop();
}
@@ -846,11 +862,7 @@ var addExchange = function(args) {
for (var a = 0; a < config._extra_arguments.length; a++) {
var r = config._extra_arguments[a].split('=');
- var value = null;
- if (r.length === 2) {
- value = r[1];
- }
- declArgs[r[0]] = value;
+ declArgs[r[0]] = getValue(r);
}
if (config._msgSequence) {
@@ -918,11 +930,7 @@ var addQueue = function(args) {
for (var a = 0; a < config._extra_arguments.length; a++) {
var r = config._extra_arguments[a].split('=');
- var value = null;
- if (r.length === 2) {
- value = r[1];
- }
- declArgs[r[0]] = value;
+ declArgs[r[0]] = getValue(r);
}
if (config._durable) {
@@ -1201,21 +1209,141 @@ console.log(args);
* The following methods are "generic" create and delete methods to for arbitrary
* Management Objects e.g. Incoming, Outgoing, Domain, Topic, QueuePolicy,
* TopicPolicy etc. use --argument k1=v1 --argument k2=v2 --argument k3=v3 to
- * pass arbitrary arguments as key/value pairs to the Object being created/deleted.
+ * pass arbitrary arguments as key/value pairs to the Object being created/deleted,
+ * for example to add a topic object that uses the fanout exchange:
+ * ./qpid-config.js add topic fanout --argument exchange=amq.fanout \
+ * --argument qpid.max_size=1000000 --argument qpid.policy_type=ring
*/
var createObject = function(type, name, args) {
-console.log("createObject");
-console.log(type);
-console.log(name);
-console.log(args);
+ correlator.request(
+ // We invoke the CRUD methods on the broker object.
+ getObjects('org.apache.qpid.broker', 'broker')
+ ).then(function(objects) {
+ var broker = objects.broker[0];
+ correlator.request(
+ // Create an object of the specified type.
+ invokeMethod(broker, 'create', {
+ "type": type,
+ "name": name,
+ "properties": args,
+ "strict": true})
+ ).then(handleMethodResponse);
+ });
+};
+var deleteObject = function(type, name, args) {
+ correlator.request(
+ // We invoke the CRUD methods on the broker object.
+ getObjects('org.apache.qpid.broker', 'broker')
+ ).then(function(objects) {
+ var broker = objects.broker[0];
+ correlator.request(
+ // Create an object of the specified type and name.
+ invokeMethod(broker, 'delete', {
+ "type": type,
+ "name": name,
+ "options": args})
+ ).then(handleMethodResponse);
+ });
};
-var deleteObject = function(args) {
-console.log("deleteObject");
-console.log(args);
+/**
+ * This is a "generic" mechanism for listing arbitrary Management Objects.
+ */
+var listObjects = function(type) {
+ correlator.request(
+ getObjects('org.apache.qpid.broker', type)
+ ).then(function(objects) {
+ // The correlator passes an object containing responses for all of the
+ // supplied requests so we index it by the supplied type to get our response.
+ objects = objects[type];
+
+ // Collect available attributes, stringify the values and compute the max
+ // length of the value of each attribute so that we can later create a table.
+ var attributes = {};
+ var lengths = {};
+ for (var i = 0; i < objects.length; i++) {
+ var object = objects[i];
+ object = object._values;
+ for (var prop in object) {
+ if (typeof object[prop] === 'object') { // Stringify Object properties.
+ // Check if property is an ObjectID (reference property),
+ // if so replace with the "name" part of the OID.
+ if (object[prop]['_object_name']) {
+ var parts = object[prop]['_object_name'].split(':');
+ object[prop] = parts[parts.length - 1];
+ } else {
+ // Stringify general Object properties.
+ object[prop] = renderObject(object[prop]);
+ }
+ } else {
+ object[prop] = object[prop].toString(); // Stringify other property types.
+ }
+
+ if (!lengths[prop] || object[prop].length > lengths[prop]) { // Compute lengths.
+ lengths[prop] = object[prop].length > prop.length ? object[prop].length : prop.length;
+ }
+
+ if (!config._list_properties || config._list_properties[prop]) { // Do we want this property?
+ attributes[prop] = true;
+ }
+ }
+ }
+
+ if (!config._list_properties && DEFAULT_PROPERTIES[type]) {
+ attributes = DEFAULT_PROPERTIES[type];
+ }
+
+ // Using the information we've previously prepared now render a table
+ // showing the required property values.
+ var desired = [];
+ var header = ''; // Table header showing the property names.
+ if (attributes['name']) {
+ desired.push('name');
+ delete attributes['name'];
+ header += 'name' + Array(lengths['name'] + 2 - 4).join(' ');
+ }
+
+ for (var prop in attributes) {
+ desired.push(prop);
+ header += prop + Array(lengths[prop] + 2 - prop.length).join(' ');
+ }
+
+ console.log("Objects of type '" + type + "'");
+ console.log(header);
+ console.log(Array(header.length).join('='));
+ for (var i = 0; i < objects.length; i++) {
+ var object = objects[i];
+ object = object._values;
+ var string = '';
+ for (var j = 0; j < desired.length; j++) {
+ var key = desired[j];
+ string += object[key] + Array(lengths[key] + 2 - object[key].length).join(' ');
+ }
+
+ console.log(string);
+ }
+ messenger.stop();
+ });
+};
+
+var reloadAcl = function() {
+ correlator.request(
+ getObjects('org.apache.qpid.acl', 'acl')
+ ).then(function(objects) {
+ if (objects.acl.length > 0) {
+ var acl = objects.acl[0];
+ correlator.request(
+ // Create an object of the specified type.
+ invokeMethod(acl, 'reloadACLFile', {})
+ ).then(handleMethodResponse);
+ } else {
+ console.log("Failed: No ACL Loaded in Broker");
+ messenger.stop();
+ }
+ });
};
@@ -1263,10 +1391,9 @@ if (args.length > 0) {
if (config._connTimeout === 0) {
config._connTimeout = null;
}
- } else if (arg === '-b' || arg === '--broker' || arg === '-b' || arg === '--broker-addr') {
- config._host = val;
- if (config._host == null) {
- config._host = 'localhost:5672';
+ } else if (arg === '-b' || arg === '--broker' || arg === '-a' || arg === '--broker-addr') {
+ if (val != null) {
+ config._host = val;
}
} else if (arg === '--alternate-exchange') {
config._altern_ex = val;
@@ -1306,7 +1433,10 @@ if (args.length > 0) {
} else if (arg === '--f' || arg === '--file') { // TODO Won't work in node.js
config._file = val;
} else if (arg === '--show-property') {
- config._list_properties = val;
+ if (config._list_properties === null) {
+ config._list_properties = {};
+ }
+ config._list_properties[val] = true;
}
} else {
params.push(arg);
@@ -1316,9 +1446,6 @@ if (args.length > 0) {
config._extra_arguments = extra_arguments;
-console.log("params");
-console.log(params);
-
// The command only *actually* gets called when the QMF connection has actually
// been established so we wrap up the function we want to get called in a lambda.
var command = function() {overview();};
@@ -1365,11 +1492,19 @@ if (params.length > 0) {
command = function() {bind(Array.prototype.slice.apply(params, [1]));};
} else if (cmd === 'unbind') {
command = function() {unbind(Array.prototype.slice.apply(params, [1]));};
+ } else if (cmd === 'reload-acl') {
+ command = function() {reloadAcl();};
+ } else if (cmd === 'list' && params.length > 1) {
+ command = function() {listObjects(modifier);};
+ } else {
+ usage();
}
}
+//console.log(config._host);
+
+
var onSubscription = function() {
command();
};
-
Added: qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.html
URL: http://svn.apache.org/viewvc/qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.html?rev=1621865&view=auto
==============================================================================
--- qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.html (added)
+++ qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.html Mon Sep 1 18:32:04 2014
@@ -0,0 +1,110 @@
+<!DOCTYPE html> <!-- HTML5 doctype -->
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<html>
+
+<head>
+ <title>Simple Proton Messenger Send Example</title>
+ <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+
+<!--
+ Import JavaScript Messenger Binding proton.js. Note that this simple example pulls
+ it from the node_modules/qpid-proton/lib which is created by the build process
+ so that the node.js based examples "just work", in a real Web App you would need
+ to copy the proton.js to your own server.
+ In actual fact the CMake build actually builds proton.js into the directory:
+ <build>/proton-c/bindings/javascript
+ where <build> is the build directory created to run cmake from.
+-->
+<script type="text/javascript" src="../../../node_modules/qpid-proton/lib/proton.js"></script>
+
+<script type="text/javascript">
+
+var message = new proton.Message();
+var messenger = new proton.Messenger();
+
+var sendMessage = function() {
+ var address = document.getElementById("address").value;
+ var subject = document.getElementById("subject").value;
+ var body = document.getElementById("body").value;
+
+console.log("sendMessage");
+console.log("address = " + address);
+console.log("subject = " + subject);
+console.log("body = " + body);
+
+ message.setAddress(address);
+ message.setSubject(subject);
+ message.body = body;
+
+ messenger.put(message);
+};
+
+messenger.on('error', function(error) {console.log("Received error " + error);});
+messenger.start();
+
+</script>
+
+<style>
+body
+{
+ font: 13px/1.5 Helvetica, Arial, 'Liberation Sans', FreeSans, sans-serif;
+ overflow-x: hidden; /* Hide horizontal scrollbar */
+ background: #dddddd;
+}
+
+label
+{
+ display: block;
+ font-size: 17px;
+}
+
+input, textarea
+{
+ font-size: 13px;
+ margin-bottom: 10px;
+}
+</style>
+
+</head>
+
+<body>
+<div>
+ <label for="address">Address:</label>
+ <input type="text" id="address" size="40"
+ placeholder="amqp://user:password@host:port"
+ name="address" value="amqp://guest:guest@0.0.0.0" />
+</div>
+<div>
+ <label for="subject">Subject:</label>
+ <input type="text" id="subject" size="40"
+ name="subject" value="Browser Message" />
+</div>
+<div>
+ <label for="body">Message:</label>
+ <textarea id="body" name="body" rows="4" cols="40">Hello From Browser!</textarea>
+</div>
+<div>
+ <input type="button" value="send" onclick="sendMessage()"/>
+</div>
+</body>
+
+</html>
Propchange: qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.html
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.html
------------------------------------------------------------------------------
svn:keywords = Rev Date
Propchange: qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.html
------------------------------------------------------------------------------
svn:mime-type = text/html
Modified: qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.js
URL: http://svn.apache.org/viewvc/qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.js?rev=1621865&r1=1621864&r2=1621865&view=diff
==============================================================================
--- qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.js (original)
+++ qpid/proton/branches/fadams-javascript-binding/examples/messenger/javascript/send.js Mon Sep 1 18:32:04 2014
@@ -33,6 +33,10 @@ var running = true;
var message = new proton.Message();
var messenger = new proton.Messenger();
+// Because this is an asynchronous send we can't simply call messenger.put(message)
+// then exit. The following callback function (and messenger.setOutgoingWindow())
+// gives us a means to wait until the consumer has received the message before
+// exiting. The recv.js example explicitly accepts messages it receives.
var pumpData = function() {
var status = messenger.status(tracker);
if (status != proton.Status.PENDING) {
@@ -81,7 +85,7 @@ console.log("Content: " + msgtext);
messenger.on('error', function(error) {console.log(error);});
messenger.on('work', pumpData);
-messenger.setOutgoingWindow(1024);
+messenger.setOutgoingWindow(1024); // So we can track status of send message.
messenger.start();
message.setAddress(address);
Modified: qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/CMakeLists.txt?rev=1621865&r1=1621864&r2=1621865&view=diff
==============================================================================
--- qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/CMakeLists.txt (original)
+++ qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/CMakeLists.txt Mon Sep 1 18:32:04 2014
@@ -19,7 +19,7 @@
# This file allows cross-compiling of proton to JavaScript using emscripten
# (https://github.com/kripken/emscripten). As it is really a cross-compilation
-# (as opposed to a binding a la swig) the approach is rather different and
+# (as opposed to a binding like with swig) the approach is rather different and
# somewhat replicates the main build in the proton-c/CMakeLists.txt using quite
# a bit of "copy and paste reuse".
# TODO refactor this file (and proton-c/CMakeLists.txt) to keep the main
@@ -27,8 +27,8 @@
message(STATUS "Found emscripten, using that to build JavaScript binding")
-# Find and install node.js packages that we might need. We can assume that
-# node.js is installed because Emscripten has a dependency on it.
+# Find and install the node.js packages that we might need. We can assume that
+# node.js itself is installed because Emscripten has a dependency on it.
find_package(NodePackages)
# Describe the target OS we are building to - Emscripten mimics the Linux platform.
@@ -43,6 +43,14 @@ set(CMAKE_C_COMPILER "${EMCC}")
include(CMakeForceCompiler)
CMAKE_FORCE_C_COMPILER("${CMAKE_C_COMPILER}" Clang)
+if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
+ message(STATUS "DEBUG JavaScript build")
+else()
+ message(STATUS "RELEASE JavaScript build")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
+ set(EMSCRIPTEN_LINK_OPTIMISATIONS "-O2 --closure 1")
+endif()
+
# From this point we should be using emscripten compilation tools.
message(STATUS "emscripten compilation environment:")
message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
@@ -193,21 +201,9 @@ set_target_properties(
RUNTIME_OUTPUT_DIRECTORY examples
DEPENDS ws
- # This build shows socket messages - useful for debugging.
- #LINK_FLAGS "-s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -s SOCKET_DEBUG=1"
-
- # Optimised build - takes somewhat longer to build.
- #LINK_FLAGS "-s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -O2 --closure 1"
-
- # This build shows up emscripten warnings when building - should be able to remove it.
- #LINK_FLAGS "-s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -s VERBOSE=1 -O2"
-
- # This build is optimised but not minified
- LINK_FLAGS "-s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -O2"
+ LINK_FLAGS "-s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -${EMSCRIPTEN_LINK_OPTIMISATIONS}"
)
-
-
# Build the main JavaScript library called proton.js
add_executable(proton.js binding.c)
target_link_libraries(proton.js qpid-proton-bitcode)
@@ -217,16 +213,13 @@ set_target_properties(
PROPERTIES
COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_PLATFORM_FLAGS}"
- # This build is optimised and minified. The --memory-init-file 0 stops emscripten
- # emitting a separate memory initialization file, if this was enabled it makes
- # packaging harder as applications would expect proton.js.mem to be served too.
- # It's even more fiddly with node.js packages. This behaviour might be reinstated
- # if the packaging mechanism improves.
-
- # --js-library ${CMAKE_CURRENT_SOURCE_DIR}/my-library.js
- #LINK_FLAGS "-s \"EXPORT_NAME='proton'\" -s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -O2 --closure 1 --memory-init-file 0 --pre-js
+ # The --memory-init-file 0 stops emscripten emitting a separate memory
+ # initialization file, if this was enabled it makes packaging harder as
+ # applications would expect proton.js.mem to be served too. It's even more
+ # fiddly with node.js packages. This behaviour might be reinstated if the
+ # packaging mechanism improves.
- LINK_FLAGS "-s \"EXPORT_NAME='proton'\" -s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" -O2 --closure 1 --memory-init-file 0 --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/binding-open.js --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/binding.js --post-js ${CMAKE_CURRENT_SOURCE_DIR}/binding-close.js -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=\"[]\" -s EXPORTED_FUNCTIONS=\"['_test', '_uuid_generate', '_pn_bytes', '_pn_error_text', '_pn_code', '_pn_messenger', '_pn_messenger_name', '_pn_messenger_set_blocking', '_pn_messenger_free', '_pn_messenger_errno', '_pn_messenger_error', '_pn_messenger_get_outgoing_window', '_pn_messenger_set_outgoing_window', '_pn_messenger_get_incoming_window', '_pn_messenger_set_incoming_window', '_pn_messenger_start', '_pn_messenger_stop', '_pn_messenger_stopped', '_pn_messenger_subscribe', '_pn_messenger_put', '_pn_messenger_status', '_pn_messenger_buffered', '_pn_messenger_settle', '_pn_messenger_outgoing_tracker', '_pn_messenger_work', '_pn_messenger_recv', '_pn_messenger_receiving', '
_pn_messenger_get', '_pn_messenger_incoming_tracker', '_pn_messenger_incoming_subscription', '_pn_messenger_accept', '_pn_messenger_reject', '_pn_messenger_outgoing', '_pn_messenger_incoming', '_pn_messenger_route', '_pn_messenger_rewrite', '_pn_subscription_get_context', '_pn_subscription_set_context', '_pn_subscription_address', '_pn_message', '_pn_message_id', '_pn_message_correlation_id', '_pn_message_free', '_pn_message_errno', '_pn_message_error', '_pn_message_clear', '_pn_message_is_inferred', '_pn_message_set_inferred', '_pn_message_is_durable', '_pn_message_set_durable', '_pn_message_get_priority', '_pn_message_set_priority', '_pn_message_get_ttl', '_pn_message_set_ttl', '_pn_message_is_first_acquirer', '_pn_message_set_first_acquirer', '_pn_message_get_delivery_count', '_pn_message_set_delivery_count', '_pn_message_get_user_id', '_pn_message_set_user_id', '_pn_message_get_address', '_pn_message_set_address', '_pn_message_get_subject', '_pn_message_set_subject', '_pn_messa
ge_get_reply_to', '_pn_message_set_reply_to', '_pn_message_get_content_type', '_pn_message_set_content_type', '_pn_message_get_content_encoding', '_pn_message_set_content_encoding', '_pn_message_get_expiry_time', '_pn_message_set_expiry_time', '_pn_message_get_creation_time', '_pn_message_set_creation_time', '_pn_message_get_group_id', '_pn_message_set_group_id', '_pn_message_get_group_sequence', '_pn_message_set_group_sequence', '_pn_message_get_reply_to_group_id', '_pn_message_set_reply_to_group_id', '_pn_message_encode', '_pn_message_decode', '_pn_message_instructions', '_pn_message_annotations', '_pn_message_properties', '_pn_message_body', '_pn_data', '_pn_data_free', '_pn_data_error', '_pn_data_errno', '_pn_data_clear', '_pn_data_rewind', '_pn_data_next', '_pn_data_prev', '_pn_data_enter', '_pn_data_exit', '_pn_data_lookup', '_pn_data_narrow', '_pn_data_widen', '_pn_data_type', '_pn_data_encode', '_pn_data_decode', '_pn_data_put_list', '_pn_data_put_map', '_pn_data_put_array',
'_pn_data_put_described', '_pn_data_put_null', '_pn_data_put_bool', '_pn_data_put_ubyte', '_pn_data_put_byte', '_pn_data_put_ushort', '_pn_data_put_short', '_pn_data_put_uint', '_pn_data_put_int', '_pn_data_put_char', '_pn_data_put_ulong', '_pn_data_put_long', '_pn_data_put_timestamp', '_pn_data_put_float', '_pn_data_put_double', '_pn_data_put_decimal32', '_pn_data_put_decimal64', '_pn_data_put_decimal128', '_pn_data_put_uuid', '_pn_data_put_binary', '_pn_data_put_string', '_pn_data_put_symbol', '_pn_data_get_list', '_pn_data_get_map', '_pn_data_get_array', '_pn_data_is_array_described', '_pn_data_get_array_type', '_pn_data_is_described', '_pn_data_is_null', '_pn_data_get_bool', '_pn_data_get_ubyte', '_pn_data_get_byte', '_pn_data_get_ushort', '_pn_data_get_short', '_pn_data_get_uint', '_pn_data_get_int', '_pn_data_get_char', '_pn_data_get_ulong', '_pn_data_get_long', '_pn_data_get_timestamp', '_pn_data_get_float', '_pn_data_get_double', '_pn_data_get_decimal32', '_pn_data_get_deci
mal64', '_pn_data_get_decimal128', '_pn_data_get_uuid', '_pn_data_get_binary', '_pn_data_get_string', '_pn_data_get_symbol', '_pn_data_copy', '_pn_data_format', '_pn_data_dump']\""
+ LINK_FLAGS "-s \"EXPORT_NAME='proton'\" -s \"WEBSOCKET_SUBPROTOCOL='AMQPWSB10'\" ${EMSCRIPTEN_LINK_OPTIMISATIONS} --memory-init-file 0 --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/binding-open.js --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/binding.js --post-js ${CMAKE_CURRENT_SOURCE_DIR}/binding-close.js -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=\"[]\" -s EXPORTED_FUNCTIONS=\"['_pn_bytes', '_pn_error_text', '_pn_code', '_pn_messenger', '_pn_messenger_name', '_pn_messenger_set_blocking', '_pn_messenger_free', '_pn_messenger_errno', '_pn_messenger_error', '_pn_messenger_get_outgoing_window', '_pn_messenger_set_outgoing_window', '_pn_messenger_get_incoming_window', '_pn_messenger_set_incoming_window', '_pn_messenger_start', '_pn_messenger_stop', '_pn_messenger_stopped', '_pn_messenger_subscribe', '_pn_messenger_put', '_pn_messenger_status', '_pn_messenger_buffered', '_pn_messenger_settle', '_pn_messenger_outgoing_tracker', '_pn_messenger_work', '_pn_messenger_recv', '_pn_messenger_receiving', '_pn_messen
ger_get', '_pn_messenger_incoming_tracker', '_pn_messenger_incoming_subscription', '_pn_messenger_accept', '_pn_messenger_reject', '_pn_messenger_outgoing', '_pn_messenger_incoming', '_pn_messenger_route', '_pn_messenger_rewrite', '_pn_subscription_get_context', '_pn_subscription_set_context', '_pn_subscription_address', '_pn_message', '_pn_message_id', '_pn_message_correlation_id', '_pn_message_free', '_pn_message_errno', '_pn_message_error', '_pn_message_clear', '_pn_message_is_inferred', '_pn_message_set_inferred', '_pn_message_is_durable', '_pn_message_set_durable', '_pn_message_get_priority', '_pn_message_set_priority', '_pn_message_get_ttl', '_pn_message_set_ttl', '_pn_message_is_first_acquirer', '_pn_message_set_first_acquirer', '_pn_message_get_delivery_count', '_pn_message_set_delivery_count', '_pn_message_get_user_id', '_pn_message_set_user_id', '_pn_message_get_address', '_pn_message_set_address', '_pn_message_get_subject', '_pn_message_set_subject', '_pn_message_get_rep
ly_to', '_pn_message_set_reply_to', '_pn_message_get_content_type', '_pn_message_set_content_type', '_pn_message_get_content_encoding', '_pn_message_set_content_encoding', '_pn_message_get_expiry_time', '_pn_message_set_expiry_time', '_pn_message_get_creation_time', '_pn_message_set_creation_time', '_pn_message_get_group_id', '_pn_message_set_group_id', '_pn_message_get_group_sequence', '_pn_message_set_group_sequence', '_pn_message_get_reply_to_group_id', '_pn_message_set_reply_to_group_id', '_pn_message_encode', '_pn_message_decode', '_pn_message_instructions', '_pn_message_annotations', '_pn_message_properties', '_pn_message_body', '_pn_data', '_pn_data_free', '_pn_data_error', '_pn_data_errno', '_pn_data_clear', '_pn_data_rewind', '_pn_data_next', '_pn_data_prev', '_pn_data_enter', '_pn_data_exit', '_pn_data_lookup', '_pn_data_narrow', '_pn_data_widen', '_pn_data_type', '_pn_data_encode', '_pn_data_decode', '_pn_data_put_list', '_pn_data_put_map', '_pn_data_put_array', '_pn_data
_put_described', '_pn_data_put_null', '_pn_data_put_bool', '_pn_data_put_ubyte', '_pn_data_put_byte', '_pn_data_put_ushort', '_pn_data_put_short', '_pn_data_put_uint', '_pn_data_put_int', '_pn_data_put_char', '_pn_data_put_ulong', '_pn_data_put_long', '_pn_data_put_timestamp', '_pn_data_put_float', '_pn_data_put_double', '_pn_data_put_decimal32', '_pn_data_put_decimal64', '_pn_data_put_decimal128', '_pn_data_put_uuid', '_pn_data_put_binary', '_pn_data_put_string', '_pn_data_put_symbol', '_pn_data_get_list', '_pn_data_get_map', '_pn_data_get_array', '_pn_data_is_array_described', '_pn_data_get_array_type', '_pn_data_is_described', '_pn_data_is_null', '_pn_data_get_bool', '_pn_data_get_ubyte', '_pn_data_get_byte', '_pn_data_get_ushort', '_pn_data_get_short', '_pn_data_get_uint', '_pn_data_get_int', '_pn_data_get_char', '_pn_data_get_ulong', '_pn_data_get_long', '_pn_data_get_timestamp', '_pn_data_get_float', '_pn_data_get_double', '_pn_data_get_decimal32', '_pn_data_get_decimal64', '_
pn_data_get_decimal128', '_pn_data_get_uuid', '_pn_data_get_binary', '_pn_data_get_string', '_pn_data_get_symbol', '_pn_data_copy', '_pn_data_format', '_pn_data_dump']\""
)
# This command packages up the compiled proton.js into a node.js package called
Modified: qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/binding.js
URL: http://svn.apache.org/viewvc/qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/binding.js?rev=1621865&r1=1621864&r2=1621865&view=diff
==============================================================================
--- qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/binding.js (original)
+++ qpid/proton/branches/fadams-javascript-binding/proton-c/bindings/javascript/binding.js Mon Sep 1 18:32:04 2014
@@ -477,6 +477,14 @@ _Messenger_['setIncomingWindow'] = funct
*/
_Messenger_['start'] = function() {
this._check(_pn_messenger_start(this._messenger));
+
+ // This call ensures that the emscripten network callback functions are set
+ // up even if a client hasn't explicity added a work function via a call to
+ // messenger.on('work', <work function>);
+ // Doing this means that pn_messenger_work() will still get called when any
+ // WebSocket events occur, which keeps things more reliable when things like
+ // reconnections occur.
+ Module.EventDispatch.addListener(this);
};
/**
@@ -541,8 +549,7 @@ _Messenger_['subscribe'] = function(sour
* Places the content contained in the message onto the outgoing queue
* of the Messenger. This method will never block, however it will send any
* unblocked Messages in the outgoing queue immediately and leave any blocked
- * Messages remaining in the outgoing queue. The send call may be used to
- * block until the outgoing queue is empty. The outgoing property may be
+ * Messages remaining in the outgoing queue. The outgoing property may be
* used to check the depth of the outgoing queue.
* <p>
* When the content in a given Message object is copied to the outgoing
@@ -554,13 +561,23 @@ _Messenger_['subscribe'] = function(sour
* @method put
* @memberof! proton.Messenger#
* @param {proton.Message} message a Message to send.
+ * @param {boolean} flush if this is set true or is undefined then messages are
+ * flushed (this is the default). If explicitly set to false then messages
+ * may not be sent immediately and might require an explicit call to work().
+ * This may be used to "batch up" messages and *may* be more efficient.
* @returns {proton.Data.Long} a tracker.
*/
-_Messenger_['put'] = function(message) {
+_Messenger_['put'] = function(message, flush) {
+ flush = flush === false ? false : true;
message._preEncode();
this._checkErrors = true;
this._check(_pn_messenger_put(this._messenger, message._message));
+ // If flush is set invoke pn_messenger_work.
+ if (flush) {
+ _pn_messenger_work(this._messenger, 0);
+ }
+
// Getting the tracker is a little tricky as it is a 64 bit number. The way
// emscripten handles this is to return the low 32 bits directly and pass
// the high 32 bits via the tempRet0 variable. We use Data.Long to pass the
@@ -578,6 +595,12 @@ _Messenger_['put'] = function(message) {
* @returns {proton.Status} one of None, PENDING, REJECTED, or ACCEPTED.
*/
_Messenger_['status'] = function(tracker) {
+ if (tracker == null) {
+ var low = _pn_messenger_outgoing_tracker(this._messenger);
+ var high = Runtime.getTempRet0();
+ tracker = new Data.Long(low, high);
+ }
+
return _pn_messenger_status(this._messenger, tracker.getLowBitsUnsigned(), tracker.getHighBits());
};
@@ -589,6 +612,12 @@ _Messenger_['status'] = function(tracker
* @returns {boolean} true if delivery is still buffered.
*/
_Messenger_['isBuffered'] = function(tracker) {
+ if (tracker == null) {
+ var low = _pn_messenger_outgoing_tracker(this._messenger);
+ var high = Runtime.getTempRet0();
+ tracker = new Data.Long(low, high);
+ }
+
return (_pn_messenger_buffered(this._messenger, tracker.getLowBitsUnsigned(), tracker.getHighBits()) > 0);
};
@@ -982,7 +1011,9 @@ Module.EventDispatch = new function() {
};
}
- _messengers[name].callbacks.push(callback);
+ if (callback) {
+ _messengers[name].callbacks.push(callback);
+ }
};
/**
Added: qpid/proton/branches/fadams-javascript-binding/tests/javascript/soak.js
URL: http://svn.apache.org/viewvc/qpid/proton/branches/fadams-javascript-binding/tests/javascript/soak.js?rev=1621865&view=auto
==============================================================================
--- qpid/proton/branches/fadams-javascript-binding/tests/javascript/soak.js (added)
+++ qpid/proton/branches/fadams-javascript-binding/tests/javascript/soak.js Mon Sep 1 18:32:04 2014
@@ -0,0 +1,99 @@
+#!/usr/bin/env node
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+// Check if the environment is Node.js and if so import the required library.
+if (typeof exports !== "undefined" && exports !== null) {
+ proton = require("qpid-proton");
+}
+
+var addr = 'guest:guest@localhost:5673';
+//var addr = 'localhost:5673';
+var address = 'amqp://' + addr;
+console.log(address);
+
+var subscriptionQueue = '';
+var subscription;
+var subscribed = false;
+var count = 0;
+var start = 0; // Start Time.
+
+var message = new proton.Message();
+var messenger = new proton.Messenger();
+
+var pumpData = function() {
+ if (!subscribed) {
+ var subscriptionAddress = subscription.getAddress();
+ if (subscriptionAddress) {
+ subscribed = true;
+ var splitAddress = subscriptionAddress.split('/');
+ subscriptionQueue = splitAddress[splitAddress.length - 1];
+ onSubscription();
+ }
+ }
+
+ while (messenger.incoming()) {
+ // The second parameter forces Binary payloads to be decoded as strings
+ // this is useful because the broker QMF Agent encodes strings as AMQP
+ // binary, which is a right pain from an interoperability perspective.
+ var t = messenger.get(message, true);
+ //console.log("Address: " + message.getAddress());
+ //console.log("Content: " + message.body);
+ messenger.accept(t);
+
+ if (count % 1000 === 0) {
+ var time = +new Date();
+ console.log("count = " + count + ", duration = " + (time - start) + ", rate = " + ((count*1000)/(time - start)));
+ }
+
+ sendMessage();
+ }
+
+ if (messenger.isStopped()) {
+ message.free();
+ messenger.free();
+ }
+};
+
+var sendMessage = function() {
+ var msgtext = "Message Number " + count;
+ count++;
+
+ message.setAddress(address + '/' + subscriptionQueue);
+ message.body = msgtext;
+ messenger.put(message);
+//messenger.settle();
+};
+
+messenger.on('error', function(error) {console.log(error);});
+messenger.on('work', pumpData);
+//messenger.setOutgoingWindow(1024);
+messenger.setIncomingWindow(1024); // The Java Broker seems to need this.
+messenger.start();
+
+subscription = messenger.subscribe('amqp://' + addr + '/#');
+messenger.recv(); // Receive as many messages as messenger can buffer.
+
+var onSubscription = function() {
+ console.log("Subscription Queue: " + subscriptionQueue);
+ start = +new Date();
+ sendMessage();
+};
+
Propchange: qpid/proton/branches/fadams-javascript-binding/tests/javascript/soak.js
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: qpid/proton/branches/fadams-javascript-binding/tests/javascript/soak.js
------------------------------------------------------------------------------
svn:executable = *
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org