thinp_xml 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.rspec +2 -0
- data/bin/cache_xml +125 -0
- data/bin/thinp_xml +5 -8
- data/features/cache_create.feature +65 -0
- data/features/cache_usage.feature +17 -0
- data/features/step_definitions/thinp_xml.rb +4 -0
- data/features/{create.feature → thinp_create.feature} +0 -0
- data/features/{usage.feature → thinp_usage.feature} +0 -0
- data/lib/thinp_xml/cache/builder.rb +92 -0
- data/lib/thinp_xml/cache/emit.rb +43 -0
- data/lib/thinp_xml/cache/metadata.rb +22 -0
- data/lib/thinp_xml/cache/parse.rb +53 -0
- data/lib/thinp_xml/cache_xml.rb +5 -0
- data/lib/thinp_xml/distribution.rb +25 -3
- data/lib/thinp_xml/emitter.rb +40 -0
- data/lib/thinp_xml/listener.rb +51 -0
- data/lib/thinp_xml/{analysis.rb → thinp/analysis.rb} +0 -0
- data/lib/thinp_xml/{builder.rb → thinp/builder.rb} +1 -1
- data/lib/thinp_xml/thinp/emit.rb +48 -0
- data/lib/thinp_xml/{metadata.rb → thinp/metadata.rb} +0 -0
- data/lib/thinp_xml/{parse.rb → thinp/parse.rb} +7 -33
- data/lib/thinp_xml/{utils.rb → thinp/utils.rb} +1 -1
- data/lib/thinp_xml/{xml_format.rb → thinp/xml_format.rb} +0 -0
- data/lib/thinp_xml/version.rb +1 -1
- data/lib/thinp_xml.rb +5 -5
- data/spec/builder_spec.rb +1 -1
- data/spec/cache_builder_spec.rb +240 -0
- data/spec/distribution_spec.rb +87 -1
- metadata +29 -13
- data/lib/thinp_xml/emit.rb +0 -69
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZTdjOGQ5NDUyYzJiYzY2MzExMjU4MzhjNWZkMjg5MzcyOTVlZDU1ZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ODNkZmU4YzE2OTQxZThjYmFlZjkxZTZjOTdkMTBhOWYyOTgwNmY0Mw==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZWI5OWZjNTEzZjUyYzQ5YzM1YTViYmIxMzcyMjZjYTg1ZDU4MzYyNjc3MzI4
|
10
|
+
NTAwNDU4ZjYzMGNhOGU2Njg0MWYzZjQxZWU1OWUyYjhmZTBkYWY4YzBjMjNh
|
11
|
+
ODJmNzAxMmYyOWY4ZDVjYTEwMTZkMGU5NGJkMWIzY2U0ZGE1MGM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTNlOGY3NDU4MWYzYWY3YjViNjJkYjE5ZTNiMmM2Y2NkZmM5NGYwMTdhZjRj
|
14
|
+
NzdjMTI1NjM1NWU1ZDI3ODU3ZjkxZGYzZGUyN2RlMjMwNmM3YTg4Mjg3NWQ4
|
15
|
+
NDBkYWZlMjA5NmU3MmFhOGE3Nzk2NzZlNGM0YTljOTZjNTgwMzc=
|
data/.rspec
ADDED
data/bin/cache_xml
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'thinp_xml/cache_xml'
|
4
|
+
require 'thinp_xml/distribution'
|
5
|
+
require 'ejt_command_line'
|
6
|
+
|
7
|
+
include ThinpXML
|
8
|
+
|
9
|
+
#----------------------------------------------------------------
|
10
|
+
|
11
|
+
CacheCommandLine = CommandLine::Parser.new do
|
12
|
+
value_type :string do |str|
|
13
|
+
str
|
14
|
+
end
|
15
|
+
|
16
|
+
value_type :int do |str|
|
17
|
+
Integer(str)
|
18
|
+
end
|
19
|
+
|
20
|
+
value_type :distribution do |str|
|
21
|
+
parse_distribution(str)
|
22
|
+
end
|
23
|
+
|
24
|
+
value_type :layout do |str|
|
25
|
+
case str
|
26
|
+
when 'random'
|
27
|
+
:random
|
28
|
+
|
29
|
+
when 'linear'
|
30
|
+
:linear
|
31
|
+
|
32
|
+
else
|
33
|
+
raise "unknown mapping layout '#{str}'"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
value_type :percentage do |str|
|
38
|
+
i = Integer(str)
|
39
|
+
raise "invalid percentage value (#{i})" if i < 0 || i > 100
|
40
|
+
i
|
41
|
+
end
|
42
|
+
|
43
|
+
simple_switch :help, '--help', '-h'
|
44
|
+
value_switch :uuid, :string, '--uuid'
|
45
|
+
value_switch :block_size, :int, '--block-size'
|
46
|
+
value_switch :nr_cache_blocks, :distribution, '--nr-cache-blocks'
|
47
|
+
value_switch :nr_mappings, :distribution, '--nr-mappings'
|
48
|
+
value_switch :mapping_policy, :layout, '--layout'
|
49
|
+
value_switch :dirty_percentage, :percentage, '--dirty-percent'
|
50
|
+
|
51
|
+
global do
|
52
|
+
switches :help
|
53
|
+
end
|
54
|
+
|
55
|
+
command :create do
|
56
|
+
switches :nr_cache_blocks, :uuid, :block_size, :nr_mappings, :mapping_policy, :dirty_percentage
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
#--------------------------------
|
61
|
+
|
62
|
+
class Dispatcher
|
63
|
+
include CacheXML
|
64
|
+
|
65
|
+
def global_command(opts, args)
|
66
|
+
if args.size > 0
|
67
|
+
die "unknown command '#{args[0]}'"
|
68
|
+
else
|
69
|
+
if opts[:help]
|
70
|
+
help(STDOUT)
|
71
|
+
else
|
72
|
+
die "no command given"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def create(opts, args)
|
78
|
+
b = Builder.new
|
79
|
+
b.uuid = opts.fetch(:uuid, '')
|
80
|
+
b.nr_cache_blocks = opts.fetch(:nr_cache_blocks, 0).to_i
|
81
|
+
b.block_size = opts.fetch(:block_size, 128)
|
82
|
+
b.nr_mappings = opts.fetch(:nr_mappings, 0)
|
83
|
+
b.mapping_policy = opts.fetch(:mapping_policy, :random)
|
84
|
+
b.dirty_percentage = opts.fetch(:dirty_percentage, 0)
|
85
|
+
md = b.generate
|
86
|
+
write_xml(md, STDOUT)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
def die(msg)
|
91
|
+
STDERR.puts msg
|
92
|
+
exit(1)
|
93
|
+
end
|
94
|
+
|
95
|
+
def help(out)
|
96
|
+
out.write <<EOF
|
97
|
+
Manipulation of cache xml format metadata
|
98
|
+
--help, -h: Show this message
|
99
|
+
EOF
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def parse_command_line(dispatcher, *args)
|
104
|
+
CacheCommandLine.parse(dispatcher, *args)
|
105
|
+
end
|
106
|
+
|
107
|
+
def top_level_handler(&block)
|
108
|
+
begin
|
109
|
+
block.call
|
110
|
+
rescue => e
|
111
|
+
STDERR.puts e.message
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
|
115
|
+
exit 0
|
116
|
+
end
|
117
|
+
|
118
|
+
#----------------------------------------------------------------
|
119
|
+
|
120
|
+
top_level_handler do
|
121
|
+
dispatcher = Dispatcher.new
|
122
|
+
parse_command_line(dispatcher, *ARGV)
|
123
|
+
end
|
124
|
+
|
125
|
+
#----------------------------------------------------------------
|
data/bin/thinp_xml
CHANGED
@@ -4,6 +4,8 @@ require 'thinp_xml'
|
|
4
4
|
require 'thinp_xml/distribution'
|
5
5
|
require 'ejt_command_line'
|
6
6
|
|
7
|
+
include ThinpXML
|
8
|
+
|
7
9
|
#----------------------------------------------------------------
|
8
10
|
|
9
11
|
XMLCommandLine = CommandLine::Parser.new do
|
@@ -15,15 +17,8 @@ XMLCommandLine = CommandLine::Parser.new do
|
|
15
17
|
Integer(str)
|
16
18
|
end
|
17
19
|
|
18
|
-
UNIFORM_REGEX = /uniform\[(\d+)..(\d+)\]/
|
19
|
-
|
20
20
|
value_type :int_distribution do |str|
|
21
|
-
|
22
|
-
if m
|
23
|
-
ThinpXML::UniformDistribution.new(m[1].to_i, m[2].to_i + 1)
|
24
|
-
else
|
25
|
-
Integer(str)
|
26
|
-
end
|
21
|
+
parse_distribution(str)
|
27
22
|
end
|
28
23
|
|
29
24
|
simple_switch :help, '--help', '-h'
|
@@ -41,6 +36,8 @@ XMLCommandLine = CommandLine::Parser.new do
|
|
41
36
|
end
|
42
37
|
end
|
43
38
|
|
39
|
+
#--------------------------------
|
40
|
+
|
44
41
|
class Dispatcher
|
45
42
|
include ThinpXML
|
46
43
|
|
@@ -0,0 +1,65 @@
|
|
1
|
+
Feature: I can create new metadata
|
2
|
+
|
3
|
+
Scenario: Create a valid superblock with no mappings
|
4
|
+
When I cache_xml create
|
5
|
+
Then the stdout should contain:
|
6
|
+
"""
|
7
|
+
<superblock uuid="" block_size="128" nr_cache_blocks="0">
|
8
|
+
</superblock>
|
9
|
+
"""
|
10
|
+
|
11
|
+
Scenario: Create a valid superblock with specified uuid
|
12
|
+
When I cache_xml create --uuid 'one two three'
|
13
|
+
Then the stdout should contain:
|
14
|
+
"""
|
15
|
+
<superblock uuid="one two three" block_size="128" nr_cache_blocks="0">
|
16
|
+
</superblock>
|
17
|
+
"""
|
18
|
+
|
19
|
+
Scenario: Create a valid superblock with specified block size
|
20
|
+
When I cache_xml create --block-size 512
|
21
|
+
Then the stdout should contain:
|
22
|
+
"""
|
23
|
+
<superblock uuid="" block_size="512" nr_cache_blocks="0">
|
24
|
+
</superblock>
|
25
|
+
"""
|
26
|
+
|
27
|
+
Scenario: Take an integer for the number of cached blocks
|
28
|
+
When I cache_xml create --nr-cache-blocks 345
|
29
|
+
Then the stdout should contain:
|
30
|
+
"""
|
31
|
+
<superblock uuid="" block_size="128" nr_cache_blocks="345">
|
32
|
+
</superblock>
|
33
|
+
"""
|
34
|
+
|
35
|
+
Scenario: Take a uniform distribution for the number of cached blocks
|
36
|
+
When I cache_xml create --nr-cache-blocks uniform[123..124]
|
37
|
+
Then the stdout should contain:
|
38
|
+
"""
|
39
|
+
<superblock uuid="" block_size="128" nr_cache_blocks="123">
|
40
|
+
</superblock>
|
41
|
+
"""
|
42
|
+
|
43
|
+
Scenario: Take an integer for the number of mappings
|
44
|
+
When I cache_xml create --nr-cache-blocks 3 --nr-mappings 3 --layout linear
|
45
|
+
Then the stdout should contain:
|
46
|
+
"""
|
47
|
+
<superblock uuid="" block_size="128" nr_cache_blocks="3">
|
48
|
+
<mapping cache_block="0" origin_block="0" dirty="false"/>
|
49
|
+
<mapping cache_block="1" origin_block="1" dirty="false"/>
|
50
|
+
<mapping cache_block="2" origin_block="2" dirty="false"/>
|
51
|
+
</superblock>
|
52
|
+
"""
|
53
|
+
|
54
|
+
Scenario: Take a percentage for the number of dirty mappings
|
55
|
+
When I cache_xml create --nr-cache-blocks 3 --nr-mappings 3 --layout linear --dirty-percent 100
|
56
|
+
Then the stdout should contain:
|
57
|
+
"""
|
58
|
+
<superblock uuid="" block_size="128" nr_cache_blocks="3">
|
59
|
+
<mapping cache_block="0" origin_block="0" dirty="true"/>
|
60
|
+
<mapping cache_block="1" origin_block="1" dirty="true"/>
|
61
|
+
<mapping cache_block="2" origin_block="2" dirty="true"/>
|
62
|
+
</superblock>
|
63
|
+
"""
|
64
|
+
|
65
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Feature: The tool should be helpful
|
2
|
+
|
3
|
+
Scenario: --help prints usage to stdout
|
4
|
+
When I cache_xml --help
|
5
|
+
Then the stdout should contain:
|
6
|
+
"""
|
7
|
+
Manipulation of cache xml format metadata
|
8
|
+
--help, -h: Show this message
|
9
|
+
"""
|
10
|
+
|
11
|
+
Scenario: Unknown sub commands cause fail
|
12
|
+
When I cache_xml unleashtheearwigs
|
13
|
+
Then it should fail
|
14
|
+
And the stderr should contain:
|
15
|
+
"""
|
16
|
+
unknown command 'unleashtheearwigs'
|
17
|
+
"""
|
File without changes
|
File without changes
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'thinp_xml/cache/metadata'
|
2
|
+
|
3
|
+
#----------------------------------------------------------------
|
4
|
+
|
5
|
+
module CacheXML
|
6
|
+
class Builder
|
7
|
+
attr_accessor :uuid, :block_size, :nr_cache_blocks, :policy_name
|
8
|
+
attr_reader :mapping_policy, :nr_mappings, :dirty_percentage
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@uuid = ''
|
12
|
+
@block_size = 128
|
13
|
+
@nr_cache_blocks = 0
|
14
|
+
@policy_name = 'mq'
|
15
|
+
@mapping_policy = :random
|
16
|
+
@nr_mappings = 0
|
17
|
+
@dirty_percentage = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate
|
21
|
+
superblock = Superblock.new(@uuid, @block_size.to_i, @nr_cache_blocks.to_i, @policy_name)
|
22
|
+
mappings = []
|
23
|
+
|
24
|
+
case @mapping_policy
|
25
|
+
when :linear
|
26
|
+
cb = 0
|
27
|
+
ob = safe_rand(@nr_cache_blocks - @nr_mappings)
|
28
|
+
|
29
|
+
@nr_mappings.times do
|
30
|
+
dirty = safe_rand(100) < @dirty_percentage
|
31
|
+
mappings << Mapping.new(cb, ob, dirty)
|
32
|
+
cb += 1
|
33
|
+
ob += 1
|
34
|
+
end
|
35
|
+
|
36
|
+
when :random
|
37
|
+
origin_blocks = []
|
38
|
+
|
39
|
+
ob = 0
|
40
|
+
@nr_mappings.times do
|
41
|
+
origin_blocks << ob
|
42
|
+
ob += 1
|
43
|
+
end
|
44
|
+
|
45
|
+
0.upto(@nr_mappings - 1) do |n|
|
46
|
+
tmp = origin_blocks[n]
|
47
|
+
|
48
|
+
index = n + rand(@nr_mappings - n)
|
49
|
+
origin_blocks[n] = origin_blocks[index]
|
50
|
+
origin_blocks[index] = tmp
|
51
|
+
|
52
|
+
dirty = safe_rand(100) < @dirty_percentage
|
53
|
+
mappings << Mapping.new(n, origin_blocks[n], dirty)
|
54
|
+
end
|
55
|
+
|
56
|
+
else
|
57
|
+
raise "unknown mapping policy"
|
58
|
+
end
|
59
|
+
|
60
|
+
hints = []
|
61
|
+
|
62
|
+
Metadata.new(superblock, mappings, hints)
|
63
|
+
end
|
64
|
+
|
65
|
+
def mapping_policy=(sym)
|
66
|
+
raise "mapping policy must be :random or :linear" unless valid_policy(sym)
|
67
|
+
@mapping_policy = sym
|
68
|
+
end
|
69
|
+
|
70
|
+
def nr_mappings=(n)
|
71
|
+
n = n.to_i
|
72
|
+
#raise "nr_mappings must not exceed nr_cache_blocks" if n > @nr_cache_blocks
|
73
|
+
@nr_mappings = n
|
74
|
+
end
|
75
|
+
|
76
|
+
def dirty_percentage=(n)
|
77
|
+
raise "invalid percentage (#{n})" if n < 0 || n > 100
|
78
|
+
@dirty_percentage = n
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
def valid_policy(sym)
|
83
|
+
[:random, :linear].member?(sym)
|
84
|
+
end
|
85
|
+
|
86
|
+
def safe_rand(n)
|
87
|
+
n == 0 ? 0 : rand(n)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#----------------------------------------------------------------
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'thinp_xml/cache/metadata'
|
2
|
+
require 'thinp_xml/emitter'
|
3
|
+
|
4
|
+
#----------------------------------------------------------------
|
5
|
+
|
6
|
+
module CacheXML
|
7
|
+
module CacheEmitterDetail
|
8
|
+
class CacheEmitter
|
9
|
+
def initialize(out)
|
10
|
+
@e = ThinpXML::Base::Emitter.new(out)
|
11
|
+
end
|
12
|
+
|
13
|
+
def emit_superblock(sb, &block)
|
14
|
+
@e.emit_tag(sb, 'superblock', :uuid, :block_size, :nr_cache_blocks, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def emit_mapping(m)
|
18
|
+
@e.emit_tag(m, 'mapping', :cache_block, :origin_block, :dirty)
|
19
|
+
end
|
20
|
+
|
21
|
+
def emit_hint(h)
|
22
|
+
@e.emit_line("<hint cache_block=\"#{m.cache_block}\" data=\"#{h.encoded_data}\"\>")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#--------------------------------
|
28
|
+
|
29
|
+
def write_xml(metadata, io)
|
30
|
+
e = CacheEmitterDetail::CacheEmitter.new(io)
|
31
|
+
e.emit_superblock(metadata.superblock) do
|
32
|
+
metadata.mappings.each do |m|
|
33
|
+
e.emit_mapping(m)
|
34
|
+
end
|
35
|
+
|
36
|
+
metadata.hints.each do |h|
|
37
|
+
e.emit_hint(h)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#----------------------------------------------------------------
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CacheXML
|
2
|
+
SUPERBLOCK_FIELDS = [[:uuid, :string],
|
3
|
+
[:block_size, :int],
|
4
|
+
[:nr_cache_blocks, :int],
|
5
|
+
[:policy_name, :string]]
|
6
|
+
|
7
|
+
MAPPING_FIELDS = [[:cache_block, :int],
|
8
|
+
[:origin_block, :int],
|
9
|
+
[:dirty, :bool]]
|
10
|
+
|
11
|
+
HINT_FIELDS = [[:cache_block, :int],
|
12
|
+
[:encoded_data, :string]]
|
13
|
+
|
14
|
+
def self.field_names(flds)
|
15
|
+
flds.map {|p| p[0]}
|
16
|
+
end
|
17
|
+
|
18
|
+
Superblock = Struct.new(*field_names(SUPERBLOCK_FIELDS))
|
19
|
+
Mapping = Struct.new(*field_names(MAPPING_FIELDS))
|
20
|
+
Hint = Struct.new(*field_names(HINT_FIELDS))
|
21
|
+
Metadata = Struct.new(:superblock, :mappings, :hints)
|
22
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'thinp_xml/listener'
|
2
|
+
require 'thinp_xml/cache/metadata'
|
3
|
+
|
4
|
+
require 'rexml/document'
|
5
|
+
require 'rexml/streamlistener'
|
6
|
+
|
7
|
+
#----------------------------------------------------------------
|
8
|
+
|
9
|
+
module ThinpXML
|
10
|
+
module CacheParseDetail
|
11
|
+
class Listener
|
12
|
+
include Base::ListenerUtils
|
13
|
+
include REXML::StreamListener
|
14
|
+
|
15
|
+
attr_reader :metadata
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@metadata = Metdadata.new(nil, [], [])
|
19
|
+
end
|
20
|
+
|
21
|
+
def tag_start(tag, args)
|
22
|
+
attr = to_hash(args)
|
23
|
+
|
24
|
+
case tag
|
25
|
+
when 'superblock'
|
26
|
+
@metadata.superblock = Superblock.new(*get_fields(attr, SUPERBLOCK_FIELDS))
|
27
|
+
|
28
|
+
when 'mapping'
|
29
|
+
m = Mapping.new(*get_fields(attr, MAPPING_FIELDS))
|
30
|
+
@metadata.mappings << m
|
31
|
+
|
32
|
+
when 'hint'
|
33
|
+
h = Hint.new(*get_fields(attr, HINT_FIELDS))
|
34
|
+
@metadata.hints << h
|
35
|
+
|
36
|
+
else
|
37
|
+
raise "unhandled tag '#{tag} #{attr.map {|x| x.inspect}.join(' ')}'"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def tag_end(tag)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def read_xml(io)
|
47
|
+
l = CacheParseDetail::Listener.new
|
48
|
+
REXML::Document.parse_stream(io, l)
|
49
|
+
l.metadata
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#----------------------------------------------------------------
|
@@ -7,10 +7,23 @@ module ThinpXML
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
class
|
10
|
+
class ConstDistribution < Distribution
|
11
|
+
def initialize(v)
|
12
|
+
raise "ConstDistribution must be constructed with an integer" if !v.kind_of?(Integer)
|
13
|
+
@v = v
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate
|
17
|
+
@v
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class UniformDistribution < Distribution
|
11
22
|
attr_accessor :start, :stop
|
12
23
|
|
13
24
|
def initialize(start, stop)
|
25
|
+
raise "invalid range [#{start}..#{stop})" unless start < stop
|
26
|
+
|
14
27
|
@start = start
|
15
28
|
@stop = stop
|
16
29
|
end
|
@@ -18,9 +31,18 @@ module ThinpXML
|
|
18
31
|
def generate
|
19
32
|
@start + rand(@stop - @start)
|
20
33
|
end
|
34
|
+
end
|
21
35
|
|
22
|
-
|
23
|
-
|
36
|
+
#--------------------------------
|
37
|
+
|
38
|
+
UNIFORM_REGEX = /uniform\[(\d+)..(\d+)\]/
|
39
|
+
|
40
|
+
def parse_distribution(str)
|
41
|
+
m = UNIFORM_REGEX.match(str)
|
42
|
+
if m
|
43
|
+
ThinpXML::UniformDistribution.new(m[1].to_i, m[2].to_i)
|
44
|
+
else
|
45
|
+
ConstDistribution.new(Integer(str))
|
24
46
|
end
|
25
47
|
end
|
26
48
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#----------------------------------------------------------------
|
2
|
+
|
3
|
+
module ThinpXML
|
4
|
+
module Base
|
5
|
+
class Emitter
|
6
|
+
def initialize(out)
|
7
|
+
@out = out
|
8
|
+
@indent = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def emit_tag(obj, tag, *fields, &block)
|
12
|
+
expanded = fields.map {|fld| "#{fld}=\"#{obj.send(fld)}\""}
|
13
|
+
if block.nil?
|
14
|
+
emit_line "<#{tag} #{expanded.join(' ')}/>"
|
15
|
+
else
|
16
|
+
emit_line "<#{tag} #{expanded.join(' ')}>"
|
17
|
+
push
|
18
|
+
yield unless block.nil?
|
19
|
+
pop
|
20
|
+
emit_line "</#{tag}>"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def emit_line(str)
|
26
|
+
@out.puts((' ' * @indent) + str)
|
27
|
+
end
|
28
|
+
|
29
|
+
def push
|
30
|
+
@indent += 2
|
31
|
+
end
|
32
|
+
|
33
|
+
def pop
|
34
|
+
@indent -= 2
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
#----------------------------------------------------------------
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#----------------------------------------------------------------
|
2
|
+
|
3
|
+
module ThinpXML
|
4
|
+
module Base
|
5
|
+
module ListenerUtils
|
6
|
+
def to_hash(pairs)
|
7
|
+
r = Hash.new
|
8
|
+
pairs.each do |p|
|
9
|
+
r[p[0].intern] = p[1]
|
10
|
+
end
|
11
|
+
r
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_fields(attr, flds)
|
15
|
+
flds.map do |n,t|
|
16
|
+
case t
|
17
|
+
when :int
|
18
|
+
attr[n].to_i
|
19
|
+
|
20
|
+
when :bool
|
21
|
+
case attr[n]
|
22
|
+
when 'true'
|
23
|
+
true
|
24
|
+
when 'false'
|
25
|
+
false
|
26
|
+
else
|
27
|
+
raise "bad boolean value '#{attr[n]}'"
|
28
|
+
end
|
29
|
+
|
30
|
+
when :string
|
31
|
+
attr[n]
|
32
|
+
|
33
|
+
when :object
|
34
|
+
attr[n]
|
35
|
+
|
36
|
+
else
|
37
|
+
raise "unknown field type"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def text(data)
|
43
|
+
return if data =~ /^\w*$/ # ignore whitespace
|
44
|
+
abbrev = data[0..40] + (data.length > 40 ? "..." : "")
|
45
|
+
puts " text : #{abbrev.inspect}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
#----------------------------------------------------------------
|
File without changes
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'thinp_xml/thinp/metadata'
|
2
|
+
require 'thinp_xml/emitter'
|
3
|
+
|
4
|
+
#----------------------------------------------------------------
|
5
|
+
|
6
|
+
module ThinpXML
|
7
|
+
module EmitterDetail
|
8
|
+
class ThinpEmitter
|
9
|
+
def initialize(out)
|
10
|
+
@e = ThinpXML::Base::Emitter.new(out)
|
11
|
+
end
|
12
|
+
|
13
|
+
def emit_superblock(sb, &block)
|
14
|
+
@e.emit_tag(sb, 'superblock', :uuid, :time, :transaction, :data_block_size, :nr_data_blocks, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def emit_device(dev, &block)
|
18
|
+
@e.emit_tag(dev, 'device', :dev_id, :mapped_blocks, :transaction, :creation_time, :snap_time, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def emit_mapping(m)
|
22
|
+
if m.length == 1
|
23
|
+
@e.emit_line("<single_mapping origin_block=\"#{m.origin_begin}\" data_block=\"#{m.data_begin}\" time=\"#{m.time}\"/>")
|
24
|
+
else
|
25
|
+
@e.emit_tag(m, 'range_mapping', :origin_begin, :data_begin, :length, :time)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#--------------------------------
|
32
|
+
|
33
|
+
def write_xml(metadata, io)
|
34
|
+
e = EmitterDetail::ThinpEmitter.new(io)
|
35
|
+
|
36
|
+
e.emit_superblock(metadata.superblock) do
|
37
|
+
metadata.devices.each do |dev|
|
38
|
+
e.emit_device(dev) do
|
39
|
+
dev.mappings.each do |m|
|
40
|
+
e.emit_mapping(m)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
#----------------------------------------------------------------
|
File without changes
|
@@ -1,12 +1,17 @@
|
|
1
|
-
require 'thinp_xml/metadata'
|
1
|
+
require 'thinp_xml/thinp/metadata'
|
2
|
+
require 'thinp_xml/listener'
|
3
|
+
|
2
4
|
require 'rexml/document'
|
3
5
|
require 'rexml/streamlistener'
|
4
6
|
|
7
|
+
#----------------------------------------------------------------
|
8
|
+
|
5
9
|
module ThinpXML
|
6
10
|
module ParseDetail
|
7
11
|
include REXML
|
8
12
|
|
9
13
|
class Listener
|
14
|
+
include Base::ListenerUtils
|
10
15
|
include REXML::StreamListener
|
11
16
|
|
12
17
|
attr_reader :metadata
|
@@ -15,31 +20,6 @@ module ThinpXML
|
|
15
20
|
@metadata = Metadata.new(nil, Array.new)
|
16
21
|
end
|
17
22
|
|
18
|
-
def to_hash(pairs)
|
19
|
-
r = Hash.new
|
20
|
-
pairs.each do |p|
|
21
|
-
r[p[0].intern] = p[1]
|
22
|
-
end
|
23
|
-
r
|
24
|
-
end
|
25
|
-
|
26
|
-
def get_fields(attr, flds)
|
27
|
-
flds.map do |n,t|
|
28
|
-
case t
|
29
|
-
when :int
|
30
|
-
attr[n].to_i
|
31
|
-
|
32
|
-
when :string
|
33
|
-
attr[n]
|
34
|
-
|
35
|
-
when :object
|
36
|
-
attr[n]
|
37
|
-
|
38
|
-
else
|
39
|
-
raise "unknown field type"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
23
|
|
44
24
|
def tag_start(tag, args)
|
45
25
|
attr = to_hash(args)
|
@@ -60,18 +40,12 @@ module ThinpXML
|
|
60
40
|
@current_device.mappings << Mapping.new(*get_fields(attr, MAPPING_FIELDS))
|
61
41
|
|
62
42
|
else
|
63
|
-
|
43
|
+
raise "unhandled tag '#{tag} #{attr.map {|x| x.inspect}.join(', ')}'"
|
64
44
|
end
|
65
45
|
end
|
66
46
|
|
67
47
|
def tag_end(tag)
|
68
48
|
end
|
69
|
-
|
70
|
-
def text(data)
|
71
|
-
return if data =~ /^\w*$/ # ignore whitespace
|
72
|
-
abbrev = data[0..40] + (data.length > 40 ? "..." : "")
|
73
|
-
puts " text : #{abbrev.inspect}"
|
74
|
-
end
|
75
49
|
end
|
76
50
|
end
|
77
51
|
|
File without changes
|
data/lib/thinp_xml/version.rb
CHANGED
data/lib/thinp_xml.rb
CHANGED
@@ -10,9 +10,9 @@ unless ThinpXML::tools_are_installed
|
|
10
10
|
raise "please install the thin provisioning tools version #{THINP_TOOLS_VERSION}"
|
11
11
|
end
|
12
12
|
|
13
|
-
require 'thinp_xml/builder'
|
14
|
-
require 'thinp_xml/emit'
|
15
|
-
require 'thinp_xml/metadata'
|
16
|
-
require 'thinp_xml/parse'
|
17
|
-
require 'thinp_xml/utils'
|
13
|
+
require 'thinp_xml/thinp/builder'
|
14
|
+
require 'thinp_xml/thinp/emit'
|
15
|
+
require 'thinp_xml/thinp/metadata'
|
16
|
+
require 'thinp_xml/thinp/parse'
|
17
|
+
require 'thinp_xml/thinp/utils'
|
18
18
|
require 'thinp_xml/version'
|
data/spec/builder_spec.rb
CHANGED
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'thinp_xml/cache/builder'
|
2
|
+
|
3
|
+
#----------------------------------------------------------------
|
4
|
+
|
5
|
+
describe "CacheXML::Builder" do
|
6
|
+
def as_percentage(n, tot)
|
7
|
+
(n * 100) / tot
|
8
|
+
end
|
9
|
+
|
10
|
+
def approx_percentage(n, tot, target)
|
11
|
+
actual = as_percentage(n, tot)
|
12
|
+
(actual - target).abs < 3
|
13
|
+
end
|
14
|
+
|
15
|
+
before :each do
|
16
|
+
@b = CacheXML::Builder.new
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "uuid" do
|
20
|
+
it "should be an empty string by default" do
|
21
|
+
@b.uuid.should == ''
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should reflect any changes" do
|
25
|
+
uuid = 'one two three'
|
26
|
+
@b.uuid = uuid
|
27
|
+
@b.uuid.should == uuid
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should generate the correct uuid" do
|
31
|
+
uuid = 'one two three'
|
32
|
+
@b.uuid = uuid
|
33
|
+
md = @b.generate
|
34
|
+
md.superblock.uuid.should == uuid
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "block_size" do
|
39
|
+
it "should be 128 by default" do
|
40
|
+
@b.block_size.should == 128
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should reflect any changes" do
|
44
|
+
@b.block_size = 512
|
45
|
+
@b.block_size.should == 512
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should generate the correct block size" do
|
49
|
+
bs = 1024
|
50
|
+
@b.block_size = bs
|
51
|
+
md = @b.generate
|
52
|
+
md.superblock.block_size.should == bs
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "nr cache blocks" do
|
57
|
+
it "should be zero by default" do
|
58
|
+
@b.nr_cache_blocks.should == 0
|
59
|
+
@b.generate.should have(0).mappings
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should reflect any changes" do
|
63
|
+
n = rand(1000)
|
64
|
+
@b.nr_cache_blocks = n
|
65
|
+
@b.nr_cache_blocks.should == n
|
66
|
+
@b.generate.superblock.nr_cache_blocks.should == n
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "policy name" do
|
71
|
+
it "should be 'mq' by default" do
|
72
|
+
@b.policy_name.should == 'mq'
|
73
|
+
@b.generate.superblock.policy_name.should == 'mq'
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should reflect changes" do
|
77
|
+
n = 'most_recently_not_used_least'
|
78
|
+
@b.policy_name = n
|
79
|
+
@b.policy_name.should == n
|
80
|
+
@b.generate.superblock.policy_name.should == n
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "mappings" do
|
85
|
+
describe "mapping policy" do
|
86
|
+
it "should default to :random" do
|
87
|
+
@b.mapping_policy.should == :random
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should only accept :random, or :linear" do
|
91
|
+
[:foo, :bar, :jumpy].each do |p|
|
92
|
+
expect {@b.mapping_policy = p}.to raise_error
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "nr mappings" do
|
98
|
+
it "should default to zero" do
|
99
|
+
@b.nr_mappings.should == 0
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should never be bigger than the nr_cache_blocks" do
|
103
|
+
100.times do
|
104
|
+
nr_cache = rand(1000)
|
105
|
+
@b.nr_cache_blocks = nr_cache
|
106
|
+
expect {@b.nr_mappings = nr_cache + rand(20) + 1}.to raise_error
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should generate the given number of mappings" do
|
111
|
+
100.times do
|
112
|
+
@b.nr_cache_blocks = rand(1000)
|
113
|
+
@b.nr_mappings = rand(@b.nr_cache_blocks)
|
114
|
+
@b.generate.should have(@b.nr_mappings).mappings
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "dirty percentage" do
|
120
|
+
it "should default to zero" do
|
121
|
+
@b.dirty_percentage.should == 0
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should throw if set to a negative number" do
|
125
|
+
expect do
|
126
|
+
@b.dirty_percentage = -20
|
127
|
+
end.to raise_error(RuntimeError, /-20/)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should throw if set to a > 100 number" do
|
131
|
+
expect do
|
132
|
+
@b.dirty_percentage = 101
|
133
|
+
end.to raise_error(RuntimeError, /101/)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should accept a valid value" do
|
137
|
+
[0, 1, 34, 78, 99, 100].each do |valid_value|
|
138
|
+
@b.dirty_percentage = valid_value
|
139
|
+
@b.dirty_percentage.should == valid_value
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should generate the required percentage" do
|
144
|
+
n_mappings = 10000
|
145
|
+
@b.nr_cache_blocks = n_mappings
|
146
|
+
@b.nr_mappings = n_mappings
|
147
|
+
|
148
|
+
[0, 1, 34, 78, 99, 100].each do |p|
|
149
|
+
@b.dirty_percentage = p
|
150
|
+
metadata = @b.generate
|
151
|
+
nr_dirty = 0
|
152
|
+
metadata.mappings.each do |m|
|
153
|
+
nr_dirty += 1 if m.dirty
|
154
|
+
end
|
155
|
+
|
156
|
+
approx_percentage(nr_dirty, n_mappings, p).should be_true
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "linear layout" do
|
162
|
+
before :each do
|
163
|
+
@b.mapping_policy = :linear
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should allocate cache blocks in order" do
|
167
|
+
@b.nr_cache_blocks = 100
|
168
|
+
@b.nr_mappings = rand(@b.nr_cache_blocks)
|
169
|
+
mappings = @b.generate.mappings
|
170
|
+
|
171
|
+
cb = 0
|
172
|
+
mappings.each do |m|
|
173
|
+
m.cache_block.should == cb
|
174
|
+
cb += 1
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should allocate origin blocks in order" do
|
179
|
+
@b.nr_cache_blocks = 100
|
180
|
+
@b.nr_mappings = 100
|
181
|
+
mappings = @b.generate.mappings
|
182
|
+
|
183
|
+
b = nil
|
184
|
+
mappings.each do |m|
|
185
|
+
if b.nil?
|
186
|
+
b = m.origin_block
|
187
|
+
else
|
188
|
+
m.origin_block.should == b
|
189
|
+
end
|
190
|
+
|
191
|
+
b += 1
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "random mapping" do
|
197
|
+
before :each do
|
198
|
+
@b.mapping_policy = :random
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should allocate cache blocks in order" do
|
202
|
+
@b.nr_cache_blocks = 100
|
203
|
+
@b.nr_mappings = rand(@b.nr_cache_blocks)
|
204
|
+
mappings = @b.generate.mappings
|
205
|
+
|
206
|
+
cb = 0
|
207
|
+
mappings.each do |m|
|
208
|
+
m.cache_block.should == cb
|
209
|
+
cb += 1
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should allocate origin blocks out of order" do
|
214
|
+
@b.nr_cache_blocks = 100
|
215
|
+
@b.nr_mappings = 100
|
216
|
+
mappings = @b.generate.mappings
|
217
|
+
|
218
|
+
in_order = true
|
219
|
+
b = nil
|
220
|
+
mappings.each do |m|
|
221
|
+
if b.nil?
|
222
|
+
b = m.origin_block
|
223
|
+
else
|
224
|
+
if m.origin_block != b
|
225
|
+
in_order = false
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
b += 1
|
230
|
+
end
|
231
|
+
|
232
|
+
in_order.should be_false
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
#----------------------------------------------------------------
|
240
|
+
|
data/spec/distribution_spec.rb
CHANGED
@@ -20,12 +20,52 @@ end
|
|
20
20
|
|
21
21
|
#----------------------------------------------------------------
|
22
22
|
|
23
|
-
describe "
|
23
|
+
describe "integer distributions" do
|
24
|
+
describe ConstDistribution do
|
25
|
+
it "should be constructed with a single value" do
|
26
|
+
expect do
|
27
|
+
dist = ConstDistribution.new
|
28
|
+
end.to raise_error
|
29
|
+
|
30
|
+
expect do
|
31
|
+
dist = ConstDistribution.new(1, 2)
|
32
|
+
end.to raise_error
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should always return it's given value" do
|
36
|
+
dist = ConstDistribution.new(5)
|
37
|
+
10.times do
|
38
|
+
dist.generate.should == 5
|
39
|
+
end
|
40
|
+
|
41
|
+
dist = ConstDistribution.new(11)
|
42
|
+
10.times do
|
43
|
+
dist.generate.should == 11
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should be passed an integer" do
|
48
|
+
expect do
|
49
|
+
dist = ConstDistribution.new('fish')
|
50
|
+
end.to raise_error
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#--------------------------------
|
55
|
+
|
24
56
|
describe UniformDistribution do
|
25
57
|
it "should be constructed with a range of values" do
|
26
58
|
dist = UniformDistribution.new(1, 10)
|
27
59
|
end
|
28
60
|
|
61
|
+
it "should only accept start and stop if they're different" do
|
62
|
+
expect {UniformDistribution.new(45, 45)}.to raise_error
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should only accept start if it's lower than stop" do
|
66
|
+
expect {UniformDistribution.new(45, 35)}.to raise_error
|
67
|
+
end
|
68
|
+
|
29
69
|
it "should generate a number from this range every time generate is called" do
|
30
70
|
dist = UniformDistribution.new(1, 10)
|
31
71
|
|
@@ -39,6 +79,7 @@ describe "random distributions" do
|
|
39
79
|
buckets[10].should == 0
|
40
80
|
|
41
81
|
1.upto(9) do |n|
|
82
|
+
buckets[n].should_not == 0
|
42
83
|
buckets[n].should be_approx(1000, 200)
|
43
84
|
end
|
44
85
|
end
|
@@ -58,6 +99,51 @@ describe "random distributions" do
|
|
58
99
|
$called456.should be_true
|
59
100
|
end
|
60
101
|
end
|
102
|
+
|
103
|
+
#--------------------------------
|
104
|
+
|
105
|
+
describe "parsing" do
|
106
|
+
describe "constant expression" do
|
107
|
+
it "should parse a const expression" do
|
108
|
+
10.times do
|
109
|
+
n = rand(50)
|
110
|
+
parse_distribution(n.to_s).to_i.should == n
|
111
|
+
parse_distribution(n.to_s).to_i.should == n
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "uniform expression" do
|
117
|
+
def check_range(b, e, n)
|
118
|
+
n.should >= b
|
119
|
+
n.should < e
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should accept well formed expressions" do
|
123
|
+
10.times do
|
124
|
+
b, e = [rand(100), rand(100)].sort
|
125
|
+
e += 1
|
126
|
+
d = parse_distribution("uniform[#{b}..#{e}]")
|
127
|
+
|
128
|
+
100.times do
|
129
|
+
check_range(b, e, d.to_i)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should reject badly formed expressions" do
|
135
|
+
bad = ['fred[1..20]',
|
136
|
+
'uniform[1..]',
|
137
|
+
'uniform[..20]',
|
138
|
+
'uniform 1..20',
|
139
|
+
'uniform[1..20',
|
140
|
+
'uniform1..20]']
|
141
|
+
bad.each do |b|
|
142
|
+
expect {parse_distribution(b)}.to raise_error
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
61
147
|
end
|
62
148
|
|
63
149
|
#----------------------------------------------------------------
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thinp_xml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Thornber
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ejt_command_line
|
@@ -114,32 +114,45 @@ email:
|
|
114
114
|
- ejt@redhat.com
|
115
115
|
executables:
|
116
116
|
- analyse_metadata
|
117
|
+
- cache_xml
|
117
118
|
- thinp_xml
|
118
119
|
extensions: []
|
119
120
|
extra_rdoc_files: []
|
120
121
|
files:
|
121
122
|
- .gitignore
|
123
|
+
- .rspec
|
122
124
|
- Gemfile
|
123
125
|
- LICENSE.txt
|
124
126
|
- README.md
|
125
127
|
- Rakefile
|
126
128
|
- bin/analyse_metadata
|
129
|
+
- bin/cache_xml
|
127
130
|
- bin/thinp_xml
|
128
|
-
- features/
|
131
|
+
- features/cache_create.feature
|
132
|
+
- features/cache_usage.feature
|
129
133
|
- features/step_definitions/thinp_xml.rb
|
130
134
|
- features/support/env.rb
|
131
|
-
- features/
|
135
|
+
- features/thinp_create.feature
|
136
|
+
- features/thinp_usage.feature
|
132
137
|
- lib/thinp_xml.rb
|
133
|
-
- lib/thinp_xml/
|
134
|
-
- lib/thinp_xml/
|
138
|
+
- lib/thinp_xml/cache/builder.rb
|
139
|
+
- lib/thinp_xml/cache/emit.rb
|
140
|
+
- lib/thinp_xml/cache/metadata.rb
|
141
|
+
- lib/thinp_xml/cache/parse.rb
|
142
|
+
- lib/thinp_xml/cache_xml.rb
|
135
143
|
- lib/thinp_xml/distribution.rb
|
136
|
-
- lib/thinp_xml/
|
137
|
-
- lib/thinp_xml/
|
138
|
-
- lib/thinp_xml/
|
139
|
-
- lib/thinp_xml/
|
144
|
+
- lib/thinp_xml/emitter.rb
|
145
|
+
- lib/thinp_xml/listener.rb
|
146
|
+
- lib/thinp_xml/thinp/analysis.rb
|
147
|
+
- lib/thinp_xml/thinp/builder.rb
|
148
|
+
- lib/thinp_xml/thinp/emit.rb
|
149
|
+
- lib/thinp_xml/thinp/metadata.rb
|
150
|
+
- lib/thinp_xml/thinp/parse.rb
|
151
|
+
- lib/thinp_xml/thinp/utils.rb
|
152
|
+
- lib/thinp_xml/thinp/xml_format.rb
|
140
153
|
- lib/thinp_xml/version.rb
|
141
|
-
- lib/thinp_xml/xml_format.rb
|
142
154
|
- spec/builder_spec.rb
|
155
|
+
- spec/cache_builder_spec.rb
|
143
156
|
- spec/distribution_spec.rb
|
144
157
|
- thinp_xml.gemspec
|
145
158
|
homepage: ''
|
@@ -167,9 +180,12 @@ signing_key:
|
|
167
180
|
specification_version: 4
|
168
181
|
summary: Thin provisioning xml
|
169
182
|
test_files:
|
170
|
-
- features/
|
183
|
+
- features/cache_create.feature
|
184
|
+
- features/cache_usage.feature
|
171
185
|
- features/step_definitions/thinp_xml.rb
|
172
186
|
- features/support/env.rb
|
173
|
-
- features/
|
187
|
+
- features/thinp_create.feature
|
188
|
+
- features/thinp_usage.feature
|
174
189
|
- spec/builder_spec.rb
|
190
|
+
- spec/cache_builder_spec.rb
|
175
191
|
- spec/distribution_spec.rb
|
data/lib/thinp_xml/emit.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'thinp_xml/metadata'
|
2
|
-
|
3
|
-
#----------------------------------------------------------------
|
4
|
-
|
5
|
-
module ThinpXML
|
6
|
-
class Emitter
|
7
|
-
def initialize(out)
|
8
|
-
@out = out
|
9
|
-
@indent = 0
|
10
|
-
end
|
11
|
-
|
12
|
-
def emit_tag(obj, tag, *fields, &block)
|
13
|
-
expanded = fields.map {|fld| "#{fld}=\"#{obj.send(fld)}\""}
|
14
|
-
if block.nil?
|
15
|
-
emit_line "<#{tag} #{expanded.join(' ')}/>"
|
16
|
-
else
|
17
|
-
emit_line "<#{tag} #{expanded.join(' ')}>"
|
18
|
-
push
|
19
|
-
yield unless block.nil?
|
20
|
-
pop
|
21
|
-
emit_line "</#{tag}>"
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def emit_line(str)
|
26
|
-
@out.puts((' ' * @indent) + str)
|
27
|
-
end
|
28
|
-
|
29
|
-
def push
|
30
|
-
@indent += 2
|
31
|
-
end
|
32
|
-
|
33
|
-
def pop
|
34
|
-
@indent -= 2
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def emit_superblock(e, sb, &block)
|
39
|
-
e.emit_tag(sb, 'superblock', :uuid, :time, :transaction, :data_block_size, :nr_data_blocks, &block)
|
40
|
-
end
|
41
|
-
|
42
|
-
def emit_device(e, dev, &block)
|
43
|
-
e.emit_tag(dev, 'device', :dev_id, :mapped_blocks, :transaction, :creation_time, :snap_time, &block)
|
44
|
-
end
|
45
|
-
|
46
|
-
def emit_mapping(e, m)
|
47
|
-
if m.length == 1
|
48
|
-
e.emit_line("<single_mapping origin_block=\"#{m.origin_begin}\" data_block=\"#{m.data_begin}\" time=\"#{m.time}\"/>")
|
49
|
-
else
|
50
|
-
e.emit_tag(m, 'range_mapping', :origin_begin, :data_begin, :length, :time)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def write_xml(metadata, io)
|
55
|
-
e = Emitter.new(io)
|
56
|
-
|
57
|
-
emit_superblock(e, metadata.superblock) do
|
58
|
-
metadata.devices.each do |dev|
|
59
|
-
emit_device(e, dev) do
|
60
|
-
dev.mappings.each do |m|
|
61
|
-
emit_mapping(e, m)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
#----------------------------------------------------------------
|