tiny_ge 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 96bc1b77a659cad57646a1398044b96c7a4b71c3156383dad83851b01a02147e
4
+ data.tar.gz: 2004c17254e109aa2df31fcc984238b33bb994df6b603f33e5dd566d08b995b0
5
+ SHA512:
6
+ metadata.gz: 70890650d6c60bfe67520de5ffca924f4402d53bb1a7453dcb56ca0511e74aa21b7fb948d5bd586fd6d1d26f14a9cd2b63692a4ae5cbfadad1df7bec45029414
7
+ data.tar.gz: dbd41fc053114b598965059296d2e60e345ccd06d3956ff1bf077f5475fa6502aadd25a54438fd0ebac6f08385019f9c498f572eff0f434fc44edc46482602b5
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.7.2
6
+ before_install: gem install bundler -v 2.1.4
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at shigeto_nishitani@me.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in tiny_ge.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "minitest", "~> 5.0"
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tiny_ge (0.1.0)
5
+ colorize
6
+ command_line
7
+ thor
8
+ yaml
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ ansi (1.5.0)
14
+ builder (3.2.4)
15
+ colorize (0.8.1)
16
+ command_line (2.0.1)
17
+ minitest (5.14.3)
18
+ minitest-reporters (1.4.3)
19
+ ansi
20
+ builder
21
+ minitest (>= 5.0)
22
+ ruby-progressbar
23
+ rake (12.3.3)
24
+ ruby-progressbar (1.11.0)
25
+ thor (1.1.0)
26
+ yaml (0.1.1)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ minitest (~> 5.0)
33
+ minitest-reporters
34
+ rake (~> 12.0)
35
+ tiny_ge!
36
+
37
+ BUNDLED WITH
38
+ 2.1.4
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Shigeto R. Nishitani
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,189 @@
1
+ #+qiita_private: 79491472592ae821dcdc
2
+ #+OPTIONS: ^:{}
3
+ #+STARTUP: indent nolineimages
4
+ #+TITLE: linuxでprocessの排他処理
5
+ #+AUTHOR: Shigeto R. Nishitani
6
+ #+EMAIL: (concat "shigeto_nishitani@mac.com")
7
+ #+LANGUAGE: jp
8
+ # +OPTIONS: H:4 toc:t num:2
9
+ #+OPTIONS: toc:nil
10
+ #+TAG: Linux, 排他処理
11
+ #+TWITTER: off
12
+ # +SETUPFILE: ~/.emacs.d/org-mode/theme-readtheorg.setup
13
+
14
+ * intro
15
+ necのvector engineでprocessを排他処理する.
16
+
17
+ necのVector Engineでmpirunを投げるとそのまま行っちゃう.
18
+ そこでlock fileによる排他処理を提案されたが,そのままだと順序が保証できない.
19
+ そこんとこちょっと改善
20
+
21
+ * 方針
22
+ 統一ファイルを用意して,そこにveにsubmitしたjobのstatusを記録し,
23
+ そこから排他処理と実行を行う.
24
+
25
+ * 実装
26
+ ** 最初の提案
27
+ 例えば、ロックファイルを作るのはどうでしょうか?
28
+ #+begin_src shell
29
+ #!/bin/sh
30
+
31
+ while [ -f "${HOME}/.running" ]; do
32
+ sleep 10
33
+ done
34
+ touch "${HOME}/.running"
35
+
36
+ [...]
37
+ mpirun -np 8 vasp_std 1> stdout 2> stderr
38
+
39
+ rm "${HOME}/.running"
40
+ #+end_src
41
+ これをバックグラウンドで実行すればVEに複数ジョブが一度に入ることはなくなります。
42
+
43
+ - 実行順は保証されません。
44
+
45
+ ** 最初の実装
46
+ home directory配下にファイルを用意してそこにstatus([finished, running, waiting])を
47
+ 書き込んでそれを参照してjobを実行する.
48
+
49
+ それぞれの投入ジョブのshellは次の通り.
50
+ #+name: check_ve.sh
51
+ #+include: "./test/check_ve.sh" src sh
52
+
53
+ 実際の稼働shellは以下の二つ.
54
+ #+name: check_ve_lock
55
+ #+include: "./lib/check_ve_lock" src ruby
56
+
57
+ #+name: unlock_ve_lock
58
+ #+include: "./lib/unlock_ve_lock" src ruby
59
+ 動いた.
60
+ #+begin_example
61
+ 12753: finished: /home/bob/bin: 2021-01-26 20:45:56 +0900
62
+ 13209: finished: /home/bob/bin: 2021-01-26 20:46:05 +0900
63
+ 13407: finished: /home/bob/bin: 2021-01-26 20:46:14 +0900
64
+ 8512: finished: /home/bob/frenkel_aurora/al_110_lambda_05: 2021-01-26 23:37:06 +0900
65
+ 20683: running: /home/bob/frenkel_aurora/al_110_lambda_075: 2021-01-26 23:48:25 +0900
66
+ #+end_example
67
+ ** rubyからbackgroundでの実行
68
+ - [[https://stackoverflow.com/questions/11982057/how-can-i-trigger-a-shell-script-and-run-in-background-async-in-ruby][How can I trigger a shell script and run in background (async) in Ruby?]]
69
+
70
+ に書かれている手法で,
71
+ #+begin_src ruby
72
+ shell_file = "./test.sh"
73
+ File.write(shell_file, "sleep 10\necho \"hoge\"\n")
74
+ command_line("chmod u+x #{shell_file}")
75
+ p pid = spawn(shell_file, :out => "test.out", :err => "test.err")
76
+ Process.detach(pid)
77
+ #+end_src
78
+ にて実装.
79
+
80
+ 結果は,
81
+ #+begin_example
82
+ > ls -la --time-style=full-iso test*
83
+ -rw-r--r--. 1 bob bob 0 2021-01-29 12:12:29.572812565 +0900 test.err
84
+ -rw-r--r--. 1 bob bob 5 2021-01-29 12:12:39.575812241 +0900 test.out
85
+ -rwxrw-r--. 1 bob bob 21 2021-01-29 12:12:29.571812565 +0900 test.sh*
86
+ -rw-rw-r--. 1 bob bob 155 2021-01-28 10:01:57.380865004 +0900 test_helper.rb
87
+ #+end_example
88
+ となり,10秒後に書き込まれているのを確認.outファイルは実行直後に出来てたみたい.
89
+ chmodが嫌ですね.
90
+ でも,変なpermissionいらないからuser directoryで実行するshellを生成するのが良さそう.
91
+
92
+ 前回これを実装しようとして,child processとかで悩んだ.
93
+
94
+ この検索過程で,gemでqueueシステムをいくつも発見.
95
+ railsとかtest用にいくつも開発されている.
96
+ - [[https://www.ruby-toolbox.com/categories/Background_Jobs]]
97
+ - [[https://blog.appsignal.com/2019/04/02/background-processing-system-in-ruby.html][Ruby Magic Learning by building, a Background Processing System in Ruby]]
98
+ ただ,難しそう...
99
+
100
+
101
+ * Tiny GE
102
+ 次節の改善案にしたがってgemで実装.
103
+ SGEのコマンドに似せて作成.
104
+
105
+
106
+ #+begin_example
107
+ > tge --help
108
+
109
+ qsub [shell] # submit shell job
110
+ qstat # show queue status
111
+ qdel [pid] # delete job
112
+ qfinish [pid] # finish forcely
113
+ #+end_example
114
+
115
+ shellを指定してqsubすると以下のtest.shが作成される.
116
+ #+begin_src shell
117
+ > cat test.sh
118
+ #!/bin/sh
119
+ while ! qsub 23520; do
120
+ sleep 10
121
+ done
122
+
123
+ sh /home/.../ve_lock_vasp.sh
124
+
125
+ qfinish 23520
126
+ #+end_src
127
+
128
+ defaultでは~/.tge_test_jobs.txtにqueueがYAML形式で保存されている.
129
+
130
+ qstatで'running'などの状況を確認.
131
+ #+begin_example shell
132
+ > qstat
133
+ 11670: 11702: finished: /home/bob/tiny_ge/test/hello_world.sh
134
+ 14735: 14764: finished: /home/bob/tiny_ge/test/hello_world.sh
135
+ 18515: 18545: finished: /home/bob/frenkel_aurora/00_1000_10/ve_lock_vasp.sh
136
+ 29533: 29562: finished: /home/bob/frenkel_aurora/00_1000_10/ve_lock_vasp.sh
137
+ 18648: 18678: running: /home/bob/frenkel_aurora/00_1000_10/ve_lock_vasp.sh
138
+ #+end_example
139
+
140
+ * 改善案
141
+ - [X] テキストにして置いておくより,yamlかjsonが良さそう.
142
+ 見にくいけれど,間違いがないだろうから.
143
+ - [X] qsubを常駐させて,そこにsubmitするという手はないか?
144
+ 1. 常駐させる必要はなくて,qsubに対してve_lock用のshellを常駐させればいい.
145
+ 1. /tmpにおく?
146
+ - [ ] 走ってないゾンビをチェックする必要あり
147
+ - [X] qstat, qdelが必要
148
+
149
+ - [X] gem化するのが良さそう.そこでは
150
+ : exeに個別のコマンドを用意するが,実体は同じclassの違う振る舞い
151
+ とすればいい.
152
+
153
+ - [X] qsub -> TGE.qsub(pid, shell_path)
154
+ - [X] qfinish -> TGE.qfinish(pid)
155
+ - [X] qstat -> TGE.qstat(line = 10)
156
+ - [X] qdel -> TGE.qdel(pid)
157
+ なんかのmodule methodを用意して,それぞれのコマンドを実行させればいい.
158
+ それにはThorなんかのCLIはいらない.
159
+
160
+ * テスト
161
+ - [[https://github.com/minitest-reporters/minitest-reporters][minitest-reporters]]
162
+
163
+ ** test_helperの呼び方
164
+ rake testでやるときと,
165
+ : ruby tiny_ge_test.rb -n test_qsub
166
+ とかでやるときでtest_helperが呼ばれない時がある.
167
+
168
+ : require_relative "./test_helper"
169
+
170
+ とすると両方で呼ばれる.
171
+
172
+ #+name: test_helper.rb
173
+ #+begin_ruby
174
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
175
+ #require 'test/unit'
176
+ require "tiny_ge"
177
+
178
+ require "minitest/autorun"
179
+ require "minitest/reporters"
180
+ Minitest::Reporters.use!
181
+ #+end_ruby
182
+ - qconf
183
+ - かきこ
184
+ ** kill zombie
185
+ 開発の段階でzombie processの大量発生が起こった.
186
+
187
+ : ps -xal |grep test.sh
188
+ とかで親プロセスまで見ることができて.殺せる.
189
+ 第4出力が親プロセス.
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tiny_ge"
4
+
5
+ TGE.new.qdel(ARGV[0].to_i)
6
+
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tiny_ge"
4
+
5
+ TGE::qstat
6
+
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tiny_ge"
4
+
5
+ TGE.new.qfinish(ARGV[0].to_i)
6
+
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tiny_ge"
4
+
5
+ TGE.new.qdel(ARGV[0].to_i)
6
+
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tiny_ge"
4
+
5
+ TGE.new.qstat(ARGV[0].to_i)
6
+
7
+
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tiny_ge"
4
+
5
+ TGE::qstat(-10)
6
+
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tiny_ge"
4
+
5
+ pid = $$
6
+ file = ARGV[0]
7
+ accepted_formats = ['.sh']
8
+ unless accepted_formats.include? File.extname(file)
9
+ pid = file.to_i
10
+ end
11
+ shell_path = File.join(Dir.pwd, ARGV[0])
12
+
13
+ res = TGE.new.qsub(pid, shell_path)
14
+ #p ['qsub_status', res, pid]
15
+ if res
16
+ exit 0
17
+ else
18
+ exit 1
19
+ end
20
+
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tiny_ge"
4
+ require 'thor'
5
+
6
+ module TinyGE
7
+ class MyCLI < Thor
8
+ desc "hello NAME", "say hello to NAME"
9
+ def hello(name)
10
+ puts "Hello " + name
11
+ end
12
+ end
13
+ end
14
+
15
+ TinyGE::MyCLI.start(ARGV)
16
+
data/exe/tge ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ str = <<-EOF
4
+ tge : tiny GE is a tiny queue system like SGE
5
+
6
+ qsub [shell] # submit job
7
+ qstat # show queue stats
8
+ qdel [pid] # delete job
9
+ qfinish # use internal
10
+ EOF
11
+
12
+ puts str
13
+
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ str = <<- EOF
4
+ hello
5
+ EOF
6
+
7
+ puts str
8
+
@@ -0,0 +1,121 @@
1
+ require "tiny_ge/version"
2
+ require 'yaml'
3
+ require 'thor'
4
+ require 'command_line/global'
5
+
6
+ #VE_SUBMIT_JOBS_FILE = File.join(ENV['HOME'],".ve_submit_jobs.txt")
7
+ VE_TEST_FILE = File.join(ENV['HOME'],".tge_test_jobs.txt")
8
+
9
+ class TGE
10
+ def initialize(q_file=VE_TEST_FILE)
11
+ @q_file = VE_TEST_FILE
12
+ @data = YAML.load(File.read(@q_file))
13
+ end
14
+
15
+ def add_job(pid, shell_path)
16
+ shell_file = "./test.s#{pid}"
17
+ shell_script = mk_shell_script(pid, shell_path)
18
+ File.write(shell_file, shell_script)
19
+
20
+ p pid0 = spawn("sh #{shell_file}", :out => "test.o#{pid}", :err => "test.e#{pid}")
21
+ Process.detach(pid0)
22
+ puts "#{pid} is added on the queue."
23
+
24
+ @data << {pid: pid, status: 'waiting', shell_path: shell_path,
25
+ real_pid: pid0,
26
+ submit: Time.now,
27
+ start: nil,
28
+ finish: nil
29
+ }
30
+ File.write(VE_TEST_FILE, YAML.dump(@data))
31
+ end
32
+
33
+ def change_job_status(pid, status)
34
+ @data.each do |job, i|
35
+ if job[:pid] == pid
36
+ job[:status] = status
37
+ case status
38
+ when 'running' ; job[:start] = Time.now
39
+ when 'finished'; job[:finish] = Time.now
40
+ end
41
+ File.write(VE_TEST_FILE, YAML.dump(@data))
42
+ break
43
+ end
44
+ end
45
+ end
46
+
47
+ def qfinish(pid)
48
+ change_job_status(pid, 'finished')
49
+ return true
50
+ end
51
+
52
+ def qsub(pid, shell_path=Dir.pwd)
53
+ unless pid_on_file(pid)
54
+ add_job(pid, shell_path)
55
+ return false
56
+ end
57
+ last_finished = -1
58
+ @data.each_with_index do |job, i|
59
+ if job[:pid] == pid
60
+ if job[:status] == 'waiting' and i == last_finished + 1
61
+ change_job_status(pid, 'running')
62
+ return true
63
+ end
64
+ if job[:status] == 'running'
65
+ return true
66
+ end
67
+ return false
68
+ end
69
+ last_finished = i if job[:status] == 'finished'
70
+ end
71
+ end
72
+
73
+ def pid_on_file(pid)
74
+ @data.each do |job, i|
75
+ return job[:status] if job[:pid] == pid
76
+ end
77
+ return false
78
+ end
79
+
80
+ def qdel(pid)
81
+ unless pid_on_file(pid)
82
+ puts "#{pid} is not on the qeueu."
83
+ return false
84
+ end
85
+ @data.each_with_index do |job, i|
86
+ if job[:pid] == pid
87
+ res = command_line("kill -9 #{job[:real_pid]}")
88
+ p res
89
+ @data.delete_at(i)
90
+ File.write(VE_TEST_FILE, YAML.dump(@data))
91
+ puts "#{pid} is deleted from the qeueu."
92
+ return true
93
+ end
94
+ end
95
+ end
96
+
97
+ def qstat(item_num=0)
98
+ if item_num == '-f'
99
+ item_num
100
+ @data = YAML.load(File.read(VE_TEST_FILE))
101
+ @data[item_num..-1].each do |job, i|
102
+ real_pid = job[:real_pid] || 0
103
+ puts "%5d: %5d: %10s: %s" % [job[:pid], real_pid, job[:status], job[:shell_path]]
104
+ end
105
+ end
106
+
107
+ def mk_shell_script(pid, shell_path)
108
+ return <<~EOS
109
+ #!/bin/sh
110
+ while ! qsub #{pid}; do
111
+ sleep 10
112
+ done
113
+
114
+ sh #{shell_path}
115
+
116
+ qfinish #{pid}
117
+ EOS
118
+ end
119
+
120
+ end
121
+
@@ -0,0 +1 @@
1
+ lib/bob@aurora0.13411:1611034391
@@ -0,0 +1,30 @@
1
+ #!/bin/env ruby
2
+ #VE_SUBMIT_JOBS_FILE = File.join(ENV['HOME'],".ve_submit_jobs.txt")
3
+ VE_SUBMIT_JOBS_FILE = File.join(ENV['HOME'],".tge_test_jobs.txt")
4
+ pid = ARGV[0] || 1234
5
+ pid = pid.to_i
6
+
7
+ status = ['not_on_file', -1]
8
+ lines = File.readlines(VE_SUBMIT_JOBS_FILE)
9
+ finished_job = -1
10
+ lines.each_with_index do |line, i|
11
+ data = line.match(/\s+(\d+):\s+(\w+):\s+(.+):/)
12
+ if data[1].to_i == pid
13
+ status = [data[2], i]
14
+ if status[1] == finished_job + 1
15
+ line.gsub!('waiting','running')
16
+ File.write(VE_SUBMIT_JOBS_FILE, lines.join)
17
+ exit 0
18
+ end
19
+ break
20
+ end
21
+ finished_job = i if data[2] == 'finished'
22
+ end
23
+
24
+ if status[0] == 'not_on_file'
25
+ line = "%8d: %10s: %s: %s\n" % [pid, 'waiting', Dir.pwd(), Time.now]
26
+ File.open(VE_SUBMIT_JOBS_FILE, 'a'){ |f| f.write line }
27
+ end
28
+
29
+ exit 1 # return false
30
+ #exit 0 # return true
@@ -0,0 +1,30 @@
1
+ #!/bin/env ruby
2
+ #VE_SUBMIT_JOBS_FILE = File.join(ENV['HOME'],".ve_submit_jobs.txt")
3
+ VE_SUBMIT_JOBS_FILE = File.join(ENV['HOME'],".tge_test_jobs.txt")
4
+ pid = ARGV[0] || 1234
5
+ pid = pid.to_i
6
+
7
+ status = ['not_on_file', -1]
8
+ lines = File.readlines(VE_SUBMIT_JOBS_FILE)
9
+ finished_job = -1
10
+ lines.each_with_index do |line, i|
11
+ data = line.match(/\s+(\d+):\s+(\w+):\s+(.+):/)
12
+ if data[1].to_i == pid
13
+ status = [data[2], i]
14
+ if status[1] == finished_job + 1
15
+ line.gsub!('waiting','running')
16
+ File.write(VE_SUBMIT_JOBS_FILE, lines.join)
17
+ exit 0
18
+ end
19
+ break
20
+ end
21
+ finished_job = i if data[2] == 'finished'
22
+ end
23
+
24
+ if status[0] == 'not_on_file'
25
+ line = "%8d: %10s: %s: %s\n" % [pid, 'waiting', Dir.pwd(), Time.now]
26
+ File.open(VE_SUBMIT_JOBS_FILE, 'a'){ |f| f.write line }
27
+ end
28
+
29
+ exit 1 # return false
30
+ #exit 0 # return true
@@ -0,0 +1,119 @@
1
+ require "tiny_ge/version"
2
+ require 'yaml'
3
+ require 'thor'
4
+ require 'command_line/global'
5
+
6
+ #VE_SUBMIT_JOBS_FILE = File.join(ENV['HOME'],".ve_submit_jobs.txt")
7
+ VE_TEST_FILE = File.join(ENV['HOME'],".tge_test_jobs.txt")
8
+
9
+ class TGE
10
+ def initialize(q_file=VE_TEST_FILE)
11
+ @q_file = VE_TEST_FILE
12
+ @data = YAML.load(File.read(@q_file))
13
+ end
14
+
15
+ def add_job(pid, shell_path)
16
+ shell_file = "./test.s#{pid}"
17
+ shell_script = mk_shell_script(pid, shell_path)
18
+ File.write(shell_file, shell_script)
19
+
20
+ p pid0 = spawn("sh #{shell_file}", :out => "test.o#{pid}", :err => "test.e#{pid}")
21
+ Process.detach(pid0)
22
+ puts "#{pid} is added on the queue."
23
+
24
+ @data << {pid: pid, status: 'waiting', shell_path: shell_path,
25
+ real_pid: pid0,
26
+ submit: Time.now,
27
+ start: nil,
28
+ finish: nil
29
+ }
30
+ File.write(VE_TEST_FILE, YAML.dump(@data))
31
+ end
32
+
33
+ def change_job_status(pid, status)
34
+ @data.each do |job, i|
35
+ if job[:pid] == pid
36
+ job[:status] = status
37
+ case status
38
+ when 'running' ; job[:start] = Time.now
39
+ when 'finished'; job[:finish] = Time.now
40
+ end
41
+ File.write(VE_TEST_FILE, YAML.dump(@data))
42
+ break
43
+ end
44
+ end
45
+ end
46
+
47
+ def qfinish(pid)
48
+ change_job_status(pid, 'finished')
49
+ return true
50
+ end
51
+
52
+ def qsub(pid, shell_path=Dir.pwd)
53
+ unless pid_on_file(pid)
54
+ add_job(pid, shell_path)
55
+ return false
56
+ end
57
+ last_finished = -1
58
+ @data.each_with_index do |job, i|
59
+ if job[:pid] == pid
60
+ if job[:status] == 'waiting' and i == last_finished + 1
61
+ change_job_status(pid, 'running')
62
+ return true
63
+ end
64
+ if job[:status] == 'running'
65
+ return true
66
+ end
67
+ return false
68
+ end
69
+ last_finished = i if job[:status] == 'finished'
70
+ end
71
+ end
72
+
73
+ def pid_on_file(pid)
74
+ @data.each do |job, i|
75
+ return job[:status] if job[:pid] == pid
76
+ end
77
+ return false
78
+ end
79
+
80
+ def qdel(pid)
81
+ unless pid_on_file(pid)
82
+ puts "#{pid} is not on the qeueu."
83
+ return false
84
+ end
85
+ @data.each_with_index do |job, i|
86
+ if job[:pid] == pid
87
+ res = command_line("kill -9 #{job[:real_pid]}")
88
+ p res
89
+ @data.delete_at(i)
90
+ File.write(VE_TEST_FILE, YAML.dump(@data))
91
+ puts "#{pid} is deleted from the qeueu."
92
+ return true
93
+ end
94
+ end
95
+ end
96
+
97
+ def qstat(item_num=0)
98
+ @data = YAML.load(File.read(VE_TEST_FILE))
99
+ @data[item_num..-1].each do |job, i|
100
+ real_pid = job[:real_pid] || 0
101
+ puts "%5d: %5d: %10s: %s" % [job[:pid], real_pid, job[:status], job[:shell_path]]
102
+ end
103
+ end
104
+
105
+ def mk_shell_script(pid, shell_path)
106
+ return <<~EOS
107
+ #!/bin/sh
108
+ while ! qsub #{pid}; do
109
+ sleep 10
110
+ done
111
+
112
+ sh #{shell_path}
113
+
114
+ qfinish #{pid}
115
+ EOS
116
+ end
117
+
118
+ end
119
+
@@ -0,0 +1,3 @@
1
+ class TGE
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,16 @@
1
+ #!/bin/env ruby
2
+ #VE_SUBMIT_JOBS_FILE = File.join(ENV['HOME'],".ve_submit_jobs.txt")
3
+ VE_SUBMIT_JOBS_FILE = File.join(ENV['HOME'],".tge_test_jobs.txt")
4
+ pid = ARGV[0] || 1234
5
+ pid = pid.to_i
6
+ lines = File.readlines(VE_SUBMIT_JOBS_FILE)
7
+ lines.each_with_index do |line, i|
8
+ data = line.match(/\s+(\d+):\s+(\w+):\s+(.+)/)
9
+ if data[1].to_i == pid
10
+ line.gsub!(' running', 'finished')
11
+ File.write(VE_SUBMIT_JOBS_FILE, lines.join)
12
+ break
13
+ end
14
+ end
15
+
16
+ exit 0 # return true
@@ -0,0 +1,15 @@
1
+ #!/bin/env ruby
2
+ VE_SUBMIT_JOBS_FILE = File.join(ENV['HOME'],".ve_submit_jobs.txt")
3
+ pid = ARGV[0] || 1234
4
+ pid = pid.to_i
5
+ lines = File.readlines(VE_SUBMIT_JOBS_FILE)
6
+ lines.each_with_index do |line, i|
7
+ data = line.match(/\s+(\d+):\s+(\w+):\s+(.+)/)
8
+ if data[1].to_i == pid
9
+ line.gsub!(' running', 'finished')
10
+ File.write(VE_SUBMIT_JOBS_FILE, lines.join)
11
+ break
12
+ end
13
+ end
14
+
15
+ exit 0 # return true
@@ -0,0 +1,34 @@
1
+ require_relative 'lib/tiny_ge/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "tiny_ge"
5
+ spec.version = TGE::VERSION
6
+ spec.authors = ["Shigeto R. Nishitani"]
7
+ spec.email = ["shigeto_nishitani@me.com"]
8
+
9
+ spec.summary = %q{tiny_ge is a tiny queue system like SGE}
10
+ spec.description = %q{tiny_ge is a tiny queue system like SGE}
11
+ spec.homepage = "https://github.com/daddygongon/tiny_ge"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+
15
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/daddygongon/tiny_ge"
19
+ spec.metadata["changelog_uri"] = "https://github.com/daddygongon/tiny_ge"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+ spec.add_runtime_dependency('thor')
30
+ spec.add_runtime_dependency "colorize"
31
+ spec.add_runtime_dependency "command_line"
32
+ spec.add_runtime_dependency "yaml"
33
+ spec.add_development_dependency "minitest-reporters"
34
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tiny_ge
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Shigeto R. Nishitani
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-02-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: command_line
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yaml
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest-reporters
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: tiny_ge is a tiny queue system like SGE
84
+ email:
85
+ - shigeto_nishitani@me.com
86
+ executables:
87
+ - qdel
88
+ - qdel~
89
+ - qfinish
90
+ - qfinish~
91
+ - qstat
92
+ - qstat~
93
+ - qsub
94
+ - qsub~
95
+ - tge
96
+ - tge~
97
+ extensions: []
98
+ extra_rdoc_files: []
99
+ files:
100
+ - ".gitignore"
101
+ - ".travis.yml"
102
+ - CODE_OF_CONDUCT.md
103
+ - Gemfile
104
+ - Gemfile.lock
105
+ - LICENSE.txt
106
+ - README.org
107
+ - Rakefile
108
+ - exe/qdel
109
+ - exe/qdel~
110
+ - exe/qfinish
111
+ - exe/qfinish~
112
+ - exe/qstat
113
+ - exe/qstat~
114
+ - exe/qsub
115
+ - exe/qsub~
116
+ - exe/tge
117
+ - exe/tge~
118
+ - lib/#tiny_ge.rb#
119
+ - lib/.#tiny_ge.rb
120
+ - lib/check_ve_lock
121
+ - lib/check_ve_lock~
122
+ - lib/tiny_ge.rb
123
+ - lib/tiny_ge/version.rb
124
+ - lib/unlock_ve_lock
125
+ - lib/unlock_ve_lock~
126
+ - tiny_ge.gemspec
127
+ homepage: https://github.com/daddygongon/tiny_ge
128
+ licenses:
129
+ - MIT
130
+ metadata:
131
+ homepage_uri: https://github.com/daddygongon/tiny_ge
132
+ source_code_uri: https://github.com/daddygongon/tiny_ge
133
+ changelog_uri: https://github.com/daddygongon/tiny_ge
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: 2.3.0
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubygems_version: 3.1.4
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: tiny_ge is a tiny queue system like SGE
153
+ test_files: []