cosmos 3.3.1 → 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb2fffb8f204bc932ef93438457c310503837e2f
4
- data.tar.gz: 6ecd99712d7682a2d70de2539c03826502868cc9
3
+ metadata.gz: d82d5f0bf5ba66085f85878c642a00882a44eae6
4
+ data.tar.gz: 06f95196ee1a8cef8a806a51ceff0bebfeb480e8
5
5
  SHA512:
6
- metadata.gz: e3b958ffc7000f284188567ae8cf57934288373617682208b913767b2d230cdeb05b98f55745347d9d6ad12ab5d4874e1a8c6f29f379baccbaf4a3f2f21c4253
7
- data.tar.gz: c3b6704c2d87fdc6a9413eab98be998fe278a364f2097776521610a876b605c3eb6b0876dd349a5f523ea5255ad7df6259769fe111d6be439b18ebfd6b3389a9
6
+ metadata.gz: e73b10b1c4ef740738c03421e698c4f6d5a1ecee377d7f147a10b28f6919a1cd0bc05a8d4db31d4cdf88232ca700df733969f594edeb32d5e3d7311faf1aa116
7
+ data.tar.gz: 03006e36721d7afcf22adcb05cc2f056d32f7d6f83270437de56a0ffbe07d1c09aa15eeb5c6a69138a46401dd537d849f0a126e77f59fceb1a4f45dbde01207c
@@ -90,7 +90,7 @@
90
90
  "lib/cosmos/gui/choosers/combobox_chooser.rb" 0xAD5383D5
91
91
  "lib/cosmos/gui/choosers/float_chooser.rb" 0x23B2FA77
92
92
  "lib/cosmos/tools/script_runner/script_runner_config.rb" 0x1E46E8AA
93
- "lib/cosmos/tools/script_runner/script_runner_frame.rb" 0xB999FC77
93
+ "lib/cosmos/tools/script_runner/script_runner_frame.rb" 0xF3F14036
94
94
  "lib/cosmos/tools/script_runner/script_runner.rb" 0x88EEB809
95
95
  "lib/cosmos/tools/script_runner/script_audit.rb" 0xB857FA4A
96
96
  "lib/cosmos/tools/cmd_extractor/cmd_extractor.rb" 0xEECB31B8
@@ -234,7 +234,7 @@
234
234
  "lib/cosmos/tools/tlm_viewer/tlm_viewer.rb" 0x1D2090F6
235
235
  "lib/cosmos/system.rb" 0x735DFB42
236
236
  "lib/cosmos/conversions.rb" 0x43679D05
237
- "lib/cosmos/version.rb" 0xFED34D5F
237
+ "lib/cosmos/version.rb" 0x1CF2C150
238
238
  "lib/cosmos/core_ext.rb" 0x1951B346
239
239
  "lib/cosmos/interfaces.rb" 0x7E3EA326
240
240
  "lib/cosmos/processors.rb" 0x5241327D
@@ -267,7 +267,7 @@
267
267
  "lib/cosmos/packets/parsers/limits_response_parser.rb" 0x05979119
268
268
  "lib/cosmos/packets/packet_config.rb" 0xFDD8F251
269
269
  "lib/cosmos/packets/binary_accessor.rb" 0xF913F2EA
270
- "lib/cosmos/packets/packet.rb" 0x39B6C0C4
270
+ "lib/cosmos/packets/packet.rb" 0x043EF800
271
271
  "lib/cosmos/packets/structure_item.rb" 0xBDC81085
272
272
  "lib/cosmos/packets/packet_item_limits.rb" 0xE187C389
273
273
  "lib/cosmos/packets/packet_item.rb" 0x2A07D5B4
@@ -277,7 +277,7 @@
277
277
  "lib/cosmos/processors/watermark_processor.rb" 0xDADF4580
278
278
  "lib/cosmos/io/stdout.rb" 0xAC9CC4B1
279
279
  "lib/cosmos/io/buffered_file.rb" 0x70A3B880
280
- "lib/cosmos/io/json_drb_object.rb" 0x58BE861D
280
+ "lib/cosmos/io/json_drb_object.rb" 0x9825D709
281
281
  "lib/cosmos/io/cosmos_snmp.rb" 0x64541158
282
282
  "lib/cosmos/io/json_rpc.rb" 0xAF9D95D5
283
283
  "lib/cosmos/io/tcpip_server.rb" 0xBAA24660
@@ -286,7 +286,7 @@
286
286
  "lib/cosmos/io/serial_driver.rb" 0x9A2515F4
287
287
  "lib/cosmos/io/raw_logger_pair.rb" 0x7A0A3F00
288
288
  "lib/cosmos/io/raw_logger.rb" 0x42BC42CC
289
- "lib/cosmos/io/json_drb.rb" 0x53EC6DBC
289
+ "lib/cosmos/io/json_drb.rb" 0x878C8A71
290
290
  "lib/cosmos/io/stderr.rb" 0x401624AF
291
291
  "lib/cosmos/io/io_multiplexer.rb" 0xD183938D
292
292
  "lib/cosmos/io/win32_serial_driver.rb" 0xA7E055CA
@@ -299,7 +299,7 @@
299
299
  "lib/cosmos/interfaces/tcpip_client_interface.rb" 0x5F0DB50D
300
300
  "lib/cosmos/interfaces/udp_interface.rb" 0xCE4532AD
301
301
  "lib/cosmos/interfaces/tcpip_server_interface.rb" 0xC8F6E908
302
- "lib/cosmos/script/script.rb" 0x06BF2D5F
302
+ "lib/cosmos/script/script.rb" 0x472901A7
303
303
  "lib/cosmos/script/extract.rb" 0xF3243476
304
304
  "lib/cosmos/core_ext/range.rb" 0x0D55D9D1
305
305
  "lib/cosmos/core_ext/stringio.rb" 0x28B64FB4
@@ -30,8 +30,6 @@ module Cosmos
30
30
 
31
31
  # @return [Integer] The number of JSON-RPC requests processed
32
32
  attr_accessor :request_count
33
- # @return [Integer] The number of clients currently connected to the server
34
- attr_accessor :num_clients
35
33
  # @return [Array<String>] List of methods that should be allowed
36
34
  attr_accessor :method_whitelist
37
35
  # @return [ACL] The access control list
@@ -47,16 +45,42 @@ module Cosmos
47
45
  @request_times = []
48
46
  @request_times_index = 0
49
47
  @request_mutex = Mutex.new
50
- @num_clients = 0
48
+ @client_sockets = []
49
+ @client_threads = []
50
+ @client_mutex = Mutex.new
51
51
  @thread_reader, @thread_writer = IO.pipe
52
52
  end
53
53
 
54
+ # Returns the number of connected clients
55
+ # @return [Integer] The number of connected clients
56
+ def num_clients
57
+ @client_threads.length
58
+ end
59
+
54
60
  # Stops the DRb service by closing the socket and the processing thread
55
61
  def stop_service
56
62
  Cosmos.kill_thread(self, @thread)
57
63
  @thread = nil
58
64
  Cosmos.close_socket(@listen_socket)
59
65
  @listen_socket = nil
66
+ client_threads = nil
67
+ @client_mutex.synchronize do
68
+ @client_sockets.each do |client_socket|
69
+ Cosmos.close_socket(client_socket)
70
+ end
71
+ client_threads = @client_threads.clone
72
+ end
73
+
74
+ # This cannot be inside of the client_mutex or the threads will not
75
+ # be able to shutdown because they will stick on the client_mutex
76
+ client_threads.each do |client_thread|
77
+ Cosmos.kill_thread(self, client_thread)
78
+ end
79
+
80
+ @client_mutex.synchronize do
81
+ @client_threads.clear
82
+ @client_sockets.clear
83
+ end
60
84
  end
61
85
 
62
86
  # Gracefully kill the thread
@@ -254,7 +278,11 @@ module Cosmos
254
278
  socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
255
279
 
256
280
  Thread.new(socket) do |my_socket|
257
- @num_clients += 1
281
+ @client_mutex.synchronize do
282
+ @client_sockets << my_socket
283
+ @client_threads << Thread.current
284
+ end
285
+
258
286
  data = ''
259
287
  begin
260
288
  while true
@@ -270,14 +298,18 @@ module Cosmos
270
298
  break unless process_request(request_data, my_socket, start_time)
271
299
  else
272
300
  # Socket was closed by client
273
- Cosmos.close_socket(my_socket)
274
301
  break
275
302
  end
276
303
  end
277
304
  rescue Exception => error
278
305
  Logger.error "JsonDrb client thread unexpectedly died.\n#{error.formatted}"
279
306
  end
280
- @num_clients -= 1
307
+
308
+ @client_mutex.synchronize do
309
+ Cosmos.close_socket(my_socket)
310
+ @client_sockets.delete(my_socket)
311
+ @client_threads.delete(Thread.current)
312
+ end
281
313
  end
282
314
  end
283
315
 
@@ -58,6 +58,10 @@ module Cosmos
58
58
  # Disconnects from the JSON server
59
59
  def disconnect
60
60
  Cosmos.close_socket(@socket)
61
+ # Cannot set @socket to nil here because this method can be called by
62
+ # other threads and @socket being nil would cause unexpected errors in method_missing
63
+ # Also don't want to take the mutex so that we can interrupt method_missing if necessary
64
+ # Only method_missing can set @socket to nil
61
65
  end
62
66
 
63
67
  # Permanently disconnects from the JSON server
@@ -75,91 +79,120 @@ module Cosmos
75
79
  # protocol a DRb::DRbConnError exception is raised.
76
80
  def method_missing(method_name, *method_params)
77
81
  @mutex.synchronize do
78
- raise DRb::DRbConnError, "Shutdown" if @shutdown
79
- if !@socket or @socket.closed? or @request_in_progress
80
- if @request_in_progress
82
+ # This flag and loop are used to automatically reconnect and retry if something goes
83
+ # wrong on the first attempt writing to the socket. Sockets can become disconnected
84
+ # between function calls, but as long as the remote server is back up and running the
85
+ # call should succeed even when it discovers a broken socket on the first attempt.
86
+ first_try = true
87
+ loop do
88
+ raise DRb::DRbConnError, "Shutdown" if @shutdown
89
+ connect() if !@socket or @socket.closed? or @request_in_progress
90
+
91
+ response = make_request(method_name, method_params, first_try)
92
+ unless response
81
93
  disconnect()
82
94
  @socket = nil
83
- @request_in_progress = false
95
+ was_first_try = first_try
96
+ first_try = false
97
+ next if was_first_try
84
98
  end
99
+ return handle_response(response)
100
+ end # loop
101
+ end # @mutex.synchronize
102
+ end # def method_missing
103
+
104
+ private
105
+
106
+ def connect
107
+ if @request_in_progress
108
+ disconnect()
109
+ @socket = nil
110
+ @request_in_progress = false
111
+ end
112
+ begin
113
+ addr = Socket.pack_sockaddr_in(@port, @hostname)
114
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
115
+ @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
116
+ begin
117
+ @socket.connect_nonblock(addr)
118
+ rescue IO::WaitWritable
85
119
  begin
86
- addr = Socket.pack_sockaddr_in(@port, @hostname)
87
- @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
88
- @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
120
+ _, sockets, _ = IO.select(nil, [@socket], nil, @connect_timeout) # wait 3-way handshake completion
121
+ rescue IOError, Errno::ENOTSOCK
122
+ disconnect()
123
+ @socket = nil
124
+ raise "Connect canceled"
125
+ end
126
+ if sockets and !sockets.empty?
89
127
  begin
90
- @socket.connect_nonblock(addr)
91
- rescue IO::WaitWritable
92
- begin
93
- _, sockets, _ = IO.select(nil, [@socket], nil, @connect_timeout) # wait 3-way handshake completion
94
- rescue IOError, Errno::ENOTSOCK
95
- disconnect()
96
- @socket = nil
97
- raise "Connect canceled"
98
- end
99
- if sockets and !sockets.empty?
100
- begin
101
- @socket.connect_nonblock(addr) # check connection failure
102
- rescue IOError, Errno::ENOTSOCK
103
- disconnect()
104
- @socket = nil
105
- raise "Connect canceled"
106
- rescue Errno::EINPROGRESS
107
- retry
108
- rescue Errno::EISCONN, Errno::EALREADY
109
- end
110
- else
111
- disconnect()
112
- @socket = nil
113
- raise "Connect timeout"
114
- end
128
+ @socket.connect_nonblock(addr) # check connection failure
115
129
  rescue IOError, Errno::ENOTSOCK
116
130
  disconnect()
117
131
  @socket = nil
118
132
  raise "Connect canceled"
133
+ rescue Errno::EINPROGRESS
134
+ retry
135
+ rescue Errno::EISCONN, Errno::EALREADY
119
136
  end
120
- rescue => e
121
- raise DRb::DRbConnError, e.message
137
+ else
138
+ disconnect()
139
+ @socket = nil
140
+ raise "Connect timeout"
122
141
  end
123
- end
124
-
125
- request = JsonRpcRequest.new(method_name, method_params, @id)
126
- @id += 1
127
-
128
- request_data = request.to_json(:allow_nan => true)
129
- begin
130
- @request_in_progress = true
131
- STDOUT.puts "Request:\n" if JsonDRb.debug?
132
- STDOUT.puts request_data if JsonDRb.debug?
133
- JsonDRb.send_data(@socket, request_data)
134
- response_data = JsonDRb.receive_message(@socket, '')
135
- STDOUT.puts "\nResponse:\n" if JsonDRb.debug?
136
- STDOUT.puts response_data if JsonDRb.debug?
137
- @request_in_progress = false
138
- rescue => e
142
+ rescue IOError, Errno::ENOTSOCK
139
143
  disconnect()
140
144
  @socket = nil
141
- raise DRb::DRbConnError, e.message, e.backtrace
145
+ raise "Connect canceled"
142
146
  end
147
+ rescue => e
148
+ raise DRb::DRbConnError, e.message
149
+ end
150
+ end
143
151
 
144
- if response_data
145
- response = JsonRpcResponse.from_json(response_data)
146
- if JsonRpcErrorResponse === response
147
- if response.error.data
148
- raise Exception.from_hash(response.error.data)
149
- else
150
- raise "JsonDRb Error (#{response.error.code}): #{response.error.message}"
151
- end
152
+ def make_request(method_name, method_params, first_try)
153
+ request = JsonRpcRequest.new(method_name, method_params, @id)
154
+ @id += 1
155
+
156
+ request_data = request.to_json(:allow_nan => true)
157
+ begin
158
+ STDOUT.puts "Request:\n" if JsonDRb.debug?
159
+ STDOUT.puts request_data if JsonDRb.debug?
160
+ @request_in_progress = true
161
+ JsonDRb.send_data(@socket, request_data)
162
+ response_data = JsonDRb.receive_message(@socket, '')
163
+ @request_in_progress = false
164
+ STDOUT.puts "\nResponse:\n" if JsonDRb.debug?
165
+ STDOUT.puts response_data if JsonDRb.debug?
166
+ rescue => e
167
+ disconnect()
168
+ @socket = nil
169
+ return false if first_try
170
+ raise DRb::DRbConnError, e.message, e.backtrace
171
+ end
172
+ response_data
173
+ end
174
+
175
+ def handle_response(response_data)
176
+ # The code below will always either raise or return breaking out of the loop
177
+ if response_data
178
+ response = JsonRpcResponse.from_json(response_data)
179
+ if JsonRpcErrorResponse === response
180
+ if response.error.data
181
+ raise Exception.from_hash(response.error.data)
152
182
  else
153
- return response.result
183
+ raise "JsonDRb Error (#{response.error.code}): #{response.error.message}"
154
184
  end
155
185
  else
156
- # Socket was closed by server
157
- disconnect()
158
- @socket = nil
159
- raise DRb::DRbConnError, "Socket closed by server"
186
+ return response.result
160
187
  end
188
+ else
189
+ # Socket was closed by server
190
+ disconnect()
191
+ @socket = nil
192
+ raise DRb::DRbConnError, "Socket closed by server"
161
193
  end
162
194
  end
163
- end
195
+
196
+ end # class JsonDRbObject
164
197
 
165
198
  end # module Cosmos
@@ -357,7 +357,7 @@ module Cosmos
357
357
 
358
358
  # Convert from value to state if possible
359
359
  if item.states
360
- if item.array_size
360
+ if Array === value
361
361
  value = value.map do |val, index|
362
362
  if item.states.key(val)
363
363
  item.states.key(val)
@@ -374,7 +374,7 @@ module Cosmos
374
374
  end
375
375
  end
376
376
  else
377
- if item.array_size
377
+ if Array === value
378
378
  value = value.map do |val, index|
379
379
  apply_format_string_and_units(item, val, value_type)
380
380
  end
@@ -970,6 +970,25 @@ module Cosmos
970
970
  end
971
971
  end
972
972
 
973
+ def disable_instrumentation
974
+ if defined? ScriptRunnerFrame and ScriptRunnerFrame.instance
975
+ ScriptRunnerFrame.instance.use_instrumentation = false
976
+ begin
977
+ yield
978
+ ensure
979
+ ScriptRunnerFrame.instance.use_instrumentation = true
980
+ end
981
+ else
982
+ yield
983
+ end
984
+ end
985
+
986
+ def set_stdout_max_lines(max_lines)
987
+ if defined? ScriptRunnerFrame and ScriptRunnerFrame.instance
988
+ ScriptRunnerFrame.instance.stdout_max_lines = max_lines
989
+ end
990
+ end
991
+
973
992
  #######################################
974
993
  # Methods for debugging
975
994
  #######################################
@@ -101,6 +101,7 @@ module Cosmos
101
101
  attr_reader :message_log
102
102
  attr_reader :script_class
103
103
  attr_reader :top_level_instrumented_cache
104
+ attr_accessor :stdout_max_lines
104
105
 
105
106
  @@instance = nil
106
107
  @@run_thread = nil
@@ -1195,8 +1196,8 @@ module Cosmos
1195
1196
  lines_to_write << line_to_write
1196
1197
 
1197
1198
  line_count += 1
1198
- if line_count > 1000
1199
- out_line = "ERROR: Too much written to stdout. Truncating output to 1000 lines.\n"
1199
+ if line_count > @stdout_max_lines
1200
+ out_line = "ERROR: Too much written to stdout. Truncating output to #{@stdout_max_lines} lines.\n"
1200
1201
  if filename
1201
1202
  line_to_write = time_formatted + " (#{out_filename}:#{out_line_number}): " + out_line
1202
1203
  else
@@ -1249,6 +1250,7 @@ module Cosmos
1249
1250
  @inline_eval = nil
1250
1251
  @current_filename = nil
1251
1252
  @current_line_number = 0
1253
+ @stdout_max_lines = 1000
1252
1254
 
1253
1255
  @script.stop_highlight
1254
1256
  @call_stack.push(@current_file.dup)
@@ -1,12 +1,12 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- COSMOS_VERSION = '3.3.1'
3
+ COSMOS_VERSION = '3.3.2'
4
4
  module Cosmos
5
5
  module Version
6
6
  MAJOR = '3'
7
7
  MINOR = '3'
8
- PATCH = '1'
9
- BUILD = 'ec5e7d055502c4160427af946416839a23cda7ea'
8
+ PATCH = '2'
9
+ BUILD = '5c4dd480988b12d90f6b7bc8c161489fca570a63'
10
10
  end
11
- VERSION = '3.3.1'
11
+ VERSION = '3.3.2'
12
12
  end
@@ -93,6 +93,26 @@ module Cosmos
93
93
  sleep(0.1)
94
94
  end
95
95
 
96
+ it "handles the remote going away and coming back" do
97
+ class JsonDRbObjectServer
98
+ def my_method(param)
99
+ param * 2
100
+ end
101
+ end
102
+
103
+ json = JsonDRb.new
104
+ json.start_service('127.0.0.1', 7777, JsonDRbObjectServer.new)
105
+ obj = JsonDRbObject.new("localhost", 7777)
106
+ expect(obj.my_method(10)).to eql 20
107
+ json.stop_service
108
+ json = JsonDRb.new
109
+ json.start_service('127.0.0.1', 7777, JsonDRbObjectServer.new)
110
+ expect(obj.my_method(10)).to eql 20
111
+ obj.disconnect
112
+ json.stop_service
113
+ sleep(0.1)
114
+ end
115
+
96
116
  end
97
117
  end
98
118
  end
@@ -449,6 +449,12 @@ module Cosmos
449
449
  expect(@p.read_item(i, :WITH_UNITS, "\x02\x04")).to eql ["TRUE","FALSE"]
450
450
  expect(@p.read("ITEM", :WITH_UNITS, "\x08")).to eql ["0x4 V"]
451
451
  expect(@p.read_item(i, :WITH_UNITS, "\x08")).to eql ["0x4 V"]
452
+ @p.define_item("item2",0, 0, :DERIVED)
453
+ i = @p.get_item("ITEM2")
454
+ i.units = "V"
455
+ i.read_conversion = GenericConversion.new("[1,2,3,4,5]")
456
+ expect(@p.read("ITEM2", :FORMATTED, "")).to eql ["1", "2", "3", "4", "5"]
457
+ expect(@p.read("ITEM2", :WITH_UNITS, "")).to eql ["1 V", "2 V", "3 V", "4 V", "5 V"]
452
458
  end
453
459
  end
454
460
 
@@ -704,6 +704,10 @@ module Cosmos
704
704
  get_line_delay
705
705
  get_scriptrunner_message_log_filename
706
706
  start_new_scriptrunner_message_log
707
+ disable_instrumentation do
708
+ value = 1
709
+ end
710
+ set_stdout_max_lines(1000)
707
711
  insert_return
708
712
  step_mode
709
713
  run_mode
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cosmos
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.1
4
+ version: 3.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Melton
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-19 00:00:00.000000000 Z
12
+ date: 2015-03-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler