cosmos 4.0.3-java → 4.1.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +12 -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