corosync 0.0.3 → 0.1.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/Gemfile.lock +4 -4
- data/README.md +24 -5
- data/Rakefile +62 -1
- data/VERSION +1 -0
- data/corosync.gemspec +1 -3
- data/examples/cmap-cli.rb +72 -0
- data/examples/cpg-chat.rb +75 -0
- data/examples/{example.rb → cpg-monitor.rb} +1 -1
- data/ffi/cmap.i +14 -0
- data/ffi/cmap.rb +91 -0
- data/ffi/common.rb +1 -1
- data/ffi/cpg.rb +57 -15
- data/ffi/quorum.i +14 -0
- data/ffi/quorum.rb +36 -0
- data/ffi/votequorum.i +14 -0
- data/ffi/votequorum.rb +87 -0
- data/lib/corosync.rb +69 -1
- data/lib/corosync/cmap.rb +381 -0
- data/lib/corosync/cpg.rb +27 -46
- data/lib/corosync/exceptions.rb +34 -0
- data/lib/corosync/quorum.rb +143 -0
- data/lib/corosync/votequorum.rb +218 -0
- data/lib/ffi_pointer.rb +28 -0
- data/spec/corosync/cmap.rb +99 -0
- data/spec/corosync/cpg.rb +1 -0
- data/spec/corosync/quorum.rb +66 -0
- data/spec/corosync/votequorum.rb +81 -0
- data/spec/spec_helper.rb +1 -1
- metadata +20 -4
- data/lib/version.rb +0 -3
data/lib/ffi_pointer.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
# We create these 2 methods because of types like `size_t`. The type changes by platform, so we don't know which write/read method to use. So we create a generic read/write that we can pass a type to and it will figure out which method needs to be used.
|
4
|
+
|
5
|
+
class FFI::Pointer
|
6
|
+
def read_type(type)
|
7
|
+
type = FFI.find_type(type) if type.is_a?(Symbol)
|
8
|
+
type = type.native_type if type.is_a?(FFI::Type::Mapped)
|
9
|
+
raise ArgumentError, "Can only read built-in types (type=#{type})" unless type.is_a?(FFI::Type::Builtin)
|
10
|
+
name = type.inspect.match(/<#{type.class}:(\S+)/)[1].downcase
|
11
|
+
method = "read_#{name}".to_sym
|
12
|
+
self.send(method)
|
13
|
+
end
|
14
|
+
def write_type(type, value)
|
15
|
+
type = FFI.find_type(type) if type.is_a?(Symbol)
|
16
|
+
type = type.native_type if type.is_a?(FFI::Type::Mapped)
|
17
|
+
raise ArgumentError, "Can only write built-in types (type=#{type})" unless type.is_a?(FFI::Type::Builtin)
|
18
|
+
name = type.inspect.match(/<#{type.class}:(\S+)/)[1].downcase
|
19
|
+
method = "write_#{name}".to_sym
|
20
|
+
self.send(method, value)
|
21
|
+
end
|
22
|
+
|
23
|
+
# these are methods where the type name doesn't match the method
|
24
|
+
alias_method :write_float32, :write_float
|
25
|
+
alias_method :read_float32, :read_float
|
26
|
+
alias_method :write_float64, :write_double
|
27
|
+
alias_method :read_float64, :read_double
|
28
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
require 'corosync/cmap'
|
5
|
+
describe Corosync::CMAP do
|
6
|
+
before(:all) do
|
7
|
+
@cmap = Corosync::CMAP.new
|
8
|
+
@cmap.connect
|
9
|
+
end
|
10
|
+
|
11
|
+
around :each do |example|
|
12
|
+
Timeout::timeout(1) do
|
13
|
+
example.run
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Corosync::CMAP::SIZEMAP.each do |type, info|
|
18
|
+
it "can set a #{type}" do
|
19
|
+
expect{@cmap.set("test.#{type}", type, info.max)}.to_not raise_error
|
20
|
+
end
|
21
|
+
it "can get a #{type}" do
|
22
|
+
expect(@cmap.get("test.#{type}")).to eq([type, info.max])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
it 'can set a float' do
|
26
|
+
expect{@cmap.set('test.float', :float, 1234.4321)}.to_not raise_error
|
27
|
+
end
|
28
|
+
it 'can get a float' do
|
29
|
+
type, value = @cmap.get('test.float')
|
30
|
+
expect(type).to eq(:float)
|
31
|
+
expect(value).to be_within(0.00005).of(1234.4321)
|
32
|
+
end
|
33
|
+
it 'can set a double' do
|
34
|
+
expect{@cmap.set('test.double', :double, 12345.54321)}.to_not raise_error
|
35
|
+
end
|
36
|
+
it 'can get a double' do
|
37
|
+
type, value = @cmap.get('test.double')
|
38
|
+
expect(type).to eq(:double)
|
39
|
+
expect(value).to be_within(0.000005).of(12345.54321)
|
40
|
+
end
|
41
|
+
it 'cat set a string' do
|
42
|
+
expect{@cmap.set("test.string", :string, 'xyzzy')}.to_not raise_error
|
43
|
+
end
|
44
|
+
it 'can get a string' do
|
45
|
+
expect(@cmap.get("test.string")).to eq([:string, 'xyzzy'])
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'can increment a value' do
|
49
|
+
@cmap.set('test.inc', :int32, 100)
|
50
|
+
expect{@cmap.inc('test.inc')}.to_not raise_error
|
51
|
+
expect(@cmap.get('test.inc')).to eq([:int32, 101])
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'can decrement a value' do
|
55
|
+
@cmap.set('test.dec', :int32, 100)
|
56
|
+
expect{@cmap.dec('test.dec')}.to_not raise_error
|
57
|
+
expect(@cmap.get('test.dec')).to eq([:int32, 99])
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'can delete a value' do
|
61
|
+
expect{@cmap.delete('test.string')}.to_not raise_error
|
62
|
+
expect{@cmap.get('test.string')}.to raise_error
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'can list keys' do
|
66
|
+
keys = @cmap.keys
|
67
|
+
|
68
|
+
expect(keys).to be_a(Array)
|
69
|
+
keys.each do |key|
|
70
|
+
expect(key).to be_a(String)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'can track a value' do
|
75
|
+
@cmap.delete('test.track') rescue Exception
|
76
|
+
|
77
|
+
events = []
|
78
|
+
track_id = @cmap.track_add('test.track', [:add, :delete, :modify]) do |*args|
|
79
|
+
events << args
|
80
|
+
end
|
81
|
+
|
82
|
+
@cmap.set('test.track', :uint32, 1234)
|
83
|
+
@cmap.dispatch
|
84
|
+
@cmap.set('test.track', :int32, 1235)
|
85
|
+
@cmap.dispatch
|
86
|
+
@cmap.delete('test.track')
|
87
|
+
@cmap.dispatch
|
88
|
+
|
89
|
+
expect(events).to eq([
|
90
|
+
[:add, 'test.track', :uint32, 1234, nil, nil],
|
91
|
+
[:modify, 'test.track', :int32, 1235, :uint32, 1234],
|
92
|
+
[:delete, 'test.track', nil, nil, :int32, 1235]
|
93
|
+
])
|
94
|
+
|
95
|
+
@cmap.track_delete(track_id)
|
96
|
+
@cmap.set('test.track', :uint32, 1236)
|
97
|
+
expect{@cmap.dispatch}.to raise_error # our timeout defined at the top should kick in
|
98
|
+
end
|
99
|
+
end
|
data/spec/corosync/cpg.rb
CHANGED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'corosync/quorum'
|
4
|
+
describe Corosync::Quorum do
|
5
|
+
context '#initialize offline' do
|
6
|
+
before(:all) do
|
7
|
+
@quorum = Corosync::Quorum.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'creates a Quorum object' do
|
11
|
+
expect(@quorum).to be_an_instance_of(Corosync::Quorum)
|
12
|
+
expect(@quorum.fd).to be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'connects' do
|
16
|
+
have_callback = false
|
17
|
+
@quorum.on_notify do
|
18
|
+
have_callback = true
|
19
|
+
end
|
20
|
+
|
21
|
+
@quorum.start(true)
|
22
|
+
|
23
|
+
expect(@quorum.fd).to be_an_instance_of(IO)
|
24
|
+
expect(have_callback).to be_true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context '#initialize with connect' do
|
29
|
+
before(:all) do
|
30
|
+
@quorum = Corosync::Quorum.new(true)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'connects' do
|
34
|
+
expect(@quorum).to be_an_instance_of(Corosync::Quorum)
|
35
|
+
expect(@quorum.fd).to_not be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'gets quorum state' do
|
39
|
+
expect([TrueClass,FalseClass]).to include(@quorum.quorate?.class)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'responds to inquorate change' do
|
43
|
+
is_quorate = nil
|
44
|
+
@quorum.on_notify {|quorate| is_quorate = quorate}
|
45
|
+
|
46
|
+
handle = @quorum.instance_variable_get(:@handle)
|
47
|
+
view_list = FFI::MemoryPointer.new(FFI.find_type(:uint32), 1)
|
48
|
+
view_list.write_array_of_type(FFI.find_type(:uint32), :write_uint32, [1])
|
49
|
+
@quorum.send(:callback_notify, handle, 0, nil, 1, view_list)
|
50
|
+
|
51
|
+
expect(is_quorate).to eq(false)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'responds to quorate change' do
|
55
|
+
is_quorate = nil
|
56
|
+
@quorum.on_notify {|quorate| is_quorate = quorate}
|
57
|
+
|
58
|
+
handle = @quorum.instance_variable_get(:@handle)
|
59
|
+
view_list = FFI::MemoryPointer.new(FFI.find_type(:uint32), 2)
|
60
|
+
view_list.write_array_of_type(FFI.find_type(:uint32), :write_uint32, [1,2])
|
61
|
+
@quorum.send(:callback_notify, handle, 1, nil, 1, view_list)
|
62
|
+
|
63
|
+
expect(is_quorate).to eq(true)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'corosync/votequorum'
|
4
|
+
describe Corosync::Votequorum do
|
5
|
+
context '#initialize offline' do
|
6
|
+
before(:all) do
|
7
|
+
@vq = Corosync::Votequorum.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'creates a Votequorum object' do
|
11
|
+
expect(@vq).to be_an_instance_of(Corosync::Votequorum)
|
12
|
+
expect(@vq.fd).to be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'connects' do
|
16
|
+
have_callback = false
|
17
|
+
@vq.on_notify do
|
18
|
+
have_callback = true
|
19
|
+
end
|
20
|
+
|
21
|
+
@vq.start(true)
|
22
|
+
|
23
|
+
expect(@vq.fd).to be_an_instance_of(IO)
|
24
|
+
expect(have_callback).to be_true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context '#initialize with connect' do
|
29
|
+
before(:all) do
|
30
|
+
@vq = Corosync::Votequorum.new(true)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'connects' do
|
34
|
+
expect(@vq).to be_an_instance_of(Corosync::Votequorum)
|
35
|
+
expect(@vq.fd).to_not be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'gets quorum state' do
|
39
|
+
expect([TrueClass,FalseClass]).to include(@vq.quorate?.class)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'responds to inquorate change' do
|
43
|
+
is_quorate = nil
|
44
|
+
@vq.on_notify {|quorate| is_quorate = quorate}
|
45
|
+
|
46
|
+
handle = @vq.instance_variable_get(:@handle)
|
47
|
+
node_states = {
|
48
|
+
1 => Corosync::VOTEQUORUM_NODESTATE_DEAD,
|
49
|
+
}
|
50
|
+
node_list = FFI::MemoryPointer.new(Corosync::VotequorumNodeT, node_states.size)
|
51
|
+
node_states.to_a.each_with_index do |node_state, i|
|
52
|
+
node = Corosync::VotequorumNodeT.new(node_list + i * Corosync::VotequorumNodeT.size)
|
53
|
+
node[:nodeid] = node_state[0]
|
54
|
+
node[:state] = node_state[1]
|
55
|
+
end
|
56
|
+
@vq.send(:callback_notify, handle, nil, 0, node_states.size, node_list)
|
57
|
+
|
58
|
+
expect(is_quorate).to eq(false)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'responds to quorate change' do
|
62
|
+
is_quorate = nil
|
63
|
+
@vq.on_notify {|quorate| is_quorate = quorate}
|
64
|
+
|
65
|
+
handle = @vq.instance_variable_get(:@handle)
|
66
|
+
node_states = {
|
67
|
+
1 => Corosync::VOTEQUORUM_NODESTATE_MEMBER,
|
68
|
+
2 => Corosync::VOTEQUORUM_NODESTATE_MEMBER,
|
69
|
+
}
|
70
|
+
node_list = FFI::MemoryPointer.new(Corosync::VotequorumNodeT, node_states.size)
|
71
|
+
node_states.to_a.each_with_index do |node_state, i|
|
72
|
+
node = Corosync::VotequorumNodeT.new(node_list + i * Corosync::VotequorumNodeT.size)
|
73
|
+
node[:nodeid] = node_state[0]
|
74
|
+
node[:state] = node_state[1]
|
75
|
+
end
|
76
|
+
@vq.send(:callback_notify, handle, nil, 1, node_states.size, node_list)
|
77
|
+
|
78
|
+
expect(is_quorate).to eq(true)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# we have to use the full path because rspec puts itself higher on the list, and we end up requiring `spec/corosync/cpg`
|
2
|
-
|
2
|
+
$:.unshift(File.expand_path('../../lib', __FILE__))
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: corosync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrick Hemmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -36,21 +36,37 @@ files:
|
|
36
36
|
- LICENSE
|
37
37
|
- README.md
|
38
38
|
- Rakefile
|
39
|
+
- VERSION
|
39
40
|
- corosync.gemspec
|
40
|
-
- examples/
|
41
|
+
- examples/cmap-cli.rb
|
42
|
+
- examples/cpg-chat.rb
|
43
|
+
- examples/cpg-monitor.rb
|
44
|
+
- ffi/cmap.i
|
45
|
+
- ffi/cmap.rb
|
41
46
|
- ffi/common.i
|
42
47
|
- ffi/common.rb
|
43
48
|
- ffi/cpg.i
|
44
49
|
- ffi/cpg.rb
|
50
|
+
- ffi/quorum.i
|
51
|
+
- ffi/quorum.rb
|
45
52
|
- ffi/service.i.erb
|
53
|
+
- ffi/votequorum.i
|
54
|
+
- ffi/votequorum.rb
|
46
55
|
- lib/corosync.rb
|
56
|
+
- lib/corosync/cmap.rb
|
47
57
|
- lib/corosync/cpg.rb
|
48
58
|
- lib/corosync/cpg/member.rb
|
49
59
|
- lib/corosync/cpg/member_list.rb
|
50
|
-
- lib/
|
60
|
+
- lib/corosync/exceptions.rb
|
61
|
+
- lib/corosync/quorum.rb
|
62
|
+
- lib/corosync/votequorum.rb
|
63
|
+
- lib/ffi_pointer.rb
|
64
|
+
- spec/corosync/cmap.rb
|
51
65
|
- spec/corosync/cpg.rb
|
52
66
|
- spec/corosync/cpg/member.rb
|
53
67
|
- spec/corosync/cpg/member_list.rb
|
68
|
+
- spec/corosync/quorum.rb
|
69
|
+
- spec/corosync/votequorum.rb
|
54
70
|
- spec/spec_helper.rb
|
55
71
|
homepage: http://github.com/phemmer/ruby-corosync/
|
56
72
|
licenses:
|
data/lib/version.rb
DELETED