rgossip 0.1.1 → 0.1.2

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.
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/