opener-core 1.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|