Class: Pokan::Server

Inherits:
Peer show all
Includes:
ServerMessages
Defined in:
lib/pokan/server.rb

Overview

Gossip server class, using the Pokan::Peer class. This is the main class instantied by user code.

When a server class is created, the user should set:

  • the gossip interval

  • actual data to be stored, and possibly shared with other servers accross the network

  • The server behavior on a defined set of events, declared in an event driven syntax.

The user can also use epoll for faster I/O notification, if the server is running on a Linux system.

Sample usage is shown below:

s = Pokan::Server.new
s.gossip_every(1) #=> tells the server to gossip every second
s.use_epoll #=> I'm in a Linux system

s.store 'k', 'v'

e.on :new_key do |key, value|
  puts "What a great key I just got: #{key}!"
end

# more event related code... 

e.start #=> last command, blocks execution

Constant Summary collapse

ON_EVENTS =
[:new_key, :key_changed, :key_removed, :start, :shutdown]
BEFORE_EVENTS =
[:gossip, :sync]
AFTER_EVENTS =
[:gossip, :sync]

Instance Attribute Summary collapse

Attributes inherited from Entity

#id

Instance Method Summary collapse

Methods included from ServerMessages

#digest_message, #goodbye_message, #hello_message

Methods inherited from Peer

#act_as_seed, #address, #address=, #alive?, #dead?, #kill, #peer?, #revive, #role, #role=, #seed?, #status, #status=, #sync_with, #tcp_port, #tcp_port=, #udp_port, #udp_port=

Methods inherited from Entity

#destroy, #digest, #keys, #match?, #merge, #newer, #older, #reload, #save, #timestamp, #value, #values

Constructor Details

#initialize(address) ⇒ Server

Creates a new gossip server. You must pass the machine’s IP address in the network. This information will be used when changing information with other peers running Pokan. This also set some defaults, namely:

  • server will bind TCP and UDP port number 5555. If you have something else running, you must set them like:

    server.tcp_port = 9876
    server.udp_port = 9989
    
  • epoll will not be used (you might want to set it if you are in a Linux system. See Pokan::Server#use_epoll

  • The server will comunicate with other peers _every second_

Of course, all of these are customizable to your particular needs.



62
63
64
65
66
67
68
69
70
# File 'lib/pokan/server.rb', line 62

def initialize(address)
  @event_handler = EventHandler.new
  @seed_address, @seed_port = '', ''
  @periodics = []
  self.address = address
  self.udp_port = 5555
  super()
  initialize_ivs
end

Instance Attribute Details

#gossip_intervalObject (readonly)

Returns the value of attribute gossip_interval.



38
39
40
# File 'lib/pokan/server.rb', line 38

def gossip_interval
  @gossip_interval
end

Instance Method Details

#after(event, &block) ⇒ Object

Same as the Pokan::Server#before, but it also supports the :sync event. Use this method to run some code after the server gossips with a random peer or after it syncs with a seed (if you passed one on initialization. See Pokan::Server#start).



133
134
135
136
# File 'lib/pokan/server.rb', line 133

def after(event, &block)
  event_name = prepend('after_', event)
  register_event(event_name, &block) if AFTER_EVENTS.include? event
end

#before(event, &block) ⇒ Object

Adds behaviour before a given event occurs. For now, the only event supported is :gossip. Use this method if you want some code to run every time before the server gossips with a random peer.



124
125
126
127
# File 'lib/pokan/server.rb', line 124

def before(event, &block)
  event_name = prepend('before_', event)
  register_event(event_name, &block) if BEFORE_EVENTS.include? event
end

#every(seconds, &action) ⇒ Object

Adds behavior to the server, to be executed periodically (every given amount of seconds).

server.every 2 do
  puts "Heya!"
end

Every 2 seconds “Heya!” will be printed out.



147
148
149
# File 'lib/pokan/server.rb', line 147

def every(seconds, &action)
  @periodics << { :period => seconds, :action => action }
end

#gossip_every(seconds) ⇒ Object

Use this method to specify the time interval you wish to use for changing gossip messages among peers. Default is 1 second.



86
87
88
# File 'lib/pokan/server.rb', line 86

def gossip_every(seconds)
  @gossip_interval = seconds
end

#on(event, &block) ⇒ Object

Defines the behaviour you want the server to have on different events. For now, you can define your behaviour for the following events:

  • :new_key - This will be called whenever a new_key is inserted (and there was no previous value for that)

  • :key_changed - This is called when a value for a certain key is updated (a value with greater timestamp)

  • :key_removed - The name speaks for itself

For all the events, both the key and the value are passed to the block.

Example:

server = Pokan::Server.new('10.10.10.8')
server.on :new_key do |key, value|
  puts "New key #{key} was inserted with value #{value}!"
end


117
118
119
# File 'lib/pokan/server.rb', line 117

def on(event, &block)
  register_event(event, &block) if ON_EVENTS.include? event
end

#start(options = {}) ⇒ Object

This method starts the server, which will bind specified TCP and UDP ports (or 5555 by default). Optionally, you can pass the address of another pokan instance (a seed), and the server will automatically send a message to the seed and update its data. If no seed information is passed, the server will start with no data and assume it is a seed.

Example:

server = Pokan::Server.new('10.10.10.8')
server.start :gossip_with => '10.10.10.9:5555'

In the example above, the server will try to contact (via TCP) a pokan server running on 10.10.10.9, port 5555, and update its data accordingly.



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/pokan/server.rb', line 166

def start(options = {})
  seed = options[:gossip_with]

  if seed.nil?
    act_as_seed
  else
    @seed_address, @seed_port = parse_host_and_port(seed)
    say_hello(@seed_address, @seed_port)
    build_trap

    @event_handler.emit :before_gossip, :with => [@seed_address, options[:redis]]
    sync_with(@seed_address, options[:redis])
    @event_handler.emit :after_sync, :with => [1]
  end

  start_event_loop
end

#stopObject

Finishes the server



185
186
187
188
# File 'lib/pokan/server.rb', line 185

def stop
  kill
  EventMachine.stop
end

#store(key, value, timestamp = Time.now) ⇒ Object

Stores a key, value pair that will be shared among all the peers in the network.



92
93
94
95
96
# File 'lib/pokan/server.rb', line 92

def store(key, value, timestamp=Time.now)
  super
  save
  @event_handler.emit :new_key, :with => [key, value]
end

#use_epollObject

Call this method if you want to use epoll in your Linux system. Warning: this will not throw an exception nor will warn you if you use this method in a non-Linux machine. You might face errors when you try to start the server, though.



76
77
78
# File 'lib/pokan/server.rb', line 76

def use_epoll
  @epoll = true
end

#using_epoll?Boolean

Returns:

  • (Boolean)


80
81
82
# File 'lib/pokan/server.rb', line 80

def using_epoll?
  @epoll
end