rhoconnect 3.0.6 → 3.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/CHANGELOG.md +9 -0
  2. data/Gemfile +3 -3
  3. data/Gemfile.lock +38 -17
  4. data/Rakefile +0 -10
  5. data/bench/benchapp/Gemfile.lock +1 -0
  6. data/bench/distr_bench/distr_bench_main +94 -27
  7. data/bench/distr_bench/run_test_query_script.sh +22 -18
  8. data/bench/lib/bench/aws_utils.rb +326 -0
  9. data/bench/lib/bench/bench_result_processor.rb +268 -75
  10. data/bench/lib/bench/cli.rb +1 -0
  11. data/bench/lib/bench/distr_runner.rb +102 -0
  12. data/bench/lib/bench/utils.rb +127 -0
  13. data/bench/lib/bench.rb +16 -15
  14. data/bench/prepare_bench +3 -11
  15. data/bench/scripts/test_query_script.rb +6 -7
  16. data/bin/rhoconnect-benchmark +257 -5
  17. data/doc/benchmarks-running.txt +140 -0
  18. data/doc/client-java.txt +236 -0
  19. data/doc/client-objc.txt +41 -1
  20. data/doc/client.txt +12 -0
  21. data/doc/command-line.txt +12 -3
  22. data/doc/cud-conflicts.txt +68 -0
  23. data/doc/deploying.txt +1 -70
  24. data/doc/hosting-rhohub.txt +3 -0
  25. data/doc/install.txt +50 -13
  26. data/doc/java-plugin.txt +217 -177
  27. data/doc/net-plugin.txt +97 -64
  28. data/doc/plugin-intro.txt +4 -2
  29. data/doc/preparing-production.txt +63 -0
  30. data/doc/rhoconnect-redis-stack.txt +252 -0
  31. data/doc/source-adapters.txt +3 -1
  32. data/doc/tutorial.txt +111 -49
  33. data/examples/simple/dump.rdb +0 -0
  34. data/installer/unix-like/rho_connect_install_constants.rb +6 -5
  35. data/installer/unix-like/rho_connect_install_installers.rb +6 -2
  36. data/installer/utils/nix_install_test.rb +2 -0
  37. data/installer/utils/package_upload/auto-repo.rb +136 -0
  38. data/installer/utils/package_upload/repos.rake +6 -3
  39. data/installer/utils/package_upload/s3_upload.rb +11 -6
  40. data/installer/windows/rhosync.nsi +5 -5
  41. data/lib/rhoconnect/client_sync.rb +2 -2
  42. data/lib/rhoconnect/document.rb +12 -0
  43. data/lib/rhoconnect/jobs/source_job.rb +2 -2
  44. data/lib/rhoconnect/predefined_adapters/bench_adapter.rb +61 -0
  45. data/lib/rhoconnect/source.rb +5 -0
  46. data/lib/rhoconnect/source_adapter.rb +10 -1
  47. data/lib/rhoconnect/source_sync.rb +161 -88
  48. data/lib/rhoconnect/store.rb +48 -0
  49. data/lib/rhoconnect/test_methods.rb +6 -6
  50. data/lib/rhoconnect/version.rb +1 -1
  51. data/lib/rhoconnect.rb +25 -2
  52. data/spec/apps/rhotestapp/sources/sample_adapter.rb +29 -0
  53. data/spec/jobs/source_job_spec.rb +5 -5
  54. data/spec/source_adapter_spec.rb +10 -0
  55. data/spec/source_sync_spec.rb +114 -33
  56. data/spec/spec_helper.rb +21 -2
  57. data/spec/store_spec.rb +29 -0
  58. data/spec/support/shared_examples.rb +1 -1
  59. data/spec/test_methods_spec.rb +4 -4
  60. data/tasks/redis.rake +2 -2
  61. metadata +59 -59
  62. data/bench/benchapp/log/passenger.3000.log +0 -1
  63. data/bench/benchapp/log/passenger.9292.log +0 -59
  64. data/bench/benchapp/tmp/pids/passenger.3000.pid.lock +0 -0
  65. data/bench/benchapp/tmp/pids/passenger.9292.pid.lock +0 -0
  66. data/bench/lib/testdata/0-data.txt +0 -0
  67. data/bench/lib/testdata/1-data.txt +0 -0
  68. data/bench/lib/testdata/10-data.txt +0 -15
  69. data/bench/lib/testdata/2-data.txt +0 -3
  70. data/bench/lib/testdata/25-data.txt +0 -39
  71. data/bench/lib/testdata/250-data.txt +0 -353
  72. data/bench/lib/testdata/3-data.txt +0 -4
  73. data/bench/lib/testdata/50-data.txt +0 -70
  74. data/bench/lib/testdata/500-data.txt +0 -711
@@ -0,0 +1,102 @@
1
+ module Bench
2
+ class DistrRunner
3
+
4
+ attr_accessor :start_time, :end_time, :clients_group
5
+ attr_accessor :total_count, :times_count, :times_sum
6
+
7
+ def initialize(clientgroup)
8
+ @clients_group = clientgroup
9
+ end
10
+
11
+ def run(server, sync_key, payload, concurrency, niterations, result_filename=nil)
12
+ # 1) Extract server name
13
+ server ||= 'default'
14
+ if server != 'default'
15
+ Bench.base_url = server
16
+ end
17
+
18
+ # 2) Simulate the payload
19
+ Bench.datasize = payload.to_i
20
+ expected_data = Bench.get_test_data(Bench.datasize)
21
+ Bench.concurrency = concurrency.to_i
22
+ Bench.iterations = niterations.to_i
23
+
24
+ # 3) extract result filename
25
+ Bench.result_filename = result_filename
26
+
27
+ # 4) Set up the server
28
+ begin
29
+ Bench.admin_login = 'rhoadmin'
30
+ Bench.admin_password = ''
31
+ Bench.get_test_server
32
+ Bench.reset_app
33
+ Bench.user_name = "benchuser"
34
+ Bench.password = "password"
35
+ Bench.set_server_state("test_db_storage:application:#{Bench.user_name}",expected_data)
36
+ Bench.reset_refresh_time('RhoInternalBenchmarkAdapter')
37
+
38
+ #6) set the sync key
39
+ @start_time = Time.now + 10.0
40
+ Bench.set_server_state(sync_key, @start_time.to_f.to_s)
41
+ puts "Sync Key #{sync_key} is set to #{@start_time} - waiting for clients now!!!"
42
+
43
+ #7) Start-up all clients
44
+ command="cd /opt/rhoconnect/bin; ruby run_client_benchmark #{server} #{sync_key} #{niterations} 1 #{Bench.datasize} 1>/dev/null"
45
+ ec2_clients = clients_group.client_instances[0,concurrency]
46
+ Bench::AWSUtils.run_stack_ssh_command(ec2_clients, command)
47
+
48
+ #8) Wait until the command is done and save all data to the disk
49
+ sleep(1)
50
+ @total_count = 0
51
+ @start_time = 0.0
52
+ @end_time = 0.0
53
+ @times_sum = 0.0
54
+ @times_count = 0
55
+ process_results
56
+ save_results
57
+
58
+ #9) Clean-up the db
59
+ Bench.reset_app
60
+ rescue Exception => e
61
+ puts "Distributed Bench Runner ERROR !!!"
62
+ puts e.message
63
+ puts e.backtrace.join("\n")
64
+ end
65
+ end
66
+
67
+ def process_results
68
+ finished_data = Bench.get_server_state("bench_statistics_data")
69
+ finished_data.each do |session,session_data|
70
+ puts "Client data for #{session} : startTime (#{session_data['start_time']}), endTime (#{session_data['end_time']})"
71
+ @total_count += session_data['count'].to_i
72
+ @start_time = session_data['start_time'].to_f unless @start_time > 0.0 and session_data['start_time'].to_f >= @start_time
73
+ @end_time = session_data['end_time'].to_f unless session_data['end_time'].to_f <= @end_time
74
+ if not session_data['times'].nil?
75
+ times_data = session_data['times'].split(',')
76
+ @times_count += times_data.size
77
+ times_data.each do |timevalue|
78
+ @times_sum += timevalue.to_f
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def average_time
85
+ @times_count > 0 ? @times_sum/@times_count : 0.0
86
+ end
87
+
88
+ def save_results
89
+ return if Bench.result_filename.nil?
90
+
91
+ res_hash = YAML.load_file(Bench.result_filename) if File.exist?(Bench.result_filename)
92
+ res_hash ||= {}
93
+ puts "Overall results are : startTime (#{@start_time.to_s}), endTime (#{@end_time.to_s}), count (#{@total_count.to_s}), payload (#{Bench.datasize}), concurrency (#{Bench.concurrency})"
94
+ res_hash[Bench.concurrency.to_s] = (@end_time > 0.0 and @start_time > 0.0) ? [@total_count/(@end_time - @start_time)] : [0.0]
95
+ res_hash[Bench.concurrency.to_s] << average_time
96
+ File.open(Bench.result_filename, 'w' ) do |file|
97
+ file.write res_hash.to_yaml unless res_hash.empty?
98
+ end
99
+ end
100
+
101
+ end
102
+ end
@@ -53,5 +53,132 @@ module Bench
53
53
  0
54
54
  end
55
55
  end
56
+
57
+ def create_subdir(dir)
58
+ begin
59
+ if File.directory? dir
60
+ dir += '_' + Time.now.strftime("%Y_%m_%d_%H_%M_%S")
61
+ end
62
+ Dir.mkdir(dir)
63
+ dir
64
+ rescue
65
+ end
66
+ end
67
+
68
+ def load_settings(file)
69
+ begin
70
+ return YAML.load_file(file)
71
+ rescue Exception => e
72
+ puts "Error opening settings file #{file}: #{e}."
73
+ puts e.backtrace.join("\n")
74
+ raise e
75
+ end
76
+ end
77
+
78
+ def start_rhoconnect_app(options)
79
+ options[:app_started] = false
80
+ path = options[:start_server] || '.'
81
+ if not File.exists?(File.join(path,'settings','settings.yml'))
82
+ puts " Invalid Rhoconnect app path '#{path}' - no app files can be found there"
83
+ return false
84
+ end
85
+ settings = load_settings(File.join(path,'settings','settings.yml'))
86
+ app_url = settings[:production][:syncserver].gsub(/\/$/,'')
87
+
88
+ uri = URI.parse(app_url)
89
+ port = (uri.port and uri.port != 80) ? ":"+uri.port.to_s : ""
90
+ options[:server_url] = "#{uri.scheme}://#{uri.host}#{port}"
91
+
92
+ already_running = check_rc_service(options[:server_url])
93
+ if already_running
94
+ puts " Another Rhoconnect Application is already running at '#{options[:server_url]}'"
95
+ return false
96
+ end
97
+
98
+ # start the app now
99
+ puts "Starting up the Rhoconnect Application at #{options[:server_url]}"
100
+ current_dir = Dir.pwd
101
+ Dir.chdir(path)
102
+ exit_code = system("rake rhoconnect:startbg")
103
+ sleep 1
104
+ Dir.chdir(current_dir)
105
+
106
+ options[:app_started] = check_rc_service(options[:server_url])
107
+ end
108
+
109
+ def stop_rhoconnect_app(options)
110
+ return unless options[:app_started] == true
111
+
112
+ path = options[:start_server] || '.'
113
+ if not File.exists?(File.join(path,'settings','settings.yml'))
114
+ puts " Invalid Rhoconnect app path '#{path}' - no app files can be found there"
115
+ return
116
+ end
117
+ puts "Stopping the Rhoconnect Application at #{options[:server_url]}"
118
+ current_dir = Dir.pwd
119
+ Dir.chdir(path)
120
+ system("rake rhoconnect:stop")
121
+ sleep 1
122
+ Dir.chdir(current_dir)
123
+ end
124
+
125
+ # check_rc_service
126
+ # Makes an HTTP request to check that the rhoconnect app is up and running
127
+ def check_rc_service(server_name)
128
+ success = false
129
+ begin
130
+ request = Net::HTTP.get_response(URI.parse("#{server_name}/console"))
131
+ if request.code == '200'
132
+ success = true
133
+ end
134
+ rescue
135
+ end
136
+ success
137
+ end #check_rc_service
138
+
139
+ # prepare bench results
140
+ def prepare_bench_results_dirs(dir)
141
+ start_dir = Dir.pwd
142
+ Dir.chdir dir
143
+
144
+ # create result directory structure
145
+ ['bench_results'].each do |dir|
146
+ next if dir.nil?
147
+ created_dir = Bench.create_subdir dir
148
+ Dir.chdir created_dir
149
+ end
150
+ result_dir = Dir.pwd
151
+ ['raw_data'].each do |dir|
152
+ Bench.create_subdir dir
153
+ end
154
+
155
+ Dir.chdir start_dir
156
+ result_dir
157
+ end
158
+
159
+ def prepare_bench_results_meta(dir, title, x_keys)
160
+ title ||= "Results"
161
+
162
+ start_dir = Dir.pwd
163
+ Dir.chdir(dir)
164
+
165
+ # 3) create meta.yml file
166
+ meta_hash = {:x_keys => {}, :metrics => {}, :label => title}
167
+ counter = 0
168
+ x_keys = x_keys.sort_by(&Bench.sort_natural_order)
169
+ x_keys.each do |x_key|
170
+ meta_hash[:x_keys][x_key] = counter
171
+ counter += 1
172
+ end
173
+
174
+ meta_hash[:metrics] = {'Throughput' => 0, 'Av.Time' => 1}
175
+
176
+ File.open(File.join(dir,'raw_data','meta.yml'), 'w') do |file|
177
+ file.write meta_hash.to_yaml unless meta_hash.empty?
178
+ end
179
+
180
+ Dir.chdir start_dir
181
+ true
182
+ end
56
183
  end
57
184
  end
data/bench/lib/bench.rb CHANGED
@@ -4,6 +4,7 @@ $:.unshift File.dirname(__FILE__)
4
4
  require 'bench/timer'
5
5
  require 'bench/logging'
6
6
  require 'bench/utils'
7
+ require 'bench/bench_result_processor'
7
8
  require 'bench/result'
8
9
  require 'bench/session'
9
10
  require 'bench/runner'
@@ -53,6 +54,14 @@ module Bench
53
54
  end
54
55
  end
55
56
 
57
+ def get_server_license_info
58
+ token = get_token
59
+ params = {:api_token => token}
60
+ @body = RestClient.post("#{@host}/api/admin/get_license_info",
61
+ params.to_json, :content_type => :json)
62
+ JSON.parse(@body.to_s)
63
+ end
64
+
56
65
  def get_server_state(doc)
57
66
  token = get_token
58
67
  params = {:api_token => token, :doc => doc}
@@ -110,15 +119,18 @@ module Bench
110
119
  def get_test_server(app_name = nil)
111
120
  if @base_url.nil?
112
121
  app_name = 'benchapp' unless app_name
113
- load_settings(File.join(File.dirname(__FILE__),'..',app_name,'settings','settings.yml'))
114
- @base_url = $settings[:development][:syncserver].gsub(/\/$/,'')
122
+ settings = load_settings(File.join(File.dirname(__FILE__),'..',app_name,'settings','settings.yml'))
123
+ @base_url = settings[:development][:syncserver].gsub(/\/$/,'')
115
124
  end
116
125
  uri = URI.parse(@base_url)
117
- port = (uri.port and uri.port != 80) ? ":"+uri.port.to_s : ""
126
+ port = (uri.port and uri.port != 80) ? ":"+uri.port.to_s : ""
127
+ if not uri.scheme
128
+ raise "URI '#{@base_url}' is invalid:\n\t- doesn't have the required scheme part (for example , http://)"
129
+ end
118
130
  @host = "#{uri.scheme}://#{uri.host}#{port}"
119
131
  puts "Test server is #{@host}..."
120
132
  end
121
-
133
+
122
134
  def test(&block)
123
135
  Runner.new.test(@concurrency,@iterations,&block)
124
136
  end
@@ -140,16 +152,5 @@ module Bench
140
152
  end
141
153
  archive
142
154
  end
143
-
144
- # TODO: Share this code with the framework Rho class
145
- def load_settings(file)
146
- begin
147
- $settings = YAML.load_file(file)
148
- rescue Exception => e
149
- puts "Error opening settings file #{file}: #{e}."
150
- puts e.backtrace.join("\n")
151
- raise e
152
- end
153
- end
154
155
  end
155
156
  end
data/bench/prepare_bench CHANGED
@@ -4,27 +4,19 @@ require 'rubygems'
4
4
  $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
5
5
  require 'bench'
6
6
 
7
- def create_subdir(dir)
8
- begin
9
- Dir.mkdir(dir)
10
- rescue
11
- end
12
- end
13
-
14
7
  # 1) Extract Bench title
15
8
  title = ARGV[0]
16
9
 
17
-
18
10
  # 2) create result directory structure
19
11
  ['bench_results', ARGV[1]].each do |dir|
20
12
  next if dir.nil?
21
- create_subdir dir
13
+ Bench.create_subdir dir
22
14
  Dir.chdir dir
23
15
  end
24
16
  result_dir = Dir.pwd
25
17
 
26
- ['raw_data', 'images'].each do |dir|
27
- create_subdir dir
18
+ ['raw_data'].each do |dir|
19
+ Bench.create_subdir dir
28
20
  end
29
21
 
30
22
  # 3) create meta.yml file
@@ -2,15 +2,14 @@ include BenchHelpers
2
2
  bench_log "Runs simple login,clientcreate,clientregister,sync session and validates response"
3
3
 
4
4
  Bench.config do |config|
5
- config.concurrency ||= 10
5
+ config.concurrency ||= 1
6
6
  config.iterations ||= 10
7
7
  config.datasize ||= 100
8
8
  config.main_marker = 'get-cud'
9
9
  config.user_name = "benchuser"
10
10
  config.password = "password"
11
11
  config.get_test_server
12
- @datasize = Bench.datasize
13
- @expected = Bench.get_test_data(@datasize)
12
+ @datasize = Bench.datasize
14
13
  @all_objects = "[{\"version\":3},{\"token\":\"%s\"},{\"count\":%i},{\"progress_count\":0},{\"total_count\":%i},{\"insert\":""}]"
15
14
  @ack_token = "[{\"version\":3},{\"token\":\"\"},{\"count\":0},{\"progress_count\":%i},{\"total_count\":%i},{}]"
16
15
  @api_token = Bench.get_token
@@ -19,8 +18,9 @@ Bench.config do |config|
19
18
  # if this is not a distributed run - reset the app
20
19
  if not Bench.sync_key
21
20
  config.reset_app
21
+ @expected = Bench.get_test_data(@datasize)
22
22
  config.set_server_state("test_db_storage:application:#{config.user_name}",@expected)
23
- config.reset_refresh_time('MockAdapter')
23
+ config.reset_refresh_time('RhoInternalBenchmarkAdapter')
24
24
  end
25
25
  end
26
26
 
@@ -34,7 +34,6 @@ Bench.synchronize do |config|
34
34
  end
35
35
  sleep(0.010)
36
36
  end
37
- puts " we have here #{cur_time}, #{sync_time}"
38
37
  end
39
38
 
40
39
  Bench.test do |config,session|
@@ -50,11 +49,11 @@ Bench.test do |config,session|
50
49
  end
51
50
 
52
51
  session.get "get-cud", "#{config.base_url}/query" do
53
- {'source_name' => 'MockAdapter', 'client_id' => session.client_id, 'p_size' => @datasize}
52
+ {'source_name' => 'RhoInternalBenchmarkAdapter', 'client_id' => session.client_id, 'p_size' => @datasize}
54
53
  end
55
54
  token = JSON.parse(session.last_result.body)[1]['token']
56
55
  session.get "ack-cud", "#{config.base_url}/query" do
57
- { 'source_name' => 'MockAdapter',
56
+ { 'source_name' => 'RhoInternalBenchmarkAdapter',
58
57
  'client_id' => session.client_id,
59
58
  'token' => token}
60
59
  end
@@ -4,10 +4,262 @@ require 'rubygems'
4
4
  $:.unshift File.join(File.dirname(__FILE__),'..','bench','lib')
5
5
  $:.unshift File.join(File.dirname(__FILE__),'..','bench')
6
6
  require 'bench'
7
+ require 'optparse'
7
8
 
8
- $ARGV.unshift ''
9
- $ARGV.unshift 'rhoadmin'
10
- $ARGV.unshift 'scripts/test_comm_script.rb'
11
- $ARGV.unshift 'start'
9
+ ENV['RACK_ENV']='production'
12
10
 
13
- Bench::Cli.start
11
+ RHOCONNECT_PATH = File.join(File.dirname(__FILE__),'..')
12
+ puts "Rhoconnect-Benchmark Script is started at #{Time.now.to_s}"
13
+
14
+ def parse_options
15
+ begin
16
+ options = {}
17
+ optparse = OptionParser.new do |opts|
18
+ # Set a banner, displayed at the top
19
+ # of the help screen.
20
+ opts.banner = "Usage: rhoconnect-benchmark [options]"
21
+
22
+ options[:server_url] = 'http://localhost:9292'
23
+ opts.on( '-u', '--url URL', 'Use URL as a server for benchmarking' ) do |url|
24
+ options[:server_url] = url
25
+ end
26
+
27
+ options[:start_server] = nil
28
+ opts.on( '-s', '--startserver [APP_PATH]', 'Starts Rhoconnect App Server on localhost and use it for benchmarking' ) do |path|
29
+ options[:start_server] = path || '.'
30
+ end
31
+
32
+ options[:num_clients] = 0
33
+ opts.on( '-C', '--nclients NUMBER', 'Number of concurrent clients to use' ) do |number|
34
+ options[:num_clients] = number
35
+ end
36
+
37
+ options[:num_iterations] = 10
38
+ opts.on( '-R', '--niterations NUMBER', 'Number of iterations to run benchmark test on each client (default - 10)' ) do |number|
39
+ options[:num_iterations] = number
40
+ end
41
+
42
+ options[:payload] = 100
43
+ opts.on( '-p', '--payload NUMBER', 'Simulate payload (number of records), default - 100 recs (~20K)' ) do |number|
44
+ options[:payload] = number
45
+ end
46
+
47
+ options[:max_payload] = 100
48
+ opts.on( '-x', '--mapayload NUMBER', 'Run the benchmarks test varying the payload from 1 to NUMBER' ) do |number|
49
+ options[:max_payload] = number
50
+ options[:payload] = number
51
+ end
52
+
53
+ options[:max_clients] = 1
54
+ opts.on( '-m', '--maxclientloops NUMBER', 'Run the benchmarks test varying the number of clients from 1 to NUMBER' ) do |number|
55
+ options[:max_clients] = number
56
+ options[:num_clients] = number
57
+ end
58
+
59
+ options[:max_payload] = 0
60
+ opts.on( '-x', '--mapayload NUMBER', 'Run the benchmarks test varying the payload from 1 to NUMBER' ) do |number|
61
+ options[:max_payload] = number
62
+ options[:payload] = number
63
+ end
64
+
65
+ options[:save_results] = nil
66
+ options[:title] = 'QUERY'
67
+ opts.on( '-S', '--save [PATH]', 'Save all benchmark results in to the file structure at PATH') do |path|
68
+ options[:save_results] = path || '.'
69
+ options[:title] ||= 'QUERY'
70
+ end
71
+
72
+ opts.on('-t', '--title TITLE', "Name this benchmark's test results with the title TITLE") do |title|
73
+ options[:title] = title
74
+ end
75
+
76
+ opts.on( '-A', '--advanced', 'This convinience option combines -m 10 and -x 500') do
77
+ options[:max_payload] = 500
78
+ options[:payload] = 500
79
+ options[:max_clients] = 10
80
+ options[:num_clients] = 10
81
+ options[:title] ||= "QUERY"
82
+ options[:save_results] = '.'
83
+ end
84
+
85
+ options[:distributed] = nil
86
+ opts.on('-D', '--distributed FNAME', 'Run benchmark test from distributed AWS Cloud Formation using FNAME for options') do |fname|
87
+ options[:max_payload] = 500
88
+ options[:payload] = 500
89
+ options[:max_clients] = 10
90
+ options[:num_clients] = 10
91
+ options[:title] ||= "QUERY"
92
+ options[:save_results] = '.'
93
+ options[:distributed] = fname
94
+ end
95
+
96
+ # This displays the help screen, all programs are
97
+ # assumed to have this option.
98
+ opts.on( '-h', '--help', 'Display rhoconnect-benchmark help information' ) do
99
+ puts opts
100
+ exit 0
101
+ end
102
+ end
103
+
104
+ optparse.parse!
105
+ rescue SystemExit => se
106
+ exit 0
107
+ rescue Exception => e
108
+ puts " Error while parsing the command line options: #{e.message}"
109
+ puts ""
110
+ puts optparse.help
111
+ puts ""
112
+ raise ""
113
+ end
114
+
115
+ options
116
+ end
117
+
118
+ begin
119
+ options = parse_options
120
+ # 1) start up the application - if required
121
+ # NOTE: server URL will be updated
122
+ # from the app's settings
123
+ if options[:start_server] != nil
124
+ if not Bench.start_rhoconnect_app(options)
125
+ puts " Cannot start rhoconnect application at path '#{options[:start_server]}'"
126
+ puts " Exiting..."
127
+ exit 10
128
+ end
129
+ end
130
+
131
+ # 2) Now, parse the server's options
132
+ Bench.base_url = "#{options[:server_url]}/api/application"
133
+ Bench.get_test_server
134
+ Bench.admin_login = 'rhoadmin'
135
+ Bench.admin_password = ''
136
+ #
137
+ if not Bench.check_rc_service(Bench.host)
138
+ puts ""
139
+ puts " In order to run benchmark tests - you need to have the Rhoconnect application"
140
+ puts " up and running on #{options[:server_url]}"
141
+ puts ""
142
+ exit 10
143
+ end
144
+
145
+ # get license info from the server
146
+ rc_license_info = Bench.get_server_license_info
147
+
148
+ if options[:num_clients] == 0
149
+ n_clients = rc_license_info['seats'].to_i / options[:num_iterations]
150
+ if n_clients > 20
151
+ n_clients = 20
152
+ end
153
+ options[:num_clients] = n_clients
154
+ end
155
+ # calculate appropriate numbers for concurrency
156
+ total_num_clients = options[:num_iterations].to_i*options[:num_clients].to_i
157
+ if total_num_clients > rc_license_info['seats']
158
+ puts ""
159
+ puts " In order to run benchmark tests with #{options[:num_clients]} concurrent clients"
160
+ puts " for #{options[:num_iterations]} iterations you need to have a license with at least #{total_num_clients} seats."
161
+ puts " Your application have only #{rc_license_info['seats']} seats available."
162
+ puts " Adjust the number of concurrent clients or number of iterations to fit within the available license."
163
+ puts ""
164
+ exit 10
165
+ end
166
+
167
+ # run test in a loop from 1 to max_clients concurrency
168
+ concurrency_array = []
169
+ if options[:max_clients].to_i > 1
170
+ concurrency_array << 1
171
+ num_loops = 5
172
+ loop_step = (options[:max_clients].to_f - 1.to_f)/(num_loops - 1)
173
+ for i in 1..num_loops-2
174
+ concurrency_array << (1 + i*loop_step + 0.5).to_i
175
+ end
176
+ end
177
+ concurrency_array << options[:num_clients].to_i
178
+ concurrency_array.uniq!
179
+
180
+ # run test in a loop from 1 to max_payload records
181
+ payload_array = []
182
+ if options[:max_payload].to_i > 1
183
+ payload_array << 1
184
+ num_loops = 10
185
+ loop_step = (options[:max_payload].to_f - 1.to_f)/(num_loops - 1)
186
+ for i in 1..num_loops-2
187
+ payload_array << (1 + i*loop_step + 0.5).to_i
188
+ end
189
+ end
190
+ payload_array << options[:payload].to_i
191
+ payload_array.uniq!
192
+
193
+ # load distributed options and create the AWS Cloud Formation Stack
194
+ if options[:distributed] != nil
195
+ puts ""
196
+ puts " Creating Distributed Clients Benchmark"
197
+ puts ""
198
+ require 'bench/aws_utils'
199
+ require 'bench/distr_runner'
200
+ Bench::AWSUtils.init_connection(options[:distributed])
201
+ options[:clients_group] = nil
202
+ options[:clients_group] = Bench::AWSUtils.create_cf_stack
203
+ exit 10 unless options[:clients_group]
204
+ options[:distr_runner] = Bench::DistrRunner.new options[:clients_group]
205
+ end
206
+
207
+ # load the save results options
208
+ result_dir = nil
209
+ if options[:save_results]
210
+ result_dir = Bench.prepare_bench_results_dirs(options[:save_results])
211
+ x_keys = concurrency_array.collect {|t| t.to_s }
212
+ Bench.prepare_bench_results_meta(result_dir, options[:title], x_keys)
213
+ end
214
+
215
+ concurrency_array.each do |concurrency|
216
+ payload_array.each do |payload|
217
+ # initialize default parameters
218
+ bench_args = []
219
+ # Thor's task
220
+ bench_args[0] = 'start'
221
+ # script
222
+ bench_args[1] = 'scripts/test_query_script.rb'
223
+ # admin
224
+ bench_args[2] = 'rhoadmin'
225
+ # admin's password
226
+ bench_args[3] = ''
227
+ # server's URL
228
+ bench_args[4] = Bench.base_url
229
+ # result fname
230
+ result_fname = nil
231
+ result_fname = File.join(result_dir,'raw_data',"bench_result.#{payload}") if result_dir
232
+ bench_args[5] = result_fname
233
+ # concurrency
234
+ bench_args[6] = concurrency
235
+ # number of iterations
236
+ bench_args[7] = options[:num_iterations]
237
+ # datasize
238
+ bench_args[8] = payload
239
+
240
+ # now execute Bench
241
+ if(options[:distributed])
242
+ sync_key = "#{options[:title]}_#{payload}"
243
+ options[:distr_runner].run(Bench.base_url, sync_key, payload, concurrency, options[:num_iterations], result_fname)
244
+ else
245
+ Bench::Cli.start bench_args
246
+ end
247
+ end
248
+ end
249
+
250
+ # once finished - post-process results
251
+ Bench::PostProcessing.execute result_dir
252
+ rescue Exception => e
253
+ puts e.message
254
+ ensure
255
+ if options and options[:app_started] == true
256
+ Bench.stop_rhoconnect_app(options)
257
+ end
258
+
259
+ if options and options[:clients_group]
260
+ Bench::AWSUtils.delete_cf_stack(options[:clients_group].stack_name)
261
+ end
262
+ end
263
+
264
+ puts "Rhoconnect-Benchmark Script is finished at #{Time.now.to_s}"
265
+ puts ""