rroonga 0.9.4-x86-mingw32 → 0.9.5-x86-mingw32

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 (153) hide show
  1. data/NEWS.ja.rdoc +29 -0
  2. data/NEWS.rdoc +29 -0
  3. data/Rakefile +6 -6
  4. data/ext/groonga/rb-grn-array.c +1 -1
  5. data/ext/groonga/rb-grn-context.c +15 -28
  6. data/ext/groonga/rb-grn-exception.c +46 -1
  7. data/ext/groonga/rb-grn-expression.c +22 -13
  8. data/ext/groonga/rb-grn-fix-size-column.c +2 -8
  9. data/ext/groonga/rb-grn-hash.c +8 -1
  10. data/ext/groonga/rb-grn-object.c +1 -1
  11. data/ext/groonga/rb-grn-patricia-trie.c +23 -1
  12. data/ext/groonga/rb-grn-table-key-support.c +22 -0
  13. data/ext/groonga/rb-grn-table.c +37 -5
  14. data/ext/groonga/rb-grn-utils.c +20 -2
  15. data/ext/groonga/rb-grn.h +1 -1
  16. data/ext/groonga/rb-groonga.c +76 -38
  17. data/extconf.rb +17 -1
  18. data/html/developer.html +32 -7
  19. data/html/footer.html.erb +5 -0
  20. data/html/heading-mark.svg +393 -0
  21. data/html/index.html +33 -3
  22. data/lib/1.8/groonga.so +0 -0
  23. data/lib/1.9/groonga.so +0 -0
  24. data/lib/groonga.rb +3 -7
  25. data/lib/groonga/context.rb +2 -13
  26. data/lib/groonga/expression-builder.rb +273 -67
  27. data/lib/groonga/pagination.rb +143 -0
  28. data/lib/groonga/record.rb +2 -0
  29. data/lib/groonga/schema.rb +140 -29
  30. data/pkg/rroonga-0.9.5/NEWS.ja.rdoc +156 -0
  31. data/pkg/rroonga-0.9.5/NEWS.rdoc +158 -0
  32. data/pkg/rroonga-0.9.5/README.ja.rdoc +65 -0
  33. data/pkg/rroonga-0.9.5/README.rdoc +66 -0
  34. data/pkg/rroonga-0.9.5/text/TUTORIAL.ja.rdoc +394 -0
  35. data/pkg/rroonga-0.9.5/text/expression.rdoc +285 -0
  36. data/rroonga-build.rb +2 -2
  37. data/test-unit/Rakefile +40 -0
  38. data/test-unit/TODO +5 -0
  39. data/test-unit/bin/testrb +5 -0
  40. data/test-unit/html/classic.html +15 -0
  41. data/test-unit/html/index.html +25 -0
  42. data/test-unit/html/index.html.ja +27 -0
  43. data/test-unit/lib/test/unit.rb +323 -0
  44. data/test-unit/lib/test/unit/assertionfailederror.rb +25 -0
  45. data/test-unit/lib/test/unit/assertions.rb +1230 -0
  46. data/test-unit/lib/test/unit/attribute.rb +125 -0
  47. data/test-unit/lib/test/unit/autorunner.rb +360 -0
  48. data/test-unit/lib/test/unit/collector.rb +36 -0
  49. data/test-unit/lib/test/unit/collector/descendant.rb +23 -0
  50. data/test-unit/lib/test/unit/collector/dir.rb +108 -0
  51. data/test-unit/lib/test/unit/collector/load.rb +144 -0
  52. data/test-unit/lib/test/unit/collector/objectspace.rb +34 -0
  53. data/test-unit/lib/test/unit/color-scheme.rb +102 -0
  54. data/test-unit/lib/test/unit/color.rb +96 -0
  55. data/test-unit/lib/test/unit/diff.rb +724 -0
  56. data/test-unit/lib/test/unit/error.rb +130 -0
  57. data/test-unit/lib/test/unit/exceptionhandler.rb +39 -0
  58. data/test-unit/lib/test/unit/failure.rb +136 -0
  59. data/test-unit/lib/test/unit/fixture.rb +176 -0
  60. data/test-unit/lib/test/unit/notification.rb +129 -0
  61. data/test-unit/lib/test/unit/omission.rb +191 -0
  62. data/test-unit/lib/test/unit/pending.rb +150 -0
  63. data/test-unit/lib/test/unit/priority.rb +180 -0
  64. data/test-unit/lib/test/unit/runner/console.rb +52 -0
  65. data/test-unit/lib/test/unit/runner/emacs.rb +8 -0
  66. data/test-unit/lib/test/unit/runner/tap.rb +8 -0
  67. data/test-unit/lib/test/unit/testcase.rb +476 -0
  68. data/test-unit/lib/test/unit/testresult.rb +89 -0
  69. data/test-unit/lib/test/unit/testsuite.rb +110 -0
  70. data/test-unit/lib/test/unit/ui/console/outputlevel.rb +14 -0
  71. data/test-unit/lib/test/unit/ui/console/testrunner.rb +466 -0
  72. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +63 -0
  73. data/test-unit/lib/test/unit/ui/tap/testrunner.rb +92 -0
  74. data/test-unit/lib/test/unit/ui/testrunner.rb +28 -0
  75. data/test-unit/lib/test/unit/ui/testrunnermediator.rb +77 -0
  76. data/test-unit/lib/test/unit/ui/testrunnerutilities.rb +41 -0
  77. data/test-unit/lib/test/unit/util/backtracefilter.rb +41 -0
  78. data/test-unit/lib/test/unit/util/method-owner-finder.rb +28 -0
  79. data/test-unit/lib/test/unit/util/observable.rb +90 -0
  80. data/test-unit/lib/test/unit/util/procwrapper.rb +48 -0
  81. data/test-unit/lib/test/unit/version.rb +7 -0
  82. data/test-unit/sample/adder.rb +13 -0
  83. data/test-unit/sample/subtracter.rb +12 -0
  84. data/test-unit/sample/test_adder.rb +20 -0
  85. data/test-unit/sample/test_subtracter.rb +20 -0
  86. data/test-unit/sample/test_user.rb +23 -0
  87. data/test-unit/test/collector/test-descendant.rb +133 -0
  88. data/test-unit/test/collector/test-load.rb +442 -0
  89. data/test-unit/test/collector/test_dir.rb +406 -0
  90. data/test-unit/test/collector/test_objectspace.rb +100 -0
  91. data/test-unit/test/run-test.rb +15 -0
  92. data/test-unit/test/test-attribute.rb +86 -0
  93. data/test-unit/test/test-color-scheme.rb +67 -0
  94. data/test-unit/test/test-color.rb +47 -0
  95. data/test-unit/test/test-diff.rb +518 -0
  96. data/test-unit/test/test-emacs-runner.rb +60 -0
  97. data/test-unit/test/test-fixture.rb +287 -0
  98. data/test-unit/test/test-notification.rb +33 -0
  99. data/test-unit/test/test-omission.rb +81 -0
  100. data/test-unit/test/test-pending.rb +70 -0
  101. data/test-unit/test/test-priority.rb +119 -0
  102. data/test-unit/test/test-testcase.rb +544 -0
  103. data/test-unit/test/test_assertions.rb +1151 -0
  104. data/test-unit/test/test_error.rb +26 -0
  105. data/test-unit/test/test_failure.rb +33 -0
  106. data/test-unit/test/test_testresult.rb +113 -0
  107. data/test-unit/test/test_testsuite.rb +129 -0
  108. data/test-unit/test/testunit-test-util.rb +14 -0
  109. data/test-unit/test/ui/test_testrunmediator.rb +20 -0
  110. data/test-unit/test/util/test-method-owner-finder.rb +38 -0
  111. data/test-unit/test/util/test_backtracefilter.rb +41 -0
  112. data/test-unit/test/util/test_observable.rb +102 -0
  113. data/test-unit/test/util/test_procwrapper.rb +36 -0
  114. data/test/groonga-test-utils.rb +3 -2
  115. data/test/run-test.rb +14 -2
  116. data/test/test-column.rb +7 -7
  117. data/test/test-context-select.rb +34 -11
  118. data/test/test-exception.rb +3 -0
  119. data/test/test-expression-builder.rb +11 -0
  120. data/test/test-expression.rb +3 -6
  121. data/test/test-gqtp.rb +3 -5
  122. data/test/test-pagination.rb +249 -0
  123. data/test/test-record.rb +36 -8
  124. data/test/test-remote.rb +11 -4
  125. data/test/test-schema-create-table.rb +251 -0
  126. data/test/test-schema.rb +4 -24
  127. data/test/test-table-offset-and-limit.rb +3 -5
  128. data/test/test-table-select-mecab.rb +80 -0
  129. data/test/test-table-select-weight.rb +104 -0
  130. data/test/test-table.rb +22 -4
  131. data/test/test-version.rb +1 -1
  132. data/text/TUTORIAL.ja.rdoc +2 -0
  133. data/text/expression.rdoc +1 -0
  134. data/vendor/local/bin/grntest.exe +0 -0
  135. data/vendor/local/bin/groonga.exe +0 -0
  136. data/vendor/local/bin/libgroonga-0.dll +0 -0
  137. data/vendor/local/include/{groonga.h → groonga/groonga.h} +93 -32
  138. data/vendor/local/lib/groonga/modules/functions/cast.dll +0 -0
  139. data/vendor/local/lib/groonga/modules/functions/cast.la +41 -0
  140. data/vendor/local/lib/pkgconfig/groonga.pc +12 -0
  141. data/vendor/local/share/groonga/admin_html/css/admin.css +104 -0
  142. data/vendor/local/share/groonga/admin_html/css/ui-lightness/jquery-ui-1.8.1.custom.css +486 -0
  143. data/vendor/local/share/groonga/admin_html/index.html +1355 -0
  144. data/vendor/local/share/groonga/admin_html/js/jquery-1.4.2.min.js +154 -0
  145. data/vendor/local/share/groonga/admin_html/js/jquery-ui-1.8.1.custom.min.js +756 -0
  146. data/vendor/local/share/groonga/munin/plugins/groonga_cpu_load +47 -0
  147. data/vendor/local/share/groonga/munin/plugins/groonga_cpu_time +57 -0
  148. data/vendor/local/share/groonga/munin/plugins/groonga_disk +162 -0
  149. data/vendor/local/share/groonga/munin/plugins/groonga_memory +51 -0
  150. data/vendor/local/share/groonga/munin/plugins/groonga_n_records +110 -0
  151. data/vendor/local/share/groonga/munin/plugins/groonga_query_performance +133 -0
  152. data/vendor/local/share/groonga/munin/plugins/groonga_status +84 -0
  153. metadata +126 -36
@@ -0,0 +1,47 @@
1
+ #!/bin/sh
2
+
3
+ #%# family=auto
4
+ #%# capabilities=autoconf
5
+
6
+ case "$1" in
7
+ autoconf|detect)
8
+ if [ -z "${pid_file}" ]; then
9
+ echo "no (PID file isn't specified by env.pid_file)"
10
+ exit 1
11
+ elif [ -f "${pid_file}" ]; then
12
+ echo "yes"
13
+ exit 0
14
+ else
15
+ echo "no (PID file doesn't exist: ${pid_file})"
16
+ exit 1
17
+ fi
18
+ ;;
19
+ config)
20
+ if [ -z "${label}" ]; then
21
+ title="groonga: CPU load"
22
+ else
23
+ title="groonga: ${label}: CPU load"
24
+ fi
25
+ cat <<EOF
26
+ graph_title ${title}
27
+ graph_vlabel CPU load (%)
28
+ graph_category groonga
29
+ graph_info groonga CPU load
30
+
31
+ cpu_load.label CPU load
32
+ cpu_load.type GAUGE
33
+ EOF
34
+ exit 0
35
+ ;;
36
+ *)
37
+ esac
38
+
39
+ if [ -z "${pid_file}" ]; then
40
+ echo "PID file isn't specified by env.pid_file"
41
+ exit 1
42
+ fi
43
+
44
+ groonga_pid=$(cat ${pid_file})
45
+ top_for_groonga=$(top -b -n 1 -p ${groonga_pid} | tail -2 | head -1)
46
+ load_in_percent=$(echo ${top_for_groonga} | sed -r -e 's/ +/ /g' | cut -d' ' -f 9)
47
+ echo "cpu_load.value ${load_in_percent}"
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #%# family=auto
4
+ #%# capabilities=autoconf
5
+
6
+ label = ENV["label"]
7
+ pid_file = ENV["pid_file"]
8
+
9
+ command = ARGV.shift
10
+
11
+ case command
12
+ when "autoconf", "detect"
13
+ if pid_file.nil?
14
+ puts "no (PID file isn't specified by env.pid_file)"
15
+ exit(false)
16
+ elsif File.exist?(pid_file)
17
+ puts "yes"
18
+ exit(true)
19
+ else
20
+ puts "no (PID file doesn't exist: #{pid_file})"
21
+ exit(false)
22
+ end
23
+ when "config"
24
+ if label
25
+ title = "groonga: #{label}: CPU time"
26
+ else
27
+ title = "groonga: CPU time"
28
+ end
29
+ puts <<EOF
30
+ graph_title #{title}
31
+ graph_vlabel CPU time (days)
32
+ graph_category groonga
33
+ graph_info groonga CPU time
34
+
35
+ cpu_time.label CPU time
36
+ cpu_time.type GAUGE
37
+ EOF
38
+ exit(true)
39
+ end
40
+
41
+ groonga_pid = File.read(pid_file).strip
42
+ time = `ps h -o time -p #{groonga_pid}`.chomp
43
+ if /\A(?:(\d+)-)?(\d+):(\d+):(\d+)\z/ =~ time
44
+ day, hours, minutes, seconds, = $1, $2, $3, $4
45
+ day = (day || 0).to_i
46
+ hours = hours.to_i
47
+ minutes = minutes.to_i
48
+ seconds = seconds.to_i
49
+ time_in_seconds = seconds + minutes * 60 + hours * 60 * 60
50
+ day_in_seconds = 60 * 60 * 24
51
+ fraction_in_day = time_in_seconds.to_f / day_in_seconds.to_f
52
+ cpu_time_in_day = day + fraction_in_day
53
+ puts "cpu_time.value #{cpu_time_in_day}"
54
+ else
55
+ puts "invalid time format: <#{time}>"
56
+ exit(false)
57
+ end
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #%# family=auto
4
+ #%# capabilities=autoconf
5
+
6
+ require 'shellwords'
7
+ require 'json'
8
+ require 'English'
9
+
10
+ label = ENV["label"]
11
+ @groonga = ENV["groonga"] || "groonga"
12
+ @du = ENV["du"] || "du"
13
+ @path = ENV["path"]
14
+
15
+ command = ARGV.shift
16
+
17
+ def parse(success, result)
18
+ if success
19
+ begin
20
+ status, body = JSON.parse(result)
21
+ return_code, start_time, elapsed, error_message = status
22
+ if return_code.zero?
23
+ [success, body]
24
+ else
25
+ [false, error_message]
26
+ end
27
+ rescue JSON::ParserError
28
+ [false, $!.message]
29
+ end
30
+ else
31
+ [success, result]
32
+ end
33
+ end
34
+
35
+ def run(command, *args)
36
+ path = Shellwords.shellescape(@path)
37
+ result = `#{@groonga} #{path} #{command} #{args.join(' ')} 2>&1`
38
+ parse($?.success?, result)
39
+ end
40
+
41
+ def parse_list(header, list)
42
+ list.collect do |item|
43
+ parsed_item = {}
44
+ header.each_with_index do |(name, type), i|
45
+ parsed_item[name] = item[i]
46
+ end
47
+ parsed_item
48
+ end
49
+ end
50
+
51
+ def schema
52
+ tables = []
53
+ success, table_list_body = run("table_list")
54
+ unless success
55
+ puts "error: #{table_list_body}"
56
+ exit(false)
57
+ end
58
+ parse_list(table_list_body[0], table_list_body[1..-1]).each do |table|
59
+ table_name = table["name"]
60
+ table["key"] = "table_#{table_name}"
61
+ success, column_list_body = run("column_list", table_name)
62
+ unless success
63
+ puts "error: #{column_list_body}"
64
+ exit(false)
65
+ end
66
+ table["columns"] = parse_list(column_list_body[0], column_list_body[1..-1])
67
+ table["columns"].each do |column|
68
+ column["key"] = "column_#{table_name}_#{column['name']}"
69
+ column["full_name"] = "#{table_name}.#{column['name']}"
70
+ end
71
+ tables << table
72
+ end
73
+ tables
74
+ end
75
+
76
+ def parse_du_result(result)
77
+ usages = {}
78
+ result.each_line do |line|
79
+ if /\A(\d+)\s+/ =~ line
80
+ usage = $1
81
+ path = $POSTMATCH.strip
82
+ usages[path] = usage.to_i
83
+ end
84
+ end
85
+ usages
86
+ end
87
+
88
+ case command
89
+ when "autoconf", "detect"
90
+ success, body = run("status")
91
+ if success
92
+ puts "yes"
93
+ exit(true)
94
+ else
95
+ puts "no (#{body})"
96
+ exit(false)
97
+ end
98
+ when "config"
99
+ if label.nil?
100
+ title = "groonga: disk usage"
101
+ else
102
+ title = "groonga: #{label}: disk usage"
103
+ end
104
+ puts <<EOF
105
+ graph_title #{title}
106
+ graph_vlabel Bytes
107
+ graph_category groonga
108
+ graph_info disk usage in groonga tables and columns
109
+ graph_args --base 1024
110
+ graph_total Total
111
+
112
+ database.label Database
113
+ database.draw AREA
114
+ EOF
115
+ schema.each do |table|
116
+ table_key = table["key"]
117
+ table_name = table["name"]
118
+ puts <<EOF
119
+
120
+ #{table_key}.label #{table_name}
121
+ #{table_key}.draw STACK
122
+ EOF
123
+ table["columns"].each do |column|
124
+ column_key = column["key"]
125
+ column_name = column["full_name"]
126
+ puts <<EOF
127
+
128
+ #{column_key}.label #{column_name}
129
+ #{column_key}.draw STACK
130
+ EOF
131
+ end
132
+ end
133
+ exit(true)
134
+ end
135
+
136
+ path = Shellwords.shellescape(@path)
137
+ du_result = `#{@du} -B1 #{path}*`
138
+ unless $?.success?
139
+ puts("error: #{du_result}")
140
+ exit(false)
141
+ end
142
+ usages = parse_du_result(du_result)
143
+ usage = usages[@path] || 0
144
+ puts <<EOF
145
+ database.value #{usage}
146
+ EOF
147
+ schema.each do |table|
148
+ table_key = table["key"]
149
+ table_name = table["name"]
150
+ usage = usages[table["path"]] || 0
151
+ puts <<EOF
152
+ #{table_key}.value #{usage}
153
+ EOF
154
+ table["columns"].each do |column|
155
+ column_key = column["key"]
156
+ usage = usages[column["path"]] || 0
157
+ usage += usages["#{column['path']}.c"] || 0
158
+ puts <<EOF
159
+ #{column_key}.value #{usage}
160
+ EOF
161
+ end
162
+ end
@@ -0,0 +1,51 @@
1
+ #!/bin/sh
2
+
3
+ #%# family=auto
4
+ #%# capabilities=autoconf
5
+
6
+ case "$1" in
7
+ autoconf|detect)
8
+ if [ -z "${pid_file}" ]; then
9
+ echo "no (PID file isn't specified by env.pid_file)"
10
+ exit 1
11
+ elif [ -f "${pid_file}" ]; then
12
+ echo "yes"
13
+ exit 0
14
+ else
15
+ echo "no (PID file doesn't exist: ${pid_file})"
16
+ exit 1
17
+ fi
18
+ ;;
19
+ config)
20
+ if [ -z "${label}" ]; then
21
+ title="groonga: memory usage"
22
+ else
23
+ title="groonga: ${label}: memory usage"
24
+ fi
25
+ cat <<EOF
26
+ graph_title ${title}
27
+ graph_vlabel memory usage
28
+ graph_category groonga
29
+ graph_info groonga memory usage
30
+
31
+ rss.label resident set size
32
+ rss.type GAUGE
33
+ vsz.label virtual memory size
34
+ vsz.type GAUGE
35
+ EOF
36
+ exit 0
37
+ ;;
38
+ *)
39
+ esac
40
+
41
+ if [ -z "${pid_file}" ]; then
42
+ echo "PID file isn't specified by env.pid_file"
43
+ exit 1
44
+ fi
45
+
46
+ groonga_pid=$(cat ${pid_file})
47
+ read rss_in_kb vsz_in_kb <<EOC
48
+ $(ps h -o rss,vsz -p ${groonga_pid})
49
+ EOC
50
+ echo "rss.value ${rss_in_kb}000"
51
+ echo "vsz.value ${vsz_in_kb}000"
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #%# family=auto
4
+ #%# capabilities=autoconf
5
+
6
+ require 'shellwords'
7
+ require 'json'
8
+
9
+ label = ENV["label"]
10
+ @groonga = ENV["groonga"] || "groonga"
11
+ @host = ENV["host"] || "localhost"
12
+ @port = ENV["port"] || 10041
13
+ @path = ENV["path"]
14
+
15
+ command = ARGV.shift
16
+
17
+ def parse(success, result)
18
+ if success
19
+ begin
20
+ status, body = JSON.parse(result)
21
+ return_code, start_time, elapsed, error_message = status
22
+ if return_code.zero?
23
+ [success, body]
24
+ else
25
+ [false, error_message]
26
+ end
27
+ rescue JSON::ParserError
28
+ [false, $!.message]
29
+ end
30
+ else
31
+ [success, result]
32
+ end
33
+ end
34
+
35
+ def run(command, *args)
36
+ if @path
37
+ path = Shellwords.shellescape(@path)
38
+ result = `#{@groonga} #{path} #{command} #{args.join(' ')} 2>&1`
39
+ else
40
+ groonga = "#{@groonga} -p #{@port} -c #{@host}"
41
+ result = `#{groonga} #{command} #{args.join(' ')} 2>&1`
42
+ end
43
+ parse($?.success?, result)
44
+ end
45
+
46
+ def parse_list(header, list)
47
+ list.collect do |item|
48
+ parsed_item = {}
49
+ header.each_with_index do |(name, type), i|
50
+ parsed_item[name] = item[i]
51
+ end
52
+ parsed_item
53
+ end
54
+ end
55
+
56
+ case command
57
+ when "autoconf", "detect"
58
+ success, body = run("status")
59
+ if success
60
+ puts "yes"
61
+ exit(true)
62
+ else
63
+ puts "no (#{body})"
64
+ exit(false)
65
+ end
66
+ when "config"
67
+ if label.nil?
68
+ title = "groonga: number of records"
69
+ else
70
+ title = "groonga: #{label}: number of records"
71
+ end
72
+ puts <<EOF
73
+ graph_title #{title}
74
+ graph_vlabel records
75
+ graph_category groonga
76
+ graph_info number of records in groonga table
77
+ EOF
78
+ success, body = run("table_list")
79
+ unless success
80
+ puts "error: #{body}"
81
+ exit(false)
82
+ end
83
+ parse_list(body[0], body[1..-1]).each do |table|
84
+ name = table["name"]
85
+ puts <<EOF
86
+
87
+ #{name}.label #{name}
88
+ #{name}.type GAUGE
89
+ EOF
90
+ end
91
+ exit(true)
92
+ end
93
+
94
+ success, body = run("table_list")
95
+ unless success
96
+ puts("error: #{body}")
97
+ exit(false)
98
+ end
99
+ parse_list(body[0], body[1..-1]).each do |table|
100
+ name = table["name"]
101
+ success, body = run("select", "#{name} --limit 0")
102
+ unless success
103
+ puts("error: #{body}")
104
+ exit(false)
105
+ end
106
+ n_records = body[0][0][0]
107
+ puts <<EOF
108
+ #{name}.value #{n_records}
109
+ EOF
110
+ end
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #%# family=auto
4
+ #%# capabilities=autoconf
5
+
6
+ require 'English'
7
+ require 'strscan'
8
+
9
+ label = ENV["label"]
10
+
11
+ @log_path = ENV["log_path"]
12
+
13
+ command = ARGV.shift
14
+
15
+ case command
16
+ when "autoconf", "detect"
17
+ if @log_path.nil?
18
+ puts "no (query log file path isn't specified by env.log_path)"
19
+ exit(false)
20
+ end
21
+ unless File.readable?(@log_path)
22
+ puts "no (query log file isn't readable: <#{@log_path}>)"
23
+ exit(false)
24
+ end
25
+ puts "yes"
26
+ exit(true)
27
+ when "config"
28
+ if label.nil?
29
+ title = "groonga: query performance"
30
+ else
31
+ title = "groonga: #{label}: query performance"
32
+ end
33
+ puts <<EOF
34
+ graph_title #{title}
35
+ graph_vlabel seconds
36
+ graph_category groonga
37
+ graph_info groonga query performance
38
+
39
+ longest.label Longest
40
+ average.label Average
41
+ median.label Median
42
+ EOF
43
+ exit(true)
44
+ end
45
+
46
+ class ReverseLineReader
47
+ def initialize(io)
48
+ @io = io
49
+ @io.seek(0, IO::SEEK_END)
50
+ @buffer = ""
51
+ @data = ""
52
+ end
53
+
54
+ def each
55
+ separator = $/
56
+ separator_length = separator.length
57
+ while read_to_buffer
58
+ loop do
59
+ index = @buffer.rindex(separator, @buffer.length - 1 - separator_length)
60
+ break if index.nil? or index.zero?
61
+ last_line = @buffer.slice!((index + separator_length)..-1)
62
+ yield(last_line)
63
+ end
64
+ end
65
+ yield(@buffer) unless @buffer.empty?
66
+ end
67
+
68
+ private
69
+ BYTES_PER_READ = 4096
70
+ def read
71
+ position = @io.pos
72
+ if position < BYTES_PER_READ
73
+ bytes_per_read = position
74
+ else
75
+ bytes_per_read = BYTES_PER_READ
76
+ end
77
+
78
+ if bytes_per_read.zero?
79
+ @data.replace("")
80
+ else
81
+ @io.seek(-bytes_per_read, IO::SEEK_CUR)
82
+ @io.read(bytes_per_read, @data)
83
+ @io.seek(-bytes_per_read, IO::SEEK_CUR)
84
+ end
85
+
86
+ @data
87
+ end
88
+
89
+ def read_to_buffer
90
+ data = read
91
+ if data.empty?
92
+ false
93
+ else
94
+ @buffer.insert(0, data)
95
+ true
96
+ end
97
+ end
98
+ end
99
+
100
+ span = 60 * 5 # 5min
101
+ mega = 1_000_000.0
102
+ now = Time.now
103
+ elapsed_times = []
104
+ File.open(@log_path) do |log_file|
105
+ ReverseLineReader.new(log_file).each do |line|
106
+ case line
107
+ when /\A(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)\.(\d+)\|([\da-f])+\|<(\d+) rc=0$/
108
+ _, year, month, day, hour, minutes, seconds, milliseconds,
109
+ context, elapsed = $LAST_MATCH_INFO.to_a
110
+ time_stamp = Time.local(year, month, day,
111
+ hour, minutes, seconds, milliseconds)
112
+ difference = now - time_stamp
113
+ break if difference > span
114
+ elapsed_in_micro_seconds = elapsed.to_i / mega
115
+ elapsed_times << elapsed_in_micro_seconds
116
+ end
117
+ end
118
+ end
119
+
120
+ sorted_elapsed_times = elapsed_times.sort
121
+ if sorted_elapsed_times.empty?
122
+ longest = 0
123
+ average = 0
124
+ median = 0
125
+ else
126
+ longest = sorted_elapsed_times.last
127
+ average = sorted_elapsed_times.inject(&:+) / sorted_elapsed_times.size.to_f
128
+ median = sorted_elapsed_times[sorted_elapsed_times.size / 2]
129
+ end
130
+
131
+ puts "longest.value #{longest}"
132
+ puts "average.value #{average}"
133
+ puts "median.value #{median}"