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.
@@ -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
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'corosync/cpg'
3
4
  describe Corosync::CPG do
4
5
  context '#initialize offline' do
5
6
  before(:all) do
@@ -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
- require File.expand_path('../../lib/corosync/cpg', __FILE__)
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.3
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: 2013-11-06 00:00:00.000000000 Z
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/example.rb
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/version.rb
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
@@ -1,3 +0,0 @@
1
- module Corosync
2
- GEM_VERSION = '0.0.3'
3
- end