From 23c19711eb0d6432e480791c71d436dac986f935 Mon Sep 17 00:00:00 2001 From: gmallard Date: Tue, 3 May 2016 20:41:02 -0400 Subject: [PATCH 01/48] Ignore vscode local artifacts. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index a95e92d..1b829af 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ coverage/* *.gem *~ temp* +# Ignore vscode artifacts +.vscode/ From 4e261b19c7e19e091db13db9092a81588249354a Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 6 May 2016 16:20:53 -0400 Subject: [PATCH 02/48] Remove README.rdoc. --- README.rdoc | 163 ---------------------------------------------------- 1 file changed, 163 deletions(-) delete mode 100644 README.rdoc diff --git a/README.rdoc b/README.rdoc deleted file mode 100644 index 51d62ed..0000000 --- a/README.rdoc +++ /dev/null @@ -1,163 +0,0 @@ -==README - -* (https://github.com/stompgem/stomp/) - -===Overview - -An implementation of the Stomp protocol for Ruby. See: - -* [STOMP 1.0, 1.1, and 1.2] (http://stomp.github.com/index.html) - -===Hash Login Example Usage (this is the recommended login technique) - - hash = { - :hosts => [ - # First connect is to remotehost1 - {:login => "login1", :passcode => "passcode1", :host => "remotehost1", :port => 61612, :ssl => true}, - # First failover connect is to remotehost2 - {:login => "login2", :passcode => "passcode2", :host => "remotehost2", :port => 61613, :ssl => false}, - - ], - # These are the default parameters and do not need to be set - :reliable => true, # reliable (use failover) - :initial_reconnect_delay => 0.01, # initial delay before reconnect (secs) - :max_reconnect_delay => 30.0, # max delay before reconnect - :use_exponential_back_off => true, # increase delay between reconnect attpempts - :back_off_multiplier => 2, # next delay multiplier - :max_reconnect_attempts => 0, # retry forever, use # for maximum attempts - :randomize => false, # do not radomize hosts hash before reconnect - :connect_timeout => 0, # Timeout for TCP/TLS connects, use # for max seconds - :connect_headers => {}, # user supplied CONNECT headers (req'd for Stomp 1.1+) - :parse_timeout => 5, # receive / read timeout, secs - :logger => nil, # user suplied callback logger instance - :dmh => false, # do not support multihomed IPV4 / IPV6 hosts during failover - :closed_check => true, # check first if closed in each protocol method - :hbser => false, # raise on heartbeat send exception - :stompconn => false, # Use STOMP instead of CONNECT - :usecrlf => false, # Use CRLF command and header line ends (1.2+) - :max_hbread_fails => 0, # Max HB read fails before retry. 0 => never retry - :max_hbrlck_fails => 0, # Max HB read lock obtain fails before retry. 0 => never retry - :fast_hbs_adjust => 0.0, # Fast heartbeat senders sleep adjustment, seconds, needed ... - # For fast heartbeat senders. 'fast' == YMMV. If not - # correct for your environment, expect unnecessary fail overs - :connread_timeout => 0, # Timeout during CONNECT for read of CONNECTED/ERROR, secs - :tcp_nodelay => true, # Turns on the TCP_NODELAY socket option; disables Nagle's algorithm - :start_timeout => 0, # Timeout around Stomp::Client initialization - :sslctx_newparm => nil, # Param for SSLContext.new - } - - # for client - client = Stomp::Client.new(hash) - - # for connection - connection = Stomp::Connection.new(hash) - -===Positional Parameter Usage - - client = Stomp::Client.new("user", "pass", "localhost", 61613) - client.publish("/queue/mine", "hello world!") - client.subscribe("/queue/mine") do |msg| - p msg - end - -===Stomp URL Usage - - # Stomp URL : - A Stomp URL must begin with 'stomp://' and can be in one of the following forms: - - stomp://host:port - stomp://host.domain.tld:port - stomp://login:passcode@host:port - stomp://login:passcode@host.domain.tld:port - - e.g. c = Stomp::Client.new(urlstring) - -===Failover + SSL Example URL Usage - - options = "initialReconnectDelay=5000&randomize=false&useExponentialBackOff=false" - - # remotehost1 uses SSL, remotehost2 doesn't - client = Stomp::Client.new("failover:(stomp+ssl://login1:passcode1@remotehost1:61612,stomp://login2:passcode2@remotehost2:61613)?#{options}") - - client.publish("/queue/mine", "hello world!") - client.subscribe("/queue/mine") do |msg| - p msg - end - -===New - -See _CHANGELOG.rdoc_ for details. - -* Gem version 1.3.5. Miscellaneous fixes, see CHANGELOG.rdoc for details. -* Gem version 1.3.4. Miscellaneous fixes, see CHANGELOG.rdoc for details. -* Gem version 1.3.3. Miscellaneous fixes, see CHANGELOG.rdoc for details. -* Gem version 1.3.2. Miscellaneous fixes, see changelog for details. -* Gem version 1.3.1. Bugfix for logging. -* Gem version 1.3.0. Added ERROR frame raising as exception, added anonymous connections, miscellaneous other fixes. -* Gem version 1.2.16. Fixed Stomp::Client to expose its connection's host parameters. -* Gem version 1.2.15. Timeout cleanup, added license info to gemspec. -* Gem version 1.2.14. Cleanup. -* Gem version 1.2.13. Stomp::Client#unreceive max_redeliveries fix. -* Gem version 1.2.12. Miscellaneous issue fixes and cleanup. -* Gem version 1.2.11. JRuby and AMQ support fixes. -* Gem version 1.2.10. Support failover from heartbeat threads. -* Gem version 1.2.9. Miscellaneous fixes and changes. -* Gem version 1.2.8. Stomp 1.1+ header codec inversion fix, test refactoring. -* Gem version 1.2.7. Stomp 1.2 support and miscellaneous fixes. -* Gem version 1.2.6. Miscellaneous fixes and changes. -* Gem version 1.2.5. Restructure. Forks with modifcations will be affected. -* Gem version 1.2.4. Stomp 1.1 heartbeat fix, autoflush capability, miscellaneous fixes. -* Gem version 1.2.3. Miscellaneous fixes, see changelog for details. -* Gem version 1.2.2. Performance and more SSL enhancements. -* Gem version 1.2.1. Full support of SSL certificates. -* Gem version 1.2.0. Support of Stomp protocol level 1.1. - -===Historical Information - -Up until March 2009 the project was maintained and primarily developed by Brian McCallister. - -===Source Code and Project URLs - - https://github.com/stompgem/stomp/ - -===Stomp Protocol Information : - - http://stomp.github.com/index.html - -= Contributors - -The following people have contributed to Stomp: - -* Brian McCallister -* Glenn Rempe -* jstrachan -* Marius Mathiesen -* Johan S√∏rensen -* Thiago Morello -* Guy M. Allard -* kookster -* Tony Garnock-Jones -* chirino -* Stefan Saasen -* Neil Wilson -* Dinesh Majrekar -* Kiall Mac Innes -* Rob Skaggs -* Tom May -* Lucas Hills -* Chris Needham -* R.I. Pienaar -* tworker -* James Pearson -* Craig -* Tommy Bishop -* Jeremy Gailor -* JP Hastings-Spital -* Glenn Roberts -* Ian Smith -* Orazio Cotroneo -* m4rCsi -* Michael Klishin -* Patrick Sharp -* Wayne Robinson - From 76065d87bb1b108f5531212ab44050b837b2faa7 Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 6 May 2016 16:22:30 -0400 Subject: [PATCH 03/48] Add utilities for generating contributor's list. --- examples/contrib.sh | 6 +++ examples/contributors.rb | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100755 examples/contrib.sh create mode 100644 examples/contributors.rb diff --git a/examples/contrib.sh b/examples/contrib.sh new file mode 100755 index 0000000..cda24ef --- /dev/null +++ b/examples/contrib.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# +#git log --reverse --all --date=iso-strict --pretty --format='%ad;%cn;%ce' +git log --reverse --all --date=short --pretty --format='%cd;%cn;%ce' | \ + ruby examples/contributors.rb + \ No newline at end of file diff --git a/examples/contributors.rb b/examples/contributors.rb new file mode 100644 index 0000000..3087e8e --- /dev/null +++ b/examples/contributors.rb @@ -0,0 +1,81 @@ +#!/usr/bin/env ruby +# +class UserData + + public + attr_accessor :count + attr_reader :time + # + def initialize(time = nil) + @count, @time = 1, time + end + # + def to_s + "UserData: time=>#{@time}, count =>#{@count}" + end +end +# Row Data +trow_s = "\n" +trow_e = "\n" +# Header Data +th_s = "\n" +th_c1 = "First Author Date" +th_c2 = "(Commit Count)" +th_c3 = "Name / E-mail" +th_e = "\n" +# User Data (partial) +td_s = "\n" +td_e = "\n" +# +userList = {} +while s = gets do + s.chomp! + t, n, e = s.split(";") + hk = "#{n}|#{e}" + if userList.has_key?(hk) + userList[hk].count += 1 + else + userList[hk] = UserData.new(t) + end + +end +# +puts trow_s +# +puts th_s +puts th_c1 +puts th_e +# +puts th_s +puts th_c2 +puts th_e +# +puts th_s +puts th_c3 +puts th_e +# +puts trow_e +# +userList.each do |k, v| + n, e = k.split("|") + oc = "(" + sprintf("%04d", v.count) + ")" + # puts "# #{v.time} (#{oc}) #{n} #{e}" + puts trow_s + # + puts td_s + puts "#{v.time}" + puts td_e + # + puts td_s + puts oc + puts td_e + # + puts td_s + puts "\n" + puts "#{n}\n" + puts "\n" + puts " / #{e}" + puts td_e + # + puts trow_e +end From 3b727ee89bd047cf8d684397ba7c677d5fec6d1f Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 6 May 2016 16:23:08 -0400 Subject: [PATCH 04/48] New README format, with updated contributor's list. --- README.md | 725 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 725 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..8f0cad0 --- /dev/null +++ b/README.md @@ -0,0 +1,725 @@ +# README + +* [Project Information](https://github.com/stompgem/stomp) + +## Overview + +An implementation of the Stomp protocol for Ruby. See: + +* [STOMP 1.0, 1.1, and 1.2] (http://stomp.github.com/index.html) + +## Hash Login Example Usage (this is the recommended login technique): + +```ruby + hash = { + :hosts => [ + # First connect is to remotehost1 + {:login => "login1", :passcode => "passcode1", :host => "remotehost1", :port => 61612, :ssl => true}, + # First failover connect is to remotehost2 + {:login => "login2", :passcode => "passcode2", :host => "remotehost2", :port => 61613, :ssl => false}, + + ], + # These are the default parameters and do not need to be set + :reliable => true, # reliable (use failover) + :initial_reconnect_delay => 0.01, # initial delay before reconnect (secs) + :max_reconnect_delay => 30.0, # max delay before reconnect + :use_exponential_back_off => true, # increase delay between reconnect attpempts + :back_off_multiplier => 2, # next delay multiplier + :max_reconnect_attempts => 0, # retry forever, use # for maximum attempts + :randomize => false, # do not radomize hosts hash before reconnect + :connect_timeout => 0, # Timeout for TCP/TLS connects, use # for max seconds + :connect_headers => {}, # user supplied CONNECT headers (req'd for Stomp 1.1+) + :parse_timeout => 5, # receive / read timeout, secs + :logger => nil, # user suplied callback logger instance + :dmh => false, # do not support multihomed IPV4 / IPV6 hosts during failover + :closed_check => true, # check first if closed in each protocol method + :hbser => false, # raise on heartbeat send exception + :stompconn => false, # Use STOMP instead of CONNECT + :usecrlf => false, # Use CRLF command and header line ends (1.2+) + :max_hbread_fails => 0, # Max HB read fails before retry. 0 => never retry + :max_hbrlck_fails => 0, # Max HB read lock obtain fails before retry. 0 => never retry + :fast_hbs_adjust => 0.0, # Fast heartbeat senders sleep adjustment, seconds, needed ... + # For fast heartbeat senders. 'fast' == YMMV. If not + # correct for your environment, expect unnecessary fail overs + :connread_timeout => 0, # Timeout during CONNECT for read of CONNECTED/ERROR, secs + :tcp_nodelay => true, # Turns on the TCP_NODELAY socket option; disables Nagle's algorithm + :start_timeout => 0, # Timeout around Stomp::Client initialization + :sslctx_newparm => nil, # Param for SSLContext.new + } + + # for client + client = Stomp::Client.new(hash) + + # for connection + connection = Stomp::Connection.new(hash) +``` + +### Positional Parameter Usage: + +```ruby + client = Stomp::Client.new("user", "pass", "localhost", 61613) + client.publish("/queue/mine", "hello world!") + client.subscribe("/queue/mine") do |msg| + p msg + end +``` + +### Stomp URL Usage: + +```ruby + # Stomp URL : + # A Stomp URL must begin with 'stomp://' and can be in one of the following forms: + + stomp://host:port + stomp://host.domain.tld:port + stomp://login:passcode@host:port + stomp://login:passcode@host.domain.tld:port + + # e.g. c = Stomp::Client.new(urlstring) +``` + +### Failover + SSL Example URL Usage: + +```ruby + options = "initialReconnectDelay=5000&randomize=false&useExponentialBackOff=false" + + # remotehost1 uses SSL, remotehost2 doesn't + client = Stomp::Client.new("failover:(stomp+ssl://login1:passcode1@remotehost1:61612,stomp://login2:passcode2@remotehost2:61613)?#{options}") + + client.publish("/queue/mine", "hello world!") + client.subscribe("/queue/mine") do |msg| + p msg + end +``` + +### New: + +See _CHANGELOG.rdoc_ for details. + +* Gem version 1.3.5. Miscellaneous fixes, see CHANGELOG.rdoc for details. +* Gem version 1.3.4. Miscellaneous fixes, see CHANGELOG.rdoc for details. +* Gem version 1.3.3. Miscellaneous fixes, see CHANGELOG.rdoc for details. +* Gem version 1.3.2. Miscellaneous fixes, see changelog for details. +* Gem version 1.3.1. Bugfix for logging. +* Gem version 1.3.0. Added ERROR frame raising as exception, added anonymous connections, miscellaneous other fixes. +* Gem version 1.2.16. Fixed Stomp::Client to expose its connection's host parameters. +* Gem version 1.2.15. Timeout cleanup, added license info to gemspec. +* Gem version 1.2.14. Cleanup. +* Gem version 1.2.13. Stomp::Client#unreceive max_redeliveries fix. +* Gem version 1.2.12. Miscellaneous issue fixes and cleanup. +* Gem version 1.2.11. JRuby and AMQ support fixes. +* Gem version 1.2.10. Support failover from heartbeat threads. +* Gem version 1.2.9. Miscellaneous fixes and changes. +* Gem version 1.2.8. Stomp 1.1+ header codec inversion fix, test refactoring. +* Gem version 1.2.7. Stomp 1.2 support and miscellaneous fixes. +* Gem version 1.2.6. Miscellaneous fixes and changes. +* Gem version 1.2.5. Restructure. Forks with modifcations will be affected. +* Gem version 1.2.4. Stomp 1.1 heartbeat fix, autoflush capability, miscellaneous fixes. +* Gem version 1.2.3. Miscellaneous fixes, see changelog for details. +* Gem version 1.2.2. Performance and more SSL enhancements. +* Gem version 1.2.1. Full support of SSL certificates. +* Gem version 1.2.0. Support of Stomp protocol level 1.1. + +### Historical Information: + +Up until March 2009 the project was maintained and primarily developed by Brian McCallister. + +### Source Code and Project URLs: + + [Source Code and Project](https://github.com/stompgem/stomp) + +### Stomp Protocol Information: + + [Protocol Information](http://stomp.github.com/index.html) + +#### Contributors (by first author date) #### + +Contribution information: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+First Author Date + +(Commit Count) + +Name / E-mail +
+2005-08-26 + +(0023) + + +brianm + + / brianm@fd4e7336-3dff-0310-b68a-b6615a75f13b +
+2006-03-16 + +(0005) + + +jstrachan + + / jstrachan@fd4e7336-3dff-0310-b68a-b6615a75f13b +
+2006-04-19 + +(0001) + + +chirino + + / chirino@fd4e7336-3dff-0310-b68a-b6615a75f13b +
+2007-05-09 + +(0003) + + +kookster + + / kookster@fd4e7336-3dff-0310-b68a-b6615a75f13b +
+2008-05-08 + +(0016) + + +Glenn Rempe + + / glenn@rempe.us +
+2009-02-03 + +(0001) + + +Tony Garnock-Jones + + / tonyg@lshift.net +
+2009-02-09 + +(0003) + + +Marius Mathiesen + + / marius.mathiesen@gmail.com +
+2009-02-13 + +(0004) + + +Johan Sørensen + + / johan@johansorensen.com +
+2009-11-17 + +(0022) + + +Thiago Morello + + / thiago.morello@locaweb.com.br +
+2009-11-22 + +(0001) + + +unknown + + / katy@.(none) +
+2009-12-18 + +(0052) + + +Thiago Morello + + / morello@queroinfra32.fabrica.locaweb.com.br +
+2009-12-25 + +(0299) + + +gmallard + + / allard.guy.m@gmail.com +
+2010-01-07 + +(0007) + + +Rafael Rosa + + / rafael.rosa@locaweb.com.br +
+2010-03-23 + +(0024) + + +Guy M. Allard + + / allard.guy.m@gmail.com +
+2010-04-01 + +(0001) + + +Dmytro Shteflyuk + + / kpumuk@kpumuk.info +
+2010-10-22 + +(0001) + + +Neil Wilson + + / neil@aldur.co.uk +
+2011-02-09 + +(0001) + + +Dinesh Majrekar + + / dinesh.majrekar@advantage-interactive.com +
+2011-04-15 + +(0002) + + +Kiall Mac Innes + + / kiall@managedit.ie +
+2011-04-29 + +(0002) + + +Rob Skaggs + + / rob@pivotal-it.com +
+2011-08-23 + +(0003) + + +Tom May + + / tom@gist.com +
+2011-08-24 + +(0002) + + +Thiago Morello + + / morellon@gmail.com +
+2011-09-11 + +(0003) + + +Lucas Hills + + / info@lucashills.com +
+2011-11-20 + +(0002) + + +Chris Needham + + / chrisn303@gmail.com +
+2011-12-11 + +(0003) + + +R.I.Pienaar + + / rip@devco.net +
+2011-12-13 + +(0001) + + +tworker + + / tworker@onyx.ove.com +
+2012-03-16 + +(0001) + + +James Pearson + + / james@fearmediocrity.co.uk +
+2012-05-10 + +(0001) + + +Tommy Bishop + + / bishop.thomas@gmail.com +
+2012-06-18 + +(0002) + + +Jeremy Gailor + + / jeremy@infinitecube.com +
+2013-02-20 + +(0002) + + +JP Hastings-Spital + + / jphastings@gmail.com +
+2013-03-14 + +(0003) + + +glennr + + / glenn@siyelo.com +
+2013-07-29 + +(0021) + + +Ian Smith + + / ian.smith@mylookout.com +
+2013-08-07 + +(0001) + + +Hiram Chirino + + / hiram@hiramchirino.com +
+2013-08-15 + +(0005) + + +Ian Smith + + / ian.smith@lookout.com +
+2013-08-22 + +(0007) + + +Ian Smith + + / ismith@mit.edu +
+2013-09-26 + +(0001) + + +Orazio Cotroneo + + / orazio@we7.com +
+2013-10-22 + +(0001) + + +OrazioWE7 + + / orazio@we7.com +
+2014-03-14 + +(0001) + + +Richard Clamp + + / richardc@unixbeard.net +
+2014-12-08 + +(0001) + + +m4rCsi + + / m4rCsi@gmail.com +
+2015-09-05 + +(0001) + + +Michael Klishin + + / michael@novemberain.com +
+2015-11-10 + +(0002) + + +Patrick Sharp + + / psharp@numerex.com +
+2016-02-03 + +(0001) + + +Wayne Robinson + + / wayne.robinson@gmail.com +
\ No newline at end of file From d43f8f741b87174accd2a5c6b6c347e5113dec40 Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 6 May 2016 16:52:23 -0400 Subject: [PATCH 05/48] Eliminate warnings for: - unused variables - ambiguous first parameter --- test/test_anonymous.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_anonymous.rb b/test/test_anonymous.rb index d30944c..cd3dd2d 100644 --- a/test/test_anonymous.rb +++ b/test/test_anonymous.rb @@ -203,11 +203,11 @@ def test_closed_checks_conn end # assert_raise Stomp::Error::NoCurrentConnection do - m = @conn.receive + _ = @conn.receive end # assert_raise Stomp::Error::NoCurrentConnection do - m = @conn.poll + _ = @conn.poll end end @@ -225,7 +225,7 @@ def test_message_to_s conn_subscribe make_destination @conn.publish make_destination, "a\0" msg = @conn.receive - assert_match /^ Date: Fri, 6 May 2016 16:59:08 -0400 Subject: [PATCH 06/48] Eliminate unused variable warnings. --- test/test_helper.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index b46e977..a7e14c0 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -13,8 +13,8 @@ end begin - dummy = RUBY_ENGINE -rescue NameError => ne + _ = RUBY_ENGINE +rescue NameError RUBY_ENGINE = "unknown" end @@ -169,6 +169,7 @@ def conn_subscribe(dest, headers = {}) def make_destination name = caller_method_name unless name qname = ENV['STOMP_DOTQUEUE'] ? "/queue/test.ruby.stomp." + name : "/queue/test/ruby/stomp/" + name + return qname end # @@ -182,6 +183,7 @@ def checkEmsg(cc) # Check for JRuby before a connection exists def jruby?() jr = defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/ ? true : false + return jr end # OK Data For Default Tests From 8c962d43823908a06945c07218641b689f408393 Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 6 May 2016 17:42:28 -0400 Subject: [PATCH 07/48] Eliminate more unused variable warnings. --- test/test_client.rb | 12 ++++++------ test/test_connection.rb | 8 ++++---- test/test_connection1p.rb | 8 ++++---- test/test_message.rb | 32 ++++++++++++++++---------------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/test/test_client.rb b/test/test_client.rb index 9ee4249..169d822 100644 --- a/test/test_client.rb +++ b/test/test_client.rb @@ -524,7 +524,7 @@ def test_thread_multi_subscribe # this is ugly ..... if acli.protocol() == Stomp::SPL_10 acli.subscribe(dest) { |m| - msg = m + _ = m lock.synchronize do msg_ctr += 1 end @@ -533,7 +533,7 @@ def test_thread_multi_subscribe } else acli.subscribe(dest, :id => acli.uuid()) { |m| - msg = m + _ = m lock.synchronize do msg_ctr += 1 end @@ -547,7 +547,7 @@ def test_thread_multi_subscribe # 1.upto(@max_msgs) do |mnum| msg = Time.now.to_s + " #{mnum}" - @client.publish(dest, message_text) + @client.publish(dest, msg) end # max_sleep = (RUBY_VERSION =~ /1\.8\.6/) ? 30 : 5 @@ -569,7 +569,7 @@ def test_closed_checks_client # assert_raise Stomp::Error::NoCurrentConnection do m = Stomp::Message.new("") - @client.acknowledge(m) {|r| receipt = r} + @client.acknowledge(m) {|r| _ = r} end # assert_raise Stomp::Error::NoCurrentConnection do @@ -585,7 +585,7 @@ def test_closed_checks_client end # assert_raise Stomp::Error::NoCurrentConnection do - @client.subscribe("dummy_data", {:ack => 'auto'}) {|msg| received = msg} + @client.subscribe("dummy_data", {:ack => 'auto'}) {|msg| _ = msg} end # assert_raise Stomp::Error::NoCurrentConnection do @@ -662,7 +662,7 @@ def test_cli_iss99_ex ex_vals = dflt_data_ex() ex_vals.each do |hsv| assert_raise ArgumentError do - cli = Stomp::Client.open(hsv) + _ = Stomp::Client.open(hsv) end end end diff --git a/test/test_connection.rb b/test/test_connection.rb index 708fdba..15f2eae 100644 --- a/test/test_connection.rb +++ b/test/test_connection.rb @@ -203,11 +203,11 @@ def test_closed_checks_conn end # assert_raise Stomp::Error::NoCurrentConnection do - m = @conn.receive + _ = @conn.receive end # assert_raise Stomp::Error::NoCurrentConnection do - m = @conn.poll + _ = @conn.poll end end @@ -225,7 +225,7 @@ def test_message_to_s conn_subscribe make_destination @conn.publish make_destination, "a\0" msg = @conn.receive - assert_match /^ "localhost"} assert_raise Stomp::Error::ProtocolErrorConnect do - conn = Stomp::Connection.open(user, passcode, host, port, false, 5, cha) + _ = Stomp::Connection.open(user, passcode, host, port, false, 5, cha) end # chb = {"accept-version" => "1.0"} assert_raise Stomp::Error::ProtocolErrorConnect do - conn = Stomp::Connection.open(user, passcode, host, port, false, 5, chb) + _ = Stomp::Connection.open(user, passcode, host, port, false, 5, chb) end end @@ -62,11 +62,11 @@ def test_conn_1p_0015 :max_reconnect_attempts => 10, } assert_raise Stomp::Error::ProtocolErrorConnect do - conn = Stomp::Connection.open(hash) + _ = Stomp::Connection.open(hash) end hash[:connect_headers] = {"accept-version" => "1.1"} assert_raise Stomp::Error::ProtocolErrorConnect do - conn = Stomp::Connection.open(hash) + _ = Stomp::Connection.open(hash) end end diff --git a/test/test_message.rb b/test/test_message.rb index ab4587f..2560b4a 100644 --- a/test/test_message.rb +++ b/test/test_message.rb @@ -104,49 +104,49 @@ def test_0030_kcode def test_0040_msg_create # assert_raise(Stomp::Error::InvalidFormat) { - aframe = Stomp::Message.new("junk", false) + _ = Stomp::Message.new("junk", false) } # assert_raise(Stomp::Error::InvalidFormat) { - aframe = Stomp::Message.new("command\njunk", false) + _ = Stomp::Message.new("command\njunk", false) } # assert_raise(Stomp::Error::InvalidFormat) { - aframe = Stomp::Message.new("command\nheaders\n\njunk", false) + _ = Stomp::Message.new("command\nheaders\n\njunk", false) } # assert_raise(Stomp::Error::InvalidServerCommand) { - aframe = Stomp::Message.new("junkcommand\nheaders\n\njunk\0\n\n", false) + _ = Stomp::Message.new("junkcommand\nheaders\n\njunk\0\n\n", false) } # assert_raise(Stomp::Error::InvalidFormat) { - aframe = Stomp::Message.new("ERROR\nbadheaders\n\njunk\0\n\n", false) + _ = Stomp::Message.new("ERROR\nbadheaders\n\njunk\0\n\n", false) } # assert_nothing_raised { - aframe = Stomp::Message.new("CONNECTED\nh1:val1\n\njunk\0\n", false) + _ = Stomp::Message.new("CONNECTED\nh1:val1\n\njunk\0\n", false) } # assert_nothing_raised { - aframe = Stomp::Message.new("MESSAGE\nh1:val1\n\njunk\0\n", false) + _ = Stomp::Message.new("MESSAGE\nh1:val1\n\njunk\0\n", false) } # assert_nothing_raised { - aframe = Stomp::Message.new("MESSAGE\nh2:val2\n\n\0", false) + _ = Stomp::Message.new("MESSAGE\nh2:val2\n\n\0", false) } # assert_nothing_raised { - aframe = Stomp::Message.new("RECEIPT\nh1:val1\n\njunk\0\n", false) + _ = Stomp::Message.new("RECEIPT\nh1:val1\n\njunk\0\n", false) } # assert_nothing_raised { - aframe = Stomp::Message.new("ERROR\nh1:val1\n\njunk\0\n", false) + _ = Stomp::Message.new("ERROR\nh1:val1\n\njunk\0\n", false) } end # Test multiple headers with the same key - def test_0050_mh_msg_create + def test_0050_mh_msg_create aframe = bframe = nil assert_nothing_raised { amsg = "MESSAGE\n" + @@ -173,7 +173,7 @@ def test_0050_mh_msg_create end # Test headers with empty key / value - def test_0060_hdr_ekv + def test_0060_hdr_ekv # amsg = "MESSAGE\n" + "h1:val1\n" + @@ -183,10 +183,10 @@ def test_0060_hdr_ekv "payload" + "\0\n" assert_raise Stomp::Error::ProtocolErrorEmptyHeaderKey do - aframe = Stomp::Message.new(amsg, false) + _ = Stomp::Message.new(amsg, false) end assert_raise Stomp::Error::ProtocolErrorEmptyHeaderKey do - aframe = Stomp::Message.new(amsg, true) + _ = Stomp::Message.new(amsg, true) end # amsg = "MESSAGE\n" + @@ -197,10 +197,10 @@ def test_0060_hdr_ekv "payload" + "\0\n" assert_raise Stomp::Error::ProtocolErrorEmptyHeaderValue do - aframe = Stomp::Message.new(amsg, false) + _ = Stomp::Message.new(amsg, false) end assert_nothing_raised { - aframe = Stomp::Message.new(amsg, true) + _ = Stomp::Message.new(amsg, true) } end From 8cb738fc0e0ce7434d9a285b3e627f59fa99e981 Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 6 May 2016 17:54:02 -0400 Subject: [PATCH 08/48] Eliminate more unused variable warnings. --- test/test_ssl.rb | 16 ++++++++-------- test/test_urlogin.rb | 4 +++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 204c55f..8a28de8 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -39,13 +39,13 @@ def test_ssl_0010_parms # Test using correct parameters. def test_ssl_0020_noraise assert_nothing_raised { - ssl_parms = Stomp::SSLParams.new(:cert_file => "dummy1", :key_file => "dummy2") + _ = Stomp::SSLParams.new(:cert_file => "dummy1", :key_file => "dummy2") } assert_nothing_raised { - ssl_parms = Stomp::SSLParams.new(:ts_files => "dummyts1") + _ = Stomp::SSLParams.new(:ts_files => "dummyts1") } assert_nothing_raised { - ssl_parms = Stomp::SSLParams.new(:ts_files => "dummyts1", + _ = Stomp::SSLParams.new(:ts_files => "dummyts1", :cert_file => "dummy1", :key_file => "dummy2") } end @@ -53,25 +53,25 @@ def test_ssl_0020_noraise # Test using incorrect / incomplete parameters. def test_ssl_0030_raise assert_raise(Stomp::Error::SSLClientParamsError) { - ssl_parms = Stomp::SSLParams.new(:cert_file => "dummy1") + _ = Stomp::SSLParams.new(:cert_file => "dummy1") } assert_raise(Stomp::Error::SSLClientParamsError) { - ssl_parms = Stomp::SSLParams.new(:key_file => "dummy2") + _ = Stomp::SSLParams.new(:key_file => "dummy2") } end # Test that :fsck works. def test_ssl_0040_fsck assert_raise(Stomp::Error::SSLNoCertFileError) { - ssl_parms = Stomp::SSLParams.new(:cert_file => "dummy1", + _ = Stomp::SSLParams.new(:cert_file => "dummy1", :key_file => "dummy2", :fsck => true) } assert_raise(Stomp::Error::SSLNoKeyFileError) { - ssl_parms = Stomp::SSLParams.new(:cert_file => __FILE__, + _ = Stomp::SSLParams.new(:cert_file => __FILE__, :key_file => "dummy2", :fsck => true) } assert_raise(Stomp::Error::SSLNoTruststoreFileError) { - ssl_parms = Stomp::SSLParams.new(:ts_files => "/tmp/not-likely-here.txt", + _ = Stomp::SSLParams.new(:ts_files => "/tmp/not-likely-here.txt", :fsck => true) } end diff --git a/test/test_urlogin.rb b/test/test_urlogin.rb index d653b12..cdd301c 100644 --- a/test/test_urlogin.rb +++ b/test/test_urlogin.rb @@ -49,6 +49,8 @@ def setup ] @badparms = "failover://(stomp://#{hostname}:#{portnum})?a=b&noequal" + + @client = nil end def teardown @@ -78,7 +80,7 @@ def test_0020_failover_urls() # test failover:// with bad parameters def test_0020_failover_badparms() assert_raise(Stomp::Error::MalformedFailoverOptionsError) { - c = Stomp::Client.new(@badparms) + _ = Stomp::Client.new(@badparms) } end From 6b8c8efee584f138bcbb3d8529a03c610550af01 Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 6 May 2016 19:31:36 -0400 Subject: [PATCH 09/48] Eliminate even more unused variable warnings. --- lib/connection/heartbeats.rb | 1 + lib/connection/netio.rb | 3 ++- lib/connection/utils.rb | 2 +- lib/stomp/connection.rb | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/connection/heartbeats.rb b/lib/connection/heartbeats.rb index ae350dd..986a8ef 100644 --- a/lib/connection/heartbeats.rb +++ b/lib/connection/heartbeats.rb @@ -253,6 +253,7 @@ def _reconn_prep_hb() end @socket = nil used_socket = socket() + return used_socket end end # class Connection diff --git a/lib/connection/netio.rb b/lib/connection/netio.rb index 27cb772..db975c6 100644 --- a/lib/connection/netio.rb +++ b/lib/connection/netio.rb @@ -49,7 +49,7 @@ def _receive(read_socket, connread = false) end until line =~ /^\s?\n$/ # Checks if it includes content_length header - content_length = message_header.match /content-length\s?:\s?(\d+)\s?\n/ + content_length = message_header.match(/content-length\s?:\s?(\d+)\s?\n/) message_body = '' # If content_length is present, read the specified amount of bytes @@ -127,6 +127,7 @@ def transmit(command, headers = {}, body = '') _transmit(used_socket, command, headers, body) return rescue Stomp::Error::MaxReconnectAttempts => e + _ = e raise rescue @failure = $! diff --git a/lib/connection/utils.rb b/lib/connection/utils.rb index cdb5dba..1e29319 100644 --- a/lib/connection/utils.rb +++ b/lib/connection/utils.rb @@ -251,7 +251,7 @@ def __old_receive() $stderr.print "\n" $stderr.print "es2_oldrecv: " + errstr $stderr.print "\n" - end + end # !!! This initiates a re-connect !!! _reconn_prep() diff --git a/lib/stomp/connection.rb b/lib/stomp/connection.rb index ae189b7..8504d09 100644 --- a/lib/stomp/connection.rb +++ b/lib/stomp/connection.rb @@ -111,6 +111,8 @@ def initialize(login = '', passcode = '', host = 'localhost', port = 61613, reli @hb_sent = true # Assumed at first @hbs = @hbr = false # Sending/Receiving heartbeats. Assume no for now. @jruby = false # Assumed at first + # Initialize some variables + @closed, @socket, @hhas10, @rt, @st = true, nil, false, nil, nil if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/ @jruby = true end From 666b1b1be85dc8e3e21b4ecac671a3931e10afcd Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 6 May 2016 19:49:09 -0400 Subject: [PATCH 10/48] Hopefully eliminate last of warnings. --- lib/client/utils.rb | 12 ++++++++++-- lib/stomp/constants.rb | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/client/utils.rb b/lib/client/utils.rb index e0b12cc..eea59f8 100644 --- a/lib/client/utils.rb +++ b/lib/client/utils.rb @@ -20,8 +20,11 @@ def parse_hash_params(params) end def parse_stomp_url(login) + original_verbose, $VERBOSE = $VERBOSE, nil # shut off warnings regexp = /^stomp:\/\/#{URL_REPAT}/ - return false unless url = regexp.match(login) + url = regexp.match(login) + $VERBOSE = original_verbose + return false unless url @parameters = { :reliable => false, :hosts => [ { :login => url[3] || "", @@ -34,7 +37,10 @@ def parse_stomp_url(login) # e.g. failover://(stomp://login1:passcode1@localhost:61616,stomp://login2:passcode2@remotehost:61617)?option1=param def parse_failover_url(login) rval = nil - if md = FAILOVER_REGEX.match(login) + original_verbose, $VERBOSE = $VERBOSE, nil # shut off warnings + md = FAILOVER_REGEX.match(login) + $VERBOSE = original_verbose + if md finhosts = parse_hosts(login) options = {} @@ -75,6 +81,7 @@ def set_subscription_id_if_missing(destination, headers) # Parse a stomp URL. def parse_hosts(url) hosts = [] + original_verbose, $VERBOSE = $VERBOSE, nil # shut off warnings host_match = /stomp(\+ssl)?:\/\/#{URL_REPAT}/ url.scan(host_match).each do |match| host = {} @@ -85,6 +92,7 @@ def parse_hosts(url) host[:port] = match[6].to_i hosts << host end + $VERBOSE = original_verbose hosts end diff --git a/lib/stomp/constants.rb b/lib/stomp/constants.rb index 10d783e..54d4602 100644 --- a/lib/stomp/constants.rb +++ b/lib/stomp/constants.rb @@ -175,6 +175,8 @@ module Stomp ["SRP-RSA-AES-256-CBC-SHA","TLSv1/SSLv3",256,256], ] + original_verbose, $VERBOSE = $VERBOSE, nil # try to shut off warnings + # stomp URL regex pattern, for e.g. login:passcode@host:port or host:port URL_REPAT = '((([\w~!@#$%^&*()\-+=.?:<>,.]*\w):([\w~!@#$%^&*()\-+=.?:<>,.]*))?@)?([\w\.\-]+):(\d+)' @@ -182,4 +184,6 @@ module Stomp #failover:(stomp+ssl://login1:passcode1@remotehost1:61612,stomp://login2:passcode2@remotehost2:61613) FAILOVER_REGEX = /^failover:(\/\/)?\(stomp(\+ssl)?:\/\/#{URL_REPAT}(,stomp(\+ssl)?:\/\/#{URL_REPAT})*\)(\?(.*))?$/ + $VERBOSE = original_verbose + end # Module Stomp From ed245de3630f80cd5433fe5776d2c404ac525139 Mon Sep 17 00:00:00 2001 From: gmallard Date: Sun, 8 May 2016 10:38:09 -0400 Subject: [PATCH 11/48] Correct test failure, broker on different host. --- lib/connection/netio.rb | 6 ++++-- test/test_urlogin.rb | 15 +++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/connection/netio.rb b/lib/connection/netio.rb index db975c6..262e877 100644 --- a/lib/connection/netio.rb +++ b/lib/connection/netio.rb @@ -200,6 +200,9 @@ def _wire_write(sock, data) # open_tcp_socket opens a TCP socket. def open_tcp_socket() + + ## $stderr.print("h: #{@host}, p: #{@port}\n") + tcp_socket = nil slog(:on_connecting, log_params) Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do @@ -378,7 +381,7 @@ def connect(used_socket) @disconnect_receipt = nil @session = @connection_frame.headers["session"] if @connection_frame # replay any subscriptions. - @subscriptions.each {|k,v| + @subscriptions.each {|k,v| _transmit(used_socket, Stomp::CMD_SUBSCRIBE, v) } end @@ -415,4 +418,3 @@ def _dump_ctx(ctx) end # class Connection end # module Stomp - diff --git a/test/test_urlogin.rb b/test/test_urlogin.rb index cdd301c..43940aa 100644 --- a/test/test_urlogin.rb +++ b/test/test_urlogin.rb @@ -14,12 +14,12 @@ =end class TestURLLogins < Test::Unit::TestCase include TestBase - + def setup hostname = host() portnum = port() sslpn = ssl_port() - @tdstomp = [ + @tdstomp = [ "stomp://guestl:guestp@#{hostname}:#{portnum}", "stomp://#{hostname}:#{portnum}", "stomp://@#{hostname}:#{portnum}", @@ -32,10 +32,10 @@ def setup "failover://(stomp://#{hostname}:#{portnum})?whatup=doc&coyote=kaboom", "failover://(stomp://#{hostname}:#{portnum})?whatup=doc", "failover://(stomp://#{hostname}:#{portnum})?whatup=doc&coyote=kaboom&randomize=true", - 'failover://(stomp://f@#$$%^&*()_+=o.o::b~!@#$%^&*()+-_=?:<>,.@@' + "localhost" + ":#{portnum}" + ")", - 'failover://(stomp://f@#$$%^&*()_+=o.o::b~!@#$%^&*()+-_=:<>,.@@' + "localhost" + ":#{portnum}" + ")", - 'failover://(stomp://f@#$$%^&*()_+=o.o::b~!@#$%^&*()+-_=?:<>,.@@' + "localhost" + ":#{portnum}" + ")?a=b", - 'failover://(stomp://f@#$$%^&*()_+=o.o::b~!@#$%^&*()+-_=:<>,.@@' + "localhost" + ":#{portnum}" + ")?c=d&e=f", + 'failover://(stomp://f@#$$%^&*()_+=o.o::b~!@#$%^&*()+-_=?:<>,.@@' + "#{hostname}" + ":#{portnum}" + ")", + 'failover://(stomp://f@#$$%^&*()_+=o.o::b~!@#$%^&*()+-_=:<>,.@@' + "#{hostname}" + ":#{portnum}" + ")", + 'failover://(stomp://f@#$$%^&*()_+=o.o::b~!@#$%^&*()+-_=?:<>,.@@' + "#{hostname}" + ":#{portnum}" + ")?a=b", + 'failover://(stomp://f@#$$%^&*()_+=o.o::b~!@#$%^&*()+-_=:<>,.@@' + "#{hostname}" + ":#{portnum}" + ")?c=d&e=f", "failover://(stomp://usera:passa@#{hostname}:#{portnum})", "failover://(stomp://usera:@#{hostname}:#{portnum})", "failover://(stomp://#{hostname}:#{portnum},stomp://#{hostname}:#{portnum})", @@ -49,7 +49,7 @@ def setup ] @badparms = "failover://(stomp://#{hostname}:#{portnum})?a=b&noequal" - + @client = nil end @@ -85,4 +85,3 @@ def test_0020_failover_badparms() end end unless ENV['STOMP_RABBIT'] - From 08efcd3a02ba4f1e1b58342d5f6f5c4b7163ef6e Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 13 May 2016 20:37:05 -0400 Subject: [PATCH 12/48] Initial ignore file for adhoc directory. --- adhoc/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 adhoc/.gitignore diff --git a/adhoc/.gitignore b/adhoc/.gitignore new file mode 100644 index 0000000..21d826d --- /dev/null +++ b/adhoc/.gitignore @@ -0,0 +1,4 @@ +# No html in this directory +*.html +*.htm + From 148993cbc101fc9d3abb0216cf11c118fc338e87 Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 13 May 2016 20:37:42 -0400 Subject: [PATCH 13/48] Initial README for the adhoc directory. --- adhoc/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 adhoc/README.md diff --git a/adhoc/README.md b/adhoc/README.md new file mode 100644 index 0000000..6431379 --- /dev/null +++ b/adhoc/README.md @@ -0,0 +1,8 @@ +# Adhoc Items For The Ruby stomp Gem # + +This directory will contain a variety of artifacts. + +It is envisioned that content will mostly be of interest to gem developers. +However gem clients may find items of interest here as well. + + From ed6df826b19c644b7d1caa2639d82a21ba32a23c Mon Sep 17 00:00:00 2001 From: gmallard Date: Sun, 15 May 2016 20:41:18 -0400 Subject: [PATCH 14/48] Very initial work on issue #121 analysis. --- adhoc/issue121_01.rb | 113 ++++++++++++++++++++++++++++++++++++ adhoc/stomp_adhoc_common.rb | 95 ++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 adhoc/issue121_01.rb create mode 100644 adhoc/stomp_adhoc_common.rb diff --git a/adhoc/issue121_01.rb b/adhoc/issue121_01.rb new file mode 100644 index 0000000..ef71279 --- /dev/null +++ b/adhoc/issue121_01.rb @@ -0,0 +1,113 @@ +# -*- encoding: utf-8 -*- + +require 'rubygems' if RUBY_VERSION < "1.9" +require 'stomp' + +# Focus on this gem's capabilities. +require 'memory_profiler' + +if Kernel.respond_to?(:require_relative) + require_relative("stomp_adhoc_common") +else + $LOAD_PATH << File.dirname(__FILE__) + require "stomp_adhoc_common" +end +include Stomp11Common + +# Initial testing around issue #121. + +class Issue121Examp01 + + attr_reader :client, :session + + # Initialize. + def initialize(topic = false) + @client, @session, @topic = nil, nil, topic + @nmsgs = nmsgs() + @queue = make_destination("issue121/test_01") + @id = "issue121_01" + @block = cli_block() + end # initialize + + # Startup + def start + # + client_hdrs = {"accept-version" => "1.1,1.2", + "host" => virt_host, + } + # + client_hash = { :hosts => [ + {:login => login(), :passcode => passcode(), :host => host(), :port => port()}, + ], + :connect_headers => client_hdrs, + } + # + @client = Stomp::Client.new(client_hash) + puts "START: Client Connect complete" + raise "START: Connection failed!!" unless @client.open? + raise "START: Unexpected protocol level!!" if @client.protocol() == Stomp::SPL_10 + cf = @client.connection_frame() + puts "START: Connection frame: #{cf}" + raise "START: Connect error!!: #{cf.body}" if @client.connection_frame().command == Stomp::CMD_ERROR + @session = @client.connection_frame().headers['session'] + puts "START: Queue/Topic Name: #{@queue}" + puts "START: Session: #{@session}" + end # start + + # + def shutdown + @client.close + puts "SHUT: Shutdown complete" + end # shutdown + + def publish + m = "Message: " + @nmsgs.times do |n| + mo = "#{m} #{n}" + puts mo + hs = {:session => @session} + if @block + @client.publish(@queue, + mo, + hs) {|m| + ip = m + puts "PUB: HAVE_RECEIPT: #{ip}" + } + else + @client.publish(@queue, mo, hs) + end + end # do @nmsgs + end # publish + + def subscribe + puts "SUB: Subscribe starts For: #{@queue}" + rmc, done = 0, false + sh = {:id => "#{@id}", :ack => "auto"} + @client.subscribe(@queue, sh) {|m| + rmc += 1 + rm = m + puts "SUB: HAVE_MESSAGE: #{rm}" + if rmc >= @nmsgs + done = true + Thread.done + puts "SUB: Subscribe is ending for #{@queue}" + end + } + while !done do + ts = rand(6) + ts = 1 if ts == 0 + break if done + end + puts "SUB: Receives Done For: #{@queue}" + end # subscribe + +end # class + +# +puts "BEG: Memory Profiler Version is: #{MemoryProfiler::VERSION}" +# +e = Issue121Examp01.new +e.start +e.publish +e.subscribe +e.shutdown diff --git a/adhoc/stomp_adhoc_common.rb b/adhoc/stomp_adhoc_common.rb new file mode 100644 index 0000000..ca89cc0 --- /dev/null +++ b/adhoc/stomp_adhoc_common.rb @@ -0,0 +1,95 @@ +# -*- encoding: utf-8 -*- + +# +# Common Stomp 1.1 code. +# +require "rubygems" if RUBY_VERSION < "1.9" +require "stomp" +# +module Stomp11Common + # Port Constants locally + STOMP_AMQ_PORT = ENV['STOMP_AMQ_PORT'] ? ENV['STOMP_AMQ_PORT'].to_i : 61613 + STOMP_APOLLO_PORT = ENV['STOMP_APOLLO_PORT'] ? ENV['STOMP_APOLLO_PORT'].to_i : 62613 + STOMP_ARTEMIS_PORT = ENV['STOMP_ARTEMIS_PORT'] ? ENV['STOMP_ARTEMIS_PORT'].to_i : 31613 + STOMP_SSNG_PORT = ENV['STOMP_SSNG_PORT'] ? ENV['STOMP_SSNG_PORT'].to_i : 51613 + STOMP_RMQ_PORT = ENV['STOMP_RMQ_PORT'] ? ENV['STOMP_RMQ_PORT'].to_i : 41613 + + # Vhost Constants + STOMP_RMQ_VHOST = ENV['STOMP_RMQ_VHOST'] || '/' + STOMP_VHOST = ENV['STOMP_VHOST'] || 'localhost' + + # Client Protocol List + STOMP_PROTOCOL = ENV['STOMP_PROTOCOL'] || "1.2" + + # User id + def login() + ENV['STOMP_USER'] || 'guest' + end + # Password + def passcode() + ENV['STOMP_PASSCODE'] || 'guest' + end + # Server host + def host() + ENV['STOMP_HOST'] || "localhost" # The connect host name + end + # Server port + def port() + if ENV['STOMP_AMQ'] + STOMP_AMQ_PORT + elsif ENV['STOMP_APOLLO'] + STOMP_APOLLO_PORT + elsif ENV['STOMP_RMQ'] + STOMP_RMQ_PORT + elsif ENV['STOMP_SSNG'] + STOMP_SSNG_PORT + elsif ENV['STOMP_PORT'] + ENV['STOMP_PORT'].to_i + else + 61613 # The default ActiveMQ stomp listener port + end + end + # Required vhost name + def virt_host() + if ENV['STOMP_RMQ'] + STOMP_RMQ_VHOST + else + STOMP_VHOST + end + end + # Create a 1.1 commection + def get_connection() + conn_hdrs = {"accept-version" => STOMP_PROTOCOL, + "host" => virt_host(), # the vhost + } + conn_hash = { :hosts => [ + {:login => login(), :passcode => passcode(), :host => host(), :port => port()}, + ], + :connect_headers => conn_hdrs, + } + conn = Stomp::Connection.new(conn_hash) + end + + # Number of messages + def nmsgs() + (ENV['STOMP_NMSGS'] || 1).to_i # Number of messages + end + + # Queue / Topic Name + def make_destination(right_part = nil, topic = false) + if ENV['STOMP_DOTQUEUE'] + right_part.gsub!('/', '.') + end + if topic + "/topic/#{right_part}" + else + "/queue/#{right_part}" + end + end + + # True if client should supply a receipt block on 'publish' + def cli_block() + ENV['STOMP_CLI_BLOCK'] + end + +end # module From 9a6cb149230153eb4df215797212a337c96fa2cc Mon Sep 17 00:00:00 2001 From: gmallard Date: Mon, 16 May 2016 08:50:31 -0400 Subject: [PATCH 15/48] First real memory profiling: - This uses the 'memory-profiler' gem. And not: - The 'memory_profiler' gem. That is TBD. --- adhoc/issue121_01.rb | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/adhoc/issue121_01.rb b/adhoc/issue121_01.rb index ef71279..b80c634 100644 --- a/adhoc/issue121_01.rb +++ b/adhoc/issue121_01.rb @@ -4,7 +4,8 @@ require 'stomp' # Focus on this gem's capabilities. -require 'memory_profiler' +# require 'memory_profiler' +require 'memory-profiler' if Kernel.respond_to?(:require_relative) require_relative("stomp_adhoc_common") @@ -47,7 +48,7 @@ def start raise "START: Connection failed!!" unless @client.open? raise "START: Unexpected protocol level!!" if @client.protocol() == Stomp::SPL_10 cf = @client.connection_frame() - puts "START: Connection frame: #{cf}" + puts "START: Connection frame\n#{cf}" raise "START: Connect error!!: #{cf.body}" if @client.connection_frame().command == Stomp::CMD_ERROR @session = @client.connection_frame().headers['session'] puts "START: Queue/Topic Name: #{@queue}" @@ -71,7 +72,7 @@ def publish mo, hs) {|m| ip = m - puts "PUB: HAVE_RECEIPT: #{ip}" + puts "PUB: HAVE_RECEIPT:\n#{ip}" } else @client.publish(@queue, mo, hs) @@ -86,7 +87,7 @@ def subscribe @client.subscribe(@queue, sh) {|m| rmc += 1 rm = m - puts "SUB: HAVE_MESSAGE: #{rm}" + puts "SUB: HAVE_MESSAGE:\n#{rm}" if rmc >= @nmsgs done = true Thread.done @@ -104,10 +105,33 @@ def subscribe end # class # -puts "BEG: Memory Profiler Version is: #{MemoryProfiler::VERSION}" +# puts "BEG: Memory Profiler Version is: #{MemoryProfiler::VERSION}" +MemoryProfiler::start_daemon( :limit=>5, :delay=>10, :marshal_size=>true, :sort_by=>:absdelta ) # +=begin +5.times do |i| + blah = Hash.new([]) + rpt = MemoryProfiler.start( :limit=>10 ) do + 100.times{ blah[1] << 'aaaaa' } + 1000.times{ blah[2] << 'bbbbb' } + end + puts "Starting 7 second stagger, time: #{i}" + puts MemoryProfiler.format(rpt) + sleep 7 +end +=end + e = Issue121Examp01.new -e.start -e.publish -e.subscribe -e.shutdown +5.times do |i| + rpt = MemoryProfiler.start( :limit=>10 ) do + # e = Issue121Examp01.new + e.start + e.publish + e.subscribe + e.shutdown + end + puts MemoryProfiler.format(rpt) + sleep 1 +end + +MemoryProfiler::stop_daemon From c017b0a857f838637037932628085b30fe5442d4 Mon Sep 17 00:00:00 2001 From: gmallard Date: Mon, 23 May 2016 15:11:49 -0400 Subject: [PATCH 16/48] Add first cut at a message payhload generator. --- adhoc/payload_generator.rb | 34 +++++++++++++++++++++++ adhoc/payload_generator_adhoctest.rb | 41 ++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 adhoc/payload_generator.rb create mode 100644 adhoc/payload_generator_adhoctest.rb diff --git a/adhoc/payload_generator.rb b/adhoc/payload_generator.rb new file mode 100644 index 0000000..02614d1 --- /dev/null +++ b/adhoc/payload_generator.rb @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- + +class PayloadGenerator + + private + + @@BSTRING = "" + @@BSTRLEN = 0 + + public + + def self.initialize(min = 1, max = 4096) + srand() + # + @@min, @@max = min, max + if @@min > @@max + @@min, @@max = @@max, @@min + warn "Swapping min and max values" + end + # + @@BSTRING = "9" * @@max + @@BSTRLEN = @@BSTRING + nil + end # of initialize + + def self.payload + i = rand(@@max - @@min) + i = 1 if i == 0 + i += @@min + # puts "DBI: #{i}" + @@BSTRING.byteslice(0, i) + end + +end # of class diff --git a/adhoc/payload_generator_adhoctest.rb b/adhoc/payload_generator_adhoctest.rb new file mode 100644 index 0000000..1396081 --- /dev/null +++ b/adhoc/payload_generator_adhoctest.rb @@ -0,0 +1,41 @@ +# -*- encoding: utf-8 -*- +if Kernel.respond_to?(:require_relative) + require_relative("payload_generator") +else + $LOAD_PATH << File.dirname(__FILE__) + require "payload_generator" +end +# +cmin, cmax = 1292, 67782 +ffmts = "%16.6f" +# +PayloadGenerator::initialize(min= cmin, max= cmax) + +to, nmts, nts, umps = 0.0, Time.now.to_f, 100, 5.6 +# p [ "nmts", nmts ] +tslt = 1.0 / umps +# p [ "tslt", tslt ] +nts.times do |i| + ns = PayloadGenerator::payload() + to += ns.bytesize + # puts "t: #{i+1}, len: #{ns.bytesize}, tslt: #{tslt}" + sleep(tslt) + # puts "Done sleep!" +end +# +te = Time.now.to_f +# p [ "te", te ] +et = te - nmts +avgsz = to / nts +mps = nts.to_f / et +# +fet = sprintf(ffmts, et) +favgsz = sprintf(ffmts, avgsz) +fmps = sprintf(ffmts, mps) +# +puts "=" * 48 +puts "\tNumber of payloads generated: #{nts}" +puts "\tMin Length: #{cmin}, Max Length: #{cmax}" +puts "\tAVG_SIZE: #{favgsz}, ELAPS_SEC: #{fet}(seconds)" +puts "\tNMSGS_PER_SEC: #{fmps}" +# From 60c8e137844f396b38bf3907abf9eda631b88ae9 Mon Sep 17 00:00:00 2001 From: gmallard Date: Mon, 23 May 2016 15:12:52 -0400 Subject: [PATCH 17/48] Update ignore list. --- adhoc/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/adhoc/.gitignore b/adhoc/.gitignore index 21d826d..4b1c96b 100644 --- a/adhoc/.gitignore +++ b/adhoc/.gitignore @@ -1,4 +1,7 @@ # No html in this directory *.html *.htm +# Typical backup files +*~ +*.bak From 213f692b5aca2aaf65647a6f5f8aac785b67af0b Mon Sep 17 00:00:00 2001 From: gmallard Date: Mon, 23 May 2016 15:13:34 -0400 Subject: [PATCH 18/48] Cleanup/remove extraneous comments. --- adhoc/issue121_01.rb | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/adhoc/issue121_01.rb b/adhoc/issue121_01.rb index b80c634..7bbfa92 100644 --- a/adhoc/issue121_01.rb +++ b/adhoc/issue121_01.rb @@ -61,6 +61,7 @@ def shutdown puts "SHUT: Shutdown complete" end # shutdown + # pub def publish m = "Message: " @nmsgs.times do |n| @@ -80,6 +81,7 @@ def publish end # do @nmsgs end # publish + # sub def subscribe puts "SUB: Subscribe starts For: #{@queue}" rmc, done = 0, false @@ -108,19 +110,6 @@ def subscribe # puts "BEG: Memory Profiler Version is: #{MemoryProfiler::VERSION}" MemoryProfiler::start_daemon( :limit=>5, :delay=>10, :marshal_size=>true, :sort_by=>:absdelta ) # -=begin -5.times do |i| - blah = Hash.new([]) - rpt = MemoryProfiler.start( :limit=>10 ) do - 100.times{ blah[1] << 'aaaaa' } - 1000.times{ blah[2] << 'bbbbb' } - end - puts "Starting 7 second stagger, time: #{i}" - puts MemoryProfiler.format(rpt) - sleep 7 -end -=end - e = Issue121Examp01.new 5.times do |i| rpt = MemoryProfiler.start( :limit=>10 ) do @@ -133,5 +122,5 @@ def subscribe puts MemoryProfiler.format(rpt) sleep 1 end - +# MemoryProfiler::stop_daemon From d5bc3a203ae4ba81e186917d1618e1b565c3f5d6 Mon Sep 17 00:00:00 2001 From: gmallard Date: Mon, 23 May 2016 20:35:01 -0400 Subject: [PATCH 19/48] Remove unused and incorrect code. --- adhoc/payload_generator.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/adhoc/payload_generator.rb b/adhoc/payload_generator.rb index 02614d1..8e1dd9c 100644 --- a/adhoc/payload_generator.rb +++ b/adhoc/payload_generator.rb @@ -5,7 +5,6 @@ class PayloadGenerator private @@BSTRING = "" - @@BSTRLEN = 0 public @@ -19,7 +18,6 @@ def self.initialize(min = 1, max = 4096) end # @@BSTRING = "9" * @@max - @@BSTRLEN = @@BSTRING nil end # of initialize From 9353be991db57080e1f25344f706e9ff4d076a02 Mon Sep 17 00:00:00 2001 From: gmallard Date: Mon, 23 May 2016 20:36:35 -0400 Subject: [PATCH 20/48] Initial cut at part 02 of testing. --- adhoc/issue121_02.rb | 118 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 adhoc/issue121_02.rb diff --git a/adhoc/issue121_02.rb b/adhoc/issue121_02.rb new file mode 100644 index 0000000..b9529dd --- /dev/null +++ b/adhoc/issue121_02.rb @@ -0,0 +1,118 @@ +# -*- encoding: utf-8 -*- + +require 'rubygems' if RUBY_VERSION < "1.9" +require 'stomp' + +# Focus on this gem's capabilities. +# require 'memory_profiler' +require 'memory-profiler' + +if Kernel.respond_to?(:require_relative) + require_relative("stomp_adhoc_common") + require_relative("payload_generator") +else + $LOAD_PATH << File.dirname(__FILE__) + require "stomp_adhoc_common" + require("payload_generator") +end +include Stomp11Common + +# Round 2 of testing around issue #121. + +class Issue121Examp02 + + attr_reader :client, :session + + # Initialize. + def initialize(topic = false) + @client, @session, @topic = nil, nil, topic + @nmsgs = nmsgs() + @queue = make_destination("issue121/test_02") + @id = "issue121_02" + @block = cli_block() + # + cmin, cmax = 1292, 67782 # From the issue discussion + PayloadGenerator::initialize(min= cmin, max= cmax) + end # initialize + + # Startup + def start + # + client_hdrs = {"accept-version" => "1.1,1.2", + "host" => virt_host, + } + # + client_hash = { :hosts => [ + {:login => login(), :passcode => passcode(), :host => host(), :port => port()}, + ], + :connect_headers => client_hdrs, + } + # + @client = Stomp::Client.new(client_hash) + puts "START: Client Connect complete" + raise "START: Connection failed!!" unless @client.open? + raise "START: Unexpected protocol level!!" if @client.protocol() == Stomp::SPL_10 + cf = @client.connection_frame() + puts "START: Connection frame\n#{cf}" + raise "START: Connect error!!: #{cf.body}" if @client.connection_frame().command == Stomp::CMD_ERROR + @session = @client.connection_frame().headers['session'] + puts "START: Queue/Topic Name: #{@queue}" + puts "START: Session: #{@session}" + puts "START: NMSGS: #{@nmsgs}" + puts "START: BLOCK: #{@block}" + end # start + + # + def shutdown + @client.close + puts "SHUT: Shutdown complete" + end # shutdown + + # pub + def publish + m = "Message: " + nm = 0 + @nmsgs.times do |n| + nm += 1 + puts "PUB: NEXT MESSAGE NUMBER: #{nm}" + p [ "nilcheck1", !@block.nil?, @block ] + mo = PayloadGenerator::payload() + p [ "nilcheck2", !@block.nil?, @block ] + hs = {:session => @session} + p [ "nilcheck3", !@block.nil?, @block ] + if !@block.nil? + p [ "good" ] + @client.publish(@queue, + mo, + hs) {|m| + ip = m + puts "PUB: HAVE_RECEIPT:\n#{ip}" + } + else + p [ "bad" ] + @client.publish(@queue, mo, hs) + end + end # do @nmsgs + end # publish + +end # class + +# +# :limit => is max number of classes to report on +MemoryProfiler::start_daemon( :limit=>10, :delay=>10, :marshal_size=>true, :sort_by=>:absdelta ) +# +e = Issue121Examp02.new +1.times do |i| + rpt = MemoryProfiler.start( :limit=> 10 ) do + # e = Issue121Examp02.new + e.start + e.publish + # No subscribes here, just publish + # See discussion in issue #121 + e.shutdown + end + puts MemoryProfiler.format(rpt) + sleep 1 +end +# +MemoryProfiler::stop_daemon From 892f9e3611c21835eae3b885d14d1bdab7f387bc Mon Sep 17 00:00:00 2001 From: gmallard Date: Mon, 23 May 2016 22:52:12 -0400 Subject: [PATCH 21/48] Attempt to homogenize examples 01 and 02. --- adhoc/issue121_01.rb | 30 +++++++++++++++++------------- adhoc/issue121_02.rb | 30 ++++++++++++++++-------------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/adhoc/issue121_01.rb b/adhoc/issue121_01.rb index 7bbfa92..0791c13 100644 --- a/adhoc/issue121_01.rb +++ b/adhoc/issue121_01.rb @@ -53,6 +53,8 @@ def start @session = @client.connection_frame().headers['session'] puts "START: Queue/Topic Name: #{@queue}" puts "START: Session: #{@session}" + puts "START: Block: #{@block}" + $stdout.flush end # start # @@ -64,21 +66,28 @@ def shutdown # pub def publish m = "Message: " + nm = 0 @nmsgs.times do |n| + nm += 1 + puts "PUB: NEXT MESSAGE NUMBER: #{nm}" mo = "#{m} #{n}" - puts mo + puts "PUB: PAYLOAD: #{mo}" hs = {:session => @session} - if @block + if @block + ip = false @client.publish(@queue, mo, hs) {|m| + puts "PUB: HAVE_RECEIPT:\nID: #{m.headers['receipt-id']}" ip = m - puts "PUB: HAVE_RECEIPT:\n#{ip}" } + sleep 0.01 until ip else @client.publish(@queue, mo, hs) - end - end # do @nmsgs + end # if @block + + end # @nmsgs.times do + end # publish # sub @@ -91,16 +100,12 @@ def subscribe rm = m puts "SUB: HAVE_MESSAGE:\n#{rm}" if rmc >= @nmsgs + puts "SUB: Subscribe is ending for #{@queue}" done = true Thread.done - puts "SUB: Subscribe is ending for #{@queue}" end } - while !done do - ts = rand(6) - ts = 1 if ts == 0 - break if done - end + sleep 0.01 until done puts "SUB: Receives Done For: #{@queue}" end # subscribe @@ -110,10 +115,9 @@ def subscribe # puts "BEG: Memory Profiler Version is: #{MemoryProfiler::VERSION}" MemoryProfiler::start_daemon( :limit=>5, :delay=>10, :marshal_size=>true, :sort_by=>:absdelta ) # -e = Issue121Examp01.new 5.times do |i| rpt = MemoryProfiler.start( :limit=>10 ) do - # e = Issue121Examp01.new + e = Issue121Examp01.new e.start e.publish e.subscribe diff --git a/adhoc/issue121_02.rb b/adhoc/issue121_02.rb index b9529dd..8dc52be 100644 --- a/adhoc/issue121_02.rb +++ b/adhoc/issue121_02.rb @@ -59,7 +59,8 @@ def start puts "START: Queue/Topic Name: #{@queue}" puts "START: Session: #{@session}" puts "START: NMSGS: #{@nmsgs}" - puts "START: BLOCK: #{@block}" + puts "START: Block: #{@block}" + $stdout.flush end # start # @@ -72,39 +73,40 @@ def shutdown def publish m = "Message: " nm = 0 + @nmsgs.times do |n| nm += 1 puts "PUB: NEXT MESSAGE NUMBER: #{nm}" - p [ "nilcheck1", !@block.nil?, @block ] mo = PayloadGenerator::payload() - p [ "nilcheck2", !@block.nil?, @block ] hs = {:session => @session} - p [ "nilcheck3", !@block.nil?, @block ] - if !@block.nil? - p [ "good" ] + + if @block + ip = false @client.publish(@queue, mo, hs) {|m| + puts "PUB: HAVE_RECEIPT:\nID: #{m.headers['receipt-id']}" ip = m - puts "PUB: HAVE_RECEIPT:\n#{ip}" + Thread::done } + sleep 0.01 until ip else - p [ "bad" ] @client.publish(@queue, mo, hs) - end - end # do @nmsgs + end # if @block + + end # @nmsgs.times do + end # publish end # class # # :limit => is max number of classes to report on -MemoryProfiler::start_daemon( :limit=>10, :delay=>10, :marshal_size=>true, :sort_by=>:absdelta ) +MemoryProfiler::start_daemon( :limit=>5, :delay=>10, :marshal_size=>true, :sort_by=>:absdelta ) # -e = Issue121Examp02.new -1.times do |i| +5.times do |i| rpt = MemoryProfiler.start( :limit=> 10 ) do - # e = Issue121Examp02.new + e = Issue121Examp02.new e.start e.publish # No subscribes here, just publish From 587f06cd36add45c843dbde1c817e423340d30e0 Mon Sep 17 00:00:00 2001 From: gmallard Date: Tue, 24 May 2016 18:17:21 -0400 Subject: [PATCH 22/48] Enhance reporting by sender. --- adhoc/issue121_02.rb | 47 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/adhoc/issue121_02.rb b/adhoc/issue121_02.rb index 8dc52be..4ff9567 100644 --- a/adhoc/issue121_02.rb +++ b/adhoc/issue121_02.rb @@ -31,8 +31,13 @@ def initialize(topic = false) @id = "issue121_02" @block = cli_block() # - cmin, cmax = 1292, 67782 # From the issue discussion - PayloadGenerator::initialize(min= cmin, max= cmax) + @cmin, @cmax = 1292, 67782 # From the issue discussion + PayloadGenerator::initialize(min= @cmin, max= @cmax) + @ffmts = "%16.6f" + # + mps = 5.6 # see issue discussion + @to, @nmts, @nts, @umps = 0.0, Time.now.to_f, @nmsgs, mps + @tslt = 1.0 / @umps end # initialize # Startup @@ -60,13 +65,34 @@ def start puts "START: Session: #{@session}" puts "START: NMSGS: #{@nmsgs}" puts "START: Block: #{@block}" + puts "START: Wanted Messages Per Second: #{@umps}" + puts "START: Sleep Time: #{@tslt}" $stdout.flush end # start # def shutdown @client.close + # + te = Time.now.to_f + et = te - @nmts + avgsz = @to / @nts + mps = @nts.to_f / et + # + fet = sprintf(@ffmts, et) + favgsz = sprintf(@ffmts, avgsz) + fmps = sprintf(@ffmts, mps) + # + sep = "=" * 72 + puts sep + puts "\tNumber of payloads generated: #{@nts}" + puts "\tMin Length: #{@cmin}, Max Length: #{@cmax}" + puts "\tAVG_SIZE: #{favgsz}, ELAPS_SEC: #{fet}(seconds)" + puts "\tNMSGS_PER_SEC: #{fmps}" + puts sep + # puts "SHUT: Shutdown complete" + $stdout.flush end # shutdown # pub @@ -76,8 +102,9 @@ def publish @nmsgs.times do |n| nm += 1 - puts "PUB: NEXT MESSAGE NUMBER: #{nm}" + puts "PUB: NEXT MESSAGE NUMBER: #{nm}"; $stdout.flush mo = PayloadGenerator::payload() + @to += mo.bytesize() hs = {:session => @session} if @block @@ -86,26 +113,32 @@ def publish mo, hs) {|m| puts "PUB: HAVE_RECEIPT:\nID: #{m.headers['receipt-id']}" + $stdout.flush ip = m - Thread::done } sleep 0.01 until ip else @client.publish(@queue, mo, hs) end # if @block + puts "PUB: start user sleep" + sleep @tslt # see issue discussion + puts "PUB: end user sleep" + $stdout.flush end # @nmsgs.times do + puts "PUB: end of publish" + $stdout.flush end # publish end # class # # :limit => is max number of classes to report on -MemoryProfiler::start_daemon( :limit=>5, :delay=>10, :marshal_size=>true, :sort_by=>:absdelta ) +MemoryProfiler::start_daemon( :limit=>25, :delay=>10, :marshal_size=>true, :sort_by=>:absdelta ) # -5.times do |i| - rpt = MemoryProfiler.start( :limit=> 10 ) do +1.times do |i| + rpt = MemoryProfiler.start( :limit=> 25 ) do e = Issue121Examp02.new e.start e.publish From 7a179d891de65ee4854ea71a62b7394312fba832 Mon Sep 17 00:00:00 2001 From: gmallard Date: Tue, 24 May 2016 18:20:54 -0400 Subject: [PATCH 23/48] Use different memory profiler. --- adhoc/issue121_03.rb | 153 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 adhoc/issue121_03.rb diff --git a/adhoc/issue121_03.rb b/adhoc/issue121_03.rb new file mode 100644 index 0000000..c2b9bfc --- /dev/null +++ b/adhoc/issue121_03.rb @@ -0,0 +1,153 @@ +# -*- encoding: utf-8 -*- + +require 'rubygems' if RUBY_VERSION < "1.9" +require 'stomp' + +# Focus on this gem's capabilities. +require 'memory_profiler' +# require 'memory-profiler' + +if Kernel.respond_to?(:require_relative) + require_relative("stomp_adhoc_common") + require_relative("payload_generator") +else + $LOAD_PATH << File.dirname(__FILE__) + require "stomp_adhoc_common" + require("payload_generator") +end +include Stomp11Common + +# Round 3 of testing around issue #121. +# Different memory profiler gem. + +class Issue121Examp03 + + attr_reader :client, :session + + # Initialize. + def initialize(topic = false) + @client, @session, @topic = nil, nil, topic + @nmsgs = nmsgs() + @queue = make_destination("issue121/test_03") + @id = "issue121_03" + @block = cli_block() + # + @cmin, @cmax = 1292, 67782 # From the issue discussion + PayloadGenerator::initialize(min= @cmin, max= @cmax) + @ffmts = "%16.6f" + # + mps = 5.6 # see issue discussion + @to, @nmts, @nts, @umps = 0.0, Time.now.to_f, @nmsgs, mps + @tslt = 1.0 / @umps + end # initialize + + # Startup + def start + # + client_hdrs = {"accept-version" => "1.1,1.2", + "host" => virt_host, + } + # + client_hash = { :hosts => [ + {:login => login(), :passcode => passcode(), :host => host(), :port => port()}, + ], + :connect_headers => client_hdrs, + } + # + @client = Stomp::Client.new(client_hash) + puts "START: Client Connect complete" + raise "START: Connection failed!!" unless @client.open? + raise "START: Unexpected protocol level!!" if @client.protocol() == Stomp::SPL_10 + cf = @client.connection_frame() + puts "START: Connection frame\n#{cf}" + raise "START: Connect error!!: #{cf.body}" if @client.connection_frame().command == Stomp::CMD_ERROR + @session = @client.connection_frame().headers['session'] + puts "START: Queue/Topic Name: #{@queue}" + puts "START: Session: #{@session}" + puts "START: NMSGS: #{@nmsgs}" + puts "START: Block: #{@block}" + puts "START: Wanted Messages Per Second: #{@umps}" + puts "START: Sleep Time: #{@tslt}" + $stdout.flush + end # start + + # + def shutdown + @client.close + # + te = Time.now.to_f + et = te - @nmts + avgsz = @to / @nts + mps = @nts.to_f / et + # + fet = sprintf(@ffmts, et) + favgsz = sprintf(@ffmts, avgsz) + fmps = sprintf(@ffmts, mps) + # + sep = "=" * 72 + puts sep + puts "\tNumber of payloads generated: #{@nts}" + puts "\tMin Length: #{@cmin}, Max Length: #{@cmax}" + puts "\tAVG_SIZE: #{favgsz}, ELAPS_SEC: #{fet}(seconds)" + puts "\tNMSGS_PER_SEC: #{fmps}" + puts sep + # + puts "SHUT: Shutdown complete" + $stdout.flush + end # shutdown + + # pub + def publish + m = "Message: " + nm = 0 + + @nmsgs.times do |n| + nm += 1 + puts "PUB: NEXT MESSAGE NUMBER: #{nm}"; $stdout.flush + mo = PayloadGenerator::payload() + @to += mo.bytesize() + hs = {:session => @session} + + if @block + ip = false + @client.publish(@queue, + mo, + hs) {|m| + puts "PUB: HAVE_RECEIPT:\nID: #{m.headers['receipt-id']}" + $stdout.flush + ip = m + } + sleep 0.01 until ip + else + @client.publish(@queue, mo, hs) + end # if @block + + puts "PUB: start user sleep" + sleep @tslt # see issue discussion + puts "PUB: end user sleep" + $stdout.flush + end # @nmsgs.times do + + puts "PUB: end of publish" + $stdout.flush + end # publish + +end # class + +# +1.times do |i| + rpt = MemoryProfiler.report do + e = Issue121Examp03.new + e.start + e.publish + # No subscribes here, just publish + # See discussion in issue #121 + e.shutdown + end + n = Time.now + nf = n.strftime("%Y%m%dT%H%M%S.%N%Z") + rpt.pretty_print(to_file: "/tmp/memory_profiler-ng-#{nf}" ) + # sleep 1 +end +# + From c8635e8af8e2a6ac4d6857f8fefd4a45b0744fc6 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 25 May 2016 10:17:38 -0400 Subject: [PATCH 24/48] Demo issue #121 using Stomp::Conection. --- adhoc/issue121_01_conn.rb | 156 ++++++++++++++++++++++++++++++++++++ adhoc/stomp_adhoc_common.rb | 4 + 2 files changed, 160 insertions(+) create mode 100644 adhoc/issue121_01_conn.rb diff --git a/adhoc/issue121_01_conn.rb b/adhoc/issue121_01_conn.rb new file mode 100644 index 0000000..8409c46 --- /dev/null +++ b/adhoc/issue121_01_conn.rb @@ -0,0 +1,156 @@ +# -*- encoding: utf-8 -*- + +require 'rubygems' if RUBY_VERSION < "1.9" +require 'stomp' + +# Focus on this gem's capabilities. +require 'memory_profiler' +# require 'memory-profiler' + +if Kernel.respond_to?(:require_relative) + require_relative("stomp_adhoc_common") + require_relative("payload_generator") +else + $LOAD_PATH << File.dirname(__FILE__) + require "stomp_adhoc_common" + require("payload_generator") +end +include Stomp11Common + +# Next of testing around issue #121. +# Different memory profiler gem. +# Use Stomp#connection to merely send + +class Issue121Examp01Conn + + attr_reader :connection, :session + + # Initialize. + def initialize(topic = false) + @connection, @session, @topic = nil, nil, topic + @nmsgs = nmsgs() + @queue = make_destination("issue121/test_01_conn") + @id = "issue121_01_conn" + @getreceipt = conn_receipt() + # + @cmin, @cmax = 1292, 67782 # From the issue discussion + PayloadGenerator::initialize(min= @cmin, max= @cmax) + @ffmts = "%16.6f" + # + mps = 5.6 # see issue discussion + @to, @nmts, @nts, @umps = 0.0, Time.now.to_f, @nmsgs, mps + @tslt = 1.0 / @umps + end # initialize + + # Startup + def start + # + connect_hdrs = {"accept-version" => "1.1,1.2", + "host" => virt_host, + } + # + connect_hash = { :hosts => [ + {:login => login(), :passcode => passcode(), :host => host(), :port => port()}, + ], + :connect_headers => connect_hdrs, + } + # + @connection = Stomp::Connection.new(connect_hash) + puts "START: Connection Connect complete" + raise "START: Connection failed!!" unless @connection.open? + raise "START: Unexpected protocol level!!" if @connection.protocol == Stomp::SPL_10 + cf = @connection.connection_frame + puts "START: Connection frame\n#{cf}" + raise "START: Connect error!!: #{cf.body}" if @connection.connection_frame.command == Stomp::CMD_ERROR + @session = @connection.connection_frame.headers['session'] + puts "START: Queue/Topic Name: #{@queue}" + puts "START: Session: #{@session}" + puts "START: NMSGS: #{@nmsgs}" + puts "START: Receipt: #{@getreceipt}" + puts "START: Wanted Messages Per Second: #{@umps}" + puts "START: Sleep Time: #{@tslt}" + $stdout.flush + end # start + + # + def shutdown + @connection.disconnect() + # + te = Time.now.to_f + et = te - @nmts + avgsz = @to / @nts + mps = @nts.to_f / et + # + fet = sprintf(@ffmts, et) + favgsz = sprintf(@ffmts, avgsz) + fmps = sprintf(@ffmts, mps) + # + sep = "=" * 72 + puts sep + puts "\tNumber of payloads generated: #{@nts}" + puts "\tMin Length: #{@cmin}, Max Length: #{@cmax}" + puts "\tAVG_SIZE: #{favgsz}, ELAPS_SEC: #{fet}(seconds)" + puts "\tNMSGS_PER_SEC: #{fmps}" + puts sep + # + puts "SHUT: Shutdown complete" + $stdout.flush + end # shutdown + + # + def msg_handler + m = "Message: " + nm = 0 + + @nmsgs.times do |n| + nm += 1 + puts "MSH: NEXT MESSAGE NUMBER: #{nm}"; $stdout.flush + mo = PayloadGenerator::payload() + @to += mo.bytesize() + + if @getreceipt + uuid = @connection.uuid() + puts "MSH: Receipt id wanted is #{uuid}" + hs = {:session => @session, :receipt => uuid} + else + hs = {:session => @session} + end + + # Move data out the door + @connection.publish(@queue, mo, hs) + + if @getreceipt + r = @connection.receive() + puts "MSH: received receipt, id is #{r.headers['receipt-id']}" + raise if uuid != r.headers['receipt-id'] + end + # + puts "MSH: start user sleep" + sleep @tslt # see issue discussion + puts "MSH: end user sleep" + $stdout.flush + end # @nmsgs.times do + + puts "MSH: end of msg_handler" + $stdout.flush + end # msg_handler + +end # class + +# +1.times do |i| + rpt = MemoryProfiler.report do + e = Issue121Examp01Conn.new + e.start + e.msg_handler + # No subscribes here, just msg_handler + # See discussion in issue #121 + e.shutdown + end + n = Time.now + nf = n.strftime("%Y%m%dT%H%M%S.%N%Z") + rpt.pretty_print(to_file: "/tmp/memory_profiler-ng-conn-#{nf}" ) + # sleep 1 +end +# + diff --git a/adhoc/stomp_adhoc_common.rb b/adhoc/stomp_adhoc_common.rb index ca89cc0..4f797dd 100644 --- a/adhoc/stomp_adhoc_common.rb +++ b/adhoc/stomp_adhoc_common.rb @@ -92,4 +92,8 @@ def cli_block() ENV['STOMP_CLI_BLOCK'] end + # True if connection should ask for a receipt + def conn_receipt() + ENV['STOMP_RECEIPT'] + end end # module From 229167aaeda940b0b56c300c51e00b903c4945b6 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 25 May 2016 11:32:02 -0400 Subject: [PATCH 25/48] Update README for adhoc directory. --- adhoc/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/adhoc/README.md b/adhoc/README.md index 6431379..a476160 100644 --- a/adhoc/README.md +++ b/adhoc/README.md @@ -1,8 +1,16 @@ -# Adhoc Items For The Ruby stomp Gem # + + +# The Ruby stomp Gem - Adhoc Items # This directory will contain a variety of artifacts. It is envisioned that content will mostly be of interest to gem developers. However gem clients may find items of interest here as well. +## Issue 121 ## + +Much of the initial work in this directory has focused on +recreating / confirming the high memory use described in +[issue 121](https://github.com/stompgem/stomp/issues/121). +Resolution of that issue is TDB (2016.05.25). From ab8d59328ed14c5def6096e46acb8570416f900c Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 25 May 2016 20:26:31 -0400 Subject: [PATCH 26/48] Rename CHANGELOG to markdown format. --- CHANGELOG.rdoc => CHANGELOG.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CHANGELOG.rdoc => CHANGELOG.md (100%) diff --git a/CHANGELOG.rdoc b/CHANGELOG.md similarity index 100% rename from CHANGELOG.rdoc rename to CHANGELOG.md From 6b7bacd1d55650c8f859aa7b6a57f18ae18f485d Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 25 May 2016 21:21:23 -0400 Subject: [PATCH 27/48] Reformat CHANGELOG. --- CHANGELOG.md | 88 +++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bba23fd..b7066ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -== 1.3.5 20160302 +# Stomp Gem Change Log + +## 1.3.5 20160302 * Add AMQ specific durable topic example. * Output error to stderr only in logger is undefined. @@ -9,21 +11,21 @@ * On misc_err, make error messages more readable. * Attempt to support both Rspec 2.14.1+ and 3.x. -== 1.3.4 20141202 +## 1.3.4 20141202 * Change :start_timeout default to 0 (might break some clients) (#98). * Allow user set of SSLContext options (#105). * Allow user set of parm in SSLContext.new(parm) (#105). -== 1.3.3 20140810 +## 1.3.3 20140810 * Do not attempt to write empty message bodies. * Explicity close ssl socket on connection timeout. * Fix incorrect behavior for empty header keys (#93) -* Do not override explicit :reliable => false. +* Do not override explicit :reliable #> false. * Fix client fail-over fails (#98) -== 1.3.2 20131208 +## 1.3.2 20131208 * Anon tests assigned unique class name. * Fix TypeError on connect timeout with 1.8.x, 2.x. @@ -31,18 +33,18 @@ * start_timeout and tcp_nodelay parameters * SSL Fix, revert not setting default ciphers. * Copy hash params at init. -* Fix ssl => true for Ruby 1.9.x and 2.x. +* Fix ssl #> true for Ruby 1.9.x and 2.x. * Expanded list of STOMP default SSL ciphers: * Do not change caller's :hosts array * Issue #78, again. * Clean up logger interfacing. * Fixes from RSpec testing -== 1.3.1 20131002 +## 1.3.1 20131002 * Method calls to the logger object should check for that method first (#83) -== 1.3.0 20130930 +## 1.3.0 20130930 * ERROR frames now raise an exception in the Stomp::Client thread(#73, #81) * Allow anonymous connections (#75) @@ -52,26 +54,26 @@ * Read receipt ids are now UUIDs * Added a :start_timeout parameter -== 1.2.16 20130812 +## 1.2.16 20130812 * Stomp::Client's should expose connection's host params -== 1.2.15 20130809 +## 1.2.15 20130809 * Add user-specified timeout for initial CONNECTED/ERROR frame read. * Eliminate dup Timeout::timeout in ssl connect * Add license information to gemspec (#69) -== 1.2.14 20130819 +## 1.2.14 20130819 * Version bump (1.2.13 release had Stomp::Version of 1.1.12.) * Prevent dup subscription header on re-receive -== 1.2.13 20130817 +## 1.2.13 20130817 * Issue #68, Stomp::Client#unreceive max_redeliveries off-by-one error -== 1.2.12 20130811 +## 1.2.12 20130811 * Fix infinite loop when max reconn attempts is reached * Enhance JRuby support in tests @@ -83,20 +85,20 @@ * Issue #65, allow non-word characters in login and passcode using stomp:// * Issue #66, allow a single broker in a failover URL -== 1.2.11 20130728 +## 1.2.11 20130728 * Issue #60, timeout/hang under JRuby * More generally support JRuby use and testing * Issue #58, nil message in Client on AMQ shutdown * More robust RabbitMQ tests -== 1.2.10 20130708 +## 1.2.10 20130708 * Issue #57, reconnect delays not honored if erroneous headers * Support fail overs when heartbeat send/receive fails * Update callback logger example -== 1.2.9 20130328 +## 1.2.9 20130328 * Refactoring and documentation updates (glennr) * Fix test encoding for Ruby 2.0+ @@ -105,19 +107,19 @@ * Correctly honor :suppress_content_length with 1.1 (JP Hastings-Spital) * Fix reference to client.publish rather than client.send (JP Hastings-Spital) -== 1.2.8 20121228 +## 1.2.8 20121228 * Fix inverted encode / decode logic (fairly major 1.1+ bug) * Enhance codec tests * Enhance Stomp 1.1+ tests -== 1.2.7 20121102 +## 1.2.7 20121102 * Stomp 1.2 support (see http://stomp.github.com) * Reset reconnect_delay to default value upon successful reconnect * Enhance tests for Stomp 1.2 -== 1.2.6 20120913 +## 1.2.6 20120913 * Provide ability to eliminate checks for closed in protocol methods * Cover ssl.connect with connection timeout parameter @@ -125,7 +127,7 @@ * Remove methods that invoke __send__ * Move internal methods to 'private' -== 1.2.5 20120804 +## 1.2.5 20120804 * Issue #48 any forks with modifications will be affected! * Source code restructured into individual files @@ -136,7 +138,7 @@ * Include examples and tests in rdoc generated during install * Issue #47 socket is open during retries -== 1.2.4 20120625 +## 1.2.4 20120625 * Add ability for client to request flush on write to the connection (Issue #45) * Add ability for client to retrieve heartbeat intervals and counters @@ -144,7 +146,7 @@ * Enhance tests for heartbeats * Correct typos and clarify comments in many examples -== 1.2.3 20120616 +## 1.2.3 20120616 * Fix UnsupportedProtocol on connect to a 1.0 broker * Add Client#poll method @@ -156,17 +158,17 @@ * Use symbols, not strings for all header keys * Add IPV6 to IPV4 failover for dual homed systems when requested -== 1.2.2 20120324 +## 1.2.2 20120324 * Major performance improvement for read of messages without content-length header * Correct Stomp 1.1 failing test * Update sample code to reflect removal of 'send' * Add on_ssl_connectfail callback and allow clients to signal quit from the callback * Ensure that SSL certificates and SSL related files exist and are readable -* Allow SSL file checks before connect using SSLParams.new(:fsck => true, ...) +* Allow SSL file checks before connect using SSLParams.new(:fsck #> true, ...) * Correct a test for Windows compatibility -== 1.2.1 20120313 +## 1.2.1 20120313 * Robust SSL certificate support. See examples and: https://github.com/stompgem/stomp/wiki/extended-ssl-overview * Really remove the deprecated #send methods @@ -175,7 +177,7 @@ * Add reconnection attempts to callback logging. * Add SSL specific connection information to callback logging. -== 1.2.0 20111214 +## 1.2.0 20111214 * Stomp 1.1 protocol support. A significant change. Please test existing 1.0 code well. See the examples directory for 1.1 examples. * Accept :reliable in a Stomp::Client connection hash @@ -185,14 +187,14 @@ * Fix subscription id in find_listener * Start to bootstrap STOMP 1.1 support -== 1.1.10 20111107 +## 1.1.10 20111107 * Fixes for JRuby support * Fix EOF error on disconnect * Refactoring and additional test * Set up tests for use of RabbitMQ -== 1.1.9 20110615 +## 1.1.9 20110615 * Support wildcard destinations * Handle subscribe with string or symbol ID @@ -203,7 +205,7 @@ * Add optional callback logging. See the examples install directory, files logexamp.rb and slogger.rb * Correct date stamps in this file -== 1.1.8 20110316 +## 1.1.8 20110316 * Set KEEPALIVE on connection socket options * Attempt to support JRuby more robustly (poll remains broken) @@ -214,23 +216,23 @@ * Allow connection to hosts with a - (dash) in the host name * Add limit parameter to thread joins -== 1.1.7 20110109 +## 1.1.7 20110109 * Binary parse of raw STOMP frame * Fix broken tests on Ruby 1.9.2 -== 1.1.6 20100610 +## 1.1.6 20100610 * Fixed multi-thread app hanging -== 1.1.5 20100317 +## 1.1.5 20100317 * Added publish method (send is now deprecated) * Changes on Rake File * Added original_destination header to unreceive * suppress content length header is send on the message for future handling (like unreceive) -== 1.1.4 20100121 +## 1.1.4 20100121 * Added unreceive message method that sends the message back to its queue or to the dead letter queue, depending on the :max_redeliveries option, similar to a13m one. @@ -245,13 +247,13 @@ * Added connection_frame accessor * Added disconnect receipt -== 1.1.3 20091124 +## 1.1.3 20091124 * Failover support * SSL support * Stomp::Connection and Stomp::Client accept a hash on their constructor -== 1.1 20090227 +## 1.1 20090227 * Ruby 1.9 Support * Add support for connect_headers, to control the CONNECT command. @@ -259,7 +261,7 @@ * Better test coverage * General code cleanup. -== 1.0.6 20080805 +## 1.0.6 20080805 * Whitespace cleanup * Refactored Rakefile and added stomp.gemspec for GitHub friendliness. @@ -271,33 +273,33 @@ * Created initial RSpec specs which stub/mock objects and should not require a running Stomp server instance. -== v1.0.5 20070201 +## v1.0.5 20070201 * better url parsing * git-svn-id: http://svn.codehaus.org/stomp/ruby/trunk@48 fd4e7336-3dff-0310-b68a-b6615a75f13b -== v1.0.4 20070115 +## v1.0.4 20070115 * Allow URL style connections descriptors * git-svn-id: http://svn.codehaus.org/stomp/ruby/trunk@44 fd4e7336-3dff-0310-b68a-b6615a75f13b -== v1.0.3 20070114 +## v1.0.3 20070114 * Additional fixes for reliable by Andrew Kuklewicz * git-svn-id: http://svn.codehaus.org/stomp/ruby/trunk@42 fd4e7336-3dff-0310-b68a-b6615a75f13b -== v1.0.2 20060922 +## v1.0.2 20060922 * Moving ruby so we can tag it ;-) * git-svn-id: http://svn.codehaus.org/stomp/ruby/trunk@37 fd4e7336-3dff-0310-b68a-b6615a75f13b -== v1.0.1 20051217 +## v1.0.1 20051217 * Increment version * git-svn-id: http://svn.codehaus.org/stomp/trunk/ruby@24 fd4e7336-3dff-0310-b68a-b6615a75f13b -== v1.0.0 20051015 +## v1.0.0 20051015 -* works in repl, getting messages in weird order or dupes in test, but unable to isolate so far =( +* works in repl, getting messages in weird order or dupes in test, but unable to isolate so far #( * git-svn-id: http://svn.codehaus.org/stomp/trunk/ruby@20 fd4e7336-3dff-0310-b68a-b6615a75f13b From c4592ab19f210edf064b1f6bd069bec38af86cb2 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 25 May 2016 21:22:24 -0400 Subject: [PATCH 28/48] Tweak README after looking at rdoc output. --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8f0cad0..7d9dfb7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ An implementation of the Stomp protocol for Ruby. See: * [STOMP 1.0, 1.1, and 1.2] (http://stomp.github.com/index.html) -## Hash Login Example Usage (this is the recommended login technique): +## Hash Login Example Usage (**this is the recommended login technique**): ```ruby hash = { @@ -47,10 +47,10 @@ An implementation of the Stomp protocol for Ruby. See: :sslctx_newparm => nil, # Param for SSLContext.new } - # for client + # for a client client = Stomp::Client.new(hash) - # for connection + # for a connection connection = Stomp::Connection.new(hash) ``` @@ -66,10 +66,9 @@ An implementation of the Stomp protocol for Ruby. See: ### Stomp URL Usage: -```ruby - # Stomp URL : - # A Stomp URL must begin with 'stomp://' and can be in one of the following forms: +A Stomp URL must begin with 'stomp://' and can be in one of the following forms: +```ruby stomp://host:port stomp://host.domain.tld:port stomp://login:passcode@host:port @@ -722,4 +721,5 @@ Wayne Robinson / wayne.robinson@gmail.com - \ No newline at end of file + + From 8c24c4bbc60e1c791b2ec7592ddb1fe89d21c1a5 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 25 May 2016 21:23:57 -0400 Subject: [PATCH 29/48] Long defered updates to the Rakefile. --- Rakefile | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Rakefile b/Rakefile index 3356594..1dc9a07 100644 --- a/Rakefile +++ b/Rakefile @@ -19,10 +19,12 @@ require 'rspec/core/rake_task' require "stomp/version" begin - require "hanna/rdoctask" + require "hanna-nouveau" + have_hanna = true rescue LoadError => e - require "rdoc/task" + have_hanna = false end +require "rdoc/task" begin require 'jeweler' @@ -38,9 +40,6 @@ begin gem.authors = ["Brian McCallister", 'Marius Mathiesen', 'Thiago Morello', 'Guy M. Allard'] gem.add_development_dependency "rspec", '>= 2.14.1' - gem.extra_rdoc_files = [ "README.rdoc", "CHANGELOG.rdoc", "LICENSE", - "lib/**/*.rb", "examples/**/*.rb", - "test/**/*.rb" ] end Jeweler::GemcutterTasks.new rescue LoadError @@ -61,12 +60,14 @@ RSpec::Core::RakeTask.new('spec:rcov') do |t| end Rake::RDocTask.new do |rdoc| - rdoc.main = "README.rdoc" + rdoc.main = "README.md" rdoc.rdoc_dir = "doc" rdoc.title = "Stomp" rdoc.options += %w[ --line-numbers --inline-source --charset utf-8 ] - rdoc.rdoc_files.include("README.rdoc", "CHANGELOG.rdoc", "lib/**/*.rb", "examples/**/*.rb", - "test/**/*.rb") + if have_hanna + rdoc.options += %w[ --format hanna ] + end + rdoc.rdoc_files.include("README.md", "CHANGELOG.md", "lib/**/*.rb") end Rake::TestTask.new do |t| @@ -77,5 +78,3 @@ end task :default => :spec - - From b22b675cd3cd2dd2263b4537f312200d8e504c88 Mon Sep 17 00:00:00 2001 From: gmallard Date: Thu, 26 May 2016 20:20:06 -0400 Subject: [PATCH 30/48] Make Win/Msys2 happy about file perms. --- examples/contributors.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 examples/contributors.rb diff --git a/examples/contributors.rb b/examples/contributors.rb old mode 100644 new mode 100755 From 382e9545407651879b0803f9e36359f94387ed0a Mon Sep 17 00:00:00 2001 From: gmallard Date: Thu, 26 May 2016 20:22:46 -0400 Subject: [PATCH 31/48] Remove unnecessary require of rubygems. --- adhoc/issue121_01.rb | 1 - adhoc/issue121_01_conn.rb | 1 - adhoc/issue121_02.rb | 1 - adhoc/issue121_03.rb | 1 - 4 files changed, 4 deletions(-) diff --git a/adhoc/issue121_01.rb b/adhoc/issue121_01.rb index 0791c13..2515c46 100644 --- a/adhoc/issue121_01.rb +++ b/adhoc/issue121_01.rb @@ -1,6 +1,5 @@ # -*- encoding: utf-8 -*- -require 'rubygems' if RUBY_VERSION < "1.9" require 'stomp' # Focus on this gem's capabilities. diff --git a/adhoc/issue121_01_conn.rb b/adhoc/issue121_01_conn.rb index 8409c46..8100f05 100644 --- a/adhoc/issue121_01_conn.rb +++ b/adhoc/issue121_01_conn.rb @@ -1,6 +1,5 @@ # -*- encoding: utf-8 -*- -require 'rubygems' if RUBY_VERSION < "1.9" require 'stomp' # Focus on this gem's capabilities. diff --git a/adhoc/issue121_02.rb b/adhoc/issue121_02.rb index 4ff9567..826f2c5 100644 --- a/adhoc/issue121_02.rb +++ b/adhoc/issue121_02.rb @@ -1,6 +1,5 @@ # -*- encoding: utf-8 -*- -require 'rubygems' if RUBY_VERSION < "1.9" require 'stomp' # Focus on this gem's capabilities. diff --git a/adhoc/issue121_03.rb b/adhoc/issue121_03.rb index c2b9bfc..aa8441d 100644 --- a/adhoc/issue121_03.rb +++ b/adhoc/issue121_03.rb @@ -1,6 +1,5 @@ # -*- encoding: utf-8 -*- -require 'rubygems' if RUBY_VERSION < "1.9" require 'stomp' # Focus on this gem's capabilities. From 0d6303adb6b4079acbdecd0639e104a9241b85d3 Mon Sep 17 00:00:00 2001 From: gmallard Date: Thu, 26 May 2016 21:14:26 -0400 Subject: [PATCH 32/48] Make file names work anywhere. --- adhoc/issue121_01_conn.rb | 7 +++++-- adhoc/issue121_03.rb | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/adhoc/issue121_01_conn.rb b/adhoc/issue121_01_conn.rb index 8100f05..0601ae7 100644 --- a/adhoc/issue121_01_conn.rb +++ b/adhoc/issue121_01_conn.rb @@ -1,6 +1,7 @@ # -*- encoding: utf-8 -*- require 'stomp' +require 'tmpdir' # Focus on this gem's capabilities. require 'memory_profiler' @@ -147,8 +148,10 @@ def msg_handler e.shutdown end n = Time.now - nf = n.strftime("%Y%m%dT%H%M%S.%N%Z") - rpt.pretty_print(to_file: "/tmp/memory_profiler-ng-conn-#{nf}" ) + nf = "memory_profiler-ng" + nf << n.strftime("%Y%m%dT%H%M%S.%N%Z") + where_name = File::join(Dir::tmpdir(), nf) + rpt.pretty_print(to_file: where_name ) # sleep 1 end # diff --git a/adhoc/issue121_03.rb b/adhoc/issue121_03.rb index aa8441d..54c9e00 100644 --- a/adhoc/issue121_03.rb +++ b/adhoc/issue121_03.rb @@ -1,6 +1,7 @@ # -*- encoding: utf-8 -*- require 'stomp' +require 'tmpdir' # Focus on this gem's capabilities. require 'memory_profiler' @@ -144,8 +145,10 @@ def publish e.shutdown end n = Time.now - nf = n.strftime("%Y%m%dT%H%M%S.%N%Z") - rpt.pretty_print(to_file: "/tmp/memory_profiler-ng-#{nf}" ) + nf = "memory_profiler-ng" + nf << n.strftime("%Y%m%dT%H%M%S.%N%Z") + where_name = File::join(Dir::tmpdir(), nf) + rpt.pretty_print(to_file: where_name ) # sleep 1 end # From ff4c11fe9f36d56c86708687f5e0359c575fd1ee Mon Sep 17 00:00:00 2001 From: gmallard Date: Thu, 26 May 2016 21:19:04 -0400 Subject: [PATCH 33/48] Yet another attempt to satisfy msys2 perms. --- examples/contributors.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 examples/contributors.rb diff --git a/examples/contributors.rb b/examples/contributors.rb old mode 100644 new mode 100755 From b68f55fc038ecb92f4614e14358c02646a26c76a Mon Sep 17 00:00:00 2001 From: gmallard Date: Sat, 28 May 2016 21:42:10 -0400 Subject: [PATCH 34/48] Skip last unnecessary sleep. --- adhoc/issue121_03.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/adhoc/issue121_03.rb b/adhoc/issue121_03.rb index 54c9e00..364a65e 100644 --- a/adhoc/issue121_03.rb +++ b/adhoc/issue121_03.rb @@ -122,9 +122,11 @@ def publish @client.publish(@queue, mo, hs) end # if @block - puts "PUB: start user sleep" - sleep @tslt # see issue discussion - puts "PUB: end user sleep" + if nm < @nmsgs + puts "PUB: start user sleep" + sleep @tslt # see issue discussion + puts "PUB: end user sleep" + end $stdout.flush end # @nmsgs.times do From 48a34575d17884465f0b70a8c3a87fb055a3862b Mon Sep 17 00:00:00 2001 From: gmallard Date: Tue, 31 May 2016 19:07:02 -0400 Subject: [PATCH 35/48] Add example utilities for sending and receiving files: The entire file is sent as a single message. This is as opposed to how 'catstomp' operates. Binary files are also supported. --- examples/consume_file.rb | 63 +++++++ examples/lflogger.rb | 316 ++++++++++++++++++++++++++++++++++ examples/publish_file.rb | 76 ++++++++ examples/publish_file_conn.rb | 75 ++++++++ examples/stomp11_common.rb | 8 +- 5 files changed, 537 insertions(+), 1 deletion(-) create mode 100644 examples/consume_file.rb create mode 100644 examples/lflogger.rb create mode 100644 examples/publish_file.rb create mode 100644 examples/publish_file_conn.rb diff --git a/examples/consume_file.rb b/examples/consume_file.rb new file mode 100644 index 0000000..dbe2337 --- /dev/null +++ b/examples/consume_file.rb @@ -0,0 +1,63 @@ +# -*- encoding: utf-8 -*- + +require 'rubygems' +require 'stomp' + +if Kernel.respond_to?(:require_relative) + require_relative("./stomp11_common") + require_relative("./lflogger") +else + $LOAD_PATH << File.dirname(__FILE__) + require "stomp11_common" + require "./lflogger" +end +include Stomp11Common +# +# Used primarily for testing performance when receiving "large" messages. +# "large" => YMMV +# +class FileReader + # Initialize. + def initialize(pto) + @parse_timeout = pto + end + # Run example. + def run + conlogger = Slogger::new + start_time = Time.now.to_f + # + connection_hdrs = {"accept-version" => "1.1", + "host" => virt_host(), + } + connection_hash = { :hosts => [ + {:login => login(), :passcode => passcode(), + :host => host(), :port => port()}, + ], + :connect_headers => connection_hdrs, + :logger => conlogger, + :reliable => false, + :parse_timeout => @parse_timeout, + } + # + # p [ "ch", connection_hash ] + connection = Stomp::Connection.new(connection_hash) + qname = ENV['STOMP_DEST'] ? ENV['STOMP_DEST'] : "/queue/a.big.file" + puts "CONF: Qname is: #{qname}" + ## connection.subscribe(qname, {:destination => qname}, "bigFileSubscriptionID") + connection.subscribe(qname, {:destination => qname}, connection.uuid()) + ## connection.subscribe(qname, {:destination => qname}, "0") + msg = connection.receive() + puts "CONF: Message Command: #{msg.command}" + puts "CONF: Message Headers: #{msg.headers}" + body_length_bytes = msg.body.respond_to?(:bytesize) ? msg.body.bytesize : msg.body.length + puts "CONF: Received: #{body_length_bytes} bytes" + connection.disconnect + end_time = Time.now.to_f + ppt = sprintf("%20.6f", end_time - start_time) + puts "CONF: File consumed: #{ppt} seconds" + end +end +# +e = FileReader.new(60) +e.run + diff --git a/examples/lflogger.rb b/examples/lflogger.rb new file mode 100644 index 0000000..090c104 --- /dev/null +++ b/examples/lflogger.rb @@ -0,0 +1,316 @@ +# -*- encoding: utf-8 -*- + +require 'logger' # use the standard Ruby logger ..... + +# == Example STOMP call back logger class. +# +# Optional callback methods: +# +# * on_connecting: connection starting +# * on_connected: successful connect +# * on_connectfail: unsuccessful connect (will usually be retried) +# * on_disconnect: successful disconnect +# +# * on_miscerr: on miscellaneous xmit/recv errors +# +# * on_publish: publish called +# * on_subscribe: subscribe called +# * on_unsubscribe: unsubscribe called +# +# * on_begin: begin called +# * on_ack: ack called +# * on_nack: nack called +# * on_commit: commit called +# * on_abort: abort called +# +# * on_receive: receive called and successful +# +# * on_ssl_connecting: SSL connection starting +# * on_ssl_connected: successful SSL connect +# * on_ssl_connectfail: unsuccessful SSL connect (will usually be retried) +# +# * on_hbread_fail: unsuccessful Heartbeat read +# * on_hbwrite_fail: unsuccessful Heartbeat write +# * on_hbfire: on any send or receive heartbeat +# +# All methods are optional, at the user's requirements. +# +# If a method is not provided, it is not called (of course.) +# +# IMPORTANT NOTE: in general, call back logging methods *SHOULD* not raise exceptions, +# otherwise the underlying STOMP connection may fail in mysterious ways. +# There are, however, exceptions to this 'rule'. +# +# Useful exceptions to this rule are: +# +# * on_connectfail +# * on_ssl_connectfail +# +# These two methods can raise a Stomp::Errors::LoggerConnectionError. If this +# exception is raised, it is passed up the chain to the caller. +# +# Callback parameters: are a copy of the @parameters instance variable for +# the Stomp::Connection. +# +# A logger class may optionally inherit from the provided NullLogger +# +# # class Slogger < Stomp::NullLogger +# +class Slogger + + MAX_BODY_LEN = 1024 # Arbitrary + + # Initialize a new callback logger instance. + def initialize(init_parms = nil) + _init + @log.info("Logger initialization complete.") + end + + def _init + @log = Logger::new(STDOUT) # User preference + @log.level = Logger::DEBUG # User preference + end + + def marshal_dump + [] + end + + def marshal_load(array) + _init + end + + # Log connecting events + def on_connecting(parms) + begin + @log.debug "Connecting: #{info(parms)}" + rescue + @log.debug "Connecting oops #{$!}" + end + end + + # Log connected events + def on_connected(parms) + begin + @log.debug "Connected Info: #{info(parms)}" + @log.debug "Connected Parms: #{parms}" + rescue + @log.debug "Connected oops #{$!}" + end + end + + # Log connectfail events + def on_connectfail(parms) + begin + @log.debug "Connect Fail #{info(parms)}" + rescue + @log.debug "Connect Fail oops #{$!}" + end +=begin + # An example LoggerConnectionError raise + @log.debug "Connect Fail, will raise" + raise Stomp::Error::LoggerConnectionError.new("quit from connect fail") +=end + end + + # Log disconnect events + def on_disconnect(parms) + begin + @log.debug "Disconnected #{info(parms)}" + rescue + @log.debug "Disconnected oops #{$!}" + end + end + + # Log miscellaneous errors + def on_miscerr(parms, errstr) + begin + @log.debug "Miscellaneous Error Info: #{info(parms)}" + @log.debug "Miscellaneous Error String: #{errstr}" + @log.debug "Miscellaneous Error Parms: #{parms}" + rescue + @log.debug "Miscellaneous Error oops #{$!}" + # Most clients will want to know about this. YMMV + raise + end + end + + # Log Subscribe + def on_subscribe(parms, headers) + begin + @log.debug "Subscribe Parms #{info(parms)}" + @log.debug "Subscribe Headers #{headers}" + rescue + @log.debug "Subscribe oops #{$!}" + end + end + + # Log UnSubscribe + def on_unsubscribe(parms, headers) + begin + @log.debug "UnSubscribe Parms #{info(parms)}" + @log.debug "UnSubscribe Headers #{headers}" + rescue + @log.debug "UnSubscribe oops #{$!}" + end + end + + # Log Publish + def on_publish(parms, body, headers) + begin + @log.debug "Publish Parms #{info(parms)}" + body_length_bytes = body.respond_to?(:bytesize) ? body.bytesize : body.length + @log.debug "Publish Message Body #{body}" if body_length_bytes <= MAX_BODY_LEN + @log.debug "Publish Headers #{headers}" + rescue + @log.debug "Publish oops #{$!}" + end + end + + # Log Receive + def on_receive(parms, result) + begin + @log.debug "Receive Parms #{info(parms)}" + @log.debug result.is_a? Stomp::Message + ## @log.debug "Receive Result #{result}" + rescue + @log.debug "Receive oops #{$!}" + end + end + + # Log Begin + def on_begin(parms, headers) + begin + @log.debug "Begin Parms #{info(parms)}" + @log.debug "Begin Result #{headers}" + rescue + @log.debug "Begin oops #{$!}" + end + end + + # Log Ack + def on_ack(parms, headers) + begin + @log.debug "Ack Parms #{info(parms)}" + @log.debug "Ack Result #{headers}" + rescue + @log.debug "Ack oops #{$!}" + end + end + + # Log NAck + def on_nack(parms, headers) + begin + @log.debug "NAck Parms #{info(parms)}" + @log.debug "NAck Result #{headers}" + rescue + @log.debug "NAck oops #{$!}" + end + end + + # Log Commit + def on_commit(parms, headers) + begin + @log.debug "Commit Parms #{info(parms)}" + @log.debug "Commit Result #{headers}" + rescue + @log.debug "Commit oops #{$!}" + end + end + + # Log Abort + def on_abort(parms, headers) + begin + @log.debug "Abort Parms #{info(parms)}" + @log.debug "Abort Result #{headers}" + rescue + @log.debug "Abort oops #{$!}" + end + end + + # Stomp 1.1+ - heart beat read (receive) failed. + def on_hbread_fail(parms, ticker_data = {}) + begin + @log.debug "Hbreadf Parms #{info(parms)}" + @log.debug "Hbreadf Result #{ticker_data.inspect}" + rescue + @log.debug "Hbreadf oops #{$!}" + end + end + + # Stomp 1.1+ - heart beat send (transmit) failed. + def on_hbwrite_fail(parms, ticker_data = {}) + begin + @log.debug "Hbwritef Parms #{info(parms)}" + @log.debug "Hbwritef Result #{ticker_data.inspect}" + rescue + @log.debug "Hbwritef oops #{$!}" + end + end + + # Log SSL connection start. + def on_ssl_connecting(parms) + begin + @log.debug "SSL Connecting Parms #{info(parms)}" + rescue + @log.debug "SSL Connecting oops #{$!}" + end + end + + # Log a successful SSL connect. + def on_ssl_connected(parms) + begin + @log.debug "SSL Connected Parms #{info(parms)}" + rescue + @log.debug "SSL Connected oops #{$!}" + end + end + + # Log an unsuccessful SSL connect. + def on_ssl_connectfail(parms) + begin + @log.debug "SSL Connect Fail Parms #{info(parms)}" + @log.debug "SSL Connect Fail Exception #{parms[:ssl_exception]}, #{parms[:ssl_exception].message}" + rescue + @log.debug "SSL Connect Fail oops #{$!}" + end +=begin + # An example LoggerConnectionError raise + @log.debug "SSL Connect Fail, will raise" + raise Stomp::Error::LoggerConnectionError.new("quit from SSL connect") +=end + end + + # Log heart beat fires + def on_hbfire(parms, srind, firedata = {}) + begin + @log.debug "HeartBeat Fire Parms #{info(parms)}" + @log.debug "HeartBeat Fire Send/Receive #{srind}" + rescue + @log.debug "HeartBeat Fire oops #{$!}" + end + end + + private + + # Example information extract. + def info(parms) + # + # Available in the parms Hash: + # parms[:cur_host] + # parms[:cur_port] + # parms[:cur_login] + # parms[:cur_passcode] + # parms[:cur_ssl] + # parms[:cur_recondelay] + # parms[:cur_parseto] + # parms[:cur_conattempts] + # parms[:cur_failure] + # parms[:openstat] + # + # For the on_ssl_connectfail callback these are also available: + # parms[:ssl_exception] + # + "Host: #{parms[:cur_host]}, Port: #{parms[:cur_port]}, Login: #{parms[:cur_login]}, Passcode: #{parms[:cur_passcode]}, ssl: #{parms[:cur_ssl]}" + end +end # of class + diff --git a/examples/publish_file.rb b/examples/publish_file.rb new file mode 100644 index 0000000..ac23584 --- /dev/null +++ b/examples/publish_file.rb @@ -0,0 +1,76 @@ +# -*- encoding: utf-8 -*- + +require 'rubygems' +require 'stomp' + +if Kernel.respond_to?(:require_relative) + require_relative("./stomp11_common") + require_relative("./lflogger") +else + $LOAD_PATH << File.dirname(__FILE__) + require "stomp11_common" + require "./lflogger" +end +include Stomp11Common +# +# Used primarily for testing performance when sending "large" messages. +# "large" => YMMV +# +class FileSender + # Initialize. + def initialize + end + # Run example. + def run + p [ "pub001", Thread.current ] + publogger = Slogger::new + start_time = Time.now.to_f + fname = ARGV[0] + puts "PUBF: File Name: #{fname}" + file = open(fname, "r") + rs = Time.now.to_f + buff = file.read + re = Time.now.to_f + ppt = sprintf("%20.6f", re - rs) + puts "PUBF: File size: #{buff.respond_to?(:bytesize) ? buff.bytesize : buff.length}" + puts "PUBF: File read: #{ppt} seconds" + file.close + # + client_hdrs = {"accept-version" => "1.1", + "host" => virt_host(), + } + client_hash = { :hosts => [ + {:login => login(), :passcode => passcode(), + :host => host(), :port => port()}, + ], + :connect_headers => client_hdrs, + :logger => publogger, + :reliable => false, ### *NOTE* + } + # + # p [ "ch", client_hash ] + client = Stomp::Client.new(client_hash) + qname = ENV['STOMP_DEST'] ? ENV['STOMP_DEST'] : "/queue/a.big.file" + puts "PUBF: Qname is: #{qname}" + # Try to gracefully handle files that exceed broker size limits. + ph = {:presistent => true} + ph['suppress_content_length'] = 'yes' if suppresscl() + puts "PUBF: Headers are: #{ph.inspect}" + begin + client.publish(qname, buff, ph) + rescue + puts "PUBF: exception on publish: #{$!}" + end + sleep 0.1 + e = client.poll() # Check for unsolicited messages from broker + puts "PUBF: unexpected broker message: #{e}" if e + client.close + end_time = Time.now.to_f + ppt = sprintf("%20.6f", end_time - start_time) + puts "PUBF: File published: #{ppt} seconds" + end +end +# +e = FileSender.new +e.run + diff --git a/examples/publish_file_conn.rb b/examples/publish_file_conn.rb new file mode 100644 index 0000000..e0eaac3 --- /dev/null +++ b/examples/publish_file_conn.rb @@ -0,0 +1,75 @@ +# -*- encoding: utf-8 -*- + +require 'rubygems' +require 'stomp' + +if Kernel.respond_to?(:require_relative) + require_relative("./stomp11_common") + require_relative("./lflogger") +else + $LOAD_PATH << File.dirname(__FILE__) + require "stomp11_common" + require "./lflogger" +end +include Stomp11Common +# +# Used primarily for testing performance when sending "large" messages. +# "large" => YMMV +# +class FileSenderConn + # Initialize. + def initialize + end + # Run example. + def run + p [ "pubc001", Thread.current ] + publogger = Slogger::new + start_time = Time.now.to_f + fname = ARGV[0] + puts "PUBFC: File Name: #{fname}" + file = open(fname, "r") + rs = Time.now.to_f + buff = file.read + re = Time.now.to_f + ppt = sprintf("%20.6f", re - rs) + puts "PUBFC: File size: #{buff.respond_to?(:bytesize) ? buff.bytesize : buff.length}" + puts "PUBFC: File read: #{ppt} seconds" + file.close + # + connection_hdrs = {"accept-version" => "1.1", + "host" => virt_host(), + } + connection_hash = { :hosts => [ + {:login => login(), :passcode => passcode(), + :host => host(), :port => port()}, + ], + :connect_headers => connection_hdrs, + :logger => publogger, + :reliable => false, ### *NOTE* + } + # + # p [ "ch", connection_hash ] + connection = Stomp::Connection.new(connection_hash) + qname = ENV['STOMP_DEST'] ? ENV['STOMP_DEST'] : "/queue/a.big.file" + puts "PUBFC: Qname is: #{qname}" + ph = {:presistent => true} + ph['suppress_content_length'] = 'yes' if suppresscl() + puts "PUBF: Headers are: #{ph.inspect}" + # Try to gracefully handle files that exceed broker size limits. + begin + connection.publish(qname, buff, ph) + rescue + puts "PUBFC: exception on publish: #{$!}" + end + e = connection.poll() # Check for unsolicited messages from broker + puts "PUBFC: unexpected broker message: #{e}" if e + connection.disconnect + end_time = Time.now.to_f + ppt = sprintf("%20.6f", end_time - start_time) + puts "PUBFC: File published: #{ppt} seconds" + end +end +# +e = FileSenderConn.new +e.run + diff --git a/examples/stomp11_common.rb b/examples/stomp11_common.rb index 4d5e001..1281f4f 100644 --- a/examples/stomp11_common.rb +++ b/examples/stomp11_common.rb @@ -21,7 +21,7 @@ def host() end # Server port def port() - (ENV['STOMP_PORT'] || 62613).to_i # !! The author runs Apollo listening here + (ENV['STOMP_PORT'] || 61613).to_i # !! The author runs AMQ listening here end # Required vhost name def virt_host() @@ -44,5 +44,11 @@ def get_connection() def nmsgs() (ENV['STOMP_NMSGS'] || 1).to_i # Number of messages end + + # Include "suppress-content-length' header + def suppresscl() + ENV['STOMP_SUPPRESS_CL'] + end + end From ed983691e23e51617adbb0bbe83c8ca254065e82 Mon Sep 17 00:00:00 2001 From: gmallard Date: Mon, 30 May 2016 20:54:19 -0400 Subject: [PATCH 36/48] Work on IO::select replacement for timeout. --- lib/connection/netio.rb | 114 +++++++++++++++++++++------------------- lib/stomp/errors.rb | 9 ++++ 2 files changed, 68 insertions(+), 55 deletions(-) diff --git a/lib/connection/netio.rb b/lib/connection/netio.rb index 262e877..53be44b 100644 --- a/lib/connection/netio.rb +++ b/lib/connection/netio.rb @@ -13,6 +13,7 @@ class Connection # Really read from the wire. def _receive(read_socket, connread = false) + # p [ "ioscheck", @iosto ] @read_semaphore.synchronize do line = nil if connread @@ -35,64 +36,65 @@ def _receive(read_socket, connread = false) line = '' if line == "\n" # p [ "wiredatain_01", line ] line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12 - # If the reading hangs for more than X seconds, abort the parsing process. - # X defaults to 5. Override allowed in connection hash parameters. - Timeout::timeout(@parse_timeout, Stomp::Error::PacketParsingTimeout) do - # Reads the beginning of the message until it runs into a empty line - message_header = '' - begin - message_header += line - line = read_socket.gets - # p [ "wiredatain_02", line ] - raise Stomp::Error::StompServerError if line.nil? - line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12 - end until line =~ /^\s?\n$/ - - # Checks if it includes content_length header - content_length = message_header.match(/content-length\s?:\s?(\d+)\s?\n/) - message_body = '' - - # If content_length is present, read the specified amount of bytes - if content_length - message_body = read_socket.read content_length[1].to_i - raise Stomp::Error::InvalidMessageLength unless parse_char(read_socket.getc) == "\0" - # Else read the rest of the message until the first \0 - else - message_body = read_socket.readline("\0") - message_body.chop! - end + # Reads the beginning of the message until it runs into a empty line + message_header = '' + begin + message_header += line + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) + line = read_socket.gets + # p [ "wiredatain_02", line ] + raise if line.nil? + line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12 + end until line =~ /^\s?\n$/ + + # Checks if it includes content_length header + content_length = message_header.match(/content-length\s?:\s?(\d+)\s?\n/) + message_body = '' + + # If content_length is present, read the specified amount of bytes + if content_length + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) + message_body = read_socket.read content_length[1].to_i + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) + raise Stomp::Error::InvalidMessageLength unless parse_char(read_socket.getc) == "\0" + # Else read the rest of the message until the first \0 + else + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) + message_body = read_socket.readline("\0") + message_body.chop! + end - # If the buffer isn't empty, reads trailing new lines. - # - # Note: experiments with JRuby seem to show that socket.ready? never - # returns true. It appears that in cases where Ruby returns true - # that JRuby returns a Fixnum. We attempt to adjust for this - # in the _is_ready? method. - # - # Note 2: the draining of new lines must be done _after_ a message - # is read. Do _not_ leave them on the wire and attempt to drain them - # at the start of the next read. Attempting to do that breaks the - # asynchronous nature of the 'poll' method. - while _is_ready?(read_socket) - last_char = read_socket.getc - break unless last_char - if parse_char(last_char) != "\n" - read_socket.ungetc(last_char) - break - end + # If the buffer isn't empty, reads trailing new lines. + # + # Note: experiments with JRuby seem to show that socket.ready? never + # returns true. It appears that in cases where Ruby returns true + # that JRuby returns a Fixnum. We attempt to adjust for this + # in the _is_ready? method. + # + # Note 2: the draining of new lines must be done _after_ a message + # is read. Do _not_ leave them on the wire and attempt to drain them + # at the start of the next read. Attempting to do that breaks the + # asynchronous nature of the 'poll' method. + while _is_ready?(read_socket) + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) + last_char = read_socket.getc + break unless last_char + if parse_char(last_char) != "\n" + read_socket.ungetc(last_char) + break end + end - if @protocol >= Stomp::SPL_11 - @lr = Time.now.to_f if @hbr - end - # Adds the excluded \n and \0 and tries to create a new message with it - msg = Message.new(message_header + "\n" + message_body + "\0", @protocol >= Stomp::SPL_11) - # - if @protocol >= Stomp::SPL_11 && msg.command != Stomp::CMD_CONNECTED - msg.headers = _decodeHeaders(msg.headers) - end - msg + if @protocol >= Stomp::SPL_11 + @lr = Time.now.to_f if @hbr + end + # Adds the excluded \n and \0 and tries to create a new message with it + msg = Message.new(message_header + "\n" + message_body + "\0", @protocol >= Stomp::SPL_11) + # + if @protocol >= Stomp::SPL_11 && msg.command != Stomp::CMD_CONNECTED + msg.headers = _decodeHeaders(msg.headers) end + msg end end @@ -352,7 +354,7 @@ def open_socket() @closed = false if @parameters # nil in some rspec tests unless @reconnect_delay - @reconnect_delay = @parameters[:initial_reconnect_delay] || 0.01 + @reconnect_delay = @parameters[:initial_reconnect_delay] || iosto1 end end # Use keepalive @@ -361,6 +363,8 @@ def open_socket() # TCP_NODELAY option (disables Nagle's algorithm) used_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, !!(@parameters && @parameters[:tcp_nodelay])) + @iosto = @parse_timeout ? @parse_timeout.to_f : 0.0 + used_socket end diff --git a/lib/stomp/errors.rb b/lib/stomp/errors.rb index 8fdd105..2f3234b 100644 --- a/lib/stomp/errors.rb +++ b/lib/stomp/errors.rb @@ -38,6 +38,15 @@ def message end end + # ReceiveTimeout is raised if: + # * The read socket shows "not ready" at any time after the timeout + # specified by :parse_timeout in the connection hash. + class ReceiveTimeout < RuntimeError + def message + "Receive status timeout" + end + end + # SocketOpenTimeout is raised if: # * A timeout occurs during a socket open. class SocketOpenTimeout < RuntimeError From 9351d9910d53fc34b7045800ced394f7b2d6c681 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 1 Jun 2016 13:42:00 -0400 Subject: [PATCH 37/48] Split up test methods, more granularity. --- test/test_urlogin.rb | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/test/test_urlogin.rb b/test/test_urlogin.rb index 43940aa..25fb729 100644 --- a/test/test_urlogin.rb +++ b/test/test_urlogin.rb @@ -43,6 +43,9 @@ def setup "failover://(stomp://usera:@#{hostname}:#{portnum},stomp://#{hostname}:#{portnum})", "failover://(stomp://#{hostname}:#{portnum},stomp://#{hostname}:#{portnum})?a=b&c=d", "failover://(stomp://#{hostname}:#{portnum},stomp://#{hostname}:#{portnum})?a=b&c=d&connect_timeout=2020", + ] + + @sslfailover = [ "failover://(stomp+ssl://#{hostname}:#{sslpn})", "failover://(stomp+ssl://usera:passa@#{hostname}:#{sslpn})", "failover://(stomp://usera:@#{hostname}:#{portnum},stomp+ssl://#{hostname}:#{sslpn})", @@ -67,9 +70,21 @@ def test_0010_stomp_urls() end end - # test failover:// urls - def test_0020_failover_urls() + # test failover:// urls - tcp + def test_0020_failover_urls_tcp() @tdfailover.each_with_index do |url, ndx| + # p [ "xurl", url, "xndx", ndx ] + c = Stomp::Client.new(url) + assert !c.nil?, url + assert c.open?, url + c.close + end + end + + # test failover:// urls - ssl + def test_0020_failover_urls_ssl() + @sslfailover.each_with_index do |url, ndx| + # p [ "sslxurl", url, "sslxndx", ndx ] c = Stomp::Client.new(url) assert !c.nil?, url assert c.open?, url From 6bc725aa633e846c566194bcfbb95466c0a1fd2d Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 1 Jun 2016 14:23:13 -0400 Subject: [PATCH 38/48] Move forward with work using IO::select on receives. --- lib/connection/netio.rb | 757 +++++++++++++++++++++------------------- lib/stomp/client.rb | 4 + 2 files changed, 404 insertions(+), 357 deletions(-) diff --git a/lib/connection/netio.rb b/lib/connection/netio.rb index 53be44b..21c7b7d 100644 --- a/lib/connection/netio.rb +++ b/lib/connection/netio.rb @@ -9,416 +9,459 @@ module Stomp class Connection - private - - # Really read from the wire. - def _receive(read_socket, connread = false) - # p [ "ioscheck", @iosto ] - @read_semaphore.synchronize do - line = nil - if connread + private + + # Really read from the wire. + def _receive(read_socket, connread = false) + # p [ "ioscheck", @iosto, connread ] + # _dump_callstack() + @read_semaphore.synchronize do + line = nil + if connread + begin + Timeout::timeout(@connread_timeout, Stomp::Error::ConnectReadTimeout) do + line = _init_line_read(read_socket) + end + rescue Stomp::Error::ConnectReadTimeout => ex + if @reliable + _reconn_prep() + end + raise ex + end + else + line = _init_line_read(read_socket) + end + # + return nil if line.nil? + #An extra \n at the beginning of the frame, possibly not caught by is_ready? + line = '' if line == "\n" + # p [ "wiredatain_01A", line, Time.now ] + line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12 + # p [ "wiredatain_01B", line, Time.now ] + # Reads the beginning of the message until it runs into a empty line + message_header = '' begin - Timeout::timeout(@connread_timeout, Stomp::Error::ConnectReadTimeout) do - line = _init_line_read(read_socket) + message_header += line + # p [ "wiredatain_02A", line, Time.now ] + unless connread + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) + end + # p [ "wiredatain_02B", line, Time.now ] + line = read_socket.gets + # p [ "wiredatain_02C", line ] + raise if line.nil? + line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12 + # p [ "wiredatain_02D", line ] + end until line =~ /^\s?\n$/ + # p [ "wiredatain_03A" ] + # Checks if it includes content_length header + content_length = message_header.match(/content-length\s?:\s?(\d+)\s?\n/) + message_body = '' + + # p [ "wiredatain_03B", content_length ] + # If content_length is present, read the specified amount of bytes + if content_length + unless connread + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) + end + message_body = read_socket.read content_length[1].to_i + unless connread + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) end - rescue Stomp::Error::ConnectReadTimeout => ex - if @reliable - _reconn_prep() + raise Stomp::Error::InvalidMessageLength unless parse_char(read_socket.getc) == "\0" + # Else read the rest of the message until the first \0 + else + unless connread + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) end - raise ex + message_body = read_socket.readline("\0") + message_body.chop! end - else - line = _init_line_read(read_socket) - end - # - return nil if line.nil? - #An extra \n at the beginning of the frame, possibly not caught by is_ready? - line = '' if line == "\n" - # p [ "wiredatain_01", line ] - line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12 - # Reads the beginning of the message until it runs into a empty line - message_header = '' - begin - message_header += line - raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) - line = read_socket.gets - # p [ "wiredatain_02", line ] - raise if line.nil? - line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12 - end until line =~ /^\s?\n$/ - - # Checks if it includes content_length header - content_length = message_header.match(/content-length\s?:\s?(\d+)\s?\n/) - message_body = '' - - # If content_length is present, read the specified amount of bytes - if content_length - raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) - message_body = read_socket.read content_length[1].to_i - raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) - raise Stomp::Error::InvalidMessageLength unless parse_char(read_socket.getc) == "\0" - # Else read the rest of the message until the first \0 - else - raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) - message_body = read_socket.readline("\0") - message_body.chop! - end - # If the buffer isn't empty, reads trailing new lines. - # - # Note: experiments with JRuby seem to show that socket.ready? never - # returns true. It appears that in cases where Ruby returns true - # that JRuby returns a Fixnum. We attempt to adjust for this - # in the _is_ready? method. - # - # Note 2: the draining of new lines must be done _after_ a message - # is read. Do _not_ leave them on the wire and attempt to drain them - # at the start of the next read. Attempting to do that breaks the - # asynchronous nature of the 'poll' method. - while _is_ready?(read_socket) - raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) - last_char = read_socket.getc - break unless last_char - if parse_char(last_char) != "\n" - read_socket.ungetc(last_char) - break + # p [ "wiredatain_04" ] + # If the buffer isn't empty, reads trailing new lines. + # + # Note: experiments with JRuby seem to show that socket.ready? never + # returns true. It appears that in cases where Ruby returns true + # that JRuby returns a Fixnum. We attempt to adjust for this + # in the _is_ready? method. + # + # Note 2: the draining of new lines must be done _after_ a message + # is read. Do _not_ leave them on the wire and attempt to drain them + # at the start of the next read. Attempting to do that breaks the + # asynchronous nature of the 'poll' method. + while _is_ready?(read_socket) + unless connread + raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) + end + last_char = read_socket.getc + break unless last_char + if parse_char(last_char) != "\n" + read_socket.ungetc(last_char) + break + end + end + # p [ "wiredatain_05A" ] + if @protocol >= Stomp::SPL_11 + @lr = Time.now.to_f if @hbr end + # Adds the excluded \n and \0 and tries to create a new message with it + # p [ "wiredatain_05B" ] + msg = Message.new(message_header + "\n" + message_body + "\0", @protocol >= Stomp::SPL_11) + # p [ "wiredatain_06", msg.command, msg.headers ] + # + if @protocol >= Stomp::SPL_11 && msg.command != Stomp::CMD_CONNECTED + msg.headers = _decodeHeaders(msg.headers) + end + # p [ "wiredatain_99", msg.command, msg.headers ] + msg end + end - if @protocol >= Stomp::SPL_11 - @lr = Time.now.to_f if @hbr + # Check if the socket is ready, i.e. there is data to read. + def _is_ready?(s) + rdy = s.ready? + if @jruby + rdy = rdy.class == Fixnum ? true : false end - # Adds the excluded \n and \0 and tries to create a new message with it - msg = Message.new(message_header + "\n" + message_body + "\0", @protocol >= Stomp::SPL_11) - # - if @protocol >= Stomp::SPL_11 && msg.command != Stomp::CMD_CONNECTED - msg.headers = _decodeHeaders(msg.headers) - end - msg + rdy end - end - # Check if the socket is ready, i.e. there is data to read. - def _is_ready?(s) - rdy = s.ready? - if @jruby - rdy = rdy.class == Fixnum ? true : false + # Normalize line ends because 1.2+ brokers can send 'mixed mode' headers, i.e.: + # - Some headers end with '\n' + # - Other headers end with '\r\n' + def _normalize_line_end(line) + return line unless @usecrlf + # p [ "nleln", line ] + line_len = line.respond_to?(:bytesize) ? line.bytesize : line.length + last2 = line[line_len-2...line_len] + # p [ "nlel2", last2 ] + return line unless last2 == "\r\n" + return line[0...line_len-2] + "\n" end - rdy - end - - # Normalize line ends because 1.2+ brokers can send 'mixed mode' headers, i.e.: - # - Some headers end with '\n' - # - Other headers end with '\r\n' - def _normalize_line_end(line) - return line unless @usecrlf - # p [ "nleln", line ] - line_len = line.respond_to?(:bytesize) ? line.bytesize : line.length - last2 = line[line_len-2...line_len] - # p [ "nlel2", last2 ] - return line unless last2 == "\r\n" - return line[0...line_len-2] + "\n" - end - - # transmit logically puts a Message on the wire. - def transmit(command, headers = {}, body = '') - # The transmit may fail so we may need to retry. - while TRUE - begin - used_socket = socket() - _transmit(used_socket, command, headers, body) - return - rescue Stomp::Error::MaxReconnectAttempts => e - _ = e - raise - rescue - @failure = $! - raise unless @reliable - errstr = "transmit to #{@host} failed: #{$!}\n" - unless slog(:on_miscerr, log_params, "es_trans: " + errstr) - $stderr.print errstr + + # transmit logically puts a Message on the wire. + def transmit(command, headers = {}, body = '') + # The transmit may fail so we may need to retry. + while TRUE + begin + used_socket = socket() + _transmit(used_socket, command, headers, body) + return + rescue Stomp::Error::MaxReconnectAttempts => e + _ = e + raise + rescue + @failure = $! + raise unless @reliable + errstr = "transmit to #{@host} failed: #{$!}\n" + unless slog(:on_miscerr, log_params, "es_trans: " + errstr) + $stderr.print errstr + end + # !!! This loop initiates a re-connect !!! + _reconn_prep() end - # !!! This loop initiates a re-connect !!! - _reconn_prep() end end - end - # _transmit is the real wire write logic. - def _transmit(used_socket, command, headers = {}, body = '') - if @protocol >= Stomp::SPL_11 && command != Stomp::CMD_CONNECT - headers = _encodeHeaders(headers) - end - @transmit_semaphore.synchronize do - # Handle nil body - body = '' if body.nil? - # The content-length should be expressed in bytes. - # Ruby 1.8: String#length => # of bytes; Ruby 1.9: String#length => # of characters - # With Unicode strings, # of bytes != # of characters. So, use String#bytesize when available. - body_length_bytes = body.respond_to?(:bytesize) ? body.bytesize : body.length - - # ActiveMQ interprets every message as a BinaryMessage - # if content_length header is included. - # Using :suppress_content_length => true will suppress this behaviour - # and ActiveMQ will interpret the message as a TextMessage. - # For more information refer to http://juretta.com/log/2009/05/24/activemq-jms-stomp/ - # Lets send this header in the message, so it can maintain state when using unreceive - headers[:'content-length'] = "#{body_length_bytes}" unless headers[:suppress_content_length] - headers[:'content-type'] = "text/plain; charset=UTF-8" unless headers[:'content-type'] - _wire_write(used_socket,command) - headers.each do |k,v| - if v.is_a?(Array) - v.each do |e| - _wire_write(used_socket,"#{k}:#{e}") + # _transmit is the real wire write logic. + def _transmit(used_socket, command, headers = {}, body = '') + + # p [ "wirewrite" ] + # _dump_callstack() + + if @protocol >= Stomp::SPL_11 && command != Stomp::CMD_CONNECT + headers = _encodeHeaders(headers) + end + @transmit_semaphore.synchronize do + # Handle nil body + body = '' if body.nil? + # The content-length should be expressed in bytes. + # Ruby 1.8: String#length => # of bytes; Ruby 1.9: String#length => # of characters + # With Unicode strings, # of bytes != # of characters. So, use String#bytesize when available. + body_length_bytes = body.respond_to?(:bytesize) ? body.bytesize : body.length + + # ActiveMQ interprets every message as a BinaryMessage + # if content_length header is included. + # Using :suppress_content_length => true will suppress this behaviour + # and ActiveMQ will interpret the message as a TextMessage. + # For more information refer to http://juretta.com/log/2009/05/24/activemq-jms-stomp/ + # Lets send this header in the message, so it can maintain state when using unreceive + headers[:'content-length'] = "#{body_length_bytes}" unless headers[:suppress_content_length] + headers[:'content-type'] = "text/plain; charset=UTF-8" unless headers[:'content-type'] + _wire_write(used_socket,command) + headers.each do |k,v| + if v.is_a?(Array) + v.each do |e| + _wire_write(used_socket,"#{k}:#{e}") + end + else + _wire_write(used_socket,"#{k}:#{v}") end - else - _wire_write(used_socket,"#{k}:#{v}") end - end - _wire_write(used_socket,"") - used_socket.write body unless body == '' - used_socket.write "\0" - used_socket.flush if autoflush + _wire_write(used_socket,"") + used_socket.write body unless body == '' + used_socket.write "\0" + used_socket.flush if autoflush - if @protocol >= Stomp::SPL_11 - @ls = Time.now.to_f if @hbs - end + if @protocol >= Stomp::SPL_11 + @ls = Time.now.to_f if @hbs + end + end end - end - - # Use CRLF if protocol is >= 1.2, and the client requested CRLF - def _wire_write(sock, data) - # p [ "debug_01", @protocol, @usecrlf ] - if @protocol >= Stomp::SPL_12 && @usecrlf - wiredata = "#{data}#{Stomp::CR}#{Stomp::LF}" - # p [ "wiredataout_01:", wiredata ] - sock.write(wiredata) - else - # p [ "wiredataout_02:", "#{data}\n" ] - sock.puts data + + # Use CRLF if protocol is >= 1.2, and the client requested CRLF + def _wire_write(sock, data) + # p [ "debug_01", @protocol, @usecrlf ] + if @protocol >= Stomp::SPL_12 && @usecrlf + wiredata = "#{data}#{Stomp::CR}#{Stomp::LF}" + # p [ "wiredataout_01:", wiredata ] + sock.write(wiredata) + else + # p [ "wiredataout_02:", "#{data}\n" ] + sock.puts data + end end - end - # open_tcp_socket opens a TCP socket. - def open_tcp_socket() + # open_tcp_socket opens a TCP socket. + def open_tcp_socket() - ## $stderr.print("h: #{@host}, p: #{@port}\n") + ## $stderr.print("h: #{@host}, p: #{@port}\n") - tcp_socket = nil - slog(:on_connecting, log_params) - Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do - tcp_socket = TCPSocket.open(@host, @port) + tcp_socket = nil + slog(:on_connecting, log_params) + Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do + tcp_socket = TCPSocket.open(@host, @port) + end + tcp_socket end - tcp_socket - end - - # open_ssl_socket opens an SSL socket. - def open_ssl_socket() - require 'openssl' unless defined?(OpenSSL) - begin # Any raised SSL exceptions - ctx = @sslctx_newparm ? OpenSSL::SSL::SSLContext.new(@sslctx_newparm) : OpenSSL::SSL::SSLContext.new - ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # Assume for now - # - # Note: if a client uses :ssl => true this would result in the gem using - # the _default_ Ruby ciphers list. This is _known_ to fail in later - # Ruby releases. The gem now detects :ssl => true, and replaces that - # with: - # * :ssl => Stomp::SSLParams.new - # - # The above results in the use of Stomp default parameters. - # - # To specifically request Stomp default parameters, use: - # * :ssl => Stomp::SSLParams.new(..., :ciphers => Stomp::DEFAULT_CIPHERS) - # - # If connecting with an SSLParams instance, and the _default_ Ruby - # ciphers list is actually required, use: - # * :ssl => Stomp::SSLParams.new(..., :use_ruby_ciphers => true) - # - # If a custom ciphers list is required, connect with: - # * :ssl => Stomp::SSLParams.new(..., :ciphers => custom_ciphers_list) - # - if @ssl != true + + # open_ssl_socket opens an SSL socket. + def open_ssl_socket() + require 'openssl' unless defined?(OpenSSL) + begin # Any raised SSL exceptions + ctx = @sslctx_newparm ? OpenSSL::SSL::SSLContext.new(@sslctx_newparm) : OpenSSL::SSL::SSLContext.new + ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # Assume for now + # + # Note: if a client uses :ssl => true this would result in the gem using + # the _default_ Ruby ciphers list. This is _known_ to fail in later + # Ruby releases. The gem now detects :ssl => true, and replaces that + # with: + # * :ssl => Stomp::SSLParams.new # - # Here @ssl is: - # * an instance of Stomp::SSLParams - # Control would not be here if @ssl == false or @ssl.nil?. + # The above results in the use of Stomp default parameters. # + # To specifically request Stomp default parameters, use: + # * :ssl => Stomp::SSLParams.new(..., :ciphers => Stomp::DEFAULT_CIPHERS) + # + # If connecting with an SSLParams instance, and the _default_ Ruby + # ciphers list is actually required, use: + # * :ssl => Stomp::SSLParams.new(..., :use_ruby_ciphers => true) + # + # If a custom ciphers list is required, connect with: + # * :ssl => Stomp::SSLParams.new(..., :ciphers => custom_ciphers_list) + # + if @ssl != true + # + # Here @ssl is: + # * an instance of Stomp::SSLParams + # Control would not be here if @ssl == false or @ssl.nil?. + # + + # Back reference the SSLContext + @ssl.ctx = ctx + + # Server authentication parameters if required + if @ssl.ts_files + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + truststores = OpenSSL::X509::Store.new + fl = @ssl.ts_files.split(",") + fl.each do |fn| + # Add next cert file listed + raise Stomp::Error::SSLNoTruststoreFileError if !File::exists?(fn) + raise Stomp::Error::SSLUnreadableTruststoreFileError if !File::readable?(fn) + truststores.add_file(fn) + end + ctx.cert_store = truststores + end - # Back reference the SSLContext - @ssl.ctx = ctx - - # Server authentication parameters if required - if @ssl.ts_files - ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER - truststores = OpenSSL::X509::Store.new - fl = @ssl.ts_files.split(",") - fl.each do |fn| - # Add next cert file listed - raise Stomp::Error::SSLNoTruststoreFileError if !File::exists?(fn) - raise Stomp::Error::SSLUnreadableTruststoreFileError if !File::readable?(fn) - truststores.add_file(fn) + # Client authentication parameters. + # Both cert file and key file must be present or not, it can not be a mix. + raise Stomp::Error::SSLClientParamsError if @ssl.cert_file.nil? && !@ssl.key_file.nil? + raise Stomp::Error::SSLClientParamsError if !@ssl.cert_file.nil? && @ssl.key_file.nil? + if @ssl.cert_file # Any check will do here + raise Stomp::Error::SSLNoCertFileError if !File::exists?(@ssl.cert_file) + raise Stomp::Error::SSLUnreadableCertFileError if !File::readable?(@ssl.cert_file) + ctx.cert = OpenSSL::X509::Certificate.new(File.read(@ssl.cert_file)) + raise Stomp::Error::SSLNoKeyFileError if !File::exists?(@ssl.key_file) + raise Stomp::Error::SSLUnreadableKeyFileError if !File::readable?(@ssl.key_file) + ctx.key = OpenSSL::PKey::RSA.new(File.read(@ssl.key_file), @ssl.key_password) + end + + # Cipher list + if !@ssl.use_ruby_ciphers # No Ruby ciphers (the default) + if @ssl.ciphers # User ciphers list? + ctx.ciphers = @ssl.ciphers # Accept user supplied ciphers + else + ctx.ciphers = Stomp::DEFAULT_CIPHERS # Just use Stomp defaults + end + end + + # Set SSLContext Options if user asks for it in Stomp::SSLParams + # and SSL supports it. + if @ssl.ssl_ctxopts && ctx.respond_to?(:options=) + ctx.options = @ssl.ssl_ctxopts end - ctx.cert_store = truststores - end - # Client authentication parameters. - # Both cert file and key file must be present or not, it can not be a mix. - raise Stomp::Error::SSLClientParamsError if @ssl.cert_file.nil? && !@ssl.key_file.nil? - raise Stomp::Error::SSLClientParamsError if !@ssl.cert_file.nil? && @ssl.key_file.nil? - if @ssl.cert_file # Any check will do here - raise Stomp::Error::SSLNoCertFileError if !File::exists?(@ssl.cert_file) - raise Stomp::Error::SSLUnreadableCertFileError if !File::readable?(@ssl.cert_file) - ctx.cert = OpenSSL::X509::Certificate.new(File.read(@ssl.cert_file)) - raise Stomp::Error::SSLNoKeyFileError if !File::exists?(@ssl.key_file) - raise Stomp::Error::SSLUnreadableKeyFileError if !File::readable?(@ssl.key_file) - ctx.key = OpenSSL::PKey::RSA.new(File.read(@ssl.key_file), @ssl.key_password) end - # Cipher list - if !@ssl.use_ruby_ciphers # No Ruby ciphers (the default) - if @ssl.ciphers # User ciphers list? - ctx.ciphers = @ssl.ciphers # Accept user supplied ciphers + # + ssl = nil + slog(:on_ssl_connecting, log_params) + # _dump_ctx(ctx) + Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do + tcp_socket = TCPSocket.open(@host, @port) + ssl = OpenSSL::SSL::SSLSocket.new(tcp_socket, ctx) + ssl.hostname = @host if ssl.respond_to? :hostname= + ssl.sync_close = true # Sync ssl close with underlying TCP socket + ssl.connect + end + def ssl.ready? + ! @rbuffer.empty? || @io.ready? + end + if @ssl != true + # Pass back results if possible + if RUBY_VERSION =~ /1\.8\.[56]/ + @ssl.verify_result = "N/A for Ruby #{RUBY_VERSION}" else - ctx.ciphers = Stomp::DEFAULT_CIPHERS # Just use Stomp defaults + @ssl.verify_result = ssl.verify_result end + @ssl.peer_cert = ssl.peer_cert end - - # Set SSLContext Options if user asks for it in Stomp::SSLParams - # and SSL supports it. - if @ssl.ssl_ctxopts && ctx.respond_to?(:options=) - ctx.options = @ssl.ssl_ctxopts + slog(:on_ssl_connected, log_params) + ssl + rescue Exception => ex + lp = log_params.clone + lp[:ssl_exception] = ex + slog(:on_ssl_connectfail, lp) + if ssl + # shut down the TCP socket - we just failed to do the SSL handshake in time + ssl.close end - + # + raise # Reraise end + end - # - ssl = nil - slog(:on_ssl_connecting, log_params) - # _dump_ctx(ctx) - Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do - tcp_socket = TCPSocket.open(@host, @port) - ssl = OpenSSL::SSL::SSLSocket.new(tcp_socket, ctx) - ssl.hostname = @host if ssl.respond_to? :hostname= - ssl.sync_close = true # Sync ssl close with underlying TCP socket - ssl.connect - end - def ssl.ready? - ! @rbuffer.empty? || @io.ready? - end - if @ssl != true - # Pass back results if possible - if RUBY_VERSION =~ /1\.8\.[56]/ - @ssl.verify_result = "N/A for Ruby #{RUBY_VERSION}" - else - @ssl.verify_result = ssl.verify_result + # close_socket closes the current open socket, and hence the connection. + def close_socket() + begin + # Need to set @closed = true before closing the socket + # within the @read_semaphore thread + @closed = true + @read_semaphore.synchronize do + @socket.close end - @ssl.peer_cert = ssl.peer_cert - end - slog(:on_ssl_connected, log_params) - ssl - rescue Exception => ex - lp = log_params.clone - lp[:ssl_exception] = ex - slog(:on_ssl_connectfail, lp) - if ssl - # shut down the TCP socket - we just failed to do the SSL handshake in time - ssl.close + rescue + #Ignoring if already closed end - # - raise # Reraise + @closed end - end - - # close_socket closes the current open socket, and hence the connection. - def close_socket() - begin - # Need to set @closed = true before closing the socket - # within the @read_semaphore thread - @closed = true - @read_semaphore.synchronize do - @socket.close + + # open_socket opens a TCP or SSL soclet as required. + def open_socket() + used_socket = @ssl ? open_ssl_socket : open_tcp_socket + # try to close the old connection if any + close_socket + + @closed = false + if @parameters # nil in some rspec tests + unless @reconnect_delay + @reconnect_delay = @parameters[:initial_reconnect_delay] || iosto1 + end end - rescue - #Ignoring if already closed + # Use keepalive + used_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true) + + # TCP_NODELAY option (disables Nagle's algorithm) + used_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, !!(@parameters && @parameters[:tcp_nodelay])) + + @iosto = @parse_timeout ? @parse_timeout.to_f : 0.0 + + used_socket end - @closed - end - - # open_socket opens a TCP or SSL soclet as required. - def open_socket() - used_socket = @ssl ? open_ssl_socket : open_tcp_socket - # try to close the old connection if any - close_socket - - @closed = false - if @parameters # nil in some rspec tests - unless @reconnect_delay - @reconnect_delay = @parameters[:initial_reconnect_delay] || iosto1 + + # connect performs a basic STOMP CONNECT operation. + def connect(used_socket) + @connect_headers = {} unless @connect_headers # Caller said nil/false + headers = @connect_headers.clone + headers[:login] = @login unless @login.to_s.empty? + headers[:passcode] = @passcode unless @login.to_s.empty? + _pre_connect + if !@hhas10 && @stompconn + _transmit(used_socket, Stomp::CMD_STOMP, headers) + else + _transmit(used_socket, Stomp::CMD_CONNECT, headers) end + @connection_frame = _receive(used_socket, true) +=begin +p [ "connect01" ] + begin + @connection_frame = _receive(used_socket, true) + rescue + p [ "exception", Time.now, $! ] + end +p [ "connect02", @connection_frame ] +=end + _post_connect + @disconnect_receipt = nil + @session = @connection_frame.headers["session"] if @connection_frame + # replay any subscriptions. + @subscriptions.each {|k,v| + _transmit(used_socket, Stomp::CMD_SUBSCRIBE, v) + } end - # Use keepalive - used_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true) - - # TCP_NODELAY option (disables Nagle's algorithm) - used_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, !!(@parameters && @parameters[:tcp_nodelay])) - - @iosto = @parse_timeout ? @parse_timeout.to_f : 0.0 - - used_socket - end - - # connect performs a basic STOMP CONNECT operation. - def connect(used_socket) - @connect_headers = {} unless @connect_headers # Caller said nil/false - headers = @connect_headers.clone - headers[:login] = @login unless @login.to_s.empty? - headers[:passcode] = @passcode unless @login.to_s.empty? - _pre_connect - if !@hhas10 && @stompconn - _transmit(used_socket, Stomp::CMD_STOMP, headers) - else - _transmit(used_socket, Stomp::CMD_CONNECT, headers) - end - @connection_frame = _receive(used_socket, true) - _post_connect - @disconnect_receipt = nil - @session = @connection_frame.headers["session"] if @connection_frame - # replay any subscriptions. - @subscriptions.each {|k,v| - _transmit(used_socket, Stomp::CMD_SUBSCRIBE, v) - } - end - - def _init_line_read(read_socket) - line = '' - if @protocol == Stomp::SPL_10 || (@protocol >= Stomp::SPL_11 && !@hbr) - if @jruby - # Handle JRuby specific behavior. + + def _init_line_read(read_socket) + line = '' + if @protocol == Stomp::SPL_10 || (@protocol >= Stomp::SPL_11 && !@hbr) + if @jruby + # Handle JRuby specific behavior. + while true + line = read_socket.gets # Data from wire + break unless line == "\n" + line = '' + end + else + line = read_socket.gets # The old way + end + else # We are >= 1.1 *AND* receiving heartbeats. while true line = read_socket.gets # Data from wire break unless line == "\n" line = '' + @lr = Time.now.to_f end - else - line = read_socket.gets # The old way - end - else # We are >= 1.1 *AND* receiving heartbeats. - while true - line = read_socket.gets # Data from wire - break unless line == "\n" - line = '' - @lr = Time.now.to_f end + line + end + + # Used for debugging + def _dump_ctx(ctx) + p [ "dc01", ctx.inspect ] + p [ "dc02ciphers", ctx.ciphers ] + end + + # used for debugging + def _dump_callstack() + i = 0 + caller.each do |c| + p [ "csn", i, c ] + i += 1 end - line - end - - # Used for debugging - def _dump_ctx(ctx) - p [ "dc01", ctx.inspect ] - p [ "dc02ciphers", ctx.ciphers ] - end + end # _dump_callstack + end # class Connection end # module Stomp diff --git a/lib/stomp/client.rb b/lib/stomp/client.rb index d0c01ff..4dfc23c 100644 --- a/lib/stomp/client.rb +++ b/lib/stomp/client.rb @@ -86,6 +86,8 @@ def initialize(login = '', passcode = '', host = 'localhost', port = 61613, reli @start_timeout = @parameters[:start_timeout] || 0 check_arguments!() + # p [ "cldbg01", @parameters ] + begin Timeout::timeout(@start_timeout) { create_error_handler @@ -93,6 +95,7 @@ def initialize(login = '', passcode = '', host = 'localhost', port = 61613, reli start_listeners() } rescue TimeoutError + # p [ "cldbg02" ] ex = Stomp::Error::StartTimeoutException.new(@start_timeout) raise ex end @@ -116,6 +119,7 @@ def create_error_handler end def create_connection(autoflush) + # p [ "ccon01", @parameters ] @connection = Connection.new(@parameters) @connection.autoflush = autoflush end From dbeaa72b117c1e8335602a0d8b329dc652681df3 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 1 Jun 2016 21:05:17 -0400 Subject: [PATCH 39/48] Interim release, for client testing. --- Rakefile | 2 +- lib/stomp/version.rb | 4 +- stomp.gemspec | 97 +++++++++++++------------------------------- 3 files changed, 31 insertions(+), 72 deletions(-) diff --git a/Rakefile b/Rakefile index 1dc9a07..6e7a675 100644 --- a/Rakefile +++ b/Rakefile @@ -32,7 +32,7 @@ begin gem.name = "stomp" gem.version = Stomp::Version::STRING gem.summary = %Q{Ruby client for the Stomp messaging protocol} - gem.license = "Apache 2.0" + gem.license = "Apache-2.0" gem.description = %Q{Ruby client for the Stomp messaging protocol. Note that this gem is no longer supported on rubyforge.} gem.email = ["brianm@apache.org", 'marius@stones.com', 'morellon@gmail.com', 'allard.guy.m@gmail.com' ] diff --git a/lib/stomp/version.rb b/lib/stomp/version.rb index 39ce6c8..198cce0 100644 --- a/lib/stomp/version.rb +++ b/lib/stomp/version.rb @@ -5,8 +5,8 @@ module Stomp # Define the gem version. module Version #:nodoc: all MAJOR = 1 - MINOR = 3 - PATCH = 5 + MINOR = 4 + PATCH = 0 STRING = "#{MAJOR}.#{MINOR}.#{PATCH}" end end diff --git a/stomp.gemspec b/stomp.gemspec index 461f470..651e40a 100644 --- a/stomp.gemspec +++ b/stomp.gemspec @@ -4,81 +4,33 @@ # -*- encoding: utf-8 -*- Gem::Specification.new do |s| - s.name = "stomp" - s.version = "1.3.5" + s.name = %q{stomp} + s.version = "1.4.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Brian McCallister", "Marius Mathiesen", "Thiago Morello", "Guy M. Allard"] - s.date = "2016-03-02" - s.description = "Ruby client for the Stomp messaging protocol. Note that this gem is no longer supported on rubyforge." + s.date = %q{2016-06-01} + s.description = %q{Ruby client for the Stomp messaging protocol. Note that this gem is no longer supported on rubyforge.} s.email = ["brianm@apache.org", "marius@stones.com", "morellon@gmail.com", "allard.guy.m@gmail.com"] s.executables = ["catstomp", "stompcat"] s.extra_rdoc_files = [ - "CHANGELOG.rdoc", "LICENSE", - "README.rdoc", - "examples/amqdurasub.rb", - "examples/client11_ex1.rb", - "examples/client11_putget1.rb", - "examples/conn11_ex1.rb", - "examples/conn11_ex2.rb", - "examples/conn11_hb1.rb", - "examples/consumer.rb", - "examples/examplogger.rb", - "examples/get11conn_ex1.rb", - "examples/get11conn_ex2.rb", - "examples/logexamp.rb", - "examples/logexamp_ssl.rb", - "examples/publisher.rb", - "examples/put11conn_ex1.rb", - "examples/putget11_rh1.rb", - "examples/ssl_ctxoptions.rb", - "examples/ssl_newparm.rb", - "examples/ssl_uc1.rb", - "examples/ssl_uc1_ciphers.rb", - "examples/ssl_uc2.rb", - "examples/ssl_uc2_ciphers.rb", - "examples/ssl_uc3.rb", - "examples/ssl_uc3_ciphers.rb", - "examples/ssl_uc4.rb", - "examples/ssl_uc4_ciphers.rb", - "examples/ssl_ucx_default_ciphers.rb", - "examples/stomp11_common.rb", - "examples/topic_consumer.rb", - "examples/topic_publisher.rb", - "lib/client/utils.rb", - "lib/connection/heartbeats.rb", - "lib/connection/netio.rb", - "lib/connection/utf8.rb", - "lib/connection/utils.rb", - "lib/stomp.rb", - "lib/stomp/client.rb", - "lib/stomp/codec.rb", - "lib/stomp/connection.rb", - "lib/stomp/constants.rb", - "lib/stomp/errors.rb", - "lib/stomp/ext/hash.rb", - "lib/stomp/message.rb", - "lib/stomp/null_logger.rb", - "lib/stomp/slogger.rb", - "lib/stomp/sslparams.rb", - "lib/stomp/version.rb", - "test/test_anonymous.rb", - "test/test_client.rb", - "test/test_codec.rb", - "test/test_connection.rb", - "test/test_connection1p.rb", - "test/test_helper.rb", - "test/test_message.rb", - "test/test_ssl.rb", - "test/test_urlogin.rb", - "test/tlogger.rb" + "README.md" ] s.files = [ - "CHANGELOG.rdoc", + "CHANGELOG.md", "LICENSE", - "README.rdoc", + "README.md", "Rakefile", + "adhoc/.gitignore", + "adhoc/README.md", + "adhoc/issue121_01.rb", + "adhoc/issue121_01_conn.rb", + "adhoc/issue121_02.rb", + "adhoc/issue121_03.rb", + "adhoc/payload_generator.rb", + "adhoc/payload_generator_adhoctest.rb", + "adhoc/stomp_adhoc_common.rb", "bin/catstomp", "bin/stompcat", "examples/amqdurasub.rb", @@ -87,12 +39,18 @@ Gem::Specification.new do |s| "examples/conn11_ex1.rb", "examples/conn11_ex2.rb", "examples/conn11_hb1.rb", + "examples/consume_file.rb", "examples/consumer.rb", + "examples/contrib.sh", + "examples/contributors.rb", "examples/examplogger.rb", "examples/get11conn_ex1.rb", "examples/get11conn_ex2.rb", + "examples/lflogger.rb", "examples/logexamp.rb", "examples/logexamp_ssl.rb", + "examples/publish_file.rb", + "examples/publish_file_conn.rb", "examples/publisher.rb", "examples/put11conn_ex1.rb", "examples/putget11_rh1.rb", @@ -145,14 +103,15 @@ Gem::Specification.new do |s| "test/test_urlogin.rb", "test/tlogger.rb" ] - s.homepage = "https://github.com/stompgem/stomp" - s.licenses = ["Apache 2.0"] + s.homepage = %q{https://github.com/stompgem/stomp} + s.licenses = ["Apache-2.0"] s.require_paths = ["lib"] - s.rubygems_version = "2.0.3" - s.summary = "Ruby client for the Stomp messaging protocol" + s.rubygems_version = %q{1.3.7} + s.summary = %q{Ruby client for the Stomp messaging protocol} if s.respond_to? :specification_version then - s.specification_version = 4 + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, [">= 2.14.1"]) From 95cd2a76778e0eb4ca6e678b1124bf5fafad5bf1 Mon Sep 17 00:00:00 2001 From: gmallard Date: Fri, 3 Jun 2016 20:34:53 -0400 Subject: [PATCH 40/48] Update documentation, prep for 1.4.0 release. --- CHANGELOG.md | 21 ++++- README.md | 197 ++++++++++++++++++--------------------- examples/contrib.sh | 6 +- examples/contributors.rb | 41 ++++++-- lib/stomp/client.rb | 49 +++++----- lib/stomp/connection.rb | 49 +++++----- 6 files changed, 196 insertions(+), 167 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7066ec..6f97cfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Stomp Gem Change Log +## 1.4.0 20160603 + +* Connection parameter :parse_timeout now means IO:select wait time for socket + reads. Consumer clients should see a significantly reduced memory + footprint. If the default (5 seconds) is not used by your client, + we suggest you test carefully. +* Add example programs for sending / receiving large messages. +* Changelog format is changed from .rdoc to .md. +* README format is changed from .rdoc to .md. +* README format change of contributor's list. +* Add example utilities for generating the contributor's list. +* Eliminate many warnings when using 'rake test', mostly from the 2.x Ruby series. +* Get rakefile up to date. +* Add the 'adhoc' subdirectory, an area for experiments and issue recreation code. + ## 1.3.5 20160302 * Add AMQ specific durable topic example. @@ -22,7 +37,7 @@ * Do not attempt to write empty message bodies. * Explicity close ssl socket on connection timeout. * Fix incorrect behavior for empty header keys (#93) -* Do not override explicit :reliable #> false. +* Do not override explicit :reliable => false. * Fix client fail-over fails (#98) ## 1.3.2 20131208 @@ -33,7 +48,7 @@ * start_timeout and tcp_nodelay parameters * SSL Fix, revert not setting default ciphers. * Copy hash params at init. -* Fix ssl #> true for Ruby 1.9.x and 2.x. +* Fix ssl => true for Ruby 1.9.x and 2.x. * Expanded list of STOMP default SSL ciphers: * Do not change caller's :hosts array * Issue #78, again. @@ -165,7 +180,7 @@ * Update sample code to reflect removal of 'send' * Add on_ssl_connectfail callback and allow clients to signal quit from the callback * Ensure that SSL certificates and SSL related files exist and are readable -* Allow SSL file checks before connect using SSLParams.new(:fsck #> true, ...) +* Allow SSL file checks before connect using SSLParams.new(:fsck => true, ...) * Correct a test for Windows compatibility ## 1.2.1 20120313 diff --git a/README.md b/README.md index 7d9dfb7..3bbb9ba 100644 --- a/README.md +++ b/README.md @@ -10,57 +10,56 @@ An implementation of the Stomp protocol for Ruby. See: ## Hash Login Example Usage (**this is the recommended login technique**): -```ruby - hash = { - :hosts => [ +``` + hash = { + :hosts => [ # First connect is to remotehost1 {:login => "login1", :passcode => "passcode1", :host => "remotehost1", :port => 61612, :ssl => true}, # First failover connect is to remotehost2 {:login => "login2", :passcode => "passcode2", :host => "remotehost2", :port => 61613, :ssl => false}, - - ], - # These are the default parameters and do not need to be set - :reliable => true, # reliable (use failover) - :initial_reconnect_delay => 0.01, # initial delay before reconnect (secs) - :max_reconnect_delay => 30.0, # max delay before reconnect - :use_exponential_back_off => true, # increase delay between reconnect attpempts - :back_off_multiplier => 2, # next delay multiplier - :max_reconnect_attempts => 0, # retry forever, use # for maximum attempts - :randomize => false, # do not radomize hosts hash before reconnect - :connect_timeout => 0, # Timeout for TCP/TLS connects, use # for max seconds - :connect_headers => {}, # user supplied CONNECT headers (req'd for Stomp 1.1+) - :parse_timeout => 5, # receive / read timeout, secs - :logger => nil, # user suplied callback logger instance - :dmh => false, # do not support multihomed IPV4 / IPV6 hosts during failover - :closed_check => true, # check first if closed in each protocol method - :hbser => false, # raise on heartbeat send exception - :stompconn => false, # Use STOMP instead of CONNECT - :usecrlf => false, # Use CRLF command and header line ends (1.2+) - :max_hbread_fails => 0, # Max HB read fails before retry. 0 => never retry - :max_hbrlck_fails => 0, # Max HB read lock obtain fails before retry. 0 => never retry - :fast_hbs_adjust => 0.0, # Fast heartbeat senders sleep adjustment, seconds, needed ... - # For fast heartbeat senders. 'fast' == YMMV. If not - # correct for your environment, expect unnecessary fail overs - :connread_timeout => 0, # Timeout during CONNECT for read of CONNECTED/ERROR, secs - :tcp_nodelay => true, # Turns on the TCP_NODELAY socket option; disables Nagle's algorithm - :start_timeout => 0, # Timeout around Stomp::Client initialization - :sslctx_newparm => nil, # Param for SSLContext.new - } - - # for a client - client = Stomp::Client.new(hash) - - # for a connection - connection = Stomp::Connection.new(hash) + ], + # These are the default parameters and do not need to be set + :reliable => true, # reliable (use failover) + :initial_reconnect_delay => 0.01, # initial delay before reconnect (secs) + :max_reconnect_delay => 30.0, # max delay before reconnect + :use_exponential_back_off => true, # increase delay between reconnect attpempts + :back_off_multiplier => 2, # next delay multiplier + :max_reconnect_attempts => 0, # retry forever, use # for maximum attempts + :randomize => false, # do not radomize hosts hash before reconnect + :connect_timeout => 0, # Timeout for TCP/TLS connects, use # for max seconds + :connect_headers => {}, # user supplied CONNECT headers (req'd for Stomp 1.1+) + :parse_timeout => 5, # IO::select wait time on socket reads + :logger => nil, # user suplied callback logger instance + :dmh => false, # do not support multihomed IPV4 / IPV6 hosts during failover + :closed_check => true, # check first if closed in each protocol method + :hbser => false, # raise on heartbeat send exception + :stompconn => false, # Use STOMP instead of CONNECT + :usecrlf => false, # Use CRLF command and header line ends (1.2+) + :max_hbread_fails => 0, # Max HB read fails before retry. 0 => never retry + :max_hbrlck_fails => 0, # Max HB read lock obtain fails before retry. 0 => never retry + :fast_hbs_adjust => 0.0, # Fast heartbeat senders sleep adjustment, seconds, needed ... + # For fast heartbeat senders. 'fast' == YMMV. If not + # correct for your environment, expect unnecessary fail overs + :connread_timeout => 0, # Timeout during CONNECT for read of CONNECTED/ERROR, secs + :tcp_nodelay => true, # Turns on the TCP_NODELAY socket option; disables Nagle's algorithm + :start_timeout => 0, # Timeout around Stomp::Client initialization + :sslctx_newparm => nil, # Param for SSLContext.new + } + + # for a client + client = Stomp::Client.new(hash) + + # for a connection + connection = Stomp::Connection.new(hash) ``` ### Positional Parameter Usage: -```ruby +``` client = Stomp::Client.new("user", "pass", "localhost", 61613) client.publish("/queue/mine", "hello world!") client.subscribe("/queue/mine") do |msg| - p msg + p msg end ``` @@ -68,26 +67,24 @@ An implementation of the Stomp protocol for Ruby. See: A Stomp URL must begin with 'stomp://' and can be in one of the following forms: -```ruby +``` stomp://host:port stomp://host.domain.tld:port stomp://login:passcode@host:port stomp://login:passcode@host.domain.tld:port - + # e.g. c = Stomp::Client.new(urlstring) ``` ### Failover + SSL Example URL Usage: -```ruby +``` options = "initialReconnectDelay=5000&randomize=false&useExponentialBackOff=false" - # remotehost1 uses SSL, remotehost2 doesn't client = Stomp::Client.new("failover:(stomp+ssl://login1:passcode1@remotehost1:61612,stomp://login2:passcode2@remotehost2:61613)?#{options}") - client.publish("/queue/mine", "hello world!") client.subscribe("/queue/mine") do |msg| - p msg + p msg end ``` @@ -95,29 +92,15 @@ A Stomp URL must begin with 'stomp://' and can be in one of the following forms: See _CHANGELOG.rdoc_ for details. +* Gem version 1.4.0. Change sementics of :parse_timeout, see CHANGELOG.rdoc for details. * Gem version 1.3.5. Miscellaneous fixes, see CHANGELOG.rdoc for details. * Gem version 1.3.4. Miscellaneous fixes, see CHANGELOG.rdoc for details. * Gem version 1.3.3. Miscellaneous fixes, see CHANGELOG.rdoc for details. * Gem version 1.3.2. Miscellaneous fixes, see changelog for details. * Gem version 1.3.1. Bugfix for logging. * Gem version 1.3.0. Added ERROR frame raising as exception, added anonymous connections, miscellaneous other fixes. -* Gem version 1.2.16. Fixed Stomp::Client to expose its connection's host parameters. -* Gem version 1.2.15. Timeout cleanup, added license info to gemspec. -* Gem version 1.2.14. Cleanup. -* Gem version 1.2.13. Stomp::Client#unreceive max_redeliveries fix. -* Gem version 1.2.12. Miscellaneous issue fixes and cleanup. -* Gem version 1.2.11. JRuby and AMQ support fixes. -* Gem version 1.2.10. Support failover from heartbeat threads. -* Gem version 1.2.9. Miscellaneous fixes and changes. -* Gem version 1.2.8. Stomp 1.1+ header codec inversion fix, test refactoring. -* Gem version 1.2.7. Stomp 1.2 support and miscellaneous fixes. -* Gem version 1.2.6. Miscellaneous fixes and changes. -* Gem version 1.2.5. Restructure. Forks with modifcations will be affected. -* Gem version 1.2.4. Stomp 1.1 heartbeat fix, autoflush capability, miscellaneous fixes. -* Gem version 1.2.3. Miscellaneous fixes, see changelog for details. -* Gem version 1.2.2. Performance and more SSL enhancements. -* Gem version 1.2.1. Full support of SSL certificates. -* Gem version 1.2.0. Support of Stomp protocol level 1.1. + +For changes in older versions see CHANGELOG.rdoc for details. ### Historical Information: @@ -146,7 +129,7 @@ First Author Date Name / E-mail - + 2005-08-26 @@ -160,7 +143,7 @@ brianm / brianm@fd4e7336-3dff-0310-b68a-b6615a75f13b - + 2006-03-16 @@ -174,7 +157,7 @@ jstrachan / jstrachan@fd4e7336-3dff-0310-b68a-b6615a75f13b - + 2006-04-19 @@ -188,7 +171,7 @@ chirino / chirino@fd4e7336-3dff-0310-b68a-b6615a75f13b - + 2007-05-09 @@ -202,7 +185,7 @@ kookster / kookster@fd4e7336-3dff-0310-b68a-b6615a75f13b - + 2008-05-08 @@ -216,7 +199,7 @@ Glenn Rempe / glenn@rempe.us - + 2009-02-03 @@ -230,7 +213,7 @@ Tony Garnock-Jones / tonyg@lshift.net - + 2009-02-09 @@ -244,7 +227,7 @@ Marius Mathiesen / marius.mathiesen@gmail.com - + 2009-02-13 @@ -258,7 +241,7 @@ Johan Sørensen / johan@johansorensen.com - + 2009-11-17 @@ -272,7 +255,7 @@ Thiago Morello / thiago.morello@locaweb.com.br - + 2009-11-22 @@ -286,7 +269,7 @@ unknown / katy@.(none) - + 2009-12-18 @@ -300,13 +283,13 @@ Thiago Morello / morello@queroinfra32.fabrica.locaweb.com.br - + 2009-12-25 -(0299) +(0344) @@ -314,7 +297,7 @@ gmallard / allard.guy.m@gmail.com - + 2010-01-07 @@ -328,7 +311,7 @@ Rafael Rosa / rafael.rosa@locaweb.com.br - + 2010-03-23 @@ -342,7 +325,7 @@ Guy M. Allard / allard.guy.m@gmail.com - + 2010-04-01 @@ -356,7 +339,7 @@ Dmytro Shteflyuk / kpumuk@kpumuk.info - + 2010-10-22 @@ -370,7 +353,7 @@ Neil Wilson / neil@aldur.co.uk - + 2011-02-09 @@ -384,7 +367,7 @@ Dinesh Majrekar / dinesh.majrekar@advantage-interactive.com - + 2011-04-15 @@ -398,7 +381,7 @@ Kiall Mac Innes / kiall@managedit.ie - + 2011-04-29 @@ -412,7 +395,7 @@ Rob Skaggs / rob@pivotal-it.com - + 2011-08-23 @@ -426,7 +409,7 @@ Tom May / tom@gist.com - + 2011-08-24 @@ -440,7 +423,7 @@ Thiago Morello / morellon@gmail.com - + 2011-09-11 @@ -454,7 +437,7 @@ Lucas Hills / info@lucashills.com - + 2011-11-20 @@ -468,7 +451,7 @@ Chris Needham / chrisn303@gmail.com - + 2011-12-11 @@ -482,7 +465,7 @@ R.I.Pienaar / rip@devco.net - + 2011-12-13 @@ -496,7 +479,7 @@ tworker / tworker@onyx.ove.com - + 2012-03-16 @@ -510,7 +493,7 @@ James Pearson / james@fearmediocrity.co.uk - + 2012-05-10 @@ -524,7 +507,7 @@ Tommy Bishop / bishop.thomas@gmail.com - + 2012-06-18 @@ -538,7 +521,7 @@ Jeremy Gailor / jeremy@infinitecube.com - + 2013-02-20 @@ -552,7 +535,7 @@ JP Hastings-Spital / jphastings@gmail.com - + 2013-03-14 @@ -566,7 +549,7 @@ glennr / glenn@siyelo.com - + 2013-07-29 @@ -580,7 +563,7 @@ Ian Smith / ian.smith@mylookout.com - + 2013-08-07 @@ -594,7 +577,7 @@ Hiram Chirino / hiram@hiramchirino.com - + 2013-08-15 @@ -608,7 +591,7 @@ Ian Smith / ian.smith@lookout.com - + 2013-08-22 @@ -622,7 +605,7 @@ Ian Smith / ismith@mit.edu - + 2013-09-26 @@ -636,7 +619,7 @@ Orazio Cotroneo / orazio@we7.com - + 2013-10-22 @@ -650,10 +633,10 @@ OrazioWE7 / orazio@we7.com - + -2014-03-14 +2014-03-13 (0001) @@ -664,7 +647,7 @@ Richard Clamp / richardc@unixbeard.net - + 2014-12-08 @@ -678,7 +661,7 @@ m4rCsi / m4rCsi@gmail.com - + 2015-09-05 @@ -692,7 +675,7 @@ Michael Klishin / michael@novemberain.com - + 2015-11-10 @@ -706,7 +689,7 @@ Patrick Sharp / psharp@numerex.com - + 2016-02-03 @@ -720,6 +703,6 @@ Wayne Robinson / wayne.robinson@gmail.com - + diff --git a/examples/contrib.sh b/examples/contrib.sh index cda24ef..d292c99 100755 --- a/examples/contrib.sh +++ b/examples/contrib.sh @@ -1,6 +1,6 @@ #!/bin/bash # -#git log --reverse --all --date=iso-strict --pretty --format='%ad;%cn;%ce' -git log --reverse --all --date=short --pretty --format='%cd;%cn;%ce' | \ +# git log --reverse --all --date=short --pretty --format='%aI;%cI;%cn;%ce' | \ +git log --reverse --all --date=short --pretty --format='%ad;%cd;%cn;%ce' | \ ruby examples/contributors.rb - \ No newline at end of file + diff --git a/examples/contributors.rb b/examples/contributors.rb index 3087e8e..61bd64a 100755 --- a/examples/contributors.rb +++ b/examples/contributors.rb @@ -4,22 +4,26 @@ class UserData public attr_accessor :count - attr_reader :time + attr_reader :ad, :cd # - def initialize(time = nil) - @count, @time = 1, time + def initialize(ad = nil, cd = nil) + @count, @ad, @cd = 1, ad, cd end # def to_s - "UserData: time=>#{@time}, count =>#{@count}" + "UserData: AuthorDate=>#{@ad}, CommitDate=>#{@cd}, CommitCount =>#{@count}" end end +# tABLE Data +ttab_s = "\n" +ttab_e = "
\n" # Row Data trow_s = "\n" -trow_e = "\n" +trow_e = "\n" # Header Data th_s = "\n" th_c1 = "First Author Date" +th_c1b = "First Commit Date" th_c2 = "(Commit Count)" th_c3 = "Name / E-mail" th_e = "\n" @@ -27,15 +31,22 @@ def to_s td_s = "\n" td_e = "\n" # +puts ttab_s # table start +# userList = {} while s = gets do s.chomp! - t, n, e = s.split(";") + ad, cd, n, e = s.split(";") hk = "#{n}|#{e}" if userList.has_key?(hk) userList[hk].count += 1 else - userList[hk] = UserData.new(t) + userList[hk] = UserData.new(ad, cd) +=begin + if ad != cd + puts "NE: #{ad}, #{cd}, #{n}, #{e}" + end +=end end end @@ -46,6 +57,12 @@ def to_s puts th_c1 puts th_e # +=begin +puts th_s +puts th_c1b +puts th_e +=end +# puts th_s puts th_c2 puts th_e @@ -63,8 +80,14 @@ def to_s puts trow_s # puts td_s - puts "#{v.time}" + puts "#{v.ad}" puts td_e +=begin + # + puts td_s + puts "#{v.cd}" + puts td_e +=end # puts td_s puts oc @@ -79,3 +102,5 @@ def to_s # puts trow_e end +# +puts ttab_e # table end diff --git a/lib/stomp/client.rb b/lib/stomp/client.rb index 4dfc23c..eb39379 100644 --- a/lib/stomp/client.rb +++ b/lib/stomp/client.rb @@ -30,29 +30,32 @@ class Client # {:login => "login1", :passcode => "passcode1", :host => "localhost", :port => 61616, :ssl => false}, # {:login => "login2", :passcode => "passcode2", :host => "remotehost", :port => 61617, :ssl => false} # ], - # :reliable => true, - # :initial_reconnect_delay => 0.01, - # :max_reconnect_delay => 30.0, - # :use_exponential_back_off => true, - # :back_off_multiplier => 2, - # :max_reconnect_attempts => 0, - # :randomize => false, - # :connect_timeout => 0, - # :connect_headers => {}, - # :parse_timeout => 5, - # :logger => nil, - # :dmh => false, - # :closed_check => true, - # :hbser => false, - # :stompconn => false, - # :usecrlf => false, - # :max_hbread_fails => 0, - # :max_hbrlck_fails => 0, - # :fast_hbs_adjust => 0.0, - # :connread_timeout => 0, - # :tcp_nodelay => true, - # :start_timeout => 0, - # :sslctx_newparm => nil, + # # These are the default parameters and do not need to be set + # :reliable => true, # reliable (use failover) + # :initial_reconnect_delay => 0.01, # initial delay before reconnect (secs) + # :max_reconnect_delay => 30.0, # max delay before reconnect + # :use_exponential_back_off => true, # increase delay between reconnect attpempts + # :back_off_multiplier => 2, # next delay multiplier + # :max_reconnect_attempts => 0, # retry forever, use # for maximum attempts + # :randomize => false, # do not radomize hosts hash before reconnect + # :connect_timeout => 0, # Timeout for TCP/TLS connects, use # for max seconds + # :connect_headers => {}, # user supplied CONNECT headers (req'd for Stomp 1.1+) + # :parse_timeout => 5, # IO::select wait time on socket reads + # :logger => nil, # user suplied callback logger instance + # :dmh => false, # do not support multihomed IPV4 / IPV6 hosts during failover + # :closed_check => true, # check first if closed in each protocol method + # :hbser => false, # raise on heartbeat send exception + # :stompconn => false, # Use STOMP instead of CONNECT + # :usecrlf => false, # Use CRLF command and header line ends (1.2+) + # :max_hbread_fails => 0, # Max HB read fails before retry. 0 => never retry + # :max_hbrlck_fails => 0, # Max HB read lock obtain fails before retry. 0 => never retry + # :fast_hbs_adjust => 0.0, # Fast heartbeat senders sleep adjustment, seconds, needed ... + # # For fast heartbeat senders. 'fast' == YMMV. If not + # # correct for your environment, expect unnecessary fail overs + # :connread_timeout => 0, # Timeout during CONNECT for read of CONNECTED/ERROR, secs + # :tcp_nodelay => true, # Turns on the TCP_NODELAY socket option; disables Nagle's algorithm + # :start_timeout => 0, # Timeout around Stomp::Client initialization + # :sslctx_newparm => nil, # Param for SSLContext.new # } # # e.g. c = Stomp::Client.new(hash) diff --git a/lib/stomp/connection.rb b/lib/stomp/connection.rb index 8504d09..ed6c9ed 100644 --- a/lib/stomp/connection.rb +++ b/lib/stomp/connection.rb @@ -67,29 +67,32 @@ def self.ssl_v2xoptions() # {:login => "login1", :passcode => "passcode1", :host => "localhost", :port => 61616, :ssl => false}, # {:login => "login2", :passcode => "passcode2", :host => "remotehost", :port => 61617, :ssl => false} # ], - # :reliable => true, - # :initial_reconnect_delay => 0.01, - # :max_reconnect_delay => 30.0, - # :use_exponential_back_off => true, - # :back_off_multiplier => 2, - # :max_reconnect_attempts => 0, - # :randomize => false, - # :connect_timeout => 0, - # :connect_headers => {}, - # :parse_timeout => 5, - # :logger => nil, - # :dmh => false, - # :closed_check => true, - # :hbser => false, - # :stompconn => false, - # :usecrlf => false, - # :max_hbread_fails => 0, - # :max_hbrlck_fails => 0, - # :fast_hbs_adjust => 0.0, - # :connread_timeout => 0, - # :tcp_nodelay => true, - # :start_timeout => 0, - # :sslctx_newparm => nil, + # # These are the default parameters and do not need to be set + # :reliable => true, # reliable (use failover) + # :initial_reconnect_delay => 0.01, # initial delay before reconnect (secs) + # :max_reconnect_delay => 30.0, # max delay before reconnect + # :use_exponential_back_off => true, # increase delay between reconnect attpempts + # :back_off_multiplier => 2, # next delay multiplier + # :max_reconnect_attempts => 0, # retry forever, use # for maximum attempts + # :randomize => false, # do not radomize hosts hash before reconnect + # :connect_timeout => 0, # Timeout for TCP/TLS connects, use # for max seconds + # :connect_headers => {}, # user supplied CONNECT headers (req'd for Stomp 1.1+) + # :parse_timeout => 5, # IO::select wait time on socket reads + # :logger => nil, # user suplied callback logger instance + # :dmh => false, # do not support multihomed IPV4 / IPV6 hosts during failover + # :closed_check => true, # check first if closed in each protocol method + # :hbser => false, # raise on heartbeat send exception + # :stompconn => false, # Use STOMP instead of CONNECT + # :usecrlf => false, # Use CRLF command and header line ends (1.2+) + # :max_hbread_fails => 0, # Max HB read fails before retry. 0 => never retry + # :max_hbrlck_fails => 0, # Max HB read lock obtain fails before retry. 0 => never retry + # :fast_hbs_adjust => 0.0, # Fast heartbeat senders sleep adjustment, seconds, needed ... + # # For fast heartbeat senders. 'fast' == YMMV. If not + # # correct for your environment, expect unnecessary fail overs + # :connread_timeout => 0, # Timeout during CONNECT for read of CONNECTED/ERROR, secs + # :tcp_nodelay => true, # Turns on the TCP_NODELAY socket option; disables Nagle's algorithm + # :start_timeout => 0, # Timeout around Stomp::Client initialization + # :sslctx_newparm => nil, # Param for SSLContext.new # } # # e.g. c = Stomp::Connection.new(hash) From d7003f1c211f0f2ff02653be410155455deeb31d Mon Sep 17 00:00:00 2001 From: gmallard Date: Tue, 7 Jun 2016 11:20:49 -0400 Subject: [PATCH 41/48] Ignore single method test file. --- test/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 test/.gitignore diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..4ebf366 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1,3 @@ +# +test_1method.rb + From 749444bc536bed0f74e1e38d21d03bffef210dae Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 8 Jun 2016 10:45:03 -0400 Subject: [PATCH 42/48] Correct ignore list for tests. --- test/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/.gitignore b/test/.gitignore index 4ebf366..638c6a9 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,3 +1,3 @@ # -test_1method.rb +1method.rb From c795e973cc2fd5448f61596ae50277e3789f33f2 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 8 Jun 2016 10:51:10 -0400 Subject: [PATCH 43/48] Correct test_unsubscribe method: I am not sure how this ever worked. --- test/test_client.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/test_client.rb b/test/test_client.rb index 169d822..7dad1ad 100644 --- a/test/test_client.rb +++ b/test/test_client.rb @@ -449,23 +449,25 @@ def test_connection_frame # Test basic unsubscribe. def test_unsubscribe + @client.close if @client && @client.open? # close setup work + @client = nil message = nil dest = make_destination to_send = message_text client = get_client() sid = nil - if @client.protocol() == Stomp::SPL_10 + if client.protocol() == Stomp::SPL_10 client.subscribe(dest, :ack => 'client') { |m| message = m } else sid = client.uuid() client.subscribe(dest, :ack => 'client', :id => sid) { |m| message = m } end - @client.publish dest, to_send + client.publish dest, to_send Timeout::timeout(4) do sleep 0.01 until message end assert_equal to_send, message.body, "first body check" - if @client.protocol() == Stomp::SPL_10 + if client.protocol() == Stomp::SPL_10 client.unsubscribe dest else client.unsubscribe dest, :id => sid @@ -474,7 +476,7 @@ def test_unsubscribe # Same message should remain on the queue. Receive it again with ack=>auto. message_copy = nil client = get_client() - if @client.protocol() == Stomp::SPL_10 + if client.protocol() == Stomp::SPL_10 client.subscribe(dest, :ack => 'auto') { |m| message_copy = m } else sid = client.uuid() @@ -485,7 +487,8 @@ def test_unsubscribe end assert_equal to_send, message_copy.body, "second body check" assert_equal message.headers['message-id'], message_copy.headers['message-id'], "header check" unless ENV['STOMP_RABBIT'] - checkEmsg(@client) + checkEmsg(client) + client.close end # Test subscribe from a worker thread. From 072dfb96fae9a6d94c2a04182dcf2fd64e3dbe99 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 8 Jun 2016 12:10:35 -0400 Subject: [PATCH 44/48] Changes for support of Jruby 1.7.x and 9.x. --- lib/connection/netio.rb | 79 ++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/lib/connection/netio.rb b/lib/connection/netio.rb index 21c7b7d..a945943 100644 --- a/lib/connection/netio.rb +++ b/lib/connection/netio.rb @@ -15,6 +15,8 @@ class Connection def _receive(read_socket, connread = false) # p [ "ioscheck", @iosto, connread ] # _dump_callstack() + # drdbg = true + drdbg = false @read_semaphore.synchronize do line = nil if connread @@ -29,41 +31,45 @@ def _receive(read_socket, connread = false) raise ex end else + p [ "CONR01" ] if drdbg + _dump_callstack() if drdbg line = _init_line_read(read_socket) end # + p [ "nilcheck", line.nil? ] if drdbg return nil if line.nil? #An extra \n at the beginning of the frame, possibly not caught by is_ready? line = '' if line == "\n" - # p [ "wiredatain_01A", line, Time.now ] + p [ "wiredatain_01A", line, Time.now ] if drdbg line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12 - # p [ "wiredatain_01B", line, Time.now ] + p [ "wiredatain_01B", line, Time.now ] if drdbg # Reads the beginning of the message until it runs into a empty line message_header = '' begin message_header += line - # p [ "wiredatain_02A", line, Time.now ] + p [ "wiredatain_02A", line, Time.now ] if drdbg unless connread raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) end - # p [ "wiredatain_02B", line, Time.now ] + p [ "wiredatain_02B", line, Time.now ] if drdbg line = read_socket.gets - # p [ "wiredatain_02C", line ] + p [ "wiredatain_02C", line ] if drdbg raise if line.nil? line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12 - # p [ "wiredatain_02D", line ] + p [ "wiredatain_02D", line ] if drdbg end until line =~ /^\s?\n$/ - # p [ "wiredatain_03A" ] + p [ "wiredatain_03A" ] if drdbg # Checks if it includes content_length header content_length = message_header.match(/content-length\s?:\s?(\d+)\s?\n/) message_body = '' - # p [ "wiredatain_03B", content_length ] + p [ "wiredatain_03B", content_length ] if drdbg # If content_length is present, read the specified amount of bytes if content_length unless connread raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) end + p [ "CL01" ] if drdbg message_body = read_socket.read content_length[1].to_i unless connread raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) @@ -74,11 +80,12 @@ def _receive(read_socket, connread = false) unless connread raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) end + p [ "NOCL01" ] if drdbg message_body = read_socket.readline("\0") message_body.chop! end - # p [ "wiredatain_04" ] + p [ "wiredatain_04" ] if drdbg # If the buffer isn't empty, reads trailing new lines. # # Note: experiments with JRuby seem to show that socket.ready? never @@ -90,10 +97,12 @@ def _receive(read_socket, connread = false) # is read. Do _not_ leave them on the wire and attempt to drain them # at the start of the next read. Attempting to do that breaks the # asynchronous nature of the 'poll' method. + p [ "wiredatain_05_prep", "isr", _is_ready?(read_socket) ] if drdbg while _is_ready?(read_socket) unless connread raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto) end + p [ "WHIR01" ] if drdbg last_char = read_socket.getc break unless last_char if parse_char(last_char) != "\n" @@ -101,32 +110,42 @@ def _receive(read_socket, connread = false) break end end - # p [ "wiredatain_05A" ] + p [ "wiredatain_05A" ] if drdbg if @protocol >= Stomp::SPL_11 @lr = Time.now.to_f if @hbr end # Adds the excluded \n and \0 and tries to create a new message with it - # p [ "wiredatain_05B" ] + p [ "wiredatain_05B" ] if drdbg msg = Message.new(message_header + "\n" + message_body + "\0", @protocol >= Stomp::SPL_11) - # p [ "wiredatain_06", msg.command, msg.headers ] + p [ "wiredatain_06", msg.command, msg.headers ] if drdbg # if @protocol >= Stomp::SPL_11 && msg.command != Stomp::CMD_CONNECTED msg.headers = _decodeHeaders(msg.headers) end - # p [ "wiredatain_99", msg.command, msg.headers ] + p [ "wiredatain_99", msg.command, msg.headers ] if drdbg msg end end - # Check if the socket is ready, i.e. there is data to read. + # + # This is a total hack, to try and guess how JRuby will behave today. + # def _is_ready?(s) rdy = s.ready? - if @jruby - rdy = rdy.class == Fixnum ? true : false + ### p [ "isr?", rdy ] + return rdy unless @jruby + ### p [ "jrdychk", rdy.class ] + if rdy.class == NilClass + # rdy = true + rdy = false # A test + else + rdy = (rdy.class == Fixnum || rdy.class == TrueClass) ? true : false end + ### p [ "isr?_last", rdy ] rdy end + # Normalize line ends because 1.2+ brokers can send 'mixed mode' headers, i.e.: # - Some headers end with '\n' # - Other headers end with '\r\n' @@ -405,15 +424,6 @@ def connect(used_socket) _transmit(used_socket, Stomp::CMD_CONNECT, headers) end @connection_frame = _receive(used_socket, true) -=begin -p [ "connect01" ] - begin - @connection_frame = _receive(used_socket, true) - rescue - p [ "exception", Time.now, $! ] - end -p [ "connect02", @connection_frame ] -=end _post_connect @disconnect_receipt = nil @session = @connection_frame.headers["session"] if @connection_frame @@ -428,10 +438,21 @@ def _init_line_read(read_socket) if @protocol == Stomp::SPL_10 || (@protocol >= Stomp::SPL_11 && !@hbr) if @jruby # Handle JRuby specific behavior. - while true - line = read_socket.gets # Data from wire - break unless line == "\n" - line = '' + ### p [ "ilrjr00", _is_ready?(read_socket), RUBY_VERSION ] + if RUBY_VERSION < "2" + while true + ### p [ "ilrjr01A1", _is_ready?(read_socket) ] + line = read_socket.gets # Data from wire + break unless line == "\n" + line = '' + end + else # RUBY_VERSION >= "2" + while _is_ready?(read_socket) + ### p [ "ilrjr01B2", _is_ready?(read_socket) ] + line = read_socket.gets # Data from wire + break unless line == "\n" + line = '' + end end else line = read_socket.gets # The old way From 10ae8cebd8ed6d2a257aed7ae7547c1639f77090 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 8 Jun 2016 14:18:07 -0400 Subject: [PATCH 45/48] Do not set cipher lists with jruby. --- lib/connection/netio.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/connection/netio.rb b/lib/connection/netio.rb index a945943..c2b97d1 100644 --- a/lib/connection/netio.rb +++ b/lib/connection/netio.rb @@ -319,13 +319,15 @@ def open_ssl_socket() end # Cipher list + # As of this writing, there are numerous problems with supplying + # cipher lists to jruby. So we do not attempt to do that here. if !@ssl.use_ruby_ciphers # No Ruby ciphers (the default) if @ssl.ciphers # User ciphers list? ctx.ciphers = @ssl.ciphers # Accept user supplied ciphers else ctx.ciphers = Stomp::DEFAULT_CIPHERS # Just use Stomp defaults end - end + end unless @jruby # Set SSLContext Options if user asks for it in Stomp::SSLParams # and SSL supports it. @@ -369,6 +371,8 @@ def ssl.ready? ssl.close end # + puts ex.backtrace + $sdtout.flush raise # Reraise end end From 2080df592a3d6e9eb66660b271bc29d9fe55a831 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 8 Jun 2016 17:35:48 -0400 Subject: [PATCH 46/48] Ignore Gemfile.lock. Reference: http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/ --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 1b829af..fe02ef5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,8 @@ coverage/* temp* # Ignore vscode artifacts .vscode/ +# Preventative medicine. +# See: http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/ +# +Gemfile.lock From a4772b418ce2c1c6f32191ce8ca61f88dc09a7f3 Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 8 Jun 2016 17:51:53 -0400 Subject: [PATCH 47/48] Prep for next release. --- CHANGELOG.md | 2 +- README.md | 2 +- stomp.gemspec | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f97cfc..3d7a71a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Stomp Gem Change Log -## 1.4.0 20160603 +## 1.4.0 20160608 * Connection parameter :parse_timeout now means IO:select wait time for socket reads. Consumer clients should see a significantly reduced memory diff --git a/README.md b/README.md index 3bbb9ba..8289d2f 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ A Stomp URL must begin with 'stomp://' and can be in one of the following forms: See _CHANGELOG.rdoc_ for details. -* Gem version 1.4.0. Change sementics of :parse_timeout, see CHANGELOG.rdoc for details. +* Gem version 1.4.0. Note: Change sementics of :parse_timeout, see CHANGELOG.md for details. * Gem version 1.3.5. Miscellaneous fixes, see CHANGELOG.rdoc for details. * Gem version 1.3.4. Miscellaneous fixes, see CHANGELOG.rdoc for details. * Gem version 1.3.3. Miscellaneous fixes, see CHANGELOG.rdoc for details. diff --git a/stomp.gemspec b/stomp.gemspec index 651e40a..be50a3c 100644 --- a/stomp.gemspec +++ b/stomp.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Brian McCallister", "Marius Mathiesen", "Thiago Morello", "Guy M. Allard"] - s.date = %q{2016-06-01} + s.date = %q{2016-06-08} s.description = %q{Ruby client for the Stomp messaging protocol. Note that this gem is no longer supported on rubyforge.} s.email = ["brianm@apache.org", "marius@stones.com", "morellon@gmail.com", "allard.guy.m@gmail.com"] s.executables = ["catstomp", "stompcat"] @@ -92,6 +92,7 @@ Gem::Specification.new do |s| "spec/message_spec.rb", "spec/spec_helper.rb", "stomp.gemspec", + "test/.gitignore", "test/test_anonymous.rb", "test/test_client.rb", "test/test_codec.rb", From cf650b87a4924ae5af9da8344d6be2645cef0b0a Mon Sep 17 00:00:00 2001 From: gmallard Date: Wed, 8 Jun 2016 17:53:37 -0400 Subject: [PATCH 48/48] Name sorting difference. --- stomp.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stomp.gemspec b/stomp.gemspec index be50a3c..640c7c5 100644 --- a/stomp.gemspec +++ b/stomp.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.date = %q{2016-06-08} s.description = %q{Ruby client for the Stomp messaging protocol. Note that this gem is no longer supported on rubyforge.} s.email = ["brianm@apache.org", "marius@stones.com", "morellon@gmail.com", "allard.guy.m@gmail.com"] - s.executables = ["catstomp", "stompcat"] + s.executables = ["stompcat", "catstomp"] s.extra_rdoc_files = [ "LICENSE", "README.md"