gri 10.0.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.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.md +132 -0
- data/Rakefile +5 -0
- data/bin/grapher +17 -0
- data/bin/gri +5 -0
- data/bin/gricast +17 -0
- data/bin/grispark +5 -0
- data/bin/griwalk +9 -0
- data/bin/trad +19 -0
- data/bin/trad-http +17 -0
- data/gri.gemspec +21 -0
- data/lib/fluent/plugin/out_gri.rb +56 -0
- data/lib/gri/api.rb +28 -0
- data/lib/gri/app_collector.rb +154 -0
- data/lib/gri/app_walker.rb +23 -0
- data/lib/gri/blank.rb +49 -0
- data/lib/gri/builtindefs.rb +211 -0
- data/lib/gri/cast.rb +84 -0
- data/lib/gri/cgraph.rb +37 -0
- data/lib/gri/clist.rb +163 -0
- data/lib/gri/collector.rb +284 -0
- data/lib/gri/config.rb +134 -0
- data/lib/gri/ds_list.rb +166 -0
- data/lib/gri/format_helper.rb +112 -0
- data/lib/gri/gparams.rb +43 -0
- data/lib/gri/graph.rb +239 -0
- data/lib/gri/grapher.rb +70 -0
- data/lib/gri/ldb.rb +160 -0
- data/lib/gri/list.rb +242 -0
- data/lib/gri/log.rb +140 -0
- data/lib/gri/loop.rb +109 -0
- data/lib/gri/ltsv.rb +58 -0
- data/lib/gri/main.rb +107 -0
- data/lib/gri/mlog.rb +22 -0
- data/lib/gri/mmsgpack.rb +57 -0
- data/lib/gri/msnmp.rb +601 -0
- data/lib/gri/page.rb +235 -0
- data/lib/gri/pcollector.rb +209 -0
- data/lib/gri/plugin.rb +75 -0
- data/lib/gri/plugin/bootstrap.rb +65 -0
- data/lib/gri/plugin/cisco.rb +98 -0
- data/lib/gri/plugin/exec_collector.rb +89 -0
- data/lib/gri/plugin/juniper.rb +5 -0
- data/lib/gri/plugin/netsnmp.rb +8 -0
- data/lib/gri/plugin/ucdavis.rb +176 -0
- data/lib/gri/plugin/writer_fluentd.rb +26 -0
- data/lib/gri/polling_unit.rb +88 -0
- data/lib/gri/q.rb +5 -0
- data/lib/gri/request.rb +29 -0
- data/lib/gri/rrd.rb +438 -0
- data/lib/gri/scheduler.rb +68 -0
- data/lib/gri/sgraph.rb +147 -0
- data/lib/gri/spark.rb +94 -0
- data/lib/gri/tra_collector.rb +80 -0
- data/lib/gri/trad.rb +170 -0
- data/lib/gri/updater.rb +201 -0
- data/lib/gri/util_daemon.rb +19 -0
- data/lib/gri/util_marshal.rb +13 -0
- data/lib/gri/utils.rb +63 -0
- data/lib/gri/vendor.rb +76 -0
- data/lib/gri/version.rb +3 -0
- data/lib/gri/wmain.rb +67 -0
- data/lib/gri/writer.rb +184 -0
- data/mcollector +47 -0
- data/test/mock.rb +60 -0
- data/test/root/gra/.sysdb/sysdb.txt +3 -0
- data/test/root/gra/testhost/.records.txt +2 -0
- data/test/root/if.def +2 -0
- data/test/root/test.conf +4 -0
- data/test/root/testtab +9 -0
- data/test/root/testtab2 +2 -0
- data/test/root/tra/testhost/_/20130614 +20 -0
- data/test/test_app.rb +58 -0
- data/test/test_builtindefs.rb +24 -0
- data/test/test_collector.rb +58 -0
- data/test/test_config.rb +62 -0
- data/test/test_ds_list.rb +48 -0
- data/test/test_exec_collector.rb +33 -0
- data/test/test_format_helper.rb +68 -0
- data/test/test_graph.rb +69 -0
- data/test/test_ldb.rb +29 -0
- data/test/test_list.rb +65 -0
- data/test/test_log.rb +16 -0
- data/test/test_loop.rb +35 -0
- data/test/test_ltsv.rb +38 -0
- data/test/test_main.rb +19 -0
- data/test/test_mmsgpack.rb +27 -0
- data/test/test_msnmp.rb +147 -0
- data/test/test_page.rb +51 -0
- data/test/test_pcollector.rb +71 -0
- data/test/test_plugin.rb +62 -0
- data/test/test_plugin_cisco.rb +23 -0
- data/test/test_polling_unit.rb +58 -0
- data/test/test_request.rb +26 -0
- data/test/test_rrd.rb +53 -0
- data/test/test_rrd_updater.rb +139 -0
- data/test/test_scheduler.rb +31 -0
- data/test/test_tra_collector.rb +40 -0
- data/test/test_trad.rb +33 -0
- data/test/test_util_marshal.rb +17 -0
- data/test/test_utils.rb +15 -0
- data/test/test_vendor.rb +40 -0
- data/test/test_writer.rb +33 -0
- data/test/unittest_helper.rb +27 -0
- metadata +208 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
module GRI
|
2
|
+
class Scheduler
|
3
|
+
attr_accessor :queue, :writers, :fake_descr_hash
|
4
|
+
|
5
|
+
def initialize loop, metrics
|
6
|
+
@loop = loop
|
7
|
+
@metrics = metrics
|
8
|
+
@loop.on_detach {process_queue}
|
9
|
+
@writers = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def process_queue
|
13
|
+
while @loop.collectors.size < 5
|
14
|
+
host, options = queue.shift
|
15
|
+
break unless host
|
16
|
+
next if host =~ /^GRIMETRICS/
|
17
|
+
|
18
|
+
ts = options['type']
|
19
|
+
col_types = ts ? ts.split(',') : ['snmp']
|
20
|
+
for col_type in col_types
|
21
|
+
process1 col_type, host, options
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def process1 col_type, host, options
|
27
|
+
collector = Collector.create(col_type, host, options,
|
28
|
+
@fake_descr_hash) {|records|
|
29
|
+
for writer in @writers
|
30
|
+
writer.write records
|
31
|
+
end
|
32
|
+
@metrics[:record_count] += records.size
|
33
|
+
}
|
34
|
+
if collector
|
35
|
+
#puts "#{collector.class} (#{col_type}): #{host}" if $debug
|
36
|
+
interval = (options['interval'] || 300).to_i
|
37
|
+
collector.interval = interval
|
38
|
+
collector.timeout = [90, interval].min
|
39
|
+
collector.on_error {@metrics[:error_count] += 1}
|
40
|
+
collector.on_retry {@metrics[:retry_count] += 1}
|
41
|
+
Log.info "[#{$$}] #{host}: collect #{col_type}"
|
42
|
+
begin
|
43
|
+
@loop.run if collector.sync?
|
44
|
+
@loop.attach collector
|
45
|
+
rescue SystemCallError
|
46
|
+
Log.error "#{host}: ERROR: #{$!}"
|
47
|
+
@loop.detach collector
|
48
|
+
end
|
49
|
+
@metrics[:run_count] += 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def finalize
|
54
|
+
@writers.each {|w| w.finalize if w.respond_to? :finalize}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class UScheduler < Scheduler
|
59
|
+
def process_queue
|
60
|
+
while @loop.collectors.size < 5
|
61
|
+
host, options = queue.shift
|
62
|
+
break unless host
|
63
|
+
@metrics[:nometrics] = 1 if host =~ /^GRIMETRICS/
|
64
|
+
process1 'tra', host, options
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/gri/sgraph.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module GRI
|
3
|
+
class Sgraph
|
4
|
+
@height = 20
|
5
|
+
|
6
|
+
def initialize options
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
BARS = [" ", "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" ]
|
11
|
+
def bar(val, unit, non_fullwidth_font = false)
|
12
|
+
n = (val.to_f/unit)
|
13
|
+
@height.times.map{|i|
|
14
|
+
x = n - (i * 8)
|
15
|
+
if x <= 0
|
16
|
+
BARS.first
|
17
|
+
else
|
18
|
+
bar_symbol = if x < 8
|
19
|
+
BARS[x]
|
20
|
+
else
|
21
|
+
BARS.last
|
22
|
+
end
|
23
|
+
bar_symbol += " " if non_fullwidth_font
|
24
|
+
bar_symbol
|
25
|
+
end
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def render(json, summary, url = nil)
|
30
|
+
#@options = {:t=>'d', :non_fullwidth_font=>false}
|
31
|
+
@height = 16
|
32
|
+
rowss = json['data']
|
33
|
+
meta = json['meta']
|
34
|
+
step = meta['step']
|
35
|
+
start_timestamp = meta["start"]
|
36
|
+
end_timestamp = meta["end"].to_i
|
37
|
+
s = Time.at(start_timestamp).localtime.strftime("%Y-%m-%d %H:%M:%S")
|
38
|
+
e = Time.at(end_timestamp ).localtime.strftime("%Y-%m-%d %H:%M:%S")
|
39
|
+
|
40
|
+
rowss.transpose.each_with_index {|rows, i|
|
41
|
+
#puts "i: #{i}"
|
42
|
+
max = rows.flatten.compact.max
|
43
|
+
|
44
|
+
u0 = (max / @height)
|
45
|
+
ex0 = (Math.log(u0) / Math.log(10)).floor
|
46
|
+
unit = (u0 / 8 / (10**(ex0-1))).ceil * (10**(ex0-1))
|
47
|
+
|
48
|
+
max_val = unit*@height
|
49
|
+
#max_val = max
|
50
|
+
#unit = max_val / (@height * 8).to_f
|
51
|
+
|
52
|
+
puts " #{(url)}"
|
53
|
+
puts " #{s} -"
|
54
|
+
puts " #{meta['legend'][i].center(78)}"
|
55
|
+
render_graph rows, unit
|
56
|
+
render_x_axis_labels(rows, start_timestamp, step)
|
57
|
+
puts ""
|
58
|
+
|
59
|
+
#sums = summary.first.last
|
60
|
+
#puts " #{sprintf("cur: %.1f ave: %.1f max: %.1f min %.1f", *sums)}"
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def render_graph rows, unit
|
65
|
+
result = []
|
66
|
+
|
67
|
+
rows.map{|row|
|
68
|
+
bar(row, unit, @options[:non_fullwidth_font])
|
69
|
+
}.transpose.reverse.each_with_index do |row, i|
|
70
|
+
i = (@height- i)
|
71
|
+
if i.even?
|
72
|
+
n = unit * i * 8
|
73
|
+
if n > 10
|
74
|
+
label = sprintf("%6s", to_scalestr(unit * i * 8))
|
75
|
+
else
|
76
|
+
label = sprintf("%6g", unit * i * 8)
|
77
|
+
end
|
78
|
+
else
|
79
|
+
label = ''
|
80
|
+
end
|
81
|
+
line = row.join
|
82
|
+
if color = @options[:color]
|
83
|
+
line = Term::ANSIColor.send(color, line)
|
84
|
+
end
|
85
|
+
result << "#{sprintf('%6s', label)}|#{line}|"
|
86
|
+
end
|
87
|
+
puts result.join("\n")
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_scalestr v, base=1000
|
91
|
+
if v == nil or base == nil or base == 0
|
92
|
+
return(v.to_i == v ? v.to_i : v)
|
93
|
+
end
|
94
|
+
v = v.to_f
|
95
|
+
if v >= base ** 4
|
96
|
+
"%gT" % (v / (base ** 4))
|
97
|
+
elsif v >= base ** 3
|
98
|
+
"%gG" % (v / (base ** 3))
|
99
|
+
elsif v >= base ** 2
|
100
|
+
"%gM" % (v / (base ** 2))
|
101
|
+
elsif v >= base
|
102
|
+
"%gK" % (v / base)
|
103
|
+
else
|
104
|
+
v.to_s
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def render_x_axis_labels(rows, start_timestamp, step)
|
109
|
+
tm = rows.size * step
|
110
|
+
|
111
|
+
x_axis_labels = rows.length.times.select{|n| n % 8 == 0}. map{|n|
|
112
|
+
t = Time.at(start_timestamp + (n * step)).localtime
|
113
|
+
sprintf("%-8s", to_axis_label(t, tm))
|
114
|
+
}.join
|
115
|
+
x_axis_arrows= rows.length.times.select{|n| n % 8 == 0}. map{|n|
|
116
|
+
" / "
|
117
|
+
}.join
|
118
|
+
|
119
|
+
case 'show'#@options[:x_axis_label]
|
120
|
+
when "show"
|
121
|
+
puts sprintf("%6s%s", "", x_axis_arrows)
|
122
|
+
puts sprintf("%6s%s", "", x_axis_labels)
|
123
|
+
when "simple"
|
124
|
+
puts sprintf("%6s%s", "", x_axis_labels)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_axis_label t, tm
|
129
|
+
f = if tm <= 3600
|
130
|
+
'%M'
|
131
|
+
elsif tm <= 48*3600
|
132
|
+
'%H:%M'
|
133
|
+
elsif tm <= 8*24*3600
|
134
|
+
'%a'
|
135
|
+
elsif tm <= 35*24*3600
|
136
|
+
'%d'
|
137
|
+
else
|
138
|
+
'%m'
|
139
|
+
end
|
140
|
+
t.strftime f
|
141
|
+
end
|
142
|
+
|
143
|
+
TERMS = {'sh'=>['Hour', 3600], 's8h'=>['8Hours', 8*3600],
|
144
|
+
'd'=>['Day', 24*3600], 'w'=>['Week', 7*24*3600],
|
145
|
+
'm'=>['Month', 31*24*3600], 'y'=>['Year', 366*24*3600]}
|
146
|
+
end
|
147
|
+
end
|
data/lib/gri/spark.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'uri'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
require 'gri/q'
|
7
|
+
require 'gri/gparams'
|
8
|
+
require 'gri/sgraph'
|
9
|
+
|
10
|
+
module GRI
|
11
|
+
class Spark
|
12
|
+
def run options={}
|
13
|
+
optparser = optparse options
|
14
|
+
optparser.parse!
|
15
|
+
exit unless (url_s = ARGV.shift)
|
16
|
+
|
17
|
+
url = URI.parse url_s
|
18
|
+
params = GParams.new
|
19
|
+
parse_query url.query, params
|
20
|
+
fix_params params, options
|
21
|
+
url.query = mk_query params
|
22
|
+
if options[:user]
|
23
|
+
if options[:pass]
|
24
|
+
http_basic_authentication = [options[:user], options[:pass]]
|
25
|
+
else
|
26
|
+
print "Password:"
|
27
|
+
system "stty -echo"
|
28
|
+
password = $stdin.gets.chop
|
29
|
+
system "stty echo"
|
30
|
+
http_basic_authentication = [options[:user], password]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
obj = fetch url, http_basic_authentication
|
34
|
+
graph = Sgraph.new options
|
35
|
+
graph.render obj, {}, url
|
36
|
+
end
|
37
|
+
|
38
|
+
def fix_params params, options
|
39
|
+
etime = params['etime'].to_i
|
40
|
+
etime = (Time.now + etime).to_i if etime <= 0
|
41
|
+
if (t = options[:t]) and (v = Sgraph::TERMS[t])
|
42
|
+
stime = (stime = params['stime']) ? stime.to_i : -v[1]
|
43
|
+
stime = (etime + stime).to_i if stime <= 0
|
44
|
+
else
|
45
|
+
stime = (stime = params['stime']) ? stime.to_i : -28*3600
|
46
|
+
stime = (etime + stime).to_i if stime <= 0
|
47
|
+
end
|
48
|
+
params['stime'] = stime
|
49
|
+
params['etime'] = etime
|
50
|
+
params['maxrows'] = 70
|
51
|
+
params['fmt'] = 'json'
|
52
|
+
end
|
53
|
+
|
54
|
+
def fetch url, http_basic_authentication
|
55
|
+
if http_basic_authentication
|
56
|
+
str = open(url,
|
57
|
+
:http_basic_authentication=>http_basic_authentication).read
|
58
|
+
else
|
59
|
+
str = open(url).read
|
60
|
+
end
|
61
|
+
obj = YAML.load str
|
62
|
+
obj
|
63
|
+
end
|
64
|
+
|
65
|
+
def mk_query params
|
66
|
+
params.map {|k, v|
|
67
|
+
(Array === v) ? v.map {|vv| "#{k}=#{vv}"} : "#{k}=#{v}"
|
68
|
+
}.flatten.join('&')
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse_query qs, params={}
|
72
|
+
(qs || '').split(/[&;] */n).each {|item|
|
73
|
+
k, v = item.split('=', 2)
|
74
|
+
params[k] = v
|
75
|
+
}
|
76
|
+
params
|
77
|
+
end
|
78
|
+
|
79
|
+
def optparse opts
|
80
|
+
op = OptionParser.new
|
81
|
+
op.on('--debug') {$debug = true; STDOUT.sync = true;
|
82
|
+
opts['log-level'] = 'debug'}
|
83
|
+
op.on('--Doption=STR') {|arg| (opts['Doption'] ||= []).push arg}
|
84
|
+
op.on('-O OPT_STR') {|arg| (opts['O'] ||= []).push arg}
|
85
|
+
op.on('-c', '--config-path=PATH') {|arg| opts[:config_path] = arg}
|
86
|
+
op.on('--log-level=LEVEL') {|arg| opts['log-level'] = arg}
|
87
|
+
op.on('--nop') {opts['nop'] = true}
|
88
|
+
op.on('-t ARG') {|arg| opts[:t] = arg}
|
89
|
+
op.on('-u', '--user=USER') {|arg| opts[:user] = arg}
|
90
|
+
op.on('-p', '--password=PASSWORD') {|arg| opts[:pass] = arg}
|
91
|
+
op
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'gri/collector'
|
2
|
+
require 'gri/ldb'
|
3
|
+
|
4
|
+
module GRI
|
5
|
+
class TraCollector < Collector
|
6
|
+
TYPES['tra'] = self
|
7
|
+
|
8
|
+
def on_attach
|
9
|
+
# @loop.detach self if @config['nop']
|
10
|
+
dir = "#{self.class.gra_dir}/#{host}"
|
11
|
+
Dir.mkdir dir unless File.directory? dir
|
12
|
+
|
13
|
+
db_class = self.class.db_class
|
14
|
+
db = (db_class <= RemoteLDB) ? db_class.new(self.class.tra_uri, host) :
|
15
|
+
db_class.new("#{self.class.tra_dir}/#{host}")
|
16
|
+
|
17
|
+
@loop.next_tick {
|
18
|
+
begin
|
19
|
+
update_rrd_dir dir, db, options
|
20
|
+
ensure
|
21
|
+
@loop.detach self
|
22
|
+
db.close
|
23
|
+
end
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def update_rrd_dir dir, db, options
|
28
|
+
data_names = db.get_data_names
|
29
|
+
for data_name, interval in data_names
|
30
|
+
lu_path = "#{dir}/.lu_#{data_name}"
|
31
|
+
lu_time = nil
|
32
|
+
lu_pos = nil
|
33
|
+
if File.exist? lu_path
|
34
|
+
str = File.read(lu_path)
|
35
|
+
if str =~ /\A(\d+) (\d+)\Z/
|
36
|
+
lu_time = Time.at $1.to_i
|
37
|
+
lu_pos = $2.to_i
|
38
|
+
end
|
39
|
+
end
|
40
|
+
lu_time ||= Time.at(0)
|
41
|
+
lu_pos ||= 0
|
42
|
+
|
43
|
+
update_p = false
|
44
|
+
t = nil
|
45
|
+
records = []
|
46
|
+
db.get_after(data_name, lu_time, lu_pos) {|t, record, pos|
|
47
|
+
if $debug
|
48
|
+
ts = t.strftime '%Y-%m-%d %H:%M:%S'
|
49
|
+
puts "update #{ts} #{record['_host']} #{record['_key']}"
|
50
|
+
end
|
51
|
+
record['_interval'] = interval
|
52
|
+
records.push record
|
53
|
+
update_p = true
|
54
|
+
lu_time = t
|
55
|
+
lu_pos = pos
|
56
|
+
if records.size > 2000
|
57
|
+
@cb.call records
|
58
|
+
records.clear
|
59
|
+
end
|
60
|
+
}
|
61
|
+
if update_p
|
62
|
+
@cb.call records
|
63
|
+
open(lu_path, 'w') {|f| f.print "#{lu_time.to_i} #{lu_pos}"}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def recdump dir, records
|
69
|
+
path = dir + '/.rdump'
|
70
|
+
open(path, 'a') {|f|
|
71
|
+
records.each {|r| f.puts r.inspect}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
class <<self
|
76
|
+
attr_accessor :tra_dir, :gra_dir
|
77
|
+
attr_accessor :db_class, :tra_uri
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/gri/trad.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'gri/ldb'
|
2
|
+
|
3
|
+
module GRI
|
4
|
+
class Trad
|
5
|
+
def initialize
|
6
|
+
@acls = nil
|
7
|
+
@tra_dir = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def public_dir
|
11
|
+
'/notexist'
|
12
|
+
end
|
13
|
+
|
14
|
+
def load_acls config
|
15
|
+
acls = config.getvar 'acl-permit'
|
16
|
+
acls = acls ? acls.map {|pat| Regexp.new pat} : []
|
17
|
+
acls.push(/^127\.0\.0\.1$/)
|
18
|
+
acls.push(/^::ffff:127\.0\.0\.1$/)
|
19
|
+
acls.push(/^::1$/)
|
20
|
+
acls
|
21
|
+
end
|
22
|
+
|
23
|
+
def allowed? acls, remote_addr
|
24
|
+
acls.detect {|re| remote_addr =~ re}
|
25
|
+
end
|
26
|
+
|
27
|
+
def call env
|
28
|
+
@acls ||= load_acls Config
|
29
|
+
unless allowed?(@acls, env['REMOTE_ADDR'])
|
30
|
+
return [401, {}, ['Unauthorized']]
|
31
|
+
end
|
32
|
+
|
33
|
+
@root_dir ||= Config['root-dir'] || Config::ROOT_PATH
|
34
|
+
@tra_dir ||= (Config['tra-dir'] || @root_dir + '/tra')
|
35
|
+
|
36
|
+
req = Rack::Request.new env
|
37
|
+
serve @tra_dir, req.path_info, req
|
38
|
+
end
|
39
|
+
|
40
|
+
def serve tra_dir, path_info, params
|
41
|
+
headers = {}
|
42
|
+
body = []
|
43
|
+
|
44
|
+
if path_info =~ /\A\/get\b/ #/
|
45
|
+
s = params['s']
|
46
|
+
dir = "#{tra_dir}/#{params['h']}"
|
47
|
+
if File.directory?(dir)
|
48
|
+
t = Time.at(params['t'].to_i)
|
49
|
+
pos = params['pos'].to_i
|
50
|
+
ldb = LocalLDB.new dir
|
51
|
+
headers.clear
|
52
|
+
prev_time = 0
|
53
|
+
ldb.getl_after(s, t, pos) {|time, line, pos|
|
54
|
+
if body.size > 1000 and time.to_i > prev_time
|
55
|
+
headers['X-GRI-Continue'] = "#{prev_time.to_s} #{pos}"
|
56
|
+
break
|
57
|
+
end
|
58
|
+
prev_time = time.to_i
|
59
|
+
body.push(line+"\n")
|
60
|
+
}
|
61
|
+
headers['X-GRI-Pos'] = pos.to_s
|
62
|
+
end
|
63
|
+
elsif path_info =~ /\A\/get_data_names\b/ #/
|
64
|
+
dir = "#{tra_dir}/#{params['h']}"
|
65
|
+
ldb = LocalLDB.new dir
|
66
|
+
ldb.get_data_names.each {|k, v| body.push "#{k}_#{v}\n"}
|
67
|
+
elsif path_info =~ /\A\/gritab\b/ #/
|
68
|
+
gritab_path = Config['gritab-path'] || @root_dir + '/gritab'
|
69
|
+
if File.exist? gritab_path
|
70
|
+
open(gritab_path) {|f|
|
71
|
+
while line = f.gets
|
72
|
+
next if line =~ /\A\s*#|\A\z/
|
73
|
+
body.push line
|
74
|
+
end
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
[200, headers, body]
|
79
|
+
end
|
80
|
+
|
81
|
+
def run options={}
|
82
|
+
optparser = optparse options
|
83
|
+
optparser.parse!
|
84
|
+
Process.daemon true if options[:daemonize] and !$debug
|
85
|
+
config_path = options[:config_path] || GRI::Config::DEFAULT_PATH
|
86
|
+
config = GRI::Config.init config_path
|
87
|
+
@acls ||= load_acls config
|
88
|
+
@root_dir ||= config['root-dir'] || GRI::Config::ROOT_PATH
|
89
|
+
@tra_dir ||= (config['tra-dir'] || @root_dir + '/tra')
|
90
|
+
log_dir = config['log-dir'] || @root_dir + '/log'
|
91
|
+
Dir.mkdir log_dir unless File.exist? log_dir
|
92
|
+
Log.init "#{log_dir}/#{optparser.program_name}.log"
|
93
|
+
|
94
|
+
bind_address = options[:bind_address] || '0.0.0.0'
|
95
|
+
port = options[:port] || 7079
|
96
|
+
server_sock = TCPServer.new bind_address, port
|
97
|
+
rs0 = [server_sock]
|
98
|
+
params = {}
|
99
|
+
while true
|
100
|
+
next unless (a = IO.select(rs0, nil, nil, 1))
|
101
|
+
rs, = a
|
102
|
+
for io in rs
|
103
|
+
begin
|
104
|
+
if io.kind_of? TCPServer
|
105
|
+
sock = server_sock.accept
|
106
|
+
peername = sock.peeraddr[2]
|
107
|
+
peeraddr = sock.peeraddr[3]
|
108
|
+
if allowed?(@acls, peeraddr)
|
109
|
+
puts "#{peeraddr}: accespt #{sock.object_id}" if $debug
|
110
|
+
else
|
111
|
+
sock.close
|
112
|
+
puts "#{peeraddr}: reject" if $debug
|
113
|
+
next
|
114
|
+
end
|
115
|
+
rs0.push sock
|
116
|
+
elsif io.eof?
|
117
|
+
io.close
|
118
|
+
rs0.delete io
|
119
|
+
else
|
120
|
+
line = io.gets
|
121
|
+
line.chomp!
|
122
|
+
if line =~ /\A(\/\w+)\s*(\S+)?$/ #/
|
123
|
+
pi = $1
|
124
|
+
qs = $2
|
125
|
+
params.clear
|
126
|
+
(qs || '').split(/[&;] */n).each {|item|
|
127
|
+
k, v = item.split('=', 2)
|
128
|
+
params[k] = v
|
129
|
+
}
|
130
|
+
puts "#{io.object_id}: serve #{pi} #{params.inspect}" if $debug
|
131
|
+
code, h, body = serve @tra_dir, pi, params
|
132
|
+
h.each {|k, v| io.puts "#{k}: #{v}"}
|
133
|
+
io.puts
|
134
|
+
body.each {|l|
|
135
|
+
if l =~ /\A\./
|
136
|
+
io.puts ".#{l}"
|
137
|
+
else
|
138
|
+
io.puts l
|
139
|
+
end
|
140
|
+
}
|
141
|
+
io.puts "."
|
142
|
+
end
|
143
|
+
end
|
144
|
+
rescue Exception
|
145
|
+
Log.error "ERROR: #{$!}: #{$@.inspect}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def optparse opts
|
152
|
+
op = OptionParser.new
|
153
|
+
op.on('--debug') {$debug = true; STDOUT.sync = true}
|
154
|
+
op.on('-c', '--config-path=PATH') {|arg| opts[:config_path] = arg}
|
155
|
+
op.on('-d', '--daemonize') {opts[:daemonize] = true}
|
156
|
+
op.on('-b', '--bind-address=ADDRESS') {|arg| opts[:bind_address] = arg}
|
157
|
+
op.on('-p', '--port=PORT', Integer) {|arg| opts[:port] = arg}
|
158
|
+
end
|
159
|
+
|
160
|
+
if __FILE__ == $0
|
161
|
+
require 'socket'
|
162
|
+
require 'optparse'
|
163
|
+
require 'gri/q'
|
164
|
+
require 'gri/config'
|
165
|
+
require 'gri/log'
|
166
|
+
require 'gri/util_daemon'
|
167
|
+
new.run
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|