origen 0.0.1 → 0.0.2

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 (336) hide show
  1. checksums.yaml +4 -4
  2. data/bin/ctags +0 -0
  3. data/bin/origen +165 -1
  4. data/bin/rgen +2 -0
  5. data/config/application.rb +141 -0
  6. data/config/commands.rb +72 -0
  7. data/config/development.rb +7 -0
  8. data/config/environment.rb +0 -0
  9. data/config/rgen.policy +7 -0
  10. data/config/rubocop/easy.yml +620 -0
  11. data/config/rubocop/easy_disabled.yml +271 -0
  12. data/config/rubocop/easy_enabled.yml +731 -0
  13. data/config/rubocop/strict.yml +620 -0
  14. data/config/rubocop/strict_disabled.yml +247 -0
  15. data/config/rubocop/strict_enabled.yml +755 -0
  16. data/config/users.rb +20 -0
  17. data/config/version.rb +1 -1
  18. data/helpers/url.rb +68 -0
  19. data/lib/c99/doc_interface.rb +56 -0
  20. data/lib/c99/j750_interface.rb +85 -0
  21. data/lib/c99/nvm.rb +89 -0
  22. data/lib/c99/target/mock2.rb +1 -0
  23. data/lib/c99/target/subdir/mock3.rb +1 -0
  24. data/lib/option_parser/optparse.rb +12 -0
  25. data/lib/origen/acronyms.rb +60 -0
  26. data/lib/origen/application/command_dispatcher.rb +12 -0
  27. data/lib/origen/application/configuration.rb +206 -0
  28. data/lib/origen/application/configuration_manager.rb +78 -0
  29. data/lib/origen/application/deployer.rb +367 -0
  30. data/lib/origen/application/environment.rb +186 -0
  31. data/lib/origen/application/lsf.rb +145 -0
  32. data/lib/origen/application/lsf_manager.rb +657 -0
  33. data/lib/origen/application/plugins_manager.rb +280 -0
  34. data/lib/origen/application/release.rb +359 -0
  35. data/lib/origen/application/runner.rb +246 -0
  36. data/lib/origen/application/statistics.rb +191 -0
  37. data/lib/origen/application/target.rb +374 -0
  38. data/lib/origen/application/version_tracker.rb +59 -0
  39. data/lib/origen/application/workspace_manager.rb +151 -0
  40. data/lib/origen/application.rb +746 -0
  41. data/lib/origen/bugs/bug.rb +36 -0
  42. data/lib/origen/bugs.rb +45 -0
  43. data/lib/origen/callbacks.rb +35 -0
  44. data/lib/origen/chip_mode.rb +118 -0
  45. data/lib/origen/chip_package.rb +461 -0
  46. data/lib/origen/client.rb +87 -0
  47. data/lib/origen/code_generators/actions.rb +258 -0
  48. data/lib/origen/code_generators/base.rb +57 -0
  49. data/lib/origen/code_generators/bundler.rb +17 -0
  50. data/lib/origen/code_generators/gem_setup.rb +49 -0
  51. data/lib/origen/code_generators/rake.rb +13 -0
  52. data/lib/origen/code_generators/rspec.rb +12 -0
  53. data/lib/origen/code_generators/semver.rb +39 -0
  54. data/lib/origen/code_generators/timever.rb +37 -0
  55. data/lib/origen/code_generators.rb +111 -0
  56. data/lib/origen/commands/add.rb +12 -0
  57. data/lib/origen/commands/compile.rb +62 -0
  58. data/lib/origen/commands/ctags.rb +9 -0
  59. data/lib/origen/commands/dispatch.rb +22 -0
  60. data/lib/origen/commands/environment.rb +11 -0
  61. data/lib/origen/commands/fetch.rb +63 -0
  62. data/lib/origen/commands/generate.rb +130 -0
  63. data/lib/origen/commands/interactive.rb +73 -0
  64. data/lib/origen/commands/lint.rb +82 -0
  65. data/lib/origen/commands/lsf.rb +93 -0
  66. data/lib/origen/commands/merge.rb +55 -0
  67. data/lib/origen/commands/modifications.rb +12 -0
  68. data/lib/origen/commands/new.rb +113 -0
  69. data/lib/origen/commands/plugin.rb +105 -0
  70. data/lib/origen/commands/program.rb +70 -0
  71. data/lib/origen/commands/rc.rb +442 -0
  72. data/lib/origen/commands/save.rb +56 -0
  73. data/lib/origen/commands/target.rb +27 -0
  74. data/lib/origen/commands/time.rb +127 -0
  75. data/lib/origen/commands/version.rb +17 -0
  76. data/lib/origen/commands/web.rb +221 -0
  77. data/lib/origen/commands.rb +272 -0
  78. data/lib/origen/commands_global.rb +76 -0
  79. data/lib/origen/controller.rb +94 -0
  80. data/lib/origen/core_ext/array.rb +23 -0
  81. data/lib/origen/core_ext/bignum.rb +36 -0
  82. data/lib/origen/core_ext/enumerable.rb +76 -0
  83. data/lib/origen/core_ext/fixnum.rb +46 -0
  84. data/lib/origen/core_ext/hash.rb +52 -0
  85. data/lib/origen/core_ext/module.rb +14 -0
  86. data/lib/origen/core_ext/numeric.rb +126 -0
  87. data/lib/origen/core_ext/object.rb +13 -0
  88. data/lib/origen/core_ext/range.rb +7 -0
  89. data/lib/origen/core_ext/string.rb +124 -0
  90. data/lib/origen/core_ext.rb +10 -0
  91. data/lib/origen/database/key_value_store.rb +111 -0
  92. data/lib/origen/database/key_value_stores.rb +108 -0
  93. data/lib/origen/database.rb +6 -0
  94. data/lib/origen/encodings.rb +102 -0
  95. data/lib/origen/features/feature.rb +22 -0
  96. data/lib/origen/features.rb +104 -0
  97. data/lib/origen/file_handler.rb +429 -0
  98. data/lib/origen/generator/comparator.rb +56 -0
  99. data/lib/origen/generator/compiler.rb +277 -0
  100. data/lib/origen/generator/flow.rb +49 -0
  101. data/lib/origen/generator/job.rb +131 -0
  102. data/lib/origen/generator/pattern.rb +356 -0
  103. data/lib/origen/generator/pattern_finder.rb +155 -0
  104. data/lib/origen/generator/pattern_iterator.rb +55 -0
  105. data/lib/origen/generator/renderer.rb +113 -0
  106. data/lib/origen/generator/resources.rb +40 -0
  107. data/lib/origen/generator/stage.rb +89 -0
  108. data/lib/origen/generator.rb +85 -0
  109. data/lib/origen/global_methods.rb +205 -0
  110. data/lib/origen/import_manager.rb +596 -0
  111. data/lib/origen/location/base.rb +116 -0
  112. data/lib/origen/location/map.rb +83 -0
  113. data/lib/origen/location.rb +6 -0
  114. data/lib/origen/log.rb +217 -0
  115. data/lib/origen/logger_methods.rb +56 -0
  116. data/lib/origen/mode.rb +61 -0
  117. data/lib/origen/model.rb +267 -0
  118. data/lib/origen/model_initializer.rb +45 -0
  119. data/lib/origen/nvm/block_array.rb +72 -0
  120. data/lib/origen/nvm.rb +6 -0
  121. data/lib/origen/parameters/live.rb +22 -0
  122. data/lib/origen/parameters/missing.rb +28 -0
  123. data/lib/origen/parameters/set.rb +144 -0
  124. data/lib/origen/parameters.rb +107 -0
  125. data/lib/origen/pdm.rb +218 -0
  126. data/lib/origen/pins/function_proxy.rb +36 -0
  127. data/lib/origen/pins/ground_pin.rb +6 -0
  128. data/lib/origen/pins/pin.rb +860 -0
  129. data/lib/origen/pins/pin_bank.rb +349 -0
  130. data/lib/origen/pins/pin_clock.rb +124 -0
  131. data/lib/origen/pins/pin_collection.rb +492 -0
  132. data/lib/origen/pins/pin_common.rb +206 -0
  133. data/lib/origen/pins/port.rb +268 -0
  134. data/lib/origen/pins/power_pin.rb +30 -0
  135. data/lib/origen/pins.rb +696 -0
  136. data/lib/origen/registers/bit.rb +562 -0
  137. data/lib/origen/registers/bit_collection.rb +787 -0
  138. data/lib/origen/registers/container.rb +288 -0
  139. data/lib/origen/registers/domain.rb +16 -0
  140. data/lib/origen/registers/reg.rb +1406 -0
  141. data/lib/origen/registers/reg_collection.rb +24 -0
  142. data/lib/origen/registers.rb +652 -0
  143. data/lib/origen/regression_manager.rb +251 -0
  144. data/lib/origen/remote_manager.rb +340 -0
  145. data/lib/origen/revision_control/base.rb +257 -0
  146. data/lib/origen/revision_control/design_sync.rb +276 -0
  147. data/lib/origen/revision_control/git.rb +243 -0
  148. data/lib/origen/revision_control/subversion.rb +6 -0
  149. data/lib/origen/revision_control.rb +44 -0
  150. data/lib/origen/ruby_version_check.rb +131 -0
  151. data/lib/origen/site_config.rb +61 -0
  152. data/lib/origen/specs/checkers.rb +103 -0
  153. data/lib/origen/specs/creation_info.rb +17 -0
  154. data/lib/origen/specs/doc_resource.rb +91 -0
  155. data/lib/origen/specs/exhibit.rb +17 -0
  156. data/lib/origen/specs/mode_select.rb +16 -0
  157. data/lib/origen/specs/note.rb +17 -0
  158. data/lib/origen/specs/override.rb +21 -0
  159. data/lib/origen/specs/power_supply.rb +13 -0
  160. data/lib/origen/specs/spec.rb +226 -0
  161. data/lib/origen/specs/version_history.rb +14 -0
  162. data/lib/origen/specs.rb +552 -0
  163. data/lib/origen/sub_blocks.rb +298 -0
  164. data/lib/origen/tester/api.rb +277 -0
  165. data/lib/origen/tester/bdm/bdm.rb +25 -0
  166. data/lib/origen/tester/command_based_tester.rb +46 -0
  167. data/lib/origen/tester/doc/doc.rb +226 -0
  168. data/lib/origen/tester/doc/generator/flow.rb +71 -0
  169. data/lib/origen/tester/doc/generator/flow_line.rb +203 -0
  170. data/lib/origen/tester/doc/generator/test.rb +68 -0
  171. data/lib/origen/tester/doc/generator/test_group.rb +66 -0
  172. data/lib/origen/tester/doc/generator/tests.rb +47 -0
  173. data/lib/origen/tester/doc/generator.rb +126 -0
  174. data/lib/origen/tester/doc/model.rb +162 -0
  175. data/lib/origen/tester/generator/flow_control_api.rb +606 -0
  176. data/lib/origen/tester/generator/identity_map.rb +25 -0
  177. data/lib/origen/tester/generator/placeholder.rb +13 -0
  178. data/lib/origen/tester/generator/test_numberer.rb +25 -0
  179. data/lib/origen/tester/generator.rb +271 -0
  180. data/lib/origen/tester/interface.rb +154 -0
  181. data/lib/origen/tester/j750/files.rb +45 -0
  182. data/lib/origen/tester/j750/generator/flow.rb +123 -0
  183. data/lib/origen/tester/j750/generator/flow_line.rb +288 -0
  184. data/lib/origen/tester/j750/generator/patgroup.rb +111 -0
  185. data/lib/origen/tester/j750/generator/patgroups.rb +41 -0
  186. data/lib/origen/tester/j750/generator/patset.rb +111 -0
  187. data/lib/origen/tester/j750/generator/patsets.rb +41 -0
  188. data/lib/origen/tester/j750/generator/templates/flow.txt.erb +9 -0
  189. data/lib/origen/tester/j750/generator/templates/instances.txt.erb +16 -0
  190. data/lib/origen/tester/j750/generator/templates/patgroups.txt.erb +8 -0
  191. data/lib/origen/tester/j750/generator/templates/patsets.txt.erb +10 -0
  192. data/lib/origen/tester/j750/generator/test_instance.rb +846 -0
  193. data/lib/origen/tester/j750/generator/test_instance_group.rb +60 -0
  194. data/lib/origen/tester/j750/generator/test_instances.rb +182 -0
  195. data/lib/origen/tester/j750/generator.rb +203 -0
  196. data/lib/origen/tester/j750/j750.rb +845 -0
  197. data/lib/origen/tester/j750/j750_hpt.rb +35 -0
  198. data/lib/origen/tester/j750/parser/ac_spec.rb +11 -0
  199. data/lib/origen/tester/j750/parser/ac_specs.rb +0 -0
  200. data/lib/origen/tester/j750/parser/dc_spec.rb +36 -0
  201. data/lib/origen/tester/j750/parser/dc_specs.rb +50 -0
  202. data/lib/origen/tester/j750/parser/descriptions.rb +340 -0
  203. data/lib/origen/tester/j750/parser/flow.rb +111 -0
  204. data/lib/origen/tester/j750/parser/flow_line.rb +207 -0
  205. data/lib/origen/tester/j750/parser/flows.rb +23 -0
  206. data/lib/origen/tester/j750/parser/pattern_set.rb +94 -0
  207. data/lib/origen/tester/j750/parser/pattern_sets.rb +33 -0
  208. data/lib/origen/tester/j750/parser/test_instance.rb +322 -0
  209. data/lib/origen/tester/j750/parser/test_instances.rb +26 -0
  210. data/lib/origen/tester/j750/parser/timeset.rb +15 -0
  211. data/lib/origen/tester/j750/parser/timesets.rb +0 -0
  212. data/lib/origen/tester/j750/parser.rb +104 -0
  213. data/lib/origen/tester/jlink/jlink.rb +33 -0
  214. data/lib/origen/tester/parser/description_lookup.rb +64 -0
  215. data/lib/origen/tester/parser/searchable_array.rb +32 -0
  216. data/lib/origen/tester/parser/searchable_hash.rb +32 -0
  217. data/lib/origen/tester/parser.rb +24 -0
  218. data/lib/origen/tester/time.rb +338 -0
  219. data/lib/origen/tester/timing.rb +253 -0
  220. data/lib/origen/tester/ultraflex/files.rb +45 -0
  221. data/lib/origen/tester/ultraflex/generator/flow.rb +119 -0
  222. data/lib/origen/tester/ultraflex/generator/flow_line.rb +269 -0
  223. data/lib/origen/tester/ultraflex/generator/patgroup.rb +111 -0
  224. data/lib/origen/tester/ultraflex/generator/patgroups.rb +41 -0
  225. data/lib/origen/tester/ultraflex/generator/patset.rb +111 -0
  226. data/lib/origen/tester/ultraflex/generator/patsets.rb +41 -0
  227. data/lib/origen/tester/ultraflex/generator/templates/flow.txt.erb +9 -0
  228. data/lib/origen/tester/ultraflex/generator/templates/instances.txt.erb +16 -0
  229. data/lib/origen/tester/ultraflex/generator/templates/patgroups.txt.erb +8 -0
  230. data/lib/origen/tester/ultraflex/generator/templates/patsets.txt.erb +10 -0
  231. data/lib/origen/tester/ultraflex/generator/test_instance.rb +622 -0
  232. data/lib/origen/tester/ultraflex/generator/test_instance_group.rb +60 -0
  233. data/lib/origen/tester/ultraflex/generator/test_instances.rb +174 -0
  234. data/lib/origen/tester/ultraflex/generator.rb +200 -0
  235. data/lib/origen/tester/ultraflex/parser/ac_spec.rb +11 -0
  236. data/lib/origen/tester/ultraflex/parser/ac_specs.rb +0 -0
  237. data/lib/origen/tester/ultraflex/parser/dc_spec.rb +36 -0
  238. data/lib/origen/tester/ultraflex/parser/dc_specs.rb +50 -0
  239. data/lib/origen/tester/ultraflex/parser/descriptions.rb +342 -0
  240. data/lib/origen/tester/ultraflex/parser/flow.rb +111 -0
  241. data/lib/origen/tester/ultraflex/parser/flow_line.rb +207 -0
  242. data/lib/origen/tester/ultraflex/parser/flows.rb +23 -0
  243. data/lib/origen/tester/ultraflex/parser/pattern_set.rb +94 -0
  244. data/lib/origen/tester/ultraflex/parser/pattern_sets.rb +33 -0
  245. data/lib/origen/tester/ultraflex/parser/test_instance.rb +262 -0
  246. data/lib/origen/tester/ultraflex/parser/test_instances.rb +26 -0
  247. data/lib/origen/tester/ultraflex/parser/timeset.rb +15 -0
  248. data/lib/origen/tester/ultraflex/parser/timesets.rb +0 -0
  249. data/lib/origen/tester/ultraflex/parser.rb +104 -0
  250. data/lib/origen/tester/ultraflex/ultraflex.rb +759 -0
  251. data/lib/origen/tester/v93k/generator/flow.rb +63 -0
  252. data/lib/origen/tester/v93k/generator/flow_node/print.rb +10 -0
  253. data/lib/origen/tester/v93k/generator/flow_node.rb +17 -0
  254. data/lib/origen/tester/v93k/generator/pattern.rb +16 -0
  255. data/lib/origen/tester/v93k/generator/pattern_master.rb +54 -0
  256. data/lib/origen/tester/v93k/generator/templates/_test_method.txt.erb +6 -0
  257. data/lib/origen/tester/v93k/generator/templates/_test_suite.txt.erb +11 -0
  258. data/lib/origen/tester/v93k/generator/templates/template.flow.erb +121 -0
  259. data/lib/origen/tester/v93k/generator/templates/template.pmfl.erb +9 -0
  260. data/lib/origen/tester/v93k/generator/test_function.rb +103 -0
  261. data/lib/origen/tester/v93k/generator/test_functions.rb +79 -0
  262. data/lib/origen/tester/v93k/generator/test_method.rb +46 -0
  263. data/lib/origen/tester/v93k/generator/test_methods.rb +75 -0
  264. data/lib/origen/tester/v93k/generator/test_suite.rb +54 -0
  265. data/lib/origen/tester/v93k/generator/test_suites.rb +65 -0
  266. data/lib/origen/tester/v93k/generator.rb +80 -0
  267. data/lib/origen/tester/v93k/v93k.rb +420 -0
  268. data/lib/origen/tester/vector.rb +86 -0
  269. data/lib/origen/tester/vector_generator.rb +633 -0
  270. data/lib/origen/tester/vector_pipeline.rb +150 -0
  271. data/lib/origen/tester.rb +56 -0
  272. data/lib/origen/top_level.rb +134 -0
  273. data/lib/origen/users/ldap.rb +65 -0
  274. data/lib/origen/users/user.rb +149 -0
  275. data/lib/origen/users.rb +30 -0
  276. data/lib/origen/utility/block_args.rb +93 -0
  277. data/lib/origen/utility/csv_data.rb +110 -0
  278. data/lib/origen/utility/design_sync.rb +494 -0
  279. data/lib/origen/utility/diff.rb +158 -0
  280. data/lib/origen/utility/input_capture.rb +121 -0
  281. data/lib/origen/utility/mailer.rb +143 -0
  282. data/lib/origen/utility/s_record.rb +205 -0
  283. data/lib/origen/utility/time_and_date.rb +30 -0
  284. data/lib/origen/utility.rb +12 -0
  285. data/lib/origen/version_checker.rb +117 -0
  286. data/lib/origen/version_string.rb +356 -0
  287. data/lib/origen.rb +648 -0
  288. data/lib/tasks/gem.rake +27 -22
  289. data/origen_site_config.yml +36 -0
  290. data/source_setup +17 -0
  291. data/spec/format/rgen_formatter.rb +14 -0
  292. data/templates/api_doc/README.txt.erb +24 -0
  293. data/templates/code_generators/gemfile_app.rb +4 -0
  294. data/templates/code_generators/gemfile_plugin.rb +6 -0
  295. data/templates/code_generators/gemspec.rb +33 -0
  296. data/templates/code_generators/rakefile.rb +10 -0
  297. data/templates/code_generators/spec_helper.rb +49 -0
  298. data/templates/code_generators/version.rb +8 -0
  299. data/templates/code_generators/version_time.rb +3 -0
  300. data/templates/git/gitignore.erb +33 -0
  301. data/templates/j750/_vt_flow.txt.erb +8 -0
  302. data/templates/j750/_vt_instances.txt.erb +4 -0
  303. data/templates/j750/program_sheet.txt.erb +9 -0
  304. data/templates/nanoc/Rules +74 -0
  305. data/templates/nanoc/config.yaml +77 -0
  306. data/templates/nanoc/content/favicon.ico +0 -0
  307. data/templates/nanoc/layouts/bootstrap.html.erb +63 -0
  308. data/templates/nanoc/layouts/bootstrap3.html.erb +71 -0
  309. data/templates/nanoc/layouts/freescale.html.erb +79 -0
  310. data/templates/nanoc/lib/bootstrap_filter.rb +49 -0
  311. data/templates/nanoc/lib/codeblocks_filter.rb +41 -0
  312. data/templates/nanoc/lib/default.rb +2 -0
  313. data/templates/nanoc/lib/gzip_filter.rb +16 -0
  314. data/templates/nanoc/lib/haml_code_filter.rb +41 -0
  315. data/templates/nanoc/lib/helpers.rb +1 -0
  316. data/templates/nanoc/lib/search_filter.rb +62 -0
  317. data/templates/nanoc_dynamic/content/search.js.erb +92 -0
  318. data/templates/shared/web/_logo.html +10 -0
  319. data/templates/test/_inline_sub.txt.erb +2 -0
  320. data/templates/test/environment.txt.erb +1 -0
  321. data/templates/test/inline.txt.erb +11 -0
  322. data/templates/test/inspections.txt.erb +19 -0
  323. data/templates/test/set1/_sub1.txt.erb +12 -0
  324. data/templates/test/set1/_sub4.txt.erb +1 -0
  325. data/templates/test/set1/_sub5.txt.erb +1 -0
  326. data/templates/test/set1/main.txt.erb +53 -0
  327. data/templates/test/set1/sub_dir/_sub2.txt.erb +20 -0
  328. data/templates/test/set1/sub_dir/_sub3.txt.erb +12 -0
  329. data/templates/test/set1/sub_dir/main2.txt.erb +4 -0
  330. data/templates/test/set2/template_with_no_erb_1.txt +9 -0
  331. data/templates/test/set2/template_with_no_erb_2.txt +9 -0
  332. data/templates/test/set3/_layout.html.erb +4 -0
  333. data/templates/test/set3/content.html.erb +6 -0
  334. data/templates/time/filter.rb.erb +15 -0
  335. data/templates/time/rules.rb.erb +45 -0
  336. metadata +639 -5
@@ -0,0 +1,657 @@
1
+ module Origen
2
+ class Application
3
+ # This class is responsible for co-ordinating and monitoring all submissions
4
+ # to the LSF. This is in contrast to Origen::Application::LSF which is an API for
5
+ # talking to the LSF.
6
+ class LSFManager
7
+ include Callbacks
8
+
9
+ # This will be set by the command dispatcher to reflect the currently executing
10
+ # command. If LSF jobs are spawned with the same command then any options passed
11
+ # to the parent command will automatically be forwarded to the children.
12
+ attr_accessor :current_command
13
+
14
+ def initialize
15
+ end
16
+
17
+ def remote_jobs_file
18
+ "#{Origen.root}/.lsf/remote_jobs"
19
+ end
20
+
21
+ # Waits for all jobs to complete, will retry lost jobs (optionally
22
+ # failed jobs).
23
+ #
24
+ # Alternatively supply an :id or an array of :ids to wait only
25
+ # for specific job(s) to complete.
26
+ def wait_for_completion(options = {})
27
+ options = {
28
+ max_lost_retries: 10,
29
+ max_fail_retries: 0,
30
+ poll_duration_in_seconds: 10,
31
+ timeout_in_seconds: 3600
32
+ }.merge(options)
33
+ options[:start_time] ||= Time.now
34
+ if Time.now - options[:start_time] < options[:timeout_in_seconds]
35
+ # When waiting for ids we will hold by monitoring for the result
36
+ # files directly, rather than using the generatic classify routine.
37
+ # This is because the most common use case for this is when jobs
38
+ # are idling remotely on the LSF and don't want to run into contention
39
+ # issues when multiple processes try to classify/save the status.
40
+ if options[:id] || options[:ids]
41
+ ids = extract_ids([options[:id], options[:ids]].flatten.compact)
42
+ if ids.any? { |id| job_running?(id) }
43
+ sleep options[:poll_duration_in_seconds]
44
+ wait_for_completion(options)
45
+ end
46
+
47
+ else
48
+ classify_jobs
49
+ print_status(print_insructions: false)
50
+ sleep options[:poll_duration_in_seconds]
51
+ classify_jobs
52
+ resumitted = false
53
+ lost_jobs.each do |job|
54
+ if job[:submissions] < options[:max_lost_retries] + 1
55
+ resubmit_job(job)
56
+ resumitted = true
57
+ end
58
+ end
59
+ failed_jobs.each do |job|
60
+ if job[:submissions] < options[:max_fail_retries] + 1
61
+ resubmit_job(job)
62
+ resumitted = true
63
+ end
64
+ end
65
+ classify_jobs
66
+ if outstanding_jobs? || resumitted
67
+ wait_for_completion(options)
68
+ else
69
+ print_status
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ def print_status(options = {})
76
+ options = {
77
+ print_insructions: true
78
+ }.merge(options)
79
+ if options[:verbose]
80
+ print_details(options)
81
+ end
82
+ Origen.log.info ''
83
+ Origen.log.info 'LSF Status'
84
+ Origen.log.info '----------'
85
+ Origen.log.info "Queuing: #{queuing_jobs.size}"
86
+ Origen.log.info "Running: #{running_jobs.size}"
87
+ Origen.log.info "Lost: #{lost_jobs.size}"
88
+ Origen.log.info ''
89
+ Origen.log.info "Passed: #{passed_jobs.size}"
90
+ Origen.log.info "Failed: #{failed_jobs.size}"
91
+ Origen.log.info ''
92
+ if options[:print_insructions]
93
+ Origen.log.info 'Common tasks'
94
+ Origen.log.info '------------'
95
+ if queuing_jobs.size > 0
96
+ Origen.log.info 'Queuing'
97
+ Origen.log.info ' Show details: origen l -v -t queuing'
98
+ Origen.log.info ' Re-submit: origen l -r -t queuing'
99
+ end
100
+ if running_jobs.size > 0
101
+ Origen.log.info 'Running'
102
+ Origen.log.info ' Show details: origen l -v -t running'
103
+ Origen.log.info ' Re-submit: origen l -r -t running'
104
+ end
105
+ if lost_jobs.size > 0
106
+ Origen.log.info 'Lost'
107
+ Origen.log.info ' Show details: origen l -v -t lost'
108
+ Origen.log.info ' Re-submit: origen l -r -t lost'
109
+ end
110
+ if passed_jobs.size > 0
111
+ Origen.log.info 'Passed'
112
+ Origen.log.info ' Build log: origen l -l'
113
+ end
114
+ if failed_jobs.size > 0
115
+ Origen.log.info 'Failed'
116
+ Origen.log.info ' Show details: origen l -v -t failed'
117
+ Origen.log.info ' Re-submit: origen l -r -t failed'
118
+ end
119
+ Origen.log.info ''
120
+ Origen.log.info 'Reset the LSF manager (clear all jobs): origen lsf -c -t all'
121
+ Origen.log.info ''
122
+ end
123
+ end
124
+
125
+ def print_details(options = {})
126
+ if options[:id]
127
+ Origen.log.info "Job: #{options[:id]}"
128
+ Origen.log.info '----' + '-' * options[:id].length
129
+ print_details_of(remote_jobs[options[:id]])
130
+ else
131
+ options[:type] ||= :all
132
+ if options[:type] == :all || options[:type] == :queuing
133
+ Origen.log.info ''
134
+ Origen.log.info 'Queuing'
135
+ Origen.log.info '-------'
136
+ queuing_jobs.each { |j| print_details_of(j) }
137
+ end
138
+ if options[:type] == :all || options[:type] == :running
139
+ Origen.log.info ''
140
+ Origen.log.info 'Running'
141
+ Origen.log.info '-------'
142
+ running_jobs.each { |j| print_details_of(j) }
143
+ end
144
+ if options[:type] == :all || options[:type] == :lost
145
+ Origen.log.info ''
146
+ Origen.log.info 'Lost'
147
+ Origen.log.info '----'
148
+ lost_jobs.each { |j| print_details_of(j) }
149
+ end
150
+ if options[:type] == :all || options[:type] == :passed
151
+ Origen.log.info ''
152
+ Origen.log.info 'Passed'
153
+ Origen.log.info '------'
154
+ passed_jobs.each { |j| print_details_of(j) }
155
+ end
156
+ if options[:type] == :all || options[:type] == :failed
157
+ Origen.log.info ''
158
+ Origen.log.info 'Failed'
159
+ Origen.log.info '------'
160
+ failed_jobs.each { |j| print_details_of(j) }
161
+ end
162
+ end
163
+ end
164
+
165
+ def print_details_of(job)
166
+ Origen.log.info "#{job[:command]} #{job[:switches]}".gsub(' --exec_remote', '')
167
+ Origen.log.info "ID: #{job[:id]}"
168
+ Origen.log.info "Submitted: #{time_ago(job[:submitted_at])}"
169
+ Origen.log.info ''
170
+ end
171
+
172
+ def time_ago(time)
173
+ seconds = (Time.now - time).to_i
174
+ if seconds < 60
175
+ unit = 'second'
176
+ number = seconds
177
+ elsif seconds < 3600
178
+ unit = 'minute'
179
+ number = seconds / 60
180
+ elsif seconds < 86_400
181
+ unit = 'hour'
182
+ number = seconds / 3600
183
+ else
184
+ unit = 'day'
185
+ number = seconds / 86_400
186
+ end
187
+ "#{number} #{unit}#{number > 1 ? 's' : ''} ago"
188
+ end
189
+
190
+ def outstanding_jobs?
191
+ (running_jobs + queuing_jobs).size > 0
192
+ end
193
+
194
+ # Clear jobs from memory
195
+ def clear(options)
196
+ if options[:type]
197
+ if options[:type] == :all
198
+ File.delete(remote_jobs_file) if File.exist?(remote_jobs_file)
199
+ @remote_jobs = {}
200
+ return
201
+ else
202
+ send("#{options[:type]}_jobs").each do |job|
203
+ remote_jobs.delete(job[:id])
204
+ end
205
+ end
206
+ else
207
+ remote_jobs.delete(options[:id])
208
+ end
209
+ end
210
+
211
+ def clear_all
212
+ File.delete(remote_jobs_file) if File.exist?(remote_jobs_file)
213
+ if File.exist?(log_file_directory)
214
+ FileUtils.rm_rf(log_file_directory)
215
+ end
216
+ FileUtils.mkdir_p(log_file_directory)
217
+ @remote_jobs = {}
218
+ clear_caches
219
+ end
220
+
221
+ # Resubmit jobs
222
+ def resubmit(options)
223
+ if options[:type]
224
+ if options[:type] == :all
225
+ remote_jobs.each do |_id, job|
226
+ resubmit_job(job)
227
+ end
228
+ else
229
+ send("#{options[:type]}_jobs").each do |job|
230
+ resubmit_job(job)
231
+ end
232
+ end
233
+ else
234
+ resubmit_job(remote_jobs[options[:id]])
235
+ end
236
+ end
237
+
238
+ def stats
239
+ Origen.app.stats
240
+ end
241
+
242
+ # Build the log file from the completed jobs
243
+ def build_log(_options = {})
244
+ Origen.log.info '*' * 70
245
+ completed_jobs.each do |job|
246
+ File.open(log_file(job[:id])) do |f|
247
+ last_line_blank = false
248
+ f.readlines.each do |line|
249
+ # Capture and combine the per job stats that look like this:
250
+ # Total patterns: 1 1347 0.003674
251
+ # New patterns: 0
252
+ # Changed patterns: 1
253
+ # FAILED patterns: 1
254
+ # Total files: 1
255
+ # New files: 0
256
+ # Changed files: 0
257
+ # FAILED files: 1
258
+ begin
259
+ line.gsub!(/\e\[\d+m/, '') # Remove any coloring
260
+ if line =~ /Total patterns:\s+(\d+)/
261
+ stats.completed_patterns += Regexp.last_match[1].to_i
262
+ elsif line =~ /Total vectors:\s+(\d+)/
263
+ stats.total_vectors += Regexp.last_match[1].to_i
264
+ elsif line =~ /Total duration:\s+(\d+\.\d+)/
265
+ stats.total_duration += Regexp.last_match[1].to_f
266
+ elsif line =~ /Total files:\s+(\d+)/
267
+ stats.completed_files += Regexp.last_match[1].to_i
268
+ elsif line =~ /Changed patterns:\s+(\d+)/
269
+ stats.changed_patterns += Regexp.last_match[1].to_i
270
+ elsif line =~ /Changed files:\s+(\d+)/
271
+ stats.changed_files += Regexp.last_match[1].to_i
272
+ elsif line =~ /New patterns:\s+(\d+)/
273
+ stats.new_patterns += Regexp.last_match[1].to_i
274
+ elsif line =~ /New files:\s+(\d+)/
275
+ stats.new_files += Regexp.last_match[1].to_i
276
+ elsif line =~ /FAILED patterns:\s+(\d+)/
277
+ stats.failed_patterns += Regexp.last_match[1].to_i
278
+ elsif line =~ /FAILED files:\s+(\d+)/
279
+ stats.failed_files += Regexp.last_match[1].to_i
280
+ elsif line =~ /ERROR!/
281
+ stats.errors += 1
282
+ Origen.log.send :relog, line
283
+ else
284
+ # Compress multiple blank lines
285
+ if line =~ /^\s*$/ || line =~ /.*\|\|\s*$/
286
+ unless last_line_blank
287
+ Origen.log.info
288
+ last_line_blank = true
289
+ end
290
+ else
291
+ # Screen std origen output
292
+ unless line =~ / origen save/ ||
293
+ line =~ /Insecure world writable dir/ ||
294
+ line =~ /To save all of/
295
+ line.strip!
296
+ # line.sub!(/.*\|\| /, '')
297
+ Origen.log.send :relog, line
298
+ last_line_blank = false
299
+ end
300
+ end
301
+ end
302
+ rescue
303
+ # Sometimes illegal UTF-8 characters can get into crash dumps, if this
304
+ # happens just print the line out rather than die
305
+ Origen.log.error line
306
+ end
307
+ end
308
+ end
309
+ end
310
+ Origen.log.info '*' * 70
311
+ stats.print_summary
312
+ end
313
+
314
+ # Returns the logfile that should be used by a given process on the LSF, this
315
+ # should be be guaranteed to be unique
316
+ def log_file(id)
317
+ "#{log_file_directory}/#{log_file_name(id)}"
318
+ end
319
+
320
+ def passed_file(id)
321
+ "#{log_file_directory}/#{log_file_name(id)}.passed"
322
+ end
323
+
324
+ def started_file(id)
325
+ "#{log_file_directory}/#{log_file_name(id)}.started"
326
+ end
327
+
328
+ def failed_file(id)
329
+ "#{log_file_directory}/#{log_file_name(id)}.failed"
330
+ end
331
+
332
+ def log_file_name(id)
333
+ # host = `hostname`.strip
334
+ "#{id}.txt"
335
+ end
336
+
337
+ def log_file_directory
338
+ "#{Origen.root}/.lsf/remote_logs"
339
+ end
340
+
341
+ # Register that the given job ID has completed successfully on the LSF
342
+ def job_passed(id)
343
+ `touch #{passed_file(id)}`
344
+ end
345
+
346
+ # Register that the given job ID has failed on the LSF
347
+ def job_failed(id)
348
+ `touch #{failed_file(id)}`
349
+ end
350
+
351
+ def job_started(id)
352
+ `touch #{started_file(id)}`
353
+ end
354
+
355
+ def resubmit_job(job)
356
+ [log_file(job[:id]), passed_file(job[:id]), failed_file(job[:id]), started_file(job[:id])].each do |file|
357
+ FileUtils.rm_f(file) if File.exist?(file)
358
+ end
359
+ job[:lsf_id] = Origen.app.lsf.submit(command_prefix(job[:id], job[:dependents_ids]) + job[:command] + job[:switches], dependents: job[:dependents_lsf_ids])
360
+ job[:status] = nil
361
+ job[:completed_at] = nil
362
+ job[:submitted_at] = Time.now
363
+ job[:submissions] += 1
364
+ end
365
+
366
+ def submit_job(command, options = {})
367
+ options = {
368
+ lsf_option_string: ''
369
+ }.merge(options)
370
+ switches = [' ', options[:lsf_option_string], command_options(command)].flatten.compact.join(' ')
371
+ id = generate_job_id
372
+ dependents_ids = extract_ids([options[:depend], options[:depends], options[:dependent], options[:dependents]].flatten.compact)
373
+ dependents_lsf_ids = dependents_ids.map { |dep_id| remote_jobs[dep_id][:lsf_id] }
374
+ lsf_id = Origen.app.lsf.submit(command_prefix(id, dependents_ids) + command + switches, dependents: dependents_lsf_ids)
375
+ job_attrs = {
376
+ id: id,
377
+ lsf_id: lsf_id,
378
+ command: command,
379
+ submitted_at: Time.now,
380
+ submissions: 1,
381
+ switches: switches,
382
+ dependents_ids: dependents_ids,
383
+ dependents_lsf_ids: dependents_lsf_ids
384
+ }
385
+ remote_jobs[id] = job_attrs
386
+ end
387
+
388
+ def extract_ids(jobs_or_ids)
389
+ jobs_or_ids.map { |j| j.is_a?(Hash) ? j[:id] : j }
390
+ end
391
+
392
+ def submit_origen_job(cmd, options = {})
393
+ if options[:action]
394
+ action = options[:action] == :pattern ? ' generate' : " #{options[:action]}"
395
+ else
396
+ action = ''
397
+ end
398
+
399
+ str = "#{action} #{cmd}".strip
400
+ str.sub('origen ', '') if str =~ /^origen /
401
+
402
+ # Append the --exec_remote switch to all Origen commands, this allows command
403
+ # processing to be altered based on whether it is running locally or
404
+ # remotely by testing Origen.running_remotely?
405
+ str += ' --exec_remote'
406
+
407
+ submit_job("origen #{str}", options)
408
+ end
409
+
410
+ def command_prefix(id, dependents)
411
+ origen = `which origen`
412
+ # http://rubular.com/r/wgKi73KjUo
413
+ if origen =~ /(^\/run\/pkg\/fs-origen-\/[^\/]+)/
414
+ prefix = "source #{Regexp.last_match[1]}/origen_setup; "
415
+ else
416
+ prefix = "cd #{Origen.top}; source source_setup; "
417
+ end
418
+ prefix += "cd #{Origen.root}; origen l --execute --id #{id} "
419
+ unless dependents.empty?
420
+ prefix += "--dependents #{dependents.join(',')} "
421
+ end
422
+ prefix
423
+ end
424
+
425
+ def command_options(command_str)
426
+ command_str.sub(/origen\s*/, '') =~ /(\w+)/
427
+ command = Regexp.last_match[1]
428
+ command = ORIGEN_COMMAND_ALIASES[command] || command
429
+ if command == current_command
430
+ @command_options
431
+ else
432
+ ''
433
+ end
434
+ end
435
+
436
+ # This will be called by the command dispatcher to record any options that were passed
437
+ # in when launching the current command.
438
+ # These will be automatically appended if the current command spawns any LSF jobs that
439
+ # will invoke the same command.
440
+ def command_options=(opts)
441
+ # Ensure these options are removed, these are either incompatible with the LSF,
442
+ # or will already have been added elsewhere
443
+ {
444
+ ['-h', '--help'] => false,
445
+ ['-w', '--wait'] => false,
446
+ ['-d', '--debug'] => false,
447
+ ['-c', '--continue'] => false,
448
+ '--exec_remote' => false,
449
+ ['-t', '--target'] => '*',
450
+ ['-e', '--environment'] => '*',
451
+ '--id' => '*',
452
+ ['-l', '--lsf'] => %w(add clear)
453
+ }.each do |names, values|
454
+ [names].flatten.each do |name|
455
+ ix = opts.index(name)
456
+ if ix
457
+ opts.delete_at(ix)
458
+ [values].flatten.each do |value|
459
+ if value && (value == '*' || opts[ix] == value)
460
+ opts.delete_at(ix)
461
+ end
462
+ end
463
+ end
464
+ end
465
+ end
466
+ @command_options ||= []
467
+ @command_options += opts
468
+ end
469
+
470
+ def add_command_option(*opts)
471
+ @command_options ||= []
472
+ @command_options += opts
473
+ end
474
+
475
+ def remote_jobs
476
+ @remote_jobs ||= restore_remote_jobs || {}
477
+ end
478
+
479
+ def classify_jobs
480
+ clear_caches
481
+ queuing_job_ids = Origen.app.lsf.queuing_job_ids
482
+ running_job_ids = Origen.app.lsf.running_job_ids
483
+ remote_jobs.each do |_id, job|
484
+ # If the status has already been determined send it straight to the bucket
485
+ if job[:status]
486
+ send("#{job[:status]}_jobs") << job
487
+ else
488
+ if job[:lsf_id] == :error
489
+ job[:status] = :lost
490
+ lost_jobs << job
491
+ elsif job_completed?(job[:id])
492
+ if job_passed?(job[:id])
493
+ job[:status] = :passed
494
+ passed_jobs << job
495
+ elsif job_failed?(job[:id])
496
+ job[:status] = :failed
497
+ failed_jobs << job
498
+ end
499
+ else
500
+ if running_job_ids.include?(job[:lsf_id])
501
+ running_jobs << job
502
+ # Once we have assigned a job as running make sure the job is marked as started
503
+ # It can flicker back to queued if the started file takes a long time to arrive
504
+ # from the remote host
505
+ job_started(job[:lsf_id])
506
+ elsif queuing_job_ids.include?(job[:lsf_id])
507
+ queuing_jobs << job
508
+ elsif job_started?(job[:id])
509
+ # There can be considerable latency between the job writing the passed/failed
510
+ # file remotely and it showing up on the local machine.
511
+ # Give some buffer to that before declaring the file lost.
512
+ if job[:completed_at]
513
+ if (Time.now - job[:completed_at]) < 60
514
+ running_jobs << job
515
+ else
516
+ lost_jobs << job
517
+ end
518
+ else
519
+ job[:completed_at] = Time.now
520
+ running_jobs << job
521
+ end
522
+ # Give jobs submitted less than a minute ago the benefit of the
523
+ # doubt, they may not have shown up in bjobs yet
524
+ elsif (Time.now - job[:submitted_at]) < 60
525
+ queuing_jobs << job
526
+ else
527
+ lost_jobs << job
528
+ end
529
+ end
530
+ end
531
+ end
532
+ end
533
+
534
+ def clear_caches
535
+ @running_jobs = nil
536
+ @queuing_jobs = nil
537
+ @passed_jobs = nil
538
+ @failed_jobs = nil
539
+ @lost_jobs = nil
540
+ end
541
+
542
+ def running_jobs
543
+ @running_jobs ||= []
544
+ end
545
+
546
+ def queuing_jobs
547
+ @queuing_jobs ||= []
548
+ end
549
+
550
+ def completed_jobs
551
+ passed_jobs + failed_jobs
552
+ end
553
+
554
+ def passed_jobs
555
+ @passed_jobs ||= []
556
+ end
557
+
558
+ # Failed jobs are those that started to produce a log file but did not complete
559
+ def failed_jobs
560
+ @failed_jobs ||= []
561
+ end
562
+
563
+ # Lost jobs are ones that for whatever reason did not start, or at least get far
564
+ # enough to log that they started
565
+ def lost_jobs
566
+ @lost_jobs ||= []
567
+ end
568
+
569
+ # Returns trus if the given job ID generated a complete file when run on the LSF.
570
+ # The complete file is created at the end of a job run and its presence indicates
571
+ # that the job ran and got past the generation/compile stage without crashing.
572
+ def job_completed?(id)
573
+ job_started?(id) &&
574
+ (job_passed?(id) || job_failed?(id))
575
+ end
576
+
577
+ def job_running?(id)
578
+ !job_completed?(id)
579
+ end
580
+
581
+ def job_started?(id)
582
+ File.exist?(started_file(id))
583
+ end
584
+
585
+ def job_passed?(id)
586
+ File.exist?(passed_file(id))
587
+ end
588
+
589
+ def job_failed?(id)
590
+ File.exist?(failed_file(id))
591
+ end
592
+
593
+ def generate_job_id
594
+ "#{Time.now.to_f}".gsub('.', '')
595
+ end
596
+
597
+ def restore_remote_jobs
598
+ if File.exist?(remote_jobs_file)
599
+ File.open(remote_jobs_file) do |f|
600
+ begin
601
+ Marshal.load(f)
602
+ rescue
603
+ nil
604
+ end
605
+ end
606
+ end
607
+ end
608
+
609
+ def on_origen_shutdown(_options = {})
610
+ save_remote_jobs if @remote_jobs
611
+ end
612
+
613
+ def save_remote_jobs
614
+ File.open(remote_jobs_file, 'w') do |f|
615
+ Marshal.dump(@remote_jobs, f)
616
+ end
617
+ end
618
+
619
+ def execute_remotely(options = {})
620
+ job_started(options[:id])
621
+ begin
622
+ if options[:dependents]
623
+ wait_for_completion(ids: options[:dependents],
624
+ poll_duration_in_seconds: 1,
625
+ # Don't wait long by the time this runs the LSF
626
+ # should have guaranteed the job has run
627
+ timeout_in_seconds: 120
628
+ )
629
+ unless options[:dependents].all? { |id| job_passed?(id) }
630
+ File.open(log_file(options[:id]), 'w') do |f|
631
+ f.puts "*** ERROR! *** #{options[:cmd].join(' ')} ***"
632
+ f.puts 'Dependents failed!'
633
+ end
634
+ fail 'Dependents failed!'
635
+ end
636
+ end
637
+ if options[:cmd].is_a?(Array)
638
+ cmd = options[:cmd].join(' ')
639
+ else
640
+ cmd = options[:cmd]
641
+ end
642
+ output = `#{cmd} 2>&1`
643
+ File.open(log_file(options[:id]), 'w') do |f|
644
+ f.write output
645
+ end
646
+ if $CHILD_STATUS.success?
647
+ job_passed(options[:id])
648
+ else
649
+ job_failed(options[:id])
650
+ end
651
+ rescue
652
+ job_failed(options[:id])
653
+ end
654
+ end
655
+ end
656
+ end
657
+ end