cosmos 4.0.3 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -5
  3. data/Manifest.txt +11 -1
  4. data/README.md +3 -2
  5. data/Rakefile +18 -4
  6. data/appveyor.yml +19 -0
  7. data/cosmos.gemspec +14 -3
  8. data/data/config/cmd_tlm_server.yaml +3 -0
  9. data/data/crc.txt +63 -60
  10. data/demo/config/targets/INST/cmd_tlm_server.txt +1 -0
  11. data/demo/config/targets/INST/cmd_tlm_server2.txt +7 -0
  12. data/demo/config/tools/cmd_sequence/cmd_sequence.txt +2 -0
  13. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +8 -12
  14. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +7 -9
  15. data/demo/lib/cmd_sequence_exporter.rb +52 -0
  16. data/demo/lib/example_background_task.rb +1 -0
  17. data/demo/procedures/replay_test.rb +32 -0
  18. data/ext/cosmos/ext/structure/structure.c +39 -3
  19. data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +1 -0
  20. data/install/config/tools/launcher/launcher.txt +2 -0
  21. data/lib/cosmos/config/config_parser.rb +2 -0
  22. data/lib/cosmos/core_ext/io.rb +89 -60
  23. data/lib/cosmos/gui/qt.rb +5 -8
  24. data/lib/cosmos/gui/qt_tool.rb +8 -8
  25. data/lib/cosmos/gui/text/ruby_editor.rb +12 -12
  26. data/lib/cosmos/gui/utilities/script_module_gui.rb +9 -9
  27. data/lib/cosmos/gui/widgets/realtime_button_bar.rb +18 -17
  28. data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +2 -2
  29. data/lib/cosmos/interfaces/protocols/template_protocol.rb +3 -0
  30. data/lib/cosmos/interfaces/udp_interface.rb +27 -14
  31. data/lib/cosmos/io/buffered_file.rb +0 -1
  32. data/lib/cosmos/io/json_drb.rb +134 -214
  33. data/lib/cosmos/io/json_drb_object.rb +22 -61
  34. data/lib/cosmos/io/json_drb_rack.rb +79 -0
  35. data/lib/cosmos/io/json_rpc.rb +27 -0
  36. data/lib/cosmos/io/udp_sockets.rb +102 -58
  37. data/lib/cosmos/packets/commands.rb +1 -1
  38. data/lib/cosmos/packets/structure.rb +1 -1
  39. data/lib/cosmos/packets/structure_item.rb +37 -5
  40. data/lib/cosmos/script/cmd_tlm_server.rb +76 -2
  41. data/lib/cosmos/script/replay.rb +60 -0
  42. data/lib/cosmos/script/script.rb +20 -2
  43. data/lib/cosmos/script/scripting.rb +9 -9
  44. data/lib/cosmos/script/tools.rb +14 -0
  45. data/lib/cosmos/system/system.rb +185 -92
  46. data/lib/cosmos/system/target.rb +1 -1
  47. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +44 -4
  48. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +4 -0
  49. data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +7 -0
  50. data/lib/cosmos/tools/cmd_tlm_server/api.rb +347 -20
  51. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +3 -0
  52. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +329 -111
  53. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +13 -0
  54. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +261 -95
  55. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +46 -35
  56. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +18 -8
  57. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +39 -28
  58. data/lib/cosmos/tools/cmd_tlm_server/gui/replay_tab.rb +242 -0
  59. data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +24 -8
  60. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +18 -6
  61. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +5 -4
  62. data/lib/cosmos/tools/cmd_tlm_server/replay_backend.rb +375 -0
  63. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +10 -2
  64. data/lib/cosmos/tools/data_viewer/data_viewer.rb +40 -5
  65. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +18 -20
  66. data/lib/cosmos/tools/launcher/launcher_config.rb +5 -16
  67. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +65 -39
  68. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +19 -0
  69. data/lib/cosmos/tools/replay/replay.rb +5 -505
  70. data/lib/cosmos/tools/script_runner/script_audit.rb +1 -0
  71. data/lib/cosmos/tools/script_runner/script_runner.rb +3 -4
  72. data/lib/cosmos/tools/script_runner/script_runner_config.rb +3 -4
  73. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +44 -23
  74. data/lib/cosmos/tools/test_runner/results_writer.rb +4 -0
  75. data/lib/cosmos/tools/test_runner/test_runner.rb +0 -3
  76. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +6 -2
  77. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +26 -1
  78. data/lib/cosmos/tools/tlm_viewer/screen.rb +24 -1
  79. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +25 -0
  80. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +24 -14
  81. data/lib/cosmos/top_level.rb +34 -24
  82. data/lib/cosmos/utilities/csv.rb +60 -8
  83. data/lib/cosmos/version.rb +5 -5
  84. data/spec/config/config_parser_spec.rb +10 -1
  85. data/spec/core_ext/socket_spec.rb +4 -2
  86. data/spec/gui/utilities/script_module_gui_spec.rb +102 -0
  87. data/spec/install/config/data/data.txt +1 -0
  88. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +2 -0
  89. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +1 -2
  90. data/spec/interfaces/protocols/template_protocol_spec.rb +72 -2
  91. data/spec/interfaces/serial_interface_spec.rb +1 -1
  92. data/spec/interfaces/udp_interface_spec.rb +14 -0
  93. data/spec/io/buffered_file_spec.rb +37 -0
  94. data/spec/io/json_drb_object_spec.rb +2 -15
  95. data/spec/io/json_drb_spec.rb +61 -121
  96. data/spec/io/udp_sockets_spec.rb +42 -2
  97. data/spec/packet_logs/packet_log_reader_spec.rb +5 -2
  98. data/spec/packets/binary_accessor_spec.rb +1 -1
  99. data/spec/packets/packet_item_spec.rb +1 -1
  100. data/spec/packets/structure_item_spec.rb +5 -6
  101. data/spec/script/cmd_tlm_server_spec.rb +39 -4
  102. data/spec/script/commands_disconnect_spec.rb +1 -1
  103. data/spec/script/commands_spec.rb +2 -1
  104. data/spec/script/scripting_spec.rb +18 -3
  105. data/spec/script/telemetry_spec.rb +5 -0
  106. data/spec/spec_helper.rb +43 -26
  107. data/spec/streams/tcpip_socket_stream_spec.rb +2 -2
  108. data/spec/system/system_spec.rb +11 -9
  109. data/spec/system/target_spec.rb +3 -0
  110. data/spec/tools/cmd_tlm_server/api_spec.rb +543 -29
  111. data/spec/tools/cmd_tlm_server/background_task_spec.rb +2 -2
  112. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +31 -75
  113. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +199 -66
  114. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +85 -9
  115. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +29 -127
  116. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +10 -50
  117. data/spec/tools/launcher/launcher_config_spec.rb +1 -1
  118. data/spec/tools/table_manager/table_item_spec.rb +1 -1
  119. data/spec/tools/table_manager/tablemanager_core_spec.rb +4 -4
  120. data/spec/top_level/top_level_spec.rb +151 -3
  121. data/spec/utilities/csv_spec.rb +24 -5
  122. metadata +61 -9
  123. data/lib/cosmos/tools/replay/replay_server.rb +0 -91
@@ -3,3 +3,4 @@
3
3
 
4
4
  INTERFACE INST_INT simulated_target_interface.rb sim_inst.rb
5
5
  TARGET INST
6
+ PROTOCOL READ_WRITE OverrideProtocol
@@ -0,0 +1,7 @@
1
+ # This is a segment of the main cmd_tlm_server.txt that will be used with
2
+ # AUTO_INTERFACE_TARGETS or INTERFACE_TARGET
3
+
4
+ INTERFACE INST2_INT simulated_target_interface.rb sim_inst.rb
5
+ TARGET INST2
6
+ DONT_LOG
7
+ PROTOCOL READ_WRITE OverrideProtocol
@@ -0,0 +1,2 @@
1
+ # Declare a custom export class
2
+ EXPORTER cmd_sequence_exporter.rb
@@ -11,18 +11,11 @@ TITLE 'COSMOS Command and Telemetry Server - Demo Configuration'
11
11
  PACKET_LOG_WRITER DEFAULT packet_log_writer.rb nil true nil 2000000000 nil false
12
12
  # PACKET_LOG_WRITER SYSTEMLOG packet_log_writer.rb system
13
13
 
14
- # AUTO_INTERFACE_TARGETS # Use cmd_tlm_server.txt from all targets declared in system.txt
15
-
16
- INTERFACE_TARGET INST cmd_tlm_server.txt # Use cmd_tlm_server.txt in target package
17
-
18
- INTERFACE INST2_INT simulated_target_interface.rb sim_inst.rb
19
- TARGET INST2
20
- DONT_LOG
21
-
22
- INTERFACE_TARGET EXAMPLE cmd_tlm_server.txt # Use cmd_tlm_server.txt in target package
23
-
24
- INTERFACE_TARGET TEMPLATED cmd_tlm_server.txt # Use cmd_tlm_server.txt in target package
14
+ # Explicitly declare these interfaces since we're using name substitution
15
+ INTERFACE_TARGET INST cmd_tlm_server.txt # Use cmd_tlm_server.txt in targets/INST
16
+ INTERFACE_TARGET INST2 cmd_tlm_server2.txt # Use cmd_tlm_server2.txt in targets/INST
25
17
 
18
+ # Here is an example of declaring the interface directly
26
19
  INTERFACE SYSTEM_INT cmd_tlm_server_interface.rb
27
20
  TARGET SYSTEM
28
21
  DISABLE_DISCONNECT
@@ -33,6 +26,9 @@ INTERFACE SYSTEM_INT cmd_tlm_server_interface.rb
33
26
  # RECONNECT_DELAY 15.0
34
27
  # LOG_RAW
35
28
 
29
+ # Auto interface the rest of the targets by using their cmd_tlm_server.txt file
30
+ AUTO_INTERFACE_TARGETS
31
+
36
32
  ROUTER INST_ROUTER tcpip_server_interface.rb 2055 2055 10.0 nil LENGTH 32 16 7
37
33
  OPTION LISTEN_ADDRESS 127.0.0.1
38
34
  ROUTE INST_INT
@@ -46,4 +42,4 @@ BACKGROUND_TASK example_background_task.rb
46
42
  STOPPED
47
43
  BACKGROUND_TASK limits_groups.rb 5 # Initial delay to allow interfaces to connect
48
44
 
49
- COLLECT_METADATA
45
+ #COLLECT_METADATA
@@ -11,16 +11,11 @@ TITLE 'COSMOS Command and Telemetry Server - Demo Configuration 2'
11
11
  PACKET_LOG_WRITER DEFAULT packet_log_writer.rb nil true nil 2000000000 nil false
12
12
  # PACKET_LOG_WRITER SYSTEMLOG packet_log_writer.rb system
13
13
 
14
- # AUTO_INTERFACE_TARGETS # Use cmd_tlm_server.txt from all targets declared in system.txt
15
-
16
- INTERFACE_TARGET INST cmd_tlm_server.txt # Use cmd_tlm_server.txt in target package
17
-
18
- INTERFACE INST2_INT simulated_target_interface.rb sim_inst.rb
19
- TARGET INST2
20
- DONT_LOG
21
-
22
- INTERFACE_TARGET EXAMPLE cmd_tlm_server.txt # Use cmd_tlm_server.txt in target package
14
+ # Explicitly declare these interfaces since we're using name substitution
15
+ INTERFACE_TARGET INST cmd_tlm_server.txt # Use cmd_tlm_server.txt in targets/INST
16
+ INTERFACE_TARGET INST2 cmd_tlm_server2.txt # Use cmd_tlm_server2.txt in targets/INST
23
17
 
18
+ # Here is an example of declaring the interface directly
24
19
  INTERFACE SYSTEM_INT cmd_tlm_server_interface.rb
25
20
  TARGET SYSTEM
26
21
  DISABLE_DISCONNECT
@@ -31,6 +26,9 @@ INTERFACE SYSTEM_INT cmd_tlm_server_interface.rb
31
26
  # RECONNECT_DELAY 15.0
32
27
  # LOG_RAW
33
28
 
29
+ # Auto interface the rest of the targets by using their cmd_tlm_server.txt file
30
+ AUTO_INTERFACE_TARGETS
31
+
34
32
  ROUTER INST_ROUTER tcpip_server_interface.rb 3055 3055 10.0 nil LENGTH 32 16 7
35
33
  ROUTE INST_INT
36
34
  # DONT_CONNECT
@@ -0,0 +1,52 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'cosmos'
12
+ require 'cosmos/ccsds/ccsds_packet'
13
+
14
+ module Cosmos
15
+ class CmdSequenceExporter
16
+ def initialize(parent)
17
+ @parent = parent
18
+ end
19
+
20
+ def export(filename, sequence_dir, sequence_list)
21
+ basename = File.basename(filename, ".*")
22
+ filename = Qt::FileDialog::getSaveFileName(@parent, # parent
23
+ 'Export', # caption
24
+ sequence_dir + "/#{basename}.bin", # dir
25
+ 'Sequence Binary (*.bin)') # filter
26
+ return if filename.nil? || filename.empty?
27
+
28
+ data = ''
29
+ sequence_list.each do |item|
30
+ begin
31
+ time = Time.parse(item.time)
32
+ day, ms, us = Time.mdy2ccsds(time.year, time.month, time.day, time.hour, time.min, time.sec, time.usec)
33
+ data << [day].pack("N") # UINT32
34
+ data << [ms].pack("N") # UINT32
35
+ rescue
36
+ time = item.time.to_f * 1000
37
+ data << [0].pack("N") # UINT32
38
+ data << [time].pack("N") # UINT32
39
+ end
40
+ data << item.command.buffer
41
+ end
42
+ ccsds = CcsdsPacket.new
43
+ ccsds.write("CCSDSTYPE", CcsdsPacket::COMMAND)
44
+ ccsds.write('CCSDSSHF', 0)
45
+ ccsds.write("CCSDSAPID", 505)
46
+ ccsds.write("CCSDSSEQFLAGS", CcsdsPacket::STANDALONE)
47
+ ccsds.write("CCSDSDATA", data)
48
+ ccsds.write("CCSDSLENGTH", data.length - 1)
49
+ File.open(filename, 'wb') { |file| file.write ccsds.buffer }
50
+ end
51
+ end
52
+ end
@@ -18,6 +18,7 @@ module Cosmos
18
18
  def initialize
19
19
  super()
20
20
  @name = 'Example Background Task'
21
+ @sleeper = Sleeper.new
21
22
  end
22
23
 
23
24
  def call
@@ -0,0 +1,32 @@
1
+ set_line_delay(0)
2
+ set_replay_mode(true)
3
+ filenames = get_output_logs_filenames()
4
+ replay_select_file(filenames[-1])
5
+ status = 'Analyzing'
6
+ while status =~ /Analyzing/
7
+ status, playback_delay, filename, file_start, file_current, file_end, file_index, file_max_index = replay_status
8
+ wait(1)
9
+ end
10
+ 100.times do
11
+ replay_step_forward()
12
+ end
13
+ 100.times do
14
+ replay_step_back()
15
+ end
16
+ replay_move_end()
17
+ replay_move_index(file_max_index / 2)
18
+ replay_move_start()
19
+ replay_set_playback_delay(0.1)
20
+ replay_play()
21
+ wait(2)
22
+ replay_set_playback_delay(0.125)
23
+ wait(5)
24
+ replay_set_playback_delay(nil)
25
+ wait(2)
26
+ replay_set_playback_delay(0.0)
27
+ wait(4)
28
+ replay_stop()
29
+ replay_reverse_play()
30
+ wait(5)
31
+ cmd_tlm_clear_counters()
32
+ cmd_tlm_reload()
@@ -64,6 +64,7 @@ static ID id_ivar_neg_bit_size = 0;
64
64
  static ID id_ivar_fixed_size = 0;
65
65
  static ID id_ivar_short_buffer_allowed = 0;
66
66
  static ID id_ivar_mutex = 0;
67
+ static ID id_ivar_create_index = 0;
67
68
 
68
69
  static ID id_const_ASCII_8BIT_STRING = 0;
69
70
  static ID id_const_ZERO_STRING = 0;
@@ -1189,6 +1190,16 @@ static VALUE structure_item_spaceship(VALUE self, VALUE other_item) {
1189
1190
  int other_bit_offset = FIX2INT(rb_ivar_get(other_item, id_ivar_bit_offset));
1190
1191
  int bit_size = 0;
1191
1192
  int other_bit_size = 0;
1193
+ int create_index = 0;
1194
+ int other_create_index = 0;
1195
+ int have_create_index = 0;
1196
+ volatile VALUE v_create_index = rb_ivar_get(self, id_ivar_create_index);
1197
+ volatile VALUE v_other_create_index = rb_ivar_get(other_item, id_ivar_create_index);
1198
+ if (RTEST(v_create_index) && RTEST(v_other_create_index)) {
1199
+ create_index = FIX2INT(v_create_index);
1200
+ other_create_index = FIX2INT(v_other_create_index);
1201
+ have_create_index = 1;
1202
+ }
1192
1203
 
1193
1204
  /* Handle same bit offset case */
1194
1205
  if ((bit_offset == 0) && (other_bit_offset == 0)) {
@@ -1198,7 +1209,15 @@ static VALUE structure_item_spaceship(VALUE self, VALUE other_item) {
1198
1209
  bit_size = FIX2INT(rb_ivar_get(self, id_ivar_bit_size));
1199
1210
  other_bit_size = FIX2INT(rb_ivar_get(other_item, id_ivar_bit_size));
1200
1211
  if (bit_size == other_bit_size) {
1201
- return INT2FIX(0);
1212
+ if (have_create_index) {
1213
+ if (create_index <= other_create_index) {
1214
+ return INT2FIX(-1);
1215
+ } else {
1216
+ return INT2FIX(1);
1217
+ }
1218
+ } else {
1219
+ return INT2FIX(0);
1220
+ }
1202
1221
  } if (bit_size < other_bit_size) {
1203
1222
  return INT2FIX(-1);
1204
1223
  } else {
@@ -1210,7 +1229,15 @@ static VALUE structure_item_spaceship(VALUE self, VALUE other_item) {
1210
1229
  if (((bit_offset >= 0) && (other_bit_offset >= 0)) || ((bit_offset < 0) && (other_bit_offset < 0))) {
1211
1230
  /* Both Have Same Sign */
1212
1231
  if (bit_offset == other_bit_offset) {
1213
- return INT2FIX(0);
1232
+ if (have_create_index) {
1233
+ if (create_index <= other_create_index) {
1234
+ return INT2FIX(-1);
1235
+ } else {
1236
+ return INT2FIX(1);
1237
+ }
1238
+ } else {
1239
+ return INT2FIX(0);
1240
+ }
1214
1241
  } else if (bit_offset < other_bit_offset) {
1215
1242
  return INT2FIX(-1);
1216
1243
  } else {
@@ -1219,7 +1246,15 @@ static VALUE structure_item_spaceship(VALUE self, VALUE other_item) {
1219
1246
  } else {
1220
1247
  /* Different Signs */
1221
1248
  if (bit_offset == other_bit_offset) {
1222
- return INT2FIX(0);
1249
+ if (have_create_index) {
1250
+ if (create_index <= other_create_index) {
1251
+ return INT2FIX(-1);
1252
+ } else {
1253
+ return INT2FIX(1);
1254
+ }
1255
+ } else {
1256
+ return INT2FIX(0);
1257
+ }
1223
1258
  } else if (bit_offset < other_bit_offset) {
1224
1259
  return INT2FIX(1);
1225
1260
  } else {
@@ -1387,6 +1422,7 @@ void Init_structure (void)
1387
1422
  id_ivar_fixed_size = rb_intern("@fixed_size");
1388
1423
  id_ivar_short_buffer_allowed = rb_intern("@short_buffer_allowed");
1389
1424
  id_ivar_mutex = rb_intern("@mutex");
1425
+ id_ivar_create_index = rb_intern("@create_index");
1390
1426
 
1391
1427
  symbol_LITTLE_ENDIAN = ID2SYM(rb_intern("LITTLE_ENDIAN"));
1392
1428
  symbol_BIG_ENDIAN = ID2SYM(rb_intern("BIG_ENDIAN"));
@@ -1,2 +1,3 @@
1
1
  TITLE 'COSMOS Command and Telemetry Server'
2
2
  AUTO_INTERFACE_TARGETS # Use cmd_tlm_server.txt from all targets declared in system.txt
3
+ COLLECT_METADATA
@@ -20,6 +20,7 @@ DIVIDER
20
20
  LABEL "Commanding and Scripting"
21
21
 
22
22
  TOOL "Command Sender" "LAUNCH CmdSender" "cmd_sender.png"
23
+ TOOL "Command Sequence" "LAUNCH CmdSequence" "cmd_sequence.png"
23
24
  TOOL "Script Runner" "LAUNCH ScriptRunner" "script_runner.png"
24
25
  TOOL "Test Runner" "LAUNCH TestRunner" "test_runner.png"
25
26
 
@@ -34,6 +35,7 @@ TOOL "Data Viewer" "LAUNCH DataViewer" "data_viewer.png"
34
35
  DIVIDER
35
36
  LABEL Utilities
36
37
 
38
+ TOOL "Config Editor" "LAUNCH ConfigEditor" "config_editor.png"
37
39
  TOOL "Telemetry Extractor" "LAUNCH TlmExtractor" "tlm_extractor.png"
38
40
  TOOL "Command Extractor" "LAUNCH CmdExtractor" "cmd_extractor.png"
39
41
  TOOL "Handbook Creator" "LAUNCH HandbookCreator" "handbook_creator.png"
@@ -146,6 +146,7 @@ module Cosmos
146
146
 
147
147
  # Called by the ERB template to render a partial
148
148
  def render(template_name, options = {})
149
+ raise Error.new(self, "Partial name '#{template_name}' must begin with an underscore.") if template_name[0] != '_'
149
150
  b = binding
150
151
  if options[:locals]
151
152
  if RUBY_VERSION.split('.')[0..1].join.to_i >= 21
@@ -178,6 +179,7 @@ module Cosmos
178
179
  yield_non_keyword_lines = false,
179
180
  remove_quotes = true,
180
181
  &block)
182
+ raise "Configuration file #{filename} does not exist." unless filename && File.exist?(filename)
181
183
  @filename = filename
182
184
 
183
185
  # Create a temp file where we write the ERB parsed output
@@ -8,6 +8,7 @@
8
8
  # as published by the Free Software Foundation; version 3 with
9
9
  # attribution addendums as found in the LICENSE.txt
10
10
 
11
+ require 'cosmos/core_ext/kernel'
11
12
  require 'cosmos/core_ext/cosmos_io'
12
13
 
13
14
  class IO
@@ -20,74 +21,102 @@ class IO
20
21
  # remaining timeout is left.
21
22
  SELECT_MAX_TIMEOUT = 0.016
22
23
 
23
- # The method is identical to IO.select but instead of calling IO.select with
24
- # the full timeout, it calls IO.select with a small timeout and then
25
- # doubles the timeout twice until eventually it calls IO.select with the
26
- # remaining passed in timeout value.
27
- # TODO: Ryan why was this originally done?
28
- #
29
- # @param read_sockets [Array<IO>] IO objects to wait to be ready to read
30
- # @param write_sockets [Array<IO>] IO objects to wait to be ready to write
31
- # @param error_array [Array<IO>] IO objects to wait for exceptions
32
- # @param timeout [Numeric] Number of seconds to wait
33
- def self.fast_select(read_sockets = nil, write_sockets = nil, error_array = nil, timeout = nil)
34
- # Always try a zero timeout first
35
- current_timeout = SELECT_BASE_TIMEOUT
36
- total_timeout = 0.0
24
+ class << self
37
25
 
38
- while true
39
- result = IO.select(read_sockets, write_sockets, error_array, current_timeout)
40
- return result if result or current_timeout.nil?
41
- return nil if timeout and total_timeout >= timeout
26
+ # Alias the original IO.select method
27
+ alias_method :__select__, :select
42
28
 
43
- if current_timeout <= 0.0001
44
- # Always try the base timeout next
45
- current_timeout = SELECT_BASE_TIMEOUT
46
- total_timeout = SELECT_BASE_TIMEOUT
47
- else
48
- # Then start doubling the timeout
49
- current_timeout = current_timeout * 2
50
-
51
- # Until it is bigger than our max timeout
52
- if current_timeout >= SELECT_MAX_TIMEOUT
53
- if timeout
54
- # Block for the remaining requested timeout
55
- current_timeout = timeout - total_timeout
56
- total_timeout = timeout
57
- else
58
- # Or block forever
59
- current_timeout = nil
60
- end
29
+ # On Windows the IO.select function (when called with no timeout) takes
30
+ # a minimum of 10 msec to return, even if one of the IO objects is
31
+ # ready to read/write sooner than that.
32
+ #
33
+ # This method is identical to IO.select but instead of calling IO.select with
34
+ # the full timeout, it calls IO.select with a small timeout and then
35
+ # doubles the timeout twice until eventually it calls IO.select with the
36
+ # remaining passed in timeout value.
37
+ #
38
+ # @param read_sockets [Array<IO>] IO objects to wait to be ready to read
39
+ # @param write_sockets [Array<IO>] IO objects to wait to be ready to write
40
+ # @param error_array [Array<IO>] IO objects to wait for exceptions
41
+ # @param timeout [Numeric] Number of seconds to wait
42
+ def fast_select(read_sockets = nil, write_sockets = nil, error_array = nil, timeout = nil)
43
+ # Always try a zero timeout first
44
+ current_timeout = SELECT_BASE_TIMEOUT
45
+ total_timeout = 0.0
46
+
47
+ while true
48
+ result = IO.__select__(read_sockets, write_sockets, error_array, current_timeout)
49
+ return result if result or current_timeout.nil?
50
+ return nil if timeout and total_timeout >= timeout
51
+
52
+ if current_timeout <= 0.0001
53
+ # Always try the base timeout next
54
+ current_timeout = SELECT_BASE_TIMEOUT
55
+ total_timeout = SELECT_BASE_TIMEOUT
61
56
  else
62
- # Or it is bigger than the given timeout
63
- if timeout and current_timeout >= timeout
64
- # Block for the remaining requested timeout
65
- current_timeout = timeout - total_timeout
66
- total_timeout = timeout
57
+ # Then start doubling the timeout
58
+ current_timeout = current_timeout * 2
59
+
60
+ # Until it is bigger than our max timeout
61
+ if current_timeout >= SELECT_MAX_TIMEOUT
62
+ if timeout
63
+ # Block for the remaining requested timeout
64
+ current_timeout = timeout - total_timeout
65
+ total_timeout = timeout
66
+ else
67
+ # Or block forever
68
+ current_timeout = nil
69
+ end
67
70
  else
68
- # Up our total time in select
69
- total_timeout += current_timeout
70
- end
71
- if timeout and total_timeout > timeout
72
- # Block for the remaining requested timeout
73
- current_timeout = timeout - total_timeout
74
- total_timeout = timeout
71
+ # Or it is bigger than the given timeout
72
+ if timeout and current_timeout >= timeout
73
+ # Block for the remaining requested timeout
74
+ current_timeout = timeout - total_timeout
75
+ total_timeout = timeout
76
+ else
77
+ # Up our total time in select
78
+ total_timeout += current_timeout
79
+ end
80
+ if timeout and total_timeout > timeout
81
+ # Block for the remaining requested timeout
82
+ current_timeout = timeout - total_timeout
83
+ total_timeout = timeout
84
+ end
75
85
  end
86
+ return nil if current_timeout and current_timeout < 0
76
87
  end
77
- return nil if current_timeout and current_timeout < 0
78
- end
79
- end # while true
80
- end # fast_select
88
+ end # while true
89
+ end # fast_select
81
90
 
82
- # @param read_sockets [Array<IO>] IO objects to wait to be ready to read
83
- # @param timeout [Numeric] Number of seconds to wait
84
- def self.fast_read_select(read_sockets, timeout)
85
- return fast_select(read_sockets, nil, nil, timeout)
91
+ # For non-windows systems, leave IO.select alone, but for windows
92
+ # monkey-patch IO.select to use our fast-select implementation.
93
+ if Kernel.is_windows?
94
+ def select(read_sockets = nil, write_sockets = nil, error_array = nil, timeout = nil)
95
+ return fast_select(read_sockets, write_sockets, error_array, timeout)
96
+ end
97
+ end
98
+
99
+ # @param read_sockets [Array<IO>] IO objects to wait to be ready to read
100
+ # @param timeout [Numeric] Number of seconds to wait
101
+ def fast_read_select(read_sockets, timeout)
102
+ return fast_select(read_sockets, nil, nil, timeout)
103
+ end
104
+
105
+ # @param write_sockets [Array<IO>] IO objects to wait to be ready to write
106
+ # @param timeout [Numeric] Number of seconds to wait
107
+ def fast_write_select(write_sockets, timeout)
108
+ return fast_select(nil, write_sockets, nil, timeout)
109
+ end
86
110
  end
87
111
 
88
- # @param write_sockets [Array<IO>] IO objects to wait to be ready to write
89
- # @param timeout [Numeric] Number of seconds to wait
90
- def self.fast_write_select(write_sockets, timeout)
91
- return fast_select(nil, write_sockets, nil, timeout)
112
+ # Alias the original close method
113
+ alias_method :__close__, :close
114
+
115
+ # Patch the close method so that it won't raise any exceptions
116
+ def close
117
+ begin
118
+ __close__
119
+ rescue
120
+ end
92
121
  end
93
122
  end