rgossip 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -18,7 +18,7 @@ gem install rgossip
18
18
  require 'rgossip'
19
19
 
20
20
  #RGossip.debug = true
21
- #RGossip.porting = 20870 # default: 100870(udp)
21
+ #RGossip.port = 20870 # default: 10870(udp)
22
22
 
23
23
  gossip = RGossip::Client.new ['10.150.174.161', '10.150.185.250', '10.150.174.30']
24
24
  # RGossip::Client#initialize(initial_nodes = [], address = nil, data = nil)
@@ -6,52 +6,62 @@ module RGossip
6
6
  attr_reader :dead_list
7
7
  attr_reader :my_node
8
8
 
9
- def initialize(initial_nodes = [], address = nil, data = nil)
9
+ def initialize(initial_nodes = [], address = nil, data = nil, callback = nil)
10
10
  raise 'too large data' if data && data.length > RGossip.bufsiz
11
11
 
12
12
  @address = address || IPSocket.getaddress(Socket.gethostname)
13
13
 
14
14
  RGossip.log("Initialize Client: initial_nodes=#{initial_nodes.inspect} address: #{@address} data: #{data.inspect}")
15
15
 
16
+ @callback = callback
16
17
  @node_list = Nodes.new
17
18
  @dead_list = Nodes.new
18
- @my_node = Node.new(@node_list, @dead_list, @address, data)
19
+
20
+ @my_node = Node.new(@node_list, @dead_list, @address, data, nil, self.method(:perform_callback))
19
21
  @my_node.update_timestamp
20
22
  @node_list << @my_node
21
23
 
22
24
  initial_nodes.uniq.each do |i|
23
- @node_list << Node.new(@node_list, @dead_list, i, nil)
25
+ @node_list << Node.new(@node_list, @dead_list, name2addr(i), nil, nil, self.method(:perform_callback))
24
26
  end
27
+
28
+ @gossiper = Gossiper.new(@my_node, @node_list)
29
+ @receiver = Receiver.new(@my_node, @node_list, @dead_list, self.method(:perform_callback))
25
30
  end
26
31
 
27
32
  def start
28
33
  return if @running
29
- RGossip.log("Start Client: address=#{@address}")
30
34
 
31
- @gossiper = Gossiper.new(@my_node, @node_list)
32
- @receiver = Receiver.new(@my_node, @node_list, @dead_list)
35
+ begin
36
+ RGossip.log("Start Client: address=#{@address}")
33
37
 
34
- @node_list.each do |node|
35
- if node.address != @my_node.address
36
- node.start_timer
38
+ @node_list.each do |node|
39
+ if node.address != @my_node.address
40
+ node.start_timer
41
+ end
37
42
  end
38
- end
39
43
 
40
- @gossiper.start
41
- @receiver.start
42
- @running = true
44
+ @gossiper.start
45
+ @receiver.start
46
+ ensure
47
+ @running = true
48
+ end
43
49
  end
44
50
 
45
51
  def stop
46
52
  return unless @running
47
- RGossip.log("Stop Client")
48
53
 
49
- @gossiper.stop
50
- @receiver.stop
51
- @running = true
54
+ begin
55
+ RGossip.log("Stop Client")
52
56
 
53
- @gossiper = nil
54
- @receiver = nil
57
+ @gossiper.stop
58
+ @receiver.stop
59
+
60
+ @gossiper = nil
61
+ @receiver = nil
62
+ ensure
63
+ @running = true
64
+ end
55
65
  end
56
66
 
57
67
  def join
@@ -63,16 +73,36 @@ module RGossip
63
73
  !!@running
64
74
  end
65
75
 
76
+ def address
77
+ @my_node.address
78
+ end
79
+
80
+ def data
81
+ @node_list.synchronize {
82
+ @my_node.data
83
+ }
84
+ end
85
+
66
86
  def data=(v)
67
87
  @node_list.synchronize {
68
88
  @my_node.data = v
69
89
  }
70
90
  end
71
91
 
92
+ def callback=(v)
93
+ @node_list.synchronize {
94
+ @dead_list.synchronize {
95
+ @callback = v
96
+ }
97
+ }
98
+ end
99
+
72
100
  def add_node(address)
101
+ address = name2addr(address)
102
+
73
103
  @node_list.synchronize {
74
104
  raise 'node is exist' if @node_list.any? {|i| i.address == address }
75
- @node_list << Node.new(@node_list, @dead_list, address, nil)
105
+ @node_list << Node.new(@node_list, @dead_list, address, nil, nil, self.method(:perform_callback))
76
106
  }
77
107
  end
78
108
 
@@ -99,5 +129,27 @@ module RGossip
99
129
  end
100
130
  }
101
131
  end
132
+
133
+ private
134
+ def name2addr(name)
135
+ if /\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\Z/ =~ name
136
+ name
137
+ else
138
+ IPSocket.getaddress(name)
139
+ end
140
+ end
141
+
142
+ def perform_callback(args)
143
+ return unless @callback
144
+
145
+ case @callback.arity
146
+ when 0
147
+ @callback.call
148
+ when 1
149
+ @callback.call(args)
150
+ else
151
+ @callback.call(*args)
152
+ end
153
+ end
102
154
  end # Client
103
155
  end # RGossip
@@ -7,18 +7,24 @@ module RGossip
7
7
  def initialize(my_node, node_list)
8
8
  @my_node = my_node
9
9
  @node_list = node_list
10
- @running = true
11
10
  end
12
11
 
13
12
  def start
14
13
  RGossip.log("Start Gossiper: interval=#{@@interval}")
14
+ @running = true
15
15
 
16
16
  @thread = Thread.start {
17
17
  begin
18
18
  sock = UDPSocket.open
19
19
 
20
20
  while @running
21
- @node_list.synchronize { gossip(sock) }
21
+ begin
22
+ @node_list.synchronize { gossip(sock) }
23
+ rescue Exception => e
24
+ raise e unless RGossip.error_handler
25
+ RGossip.error_handler.call(e)
26
+ end
27
+
22
28
  sleep(@@interval)
23
29
  end
24
30
  ensure
@@ -47,12 +53,7 @@ module RGossip
47
53
  RGossip.log("Gossip: destination=#{dest.address}")
48
54
 
49
55
  @node_list.serialize_to_chunks.each do |chunk|
50
- begin
51
- sock.send(chunk, 0, dest.address, RGossip.port)
52
- rescue Exception => e
53
- raise e unless RGossip.error_handler
54
- RGossip.error_handler.call(e)
55
- end
56
+ sock.send(chunk, 0, dest.address, RGossip.port)
56
57
  end
57
58
  end
58
59
  end # Gossiper
data/lib/rgossip/node.rb CHANGED
@@ -3,17 +3,19 @@ module RGossip
3
3
  attr_reader :address
4
4
  attr_accessor :timestamp
5
5
  attr_accessor :data
6
+ attr_accessor :callback
6
7
 
7
8
  @@lifetime = 10
8
9
  def self.lifetime; @@lifetime; end
9
10
  def self.lifetime=(v); @@lifetime = v; end
10
11
 
11
- def initialize(node_list, dead_list, address, data, timestamp = nil)
12
+ def initialize(node_list, dead_list, address, data, timestamp, callback = nil)
12
13
  @node_list = node_list
13
14
  @dead_list = dead_list
14
15
  @address = address
15
16
  @data = data
16
17
  @timestamp = timestamp || ""
18
+ @callback = callback
17
19
 
18
20
  @timer = Timer.new(@@lifetime) do
19
21
  RGossip.log("Timeout Node: address=#{@address}")
@@ -27,6 +29,8 @@ module RGossip
27
29
  @dead_list.synchronize {
28
30
  @dead_list << self
29
31
  }
32
+
33
+ @callback.call([:delete, address, timestamp, data]) if @callback
30
34
  end
31
35
  end
32
36
 
@@ -40,13 +44,13 @@ module RGossip
40
44
  end
41
45
 
42
46
  def start_timer
43
- RGossip.log("Start Timer: address=#{@address}")
47
+ RGossip.log("Start Timer: address=#{@address} lifetime=#{@@lifetime}")
44
48
 
45
49
  @timer.start
46
50
  end
47
51
 
48
52
  def reset_timer
49
- RGossip.log("Reset Timer: address=#{@address}")
53
+ RGossip.log("Reset Timer: address=#{@address} lifetime=#{@@lifetime}")
50
54
 
51
55
  @timer.reset
52
56
  end
@@ -4,15 +4,18 @@ module RGossip
4
4
  def self.timeout; @@timeout; end
5
5
  def self.timeout=(v); @@timeout = v; end
6
6
 
7
- def initialize(my_node, node_list, dead_list)
7
+ attr_accessor :callback
8
+
9
+ def initialize(my_node, node_list, dead_list, callback = nil)
8
10
  @my_node = my_node
9
11
  @node_list = node_list
10
12
  @dead_list = dead_list
11
- @running = true
13
+ @callback = callback
12
14
  end
13
15
 
14
16
  def start
15
17
  RGossip.log("Start Receiver: port=#{RGossip.port}")
18
+ @running = true
16
19
 
17
20
  @thread = Thread.start {
18
21
  begin
@@ -70,25 +73,31 @@ module RGossip
70
73
  node.timestamp = timestamp
71
74
  node.data = data
72
75
  node.reset_timer
76
+
77
+ @callback.call([:update, address, timestamp, data]) if @callback
73
78
  end
74
79
  elsif (index = @dead_list.synchronize { @dead_list.index {|i| i.address == address } })
75
- RGossip.log("Come back Node: address=#{address} timestamp=#{timestamp}")
76
-
77
80
  @dead_list.synchronize {
78
81
  node = @dead_list[index]
79
82
 
80
83
  if timestamp > node.timestamp
84
+ RGossip.log("Come back Node: address=#{address} timestamp=#{timestamp}")
85
+
81
86
  @dead_list.delete_at(index)
82
87
  @node_list << node
83
88
  node.start_timer
89
+
90
+ @callback.call([:comeback, address, timestamp, data]) if @callback
84
91
  end
85
92
  }
86
93
  else
87
94
  RGossip.log("Add Node: address=#{address} timestamp=#{timestamp}")
88
95
 
89
- node = Node.new(@node_list, @dead_list, address, data, timestamp)
96
+ node = Node.new(@node_list, @dead_list, address, data, timestamp, @callback)
90
97
  @node_list << node
91
98
  node.start_timer
99
+
100
+ @callback.call([:add, address, timestamp, data]) if @callback
92
101
  end
93
102
  end
94
103
  end
data/lib/rgossip.rb CHANGED
@@ -11,6 +11,8 @@ require 'rgossip/receiver'
11
11
  require 'rgossip/timer'
12
12
 
13
13
  module RGossip
14
+ DEFAULT_LOGGER = Logger.new($stderr)
15
+
14
16
  @@port = 10870
15
17
  def self.port; @@port; end
16
18
  def self.port=(v); @@port = v; end
@@ -23,7 +25,16 @@ module RGossip
23
25
  def self.allowance; @@allowance; end
24
26
  def self.allowance=(v); @@allowance = v; end
25
27
 
26
- @@error_handler = lambda {|e| $stderr.puts((["#{e.class}: #{e.message}"] + (e.backtrace || [])).join("\n\tfrom ")) }
28
+ @@error_handler = lambda do |e|
29
+ message = (["#{e.class}: #{e.message}"] + (e.backtrace || [])).join("\n\tfrom ")
30
+
31
+ if self.debug_logger
32
+ self.debug_logger.call(message)
33
+ else
34
+ $stderr.puts(message)
35
+ end
36
+ end
37
+
27
38
  def self.error_handler; @@error_handler; end
28
39
  def self.error_handler=(v); @@error_handler = v; end
29
40
 
@@ -31,7 +42,7 @@ module RGossip
31
42
  def self.debug; @@debug; end
32
43
  def self.debug=(v); @@debug = v; end
33
44
 
34
- @@debug_logger = lambda {|message| $stderr.puts "[#{Time.now.strftime '%x %X'} ##{$$}] #{message}" }
45
+ @@debug_logger = lambda {|message| DEFAULT_LOGGER.debug(message) }
35
46
  def self.debug_logger; @@debug_logger; end
36
47
  def self.debug_logger=(v); @@debug_logger = v; end
37
48
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgossip
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - winebarrel
@@ -15,7 +15,8 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-22 00:00:00 Z
18
+ date: 2011-05-23 00:00:00 +09:00
19
+ default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: msgpack
@@ -41,13 +42,14 @@ extra_rdoc_files: []
41
42
 
42
43
  files:
43
44
  - README
44
- - lib/rgossip/timer.rb
45
- - lib/rgossip/gossipper.rb
46
45
  - lib/rgossip/client.rb
47
- - lib/rgossip/receiver.rb
48
- - lib/rgossip/nodes.rb
46
+ - lib/rgossip/gossipper.rb
49
47
  - lib/rgossip/node.rb
48
+ - lib/rgossip/nodes.rb
49
+ - lib/rgossip/receiver.rb
50
+ - lib/rgossip/timer.rb
50
51
  - lib/rgossip.rb
52
+ has_rdoc: true
51
53
  homepage: https://bitbucket.org/winebarrel/rgossip
52
54
  licenses: []
53
55
 
@@ -77,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
79
  requirements: []
78
80
 
79
81
  rubyforge_project:
80
- rubygems_version: 1.8.1
82
+ rubygems_version: 1.4.2
81
83
  signing_key:
82
84
  specification_version: 3
83
85
  summary: Basic implementation of a gossip protocol. This is a porting of Java implementation. see http://code.google.com/p/gossip-protocol-java/