rbbt-util 5.13.31 → 5.13.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/rbbt +11 -0
- data/lib/rbbt/monitor.rb +152 -10
- data/lib/rbbt/persist/tsv/adapter.rb +109 -0
- data/lib/rbbt/persist/tsv/kyotocabinet.rb +3 -77
- data/lib/rbbt/persist/tsv/lmdb.rb +1 -88
- data/lib/rbbt/persist/tsv/tokyocabinet.rb +126 -93
- data/lib/rbbt/persist/tsv.rb +2 -0
- data/lib/rbbt/persist.rb +21 -91
- data/lib/rbbt/tsv/parallel/traverse.rb +9 -5
- data/lib/rbbt/util/cmd.rb +1 -1
- data/lib/rbbt/util/log.rb +7 -6
- data/lib/rbbt/util/misc/concurrent_stream.rb +2 -1
- data/lib/rbbt/util/misc/development.rb +23 -0
- data/lib/rbbt/util/misc/lock.rb +18 -13
- data/lib/rbbt/util/misc/pipes.rb +23 -11
- data/lib/rbbt/util/open.rb +5 -5
- data/lib/rbbt/util/simpleopt/doc.rb +1 -1
- data/lib/rbbt/workflow/step/run.rb +3 -2
- data/lib/rbbt/workflow/step.rb +7 -1
- data/lib/rbbt/workflow.rb +18 -11
- data/share/rbbt_commands/system/clean +57 -58
- data/share/rbbt_commands/system/status +59 -40
- data/share/rbbt_commands/tsv/info +1 -1
- data/test/rbbt/test_monitor.rb +13 -0
- data/test/rbbt/tsv/parallel/test_traverse.rb +44 -22
- data/test/rbbt/util/test_misc.rb +10 -0
- data/test/rbbt/util/test_open.rb +16 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03d6c0cd25cb674bc5fb28731e6c936d32a8468c
|
4
|
+
data.tar.gz: 0a8c5ba0281f806e9d8712e527b011bae576bacf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24555145911d44367c1b9ddfe30c96b7e205811b9838508e68faebeb07da384b4fdc1d9bed59a221f97b00e51ba8ea816fccbb7c26517de79433e3306a9e8fbc
|
7
|
+
data.tar.gz: 6b275e80ce80ac94a8067c8f255c50d718fab0717934ff46e5354640951d4f94ae5361cb92d429b2cd14ba3edaea35f5dd26e9748eb4021a53bd1c33f576592b
|
data/bin/rbbt
CHANGED
@@ -42,8 +42,19 @@ $ rbbt <command> <subcommand> ... -a --arg1 --arg2='value' --arg3 'another-value
|
|
42
42
|
--nocolor #{Log.color :yellow, "Disable colored output"}
|
43
43
|
--nobar #{Log.color :yellow, "Disable progress report"}
|
44
44
|
--locate_file #{Log.color :yellow, "Report the location of the script instead of executing it"}
|
45
|
+
--dump_mem* #{Log.color :yellow, "Dump strings in memory each second into file"}
|
46
|
+
--no_lock_id #{Log.color :yellow, "Do not track lockfiles with ids (for high-througput and high-concurrency"}
|
45
47
|
EOF
|
46
48
|
|
49
|
+
if options.delete(:no_lock_id)
|
50
|
+
Misc.use_lock_id = false
|
51
|
+
end
|
52
|
+
|
53
|
+
if mem_dump = options.delete(:dump_mem)
|
54
|
+
require 'rbbt/monitor'
|
55
|
+
Rbbt.dump_memory(mem_dump, Symbol)
|
56
|
+
end
|
57
|
+
|
47
58
|
if options.delete :nobar
|
48
59
|
ENV["RBBT_NO_PROGRESS"] = "true"
|
49
60
|
end
|
data/lib/rbbt/monitor.rb
CHANGED
@@ -5,28 +5,170 @@ module Rbbt
|
|
5
5
|
LOCK_DIRS = Rbbt.share.find_all + Rbbt.var.cache.persistence.find_all + Rbbt.var.jobs.find_all +
|
6
6
|
Rbbt.tmp.tsv_open_locks.find_all + Rbbt.tmp.persist_locks.find_all
|
7
7
|
|
8
|
+
SENSIBLE_WRITE_DIRS = Misc.sensiblewrite_dir.find_all
|
9
|
+
|
10
|
+
PERSIST_DIRS = Rbbt.share.find_all + Rbbt.var.cache.persistence.find_all
|
11
|
+
|
12
|
+
JOB_DIRS = Rbbt.var.jobs.find_all
|
13
|
+
|
14
|
+
def self.dump_memory(file, obj = nil)
|
15
|
+
Log.info "Dumping #{obj} objects into #{ file }"
|
16
|
+
Thread.new do
|
17
|
+
while true
|
18
|
+
Open.write(file) do |f|
|
19
|
+
Thread.exclusive do
|
20
|
+
GC.start
|
21
|
+
ObjectSpace.each_object(obj) do |o|
|
22
|
+
f.puts "---"
|
23
|
+
f.puts(String === o ? o : o.inspect)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
FileUtils.cp file, file + '.save'
|
28
|
+
sleep 3
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.file_time(file)
|
34
|
+
ctime = File.ctime file
|
35
|
+
atime = File.atime file
|
36
|
+
elapsed = Time.now - ctime
|
37
|
+
{:ctime => ctime, :atime => atime, :elapsed => elapsed}
|
38
|
+
end
|
39
|
+
|
40
|
+
#{{{ LOCKS
|
41
|
+
|
8
42
|
def self.locks(dirs = LOCK_DIRS)
|
9
43
|
dirs.collect do |dir|
|
10
|
-
dir
|
11
|
-
|
44
|
+
next unless Open.exists? dir
|
45
|
+
`find "#{ dir }" -name "*.lock"`.split "\n"
|
46
|
+
end.compact.flatten
|
12
47
|
end
|
13
48
|
|
14
|
-
|
49
|
+
def self.lock_info(dirs = LOCK_DIRS)
|
50
|
+
lock_info = {}
|
51
|
+
locks(dirs).each do |f|
|
52
|
+
begin
|
53
|
+
i = file_time(f)
|
54
|
+
if File.size(f) > 0
|
55
|
+
info = Open.open(f) do |s|
|
56
|
+
YAML.load(s)
|
57
|
+
end
|
58
|
+
i[:pid] = info[:pid]
|
59
|
+
i[:ppid] = info[:ppid]
|
60
|
+
end
|
61
|
+
lock_info[f] = i
|
62
|
+
rescue
|
63
|
+
Log.exception $!
|
64
|
+
end
|
65
|
+
end
|
66
|
+
lock_info
|
67
|
+
end
|
68
|
+
|
69
|
+
#{{{ SENSIBLE WRITES
|
70
|
+
|
15
71
|
def self.sensiblewrites(dirs = SENSIBLE_WRITE_DIRS)
|
16
72
|
dirs.collect do |dir|
|
17
|
-
|
18
|
-
|
73
|
+
next unless Open.exists? dir
|
74
|
+
`find "#{ dir }" -not -name "*.lock" -not -type d`.split "\n"
|
75
|
+
end.compact.flatten
|
19
76
|
end
|
20
77
|
|
21
|
-
|
78
|
+
def self.sensiblewrite_info(dirs = SENSIBLE_WRITE_DIRS)
|
79
|
+
info = {}
|
80
|
+
sensiblewrites(dirs).each do |f|
|
81
|
+
begin
|
82
|
+
i = file_time(f)
|
83
|
+
info[f] = i
|
84
|
+
rescue
|
85
|
+
Log.exception $!
|
86
|
+
end
|
87
|
+
end
|
88
|
+
info
|
89
|
+
end
|
90
|
+
|
91
|
+
# PERSISTS
|
92
|
+
|
22
93
|
def self.persists(dirs = PERSIST_DIRS)
|
23
94
|
dirs.collect do |dir|
|
24
|
-
|
25
|
-
|
95
|
+
next unless Open.exists? dir
|
96
|
+
`find "#{ dir }" -name "*.persist"`.split "\n"
|
97
|
+
end.compact.flatten
|
26
98
|
end
|
27
99
|
|
28
|
-
|
29
|
-
|
100
|
+
def self.persist_info(dirs = PERSIST_DIRS)
|
101
|
+
info = {}
|
102
|
+
persists(dirs).each do |f|
|
103
|
+
begin
|
104
|
+
i = file_time(f)
|
105
|
+
info[f] = i
|
106
|
+
rescue
|
107
|
+
Log.exception $!
|
108
|
+
end
|
109
|
+
end
|
110
|
+
info
|
111
|
+
end
|
112
|
+
|
113
|
+
# PERSISTS
|
114
|
+
|
115
|
+
def self.job_info(workflows = nil, tasks = nil, dirs = JOB_DIRS)
|
116
|
+
require 'rbbt/workflow/step'
|
117
|
+
|
118
|
+
workflows = [workflows] if workflows and not Array === workflows
|
119
|
+
workflows = workflows.collect{|w| w.to_s} if workflows
|
120
|
+
|
121
|
+
tasks = [tasks] if tasks and not Array === tasks
|
122
|
+
tasks = tasks.collect{|w| w.to_s} if tasks
|
123
|
+
|
124
|
+
jobs = {}
|
125
|
+
dirs.collect do |dir|
|
126
|
+
next unless Open.exists? dir
|
127
|
+
|
128
|
+
dir.glob("*").collect do |workflowdir|
|
129
|
+
workflow = File.basename(workflowdir)
|
130
|
+
next if workflows and not workflows.include? workflow
|
131
|
+
|
132
|
+
workflowdir.glob("*").collect do |taskdir|
|
133
|
+
task = File.basename(taskdir)
|
134
|
+
next if tasks and not tasks.include? task
|
135
|
+
|
136
|
+
files = `find "#{ taskdir }/" -not -type d -not -path "*/*.files/*"`.split("\n").sort
|
137
|
+
_files = Set.new files
|
138
|
+
TSV.traverse files, :type => :array, :into => jobs do |file|
|
139
|
+
if m = file.match(/(.*).info$/)
|
140
|
+
file = m[1]
|
141
|
+
end
|
142
|
+
|
143
|
+
name = file[taskdir.length+1..-1]
|
144
|
+
info_file = file + '.info'
|
145
|
+
|
146
|
+
info = {}
|
147
|
+
|
148
|
+
info[:workflow] = workflow
|
149
|
+
info[:task] = task
|
150
|
+
info[:name] = name
|
151
|
+
|
152
|
+
if _files.include? file
|
153
|
+
info = info.merge(file_time(file))
|
154
|
+
info[:done] = true
|
155
|
+
info[:info_file] = File.exists?(info_file) ? info_file : nil
|
156
|
+
else
|
157
|
+
info = info.merge({:info_file => info_file, :done => false})
|
158
|
+
end
|
159
|
+
|
160
|
+
[file, info]
|
161
|
+
end
|
162
|
+
|
163
|
+
end.compact.flatten
|
164
|
+
end.compact.flatten
|
165
|
+
end.compact.flatten
|
166
|
+
jobs
|
167
|
+
end
|
168
|
+
|
169
|
+
# REST
|
170
|
+
|
171
|
+
def self.__jobs(dirs = JOB_DIRS)
|
30
172
|
job_files = {}
|
31
173
|
dirs.each do |dir|
|
32
174
|
workflow_dirs = dir.glob("*").each do |wdir|
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'rbbt/tsv'
|
2
|
+
module Persist
|
3
|
+
module TSVAdapter
|
4
|
+
attr_accessor :persistence_path, :closed, :writable, :mutex
|
5
|
+
|
6
|
+
MAX_CHAR = 255.chr
|
7
|
+
|
8
|
+
def mutex
|
9
|
+
@mutex ||= Mutex.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def prefix(key)
|
13
|
+
range(key, 1, key + MAX_CHAR, 1)
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_prefix(key)
|
17
|
+
keys = prefix(key)
|
18
|
+
select(:key => keys)
|
19
|
+
end
|
20
|
+
|
21
|
+
def closed?
|
22
|
+
@closed
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
@closed = true
|
27
|
+
super
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def write?
|
32
|
+
@writable
|
33
|
+
end
|
34
|
+
|
35
|
+
def read?
|
36
|
+
! write?
|
37
|
+
end
|
38
|
+
|
39
|
+
def collect
|
40
|
+
res = []
|
41
|
+
each do |key, value|
|
42
|
+
res << if block_given?
|
43
|
+
yield key, value
|
44
|
+
else
|
45
|
+
[key, value]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
res
|
49
|
+
end
|
50
|
+
|
51
|
+
def delete(key)
|
52
|
+
out(key)
|
53
|
+
end
|
54
|
+
|
55
|
+
def write_and_read
|
56
|
+
lock_filename = Persist.persistence_path(persistence_path + '.write', {:dir => TSV.lock_dir})
|
57
|
+
Misc.lock(lock_filename) do
|
58
|
+
mutex.synchronize do
|
59
|
+
write if closed? or not write?
|
60
|
+
res = begin
|
61
|
+
yield
|
62
|
+
ensure
|
63
|
+
read
|
64
|
+
end
|
65
|
+
res
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def write_and_close
|
71
|
+
lock_filename = Persist.persistence_path(persistence_path + '.write', {:dir => TSV.lock_dir})
|
72
|
+
Misc.lock(lock_filename) do
|
73
|
+
mutex.synchronize do
|
74
|
+
write if closed? or not write?
|
75
|
+
res = begin
|
76
|
+
yield
|
77
|
+
ensure
|
78
|
+
close
|
79
|
+
end
|
80
|
+
res
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def read_and_close
|
86
|
+
mutex.synchronize do
|
87
|
+
read if closed? or not read?
|
88
|
+
res = begin
|
89
|
+
yield
|
90
|
+
ensure
|
91
|
+
close
|
92
|
+
end
|
93
|
+
res
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def merge!(hash)
|
99
|
+
hash.each do |key,values|
|
100
|
+
self[key] = values
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def range(*args)
|
106
|
+
super(*args) #- TSV::ENTRY_KEYS.to_a
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -3,7 +3,8 @@ require 'kyotocabinet'
|
|
3
3
|
module Persist
|
4
4
|
|
5
5
|
module KCAdapter
|
6
|
-
|
6
|
+
include Persist::TSVAdapter
|
7
|
+
attr_accessor :kyotocabinet_class
|
7
8
|
|
8
9
|
def self.open(path, write, kyotocabinet_class = "kch")
|
9
10
|
real_path = path + ".#{kyotocabinet_class}"
|
@@ -24,33 +25,10 @@ module Persist
|
|
24
25
|
database
|
25
26
|
end
|
26
27
|
|
27
|
-
def keys
|
28
|
-
keys = []
|
29
|
-
each_key{|k| keys.concat k}
|
30
|
-
keys
|
31
|
-
end
|
32
|
-
|
33
|
-
def prefix(key)
|
34
|
-
range(key, 1, key + 255.chr, 1)
|
35
|
-
end
|
36
|
-
|
37
|
-
def get_prefix(key)
|
38
|
-
keys = prefix(key)
|
39
|
-
select(:key => keys)
|
40
|
-
end
|
41
|
-
|
42
|
-
def include?(key)
|
43
|
-
value = get(key)
|
44
|
-
! value.nil?
|
45
|
-
end
|
46
|
-
|
47
|
-
def closed?
|
48
|
-
@closed
|
49
|
-
end
|
50
|
-
|
51
28
|
def close
|
52
29
|
@closed = true
|
53
30
|
super
|
31
|
+
self
|
54
32
|
end
|
55
33
|
|
56
34
|
def read(force = false)
|
@@ -96,58 +74,6 @@ module Persist
|
|
96
74
|
def delete(key)
|
97
75
|
out(key)
|
98
76
|
end
|
99
|
-
|
100
|
-
def write_and_read
|
101
|
-
lock_filename = Persist.persistence_path(persistence_path, {:dir => TSV.lock_dir})
|
102
|
-
Misc.lock(lock_filename) do
|
103
|
-
write if @closed or not write?
|
104
|
-
res = begin
|
105
|
-
yield
|
106
|
-
ensure
|
107
|
-
read
|
108
|
-
end
|
109
|
-
res
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
def write_and_close
|
114
|
-
lock_filename = Persist.persistence_path(persistence_path, {:dir => TSV.lock_dir})
|
115
|
-
Misc.lock(lock_filename) do
|
116
|
-
write if @closed or not write?
|
117
|
-
res = begin
|
118
|
-
yield
|
119
|
-
ensure
|
120
|
-
close
|
121
|
-
end
|
122
|
-
res
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def read_and_close
|
127
|
-
read if @closed or write?
|
128
|
-
res = begin
|
129
|
-
yield
|
130
|
-
ensure
|
131
|
-
close
|
132
|
-
end
|
133
|
-
res
|
134
|
-
end
|
135
|
-
|
136
|
-
def merge!(hash)
|
137
|
-
hash.each do |key,values|
|
138
|
-
self[key] = values
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
#def []=(key,value)
|
143
|
-
# super(key,value)
|
144
|
-
# self.synchronize
|
145
|
-
#end
|
146
|
-
|
147
|
-
|
148
|
-
def range(*args)
|
149
|
-
super(*args) - TSV::ENTRY_KEYS.to_a
|
150
|
-
end
|
151
77
|
end
|
152
78
|
|
153
79
|
|
@@ -3,8 +3,7 @@ require 'lmdb'
|
|
3
3
|
module Persist
|
4
4
|
|
5
5
|
module LMDBAdapter
|
6
|
-
|
7
|
-
|
6
|
+
include Persist::TSVAdapter
|
8
7
|
def self.open(path, write)
|
9
8
|
|
10
9
|
database = CONNECTIONS[path] ||= begin
|
@@ -21,40 +20,6 @@ module Persist
|
|
21
20
|
database
|
22
21
|
end
|
23
22
|
|
24
|
-
def keys
|
25
|
-
keys = []
|
26
|
-
cursor do |cursor|
|
27
|
-
while p = cursor.next
|
28
|
-
keys << p.first
|
29
|
-
end
|
30
|
-
end
|
31
|
-
keys
|
32
|
-
end
|
33
|
-
|
34
|
-
def include?(key)
|
35
|
-
self.send(:[], key, true)
|
36
|
-
end
|
37
|
-
|
38
|
-
def closed?
|
39
|
-
false
|
40
|
-
end
|
41
|
-
|
42
|
-
def close
|
43
|
-
self
|
44
|
-
end
|
45
|
-
|
46
|
-
def read(force = false)
|
47
|
-
self
|
48
|
-
end
|
49
|
-
|
50
|
-
def write(force = true)
|
51
|
-
self
|
52
|
-
end
|
53
|
-
|
54
|
-
def write?
|
55
|
-
@writable
|
56
|
-
end
|
57
|
-
|
58
23
|
def each
|
59
24
|
cursor do |cursor|
|
60
25
|
while pair = cursor.next
|
@@ -77,60 +42,8 @@ module Persist
|
|
77
42
|
end
|
78
43
|
res
|
79
44
|
end
|
80
|
-
|
81
|
-
def delete(key)
|
82
|
-
out(key)
|
83
|
-
end
|
84
|
-
|
85
|
-
def write_and_read
|
86
|
-
lock_filename = Persist.persistence_path(persistence_path, {:dir => TSV.lock_dir})
|
87
|
-
Misc.lock(lock_filename) do
|
88
|
-
write if @closed or not write?
|
89
|
-
res = begin
|
90
|
-
yield
|
91
|
-
ensure
|
92
|
-
read
|
93
|
-
end
|
94
|
-
res
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def write_and_close
|
99
|
-
lock_filename = Persist.persistence_path(persistence_path, {:dir => TSV.lock_dir})
|
100
|
-
Misc.lock(lock_filename) do
|
101
|
-
write if @closed or not write?
|
102
|
-
res = begin
|
103
|
-
yield
|
104
|
-
ensure
|
105
|
-
close
|
106
|
-
end
|
107
|
-
res
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def read_and_close
|
112
|
-
read if @closed or write?
|
113
|
-
res = begin
|
114
|
-
yield
|
115
|
-
ensure
|
116
|
-
close
|
117
|
-
end
|
118
|
-
res
|
119
|
-
end
|
120
|
-
|
121
|
-
def merge!(hash)
|
122
|
-
hash.each do |key,values|
|
123
|
-
self[key] = values
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
|
128
|
-
def range(*args)
|
129
|
-
super(*args) - TSV::ENTRY_KEYS.to_a
|
130
|
-
end
|
131
45
|
end
|
132
46
|
|
133
|
-
|
134
47
|
def self.open_lmdb(path, write, serializer = nil)
|
135
48
|
write = true unless File.exists? path
|
136
49
|
|