opener-core 1.0.2 → 2.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 +4 -4
- data/LICENSE.txt +13 -0
- data/README.md +13 -1
- data/lib/opener/core.rb +7 -7
- data/lib/opener/core/resource_switcher.rb +102 -59
- data/lib/opener/core/syslog.rb +67 -0
- data/lib/opener/core/version.rb +1 -1
- data/opener-core.gemspec +6 -3
- metadata +60 -33
- data/lib/opener/core/argv_splitter.rb +0 -19
- data/lib/opener/core/benchmark.rb +0 -137
- data/lib/opener/core/error_layer.rb +0 -89
- data/lib/opener/core/memory_usage.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87117423cfca0b17170602c260fc9104ba2b45ac
|
4
|
+
data.tar.gz: 9d4bb57cb373d9267e7919a931f8bbed7df2f674
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82117f92f331dce2a4f0d59e4da78028afc67c2eac93710d8d87b0b5c9440aa2a3bae643a62c1880cc8687401437c6ad5cb96417dd6df6040a0e16bfad7d9712
|
7
|
+
data.tar.gz: 005414617ad9a815772613340254c8d955c4c0b8a388587eb8f37f3dcd793b2df8c9c8babcfbda40baaebc4e8dd6c2173e439058c05a040e7ac97fbd8f3f2888
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2014 OpeNER Project Consortium
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
CHANGED
@@ -1,7 +1,19 @@
|
|
1
|
-
# Opener
|
1
|
+
# Opener Core
|
2
2
|
|
3
3
|
A Gem that provides commonly re-used functionality for the various OpeNER Gems.
|
4
4
|
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
| Ruby | Required | Recommended |
|
8
|
+
|:---------|:--------------|:------------|
|
9
|
+
| MRI | >= 1.9.3 | >= 2.1.4 |
|
10
|
+
| Rubinius | >= 2.2 | >= 2.3.0 |
|
11
|
+
| JRuby | >= 1.7 | >= 1.7.16 |
|
12
|
+
|
13
|
+
For the resource switcher you'll need to have
|
14
|
+
[libarchive](http://www.libarchive.org/) installed as it's used for unpacking
|
15
|
+
archives.
|
16
|
+
|
5
17
|
## Installation
|
6
18
|
|
7
19
|
You can install opener-core as a Gem by running:
|
data/lib/opener/core.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
require 'benchmark'
|
2
|
-
require 'optparse'
|
3
1
|
require 'tempfile'
|
4
2
|
require 'uri'
|
5
|
-
require '
|
3
|
+
require 'syslog'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
require 'slop'
|
7
|
+
require 'httpclient'
|
8
|
+
require 'archive'
|
6
9
|
|
7
10
|
require_relative 'core/version'
|
8
|
-
require_relative 'core/argv_splitter'
|
9
11
|
require_relative 'core/opt_parser'
|
10
12
|
require_relative 'core/resource_switcher'
|
11
|
-
require_relative 'core/
|
12
|
-
require_relative 'core/benchmark'
|
13
|
-
require_relative 'core/error_layer'
|
13
|
+
require_relative 'core/syslog'
|
@@ -1,85 +1,128 @@
|
|
1
1
|
module Opener
|
2
2
|
module Core
|
3
|
+
##
|
4
|
+
# Class for downloading and extracting external resources such as
|
5
|
+
# models/lexicons.
|
6
|
+
#
|
7
|
+
# @!attribute [r] http
|
8
|
+
# @return [HTTPClient]
|
9
|
+
#
|
3
10
|
class ResourceSwitcher
|
11
|
+
attr_reader :http
|
4
12
|
|
5
|
-
def
|
6
|
-
|
13
|
+
def initialize
|
14
|
+
@http = HTTPClient.new
|
7
15
|
end
|
8
16
|
|
9
|
-
|
10
|
-
|
17
|
+
##
|
18
|
+
# Adds extra CLI options to the given Slop instance.
|
19
|
+
#
|
20
|
+
# @param [Slop] slop
|
21
|
+
#
|
22
|
+
def bind(slop)
|
23
|
+
slop.separator "\nResource Options:\n"
|
24
|
+
|
25
|
+
slop.on :'resource-url=',
|
26
|
+
'URL pointing to a .zip/.tar.gz file to download',
|
27
|
+
:as => String
|
28
|
+
|
29
|
+
slop.on :'resource-path=',
|
30
|
+
'Path where the resources should be saved',
|
31
|
+
:as => String
|
32
|
+
|
33
|
+
# Hijack Slop's run block so we can inject our own code before it. This
|
34
|
+
# is quite grotesque, but sadly the only way.
|
35
|
+
old_runner = slop.instance_variable_get(:@runner)
|
36
|
+
|
37
|
+
slop.run do |opts, args|
|
38
|
+
if opts[:'resource-path'] and opts[:'resource-url']
|
39
|
+
download_and_extract(opts[:'resource-url'], opts[:'resource-path'])
|
40
|
+
end
|
41
|
+
|
42
|
+
old_runner.call(opts, args)
|
43
|
+
end
|
11
44
|
end
|
12
45
|
|
13
|
-
|
14
|
-
|
46
|
+
##
|
47
|
+
# @param [String] url
|
48
|
+
# @param [String] path
|
49
|
+
#
|
50
|
+
def download_and_extract(url, path)
|
51
|
+
filename = filename_from_url(url)
|
52
|
+
temp_path = File.join(path, filename)
|
15
53
|
|
16
|
-
|
17
|
-
@options = options
|
18
|
-
end
|
54
|
+
create_directory(path)
|
19
55
|
|
20
|
-
|
21
|
-
return if !options[:resource_path] && !options[:resource_url]
|
56
|
+
download(url, temp_path)
|
22
57
|
|
23
|
-
|
24
|
-
if options[:resource_url] && path.nil? && force
|
25
|
-
raise ArgumentError, "No resource-path given"
|
26
|
-
end
|
58
|
+
Archive.extract(temp_path, path)
|
27
59
|
|
28
|
-
|
60
|
+
remove_file(temp_path)
|
61
|
+
end
|
29
62
|
|
30
|
-
|
31
|
-
|
63
|
+
##
|
64
|
+
# Downloads the given file.
|
65
|
+
#
|
66
|
+
# @param [String] url
|
67
|
+
# @param [String] path
|
68
|
+
#
|
69
|
+
def download(url, path)
|
70
|
+
File.open(path, 'w', :encoding => Encoding::BINARY) do |handle|
|
71
|
+
http.get(url) do |chunk|
|
72
|
+
handle.write(chunk)
|
32
73
|
end
|
33
74
|
end
|
75
|
+
end
|
34
76
|
|
35
|
-
|
36
|
-
|
37
|
-
|
77
|
+
##
|
78
|
+
# Returns the filename of the file located at `url`.
|
79
|
+
#
|
80
|
+
# @param [String] url
|
81
|
+
# @return [String]
|
82
|
+
#
|
83
|
+
def filename_from_url(url)
|
84
|
+
headers = get_headers(url)
|
85
|
+
|
86
|
+
unless headers['Content-Disposition']
|
87
|
+
raise "The URL #{url.inspect} did not return a Content-Disposition " \
|
88
|
+
"header. This header is required to figure out the filename"
|
38
89
|
end
|
39
90
|
|
40
|
-
|
41
|
-
filename = get_filename_from_url(url)
|
42
|
-
destination = File.expand_path(filename, path)
|
43
|
-
`wget -N -P #{path} #{url}`
|
44
|
-
return destination
|
45
|
-
end
|
91
|
+
matches = headers['Content-Disposition'].match(/filename=(.+)/)
|
46
92
|
|
47
|
-
|
48
|
-
|
49
|
-
full_filename = Dir.glob("#{file}*").first
|
50
|
-
puts "Extracting full_filename"
|
51
|
-
if extname == ".zip"
|
52
|
-
puts `unzip -o #{full_filename} -d #{path}`
|
53
|
-
else
|
54
|
-
puts `tar -zxvf #{full_filename} --directory #{path}`
|
55
|
-
end
|
93
|
+
if !matches or !matches[1]
|
94
|
+
raise 'No filename could be found in the Content-Disposition header'
|
56
95
|
end
|
57
96
|
|
58
|
-
|
59
|
-
URI.parse(url).path[1..-1].split("/").last
|
60
|
-
end
|
97
|
+
return matches[1]
|
61
98
|
end
|
62
99
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
100
|
+
##
|
101
|
+
# Creates the path. This method mainly exists to make testing a bit
|
102
|
+
# easier.
|
103
|
+
#
|
104
|
+
# @param [String] path
|
105
|
+
#
|
106
|
+
def create_directory(path)
|
107
|
+
FileUtils.mkdir_p(path)
|
108
|
+
end
|
70
109
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
110
|
+
##
|
111
|
+
# Removes the given file, mainly exists to make testing easier.
|
112
|
+
#
|
113
|
+
# @param [String] path
|
114
|
+
#
|
115
|
+
def remove_file(path)
|
116
|
+
File.unlink(path)
|
117
|
+
end
|
76
118
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
119
|
+
##
|
120
|
+
# @param [String] url
|
121
|
+
# @return [Hash]
|
122
|
+
#
|
123
|
+
def get_headers(url)
|
124
|
+
return http.head(url).headers
|
82
125
|
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
126
|
+
end # ResourceSwitcher
|
127
|
+
end # Core
|
128
|
+
end # Opener
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Opener
|
2
|
+
module Core
|
3
|
+
##
|
4
|
+
# Wrapper around `Syslog` that makes it easier to disable loggers and to log
|
5
|
+
# custom key/value pairs in message.
|
6
|
+
#
|
7
|
+
module Syslog
|
8
|
+
##
|
9
|
+
# Returns `true` if Syslog should be enabled.
|
10
|
+
#
|
11
|
+
# @return [TrueClass|FalseClass]
|
12
|
+
#
|
13
|
+
def self.enabled?
|
14
|
+
return !!ENV['ENABLE_SYSLOG']
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Configures Syslog.
|
19
|
+
#
|
20
|
+
# @see [Syslog.open]
|
21
|
+
# @param [String] name The name of the program.
|
22
|
+
# @param [Fixnum] facility
|
23
|
+
#
|
24
|
+
def self.open(name, facility = nil)
|
25
|
+
::Syslog.open(name, facility) if enabled?
|
26
|
+
end
|
27
|
+
|
28
|
+
# methods defined using define_method() are slower than those defined
|
29
|
+
# using eval() on JRuby and Rubinius.
|
30
|
+
[:debug, :err, :fatal, :info, :warn, :unknown].each do |method|
|
31
|
+
eval <<-EOF, nil, __FILE__, __LINE__ + 1
|
32
|
+
def self.#{method}(message, meta = {})
|
33
|
+
add(:#{method}, message, meta)
|
34
|
+
end
|
35
|
+
EOF
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Adds a new log message.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# add(:info, 'Testing Syslog', :user_id => 19)
|
43
|
+
#
|
44
|
+
# @param [Symbol] type The type of log message to add, corresponds to the
|
45
|
+
# logger method that will be called.
|
46
|
+
#
|
47
|
+
# @param [String] message The message to log.
|
48
|
+
# @param [Hash] meta Extra meta data to log.
|
49
|
+
#
|
50
|
+
def self.add(type, message, meta = {})
|
51
|
+
return unless enabled?
|
52
|
+
|
53
|
+
pairs = make_pairs(meta)
|
54
|
+
|
55
|
+
::Syslog.send(type, "#{pairs} #{message}".strip)
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# @param [Hash] meta
|
60
|
+
# @return [String]
|
61
|
+
#
|
62
|
+
def self.make_pairs(meta)
|
63
|
+
return meta.map { |(key, value)| "#{key}=#{value.inspect}" }.join(' ')
|
64
|
+
end
|
65
|
+
end # Syslog
|
66
|
+
end # Core
|
67
|
+
end # Opener
|
data/lib/opener/core/version.rb
CHANGED
data/opener-core.gemspec
CHANGED
@@ -7,17 +7,20 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.summary = 'Gem that contains some low level generic functions for all OpeNER components.'
|
8
8
|
spec.description = spec.summary
|
9
9
|
spec.homepage = 'http://opener-project.github.com'
|
10
|
-
spec.license = '
|
10
|
+
spec.license = 'Apache 2.0'
|
11
11
|
|
12
12
|
spec.files = Dir.glob([
|
13
13
|
'lib/**/*',
|
14
14
|
'*.gemspec',
|
15
|
-
'README.md'
|
15
|
+
'README.md',
|
16
|
+
'LICENSE.txt'
|
16
17
|
]).select { |file| File.file?(file) }
|
17
18
|
|
18
19
|
spec.executables = Dir.glob('bin/*').map { |file| File.basename(file) }
|
19
20
|
|
20
|
-
spec.add_dependency '
|
21
|
+
spec.add_dependency 'slop', '~> 3.0'
|
22
|
+
spec.add_dependency 'httpclient'
|
23
|
+
spec.add_dependency 'archive'
|
21
24
|
|
22
25
|
spec.add_development_dependency 'bundler'
|
23
26
|
spec.add_development_dependency 'rake'
|
metadata
CHANGED
@@ -1,109 +1,136 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opener-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- development@olery.com
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: slop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
15
22
|
version_requirements: !ruby/object:Gem::Requirement
|
16
23
|
requirements:
|
17
|
-
- -
|
24
|
+
- - "~>"
|
18
25
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: httpclient
|
20
29
|
requirement: !ruby/object:Gem::Requirement
|
21
30
|
requirements:
|
22
|
-
- -
|
31
|
+
- - ">="
|
23
32
|
- !ruby/object:Gem::Version
|
24
33
|
version: '0'
|
25
|
-
prerelease: false
|
26
34
|
type: :runtime
|
27
|
-
|
28
|
-
name: bundler
|
35
|
+
prerelease: false
|
29
36
|
version_requirements: !ruby/object:Gem::Requirement
|
30
37
|
requirements:
|
31
|
-
- -
|
38
|
+
- - ">="
|
32
39
|
- !ruby/object:Gem::Version
|
33
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: archive
|
34
43
|
requirement: !ruby/object:Gem::Requirement
|
35
44
|
requirements:
|
36
|
-
- -
|
45
|
+
- - ">="
|
37
46
|
- !ruby/object:Gem::Version
|
38
47
|
version: '0'
|
48
|
+
type: :runtime
|
39
49
|
prerelease: false
|
40
|
-
type: :development
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
43
50
|
version_requirements: !ruby/object:Gem::Requirement
|
44
51
|
requirements:
|
45
|
-
- -
|
52
|
+
- - ">="
|
46
53
|
- !ruby/object:Gem::Version
|
47
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
48
57
|
requirement: !ruby/object:Gem::Requirement
|
49
58
|
requirements:
|
50
|
-
- -
|
59
|
+
- - ">="
|
51
60
|
- !ruby/object:Gem::Version
|
52
61
|
version: '0'
|
53
|
-
prerelease: false
|
54
62
|
type: :development
|
55
|
-
|
56
|
-
name: rspec
|
63
|
+
prerelease: false
|
57
64
|
version_requirements: !ruby/object:Gem::Requirement
|
58
65
|
requirements:
|
59
|
-
- -
|
66
|
+
- - ">="
|
60
67
|
- !ruby/object:Gem::Version
|
61
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
62
71
|
requirement: !ruby/object:Gem::Requirement
|
63
72
|
requirements:
|
64
|
-
- -
|
73
|
+
- - ">="
|
65
74
|
- !ruby/object:Gem::Version
|
66
75
|
version: '0'
|
76
|
+
type: :development
|
67
77
|
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
68
90
|
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
69
97
|
description: Gem that contains some low level generic functions for all OpeNER components.
|
70
|
-
email:
|
98
|
+
email:
|
71
99
|
executables: []
|
72
100
|
extensions: []
|
73
101
|
extra_rdoc_files: []
|
74
102
|
files:
|
103
|
+
- LICENSE.txt
|
75
104
|
- README.md
|
76
105
|
- lib/opener/core.rb
|
77
|
-
- lib/opener/core/argv_splitter.rb
|
78
|
-
- lib/opener/core/benchmark.rb
|
79
|
-
- lib/opener/core/error_layer.rb
|
80
|
-
- lib/opener/core/memory_usage.rb
|
81
106
|
- lib/opener/core/opt_parser.rb
|
82
107
|
- lib/opener/core/resource_switcher.rb
|
108
|
+
- lib/opener/core/syslog.rb
|
83
109
|
- lib/opener/core/version.rb
|
84
110
|
- opener-core.gemspec
|
85
111
|
homepage: http://opener-project.github.com
|
86
112
|
licenses:
|
87
|
-
-
|
113
|
+
- Apache 2.0
|
88
114
|
metadata: {}
|
89
|
-
post_install_message:
|
115
|
+
post_install_message:
|
90
116
|
rdoc_options: []
|
91
117
|
require_paths:
|
92
118
|
- lib
|
93
119
|
required_ruby_version: !ruby/object:Gem::Requirement
|
94
120
|
requirements:
|
95
|
-
- -
|
121
|
+
- - ">="
|
96
122
|
- !ruby/object:Gem::Version
|
97
123
|
version: '0'
|
98
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
125
|
requirements:
|
100
|
-
- -
|
126
|
+
- - ">="
|
101
127
|
- !ruby/object:Gem::Version
|
102
128
|
version: '0'
|
103
129
|
requirements: []
|
104
|
-
rubyforge_project:
|
130
|
+
rubyforge_project:
|
105
131
|
rubygems_version: 2.2.2
|
106
|
-
signing_key:
|
132
|
+
signing_key:
|
107
133
|
specification_version: 4
|
108
134
|
summary: Gem that contains some low level generic functions for all OpeNER components.
|
109
135
|
test_files: []
|
136
|
+
has_rdoc:
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Opener
|
2
|
-
module Core
|
3
|
-
class ArgvSplitter
|
4
|
-
|
5
|
-
def self.split(args, char="--")
|
6
|
-
if index = args.index(char)
|
7
|
-
first = args[0..index-1]
|
8
|
-
second = args[index+1..-1]
|
9
|
-
else
|
10
|
-
first = args
|
11
|
-
second = []
|
12
|
-
end
|
13
|
-
|
14
|
-
[first,second]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
@@ -1,137 +0,0 @@
|
|
1
|
-
module Opener
|
2
|
-
module Core
|
3
|
-
##
|
4
|
-
# Class for measuring and adding benchmarking information to KAF documents.
|
5
|
-
#
|
6
|
-
# Basic usage is as following:
|
7
|
-
#
|
8
|
-
# benchmark = Opener::Core::Benchmark.new('opener-property-tagger')
|
9
|
-
# document = nil
|
10
|
-
# results = benchmark.measure do
|
11
|
-
# document = some_stuff_that_emits_kaf
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# # Add the data to the document. This method returns the new XML as a
|
15
|
-
# # String.
|
16
|
-
# xml = benchmark.write(document, results)
|
17
|
-
#
|
18
|
-
# ## Metrics
|
19
|
-
#
|
20
|
-
# The following metrics are gathered:
|
21
|
-
#
|
22
|
-
# * Starting memory usage
|
23
|
-
# * End memory usage
|
24
|
-
# * Memory increase (if any)
|
25
|
-
# * CPU system time
|
26
|
-
# * CPU user time
|
27
|
-
# * Real time
|
28
|
-
# * Total time
|
29
|
-
#
|
30
|
-
# @!attribute [r] name
|
31
|
-
# @return [String]
|
32
|
-
#
|
33
|
-
# @!attribute [r] results
|
34
|
-
# @return [Hash]
|
35
|
-
#
|
36
|
-
class Benchmark
|
37
|
-
attr_reader :name
|
38
|
-
|
39
|
-
##
|
40
|
-
# @param [String] name The name of the benchmark.
|
41
|
-
#
|
42
|
-
def initialize(name)
|
43
|
-
@name = name
|
44
|
-
end
|
45
|
-
|
46
|
-
##
|
47
|
-
# Measures the block and returns the results as a Hash.
|
48
|
-
#
|
49
|
-
# @example
|
50
|
-
# measure do
|
51
|
-
# sleep(5)
|
52
|
-
# end
|
53
|
-
#
|
54
|
-
# @return [Hash]
|
55
|
-
#
|
56
|
-
def measure
|
57
|
-
mem_usage = MemoryUsage.new
|
58
|
-
mem_start = mem_usage.usage
|
59
|
-
timings = ::Benchmark.measure do
|
60
|
-
yield
|
61
|
-
end
|
62
|
-
|
63
|
-
mem_end = mem_usage.usage
|
64
|
-
|
65
|
-
return {
|
66
|
-
:memory_start => mem_start,
|
67
|
-
:memory_end => mem_end,
|
68
|
-
:memory_increase => mem_end - mem_start,
|
69
|
-
:time_cpu_system => timings.stime,
|
70
|
-
:time_cpu_user => timings.utime,
|
71
|
-
:time_real => timings.real,
|
72
|
-
:time_total => timings.total
|
73
|
-
}
|
74
|
-
end
|
75
|
-
|
76
|
-
##
|
77
|
-
# Writes benchmarking results to the specified document.
|
78
|
-
#
|
79
|
-
# @param [String] xml The XML document.
|
80
|
-
# @param [Hash] results The benchmarking results to write.
|
81
|
-
# @return [String]
|
82
|
-
#
|
83
|
-
def write(xml, results)
|
84
|
-
document = Nokogiri::XML(xml)
|
85
|
-
root = document.at('KAF')
|
86
|
-
benchmarks = root.at('benchmarks')
|
87
|
-
|
88
|
-
unless benchmarks
|
89
|
-
benchmarks = Nokogiri::XML::Node.new('benchmarks', document)
|
90
|
-
|
91
|
-
root.add_child(benchmarks)
|
92
|
-
end
|
93
|
-
|
94
|
-
benchmark = create_benchmark_node(document)
|
95
|
-
|
96
|
-
results.each do |name, val|
|
97
|
-
benchmark.add_child(create_node(name, val, document))
|
98
|
-
end
|
99
|
-
|
100
|
-
benchmarks.add_child(benchmark)
|
101
|
-
|
102
|
-
return document.to_xml(
|
103
|
-
:indent => 2,
|
104
|
-
:encoding => document.encoding || 'UTF-8'
|
105
|
-
)
|
106
|
-
end
|
107
|
-
|
108
|
-
private
|
109
|
-
|
110
|
-
##
|
111
|
-
# @param [Nokogiri::XML::Document] document
|
112
|
-
# @return [Nokogiri::XML::Node]
|
113
|
-
#
|
114
|
-
def create_benchmark_node(document)
|
115
|
-
node = Nokogiri::XML::Node.new('benchmark', document)
|
116
|
-
|
117
|
-
node.set_attribute('name', name)
|
118
|
-
|
119
|
-
return node
|
120
|
-
end
|
121
|
-
|
122
|
-
##
|
123
|
-
# @param [String|Symbol] name
|
124
|
-
# @param [Mixed] text
|
125
|
-
# @param [Nokogiri::XML::Document] document
|
126
|
-
# @return [Nokogiri::XML::Node]
|
127
|
-
#
|
128
|
-
def create_node(name, text, document)
|
129
|
-
node = Nokogiri::XML::Node.new(name.to_s, document)
|
130
|
-
|
131
|
-
node.inner_html = text.to_s
|
132
|
-
|
133
|
-
return node
|
134
|
-
end
|
135
|
-
end # Benchmark
|
136
|
-
end # Core
|
137
|
-
end # Opener
|
@@ -1,89 +0,0 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
|
3
|
-
module Opener
|
4
|
-
module Core
|
5
|
-
##
|
6
|
-
# Add Error Layer to KAF file instead of throwing an error.
|
7
|
-
#
|
8
|
-
class ErrorLayer
|
9
|
-
attr_accessor :input, :document, :error, :klass
|
10
|
-
|
11
|
-
def initialize(input, error, klass)
|
12
|
-
@input = input.to_s
|
13
|
-
# Make sure there is always a document, even if it is empty.
|
14
|
-
@document = Nokogiri::XML(input) rescue Nokogiri::XML(nil)
|
15
|
-
@error = error
|
16
|
-
@klass = klass
|
17
|
-
end
|
18
|
-
|
19
|
-
def add
|
20
|
-
if is_xml?
|
21
|
-
unless has_errors_layer?
|
22
|
-
add_errors_layer
|
23
|
-
end
|
24
|
-
else
|
25
|
-
add_root
|
26
|
-
add_text
|
27
|
-
add_errors_layer
|
28
|
-
end
|
29
|
-
add_error
|
30
|
-
|
31
|
-
xml = !!document.encoding ? document.to_xml : document.to_xml(:encoding => "UTF-8")
|
32
|
-
|
33
|
-
return xml
|
34
|
-
end
|
35
|
-
|
36
|
-
##
|
37
|
-
# Check if the document is a valid XML file.
|
38
|
-
#
|
39
|
-
def is_xml?
|
40
|
-
!!document.root
|
41
|
-
end
|
42
|
-
|
43
|
-
##
|
44
|
-
# Add root element to the XML file.
|
45
|
-
#
|
46
|
-
def add_root
|
47
|
-
root = Nokogiri::XML::Node.new "KAF", document
|
48
|
-
document.add_child(root)
|
49
|
-
end
|
50
|
-
|
51
|
-
##
|
52
|
-
# Check if the document already has an errors layer.
|
53
|
-
#
|
54
|
-
def has_errors_layer?
|
55
|
-
!!document.at('errors')
|
56
|
-
end
|
57
|
-
|
58
|
-
##
|
59
|
-
# Add errors element to the XML file.
|
60
|
-
#
|
61
|
-
def add_errors_layer
|
62
|
-
node = Nokogiri::XML::Node.new "errors", document
|
63
|
-
document.root.add_child(node)
|
64
|
-
end
|
65
|
-
|
66
|
-
##
|
67
|
-
# Add the text file incase it is not a valid XML document. More
|
68
|
-
# info for debugging.
|
69
|
-
#
|
70
|
-
def add_text
|
71
|
-
node = Nokogiri::XML::Node.new "raw", document
|
72
|
-
node.inner_html = input
|
73
|
-
document.root.add_child(node)
|
74
|
-
end
|
75
|
-
|
76
|
-
##
|
77
|
-
# Add the actual error to the errors layer.
|
78
|
-
#
|
79
|
-
def add_error
|
80
|
-
node = document.at('errors')
|
81
|
-
error_node = Nokogiri::XML::Node.new "error", node
|
82
|
-
error_node['class'] = klass.to_s
|
83
|
-
error_node['version'] = klass::VERSION
|
84
|
-
error_node.inner_html = error
|
85
|
-
node.add_child(error_node)
|
86
|
-
end
|
87
|
-
end # ErrorLayer
|
88
|
-
end # Core
|
89
|
-
end # Opener
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module Opener
|
2
|
-
module Core
|
3
|
-
##
|
4
|
-
# Class for returning the memory usage of the current process. This uses
|
5
|
-
# the `/proc` filesystem if available and falls back to `ps`.
|
6
|
-
#
|
7
|
-
class MemoryUsage
|
8
|
-
##
|
9
|
-
# Returns the RSS (aka total memory) in bytes.
|
10
|
-
#
|
11
|
-
# @return [Fixnum]
|
12
|
-
#
|
13
|
-
def usage
|
14
|
-
return has_proc? ? rss_proc : rss_ps
|
15
|
-
end
|
16
|
-
|
17
|
-
##
|
18
|
-
# @return [TrueClass|FalseClass]
|
19
|
-
#
|
20
|
-
def has_proc?
|
21
|
-
return File.exists?('/proc')
|
22
|
-
end
|
23
|
-
|
24
|
-
##
|
25
|
-
# Returns the RSS using the `/proc` filesystem.
|
26
|
-
#
|
27
|
-
# @return [Fixnum]
|
28
|
-
#
|
29
|
-
def rss_proc
|
30
|
-
kb = File.read('/proc/self/status').match(/VmRSS:\s+(\d+)/)[1].to_i
|
31
|
-
|
32
|
-
return kb * 1024
|
33
|
-
end
|
34
|
-
|
35
|
-
##
|
36
|
-
# Returns the RSS using the `ps` command.
|
37
|
-
#
|
38
|
-
# @return [Fixnum]
|
39
|
-
#
|
40
|
-
def rss_ps
|
41
|
-
kb = `ps -o rss= #{Process.pid}`.strip.to_i
|
42
|
-
|
43
|
-
return kb * 1024
|
44
|
-
end
|
45
|
-
end # MemoryUsage
|
46
|
-
end # Core
|
47
|
-
end # Opener
|