Module: EMRPC::Pid

Includes:
DebugPidCallbacks, DefaultCallbacks, ProtocolMapper
Included in:
EventedWrapper, ReconnectingPid, RemotePid, Timer
Defined in:
lib/emrpc/evented_api/pid.rb,
lib/emrpc/util/codec.rb

Overview

Pid is a abbreviation for “process id”. Pid represents so-called lightweight process (like in Erlang OTP) Pids can be created, connected, disconnected, spawned, killed. When pid is created, it exists on its own. When someone connects to the pid, connection is established. When pid is killed, all its connections are unbinded.

Defined Under Namespace

Classes: Marshallable

Constant Summary

Constants included from ProtocolMapper

EMRPC::ProtocolMapper::MAP

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DebugPidCallbacks

#_debug, #connected, #connection_failed, #disconnected, #handshake_failed, #on_raise, #on_return

Methods included from ProtocolMapper

#make_client_connection, #make_server_connection, register_protocol

Methods included from DefaultCallbacks

#connected, #connection_failed, #disconnected, #handshake_failed, #on_raise, #on_return

Instance Attribute Details

#_bind_addressObject

Returns the value of attribute _bind_address.



11
12
13
# File 'lib/emrpc/evented_api/pid.rb', line 11

def _bind_address
  @_bind_address
end

#_em_server_signatureObject

Returns the value of attribute _em_server_signature.



11
12
13
# File 'lib/emrpc/evented_api/pid.rb', line 11

def _em_server_signature
  @_em_server_signature
end

#_protocolObject

Private, but accessible from outside methods are prefixed with underscore.



167
168
169
# File 'lib/emrpc/evented_api/pid.rb', line 167

def _protocol
  @_protocol
end

#connectionsObject

Returns the value of attribute connections.



10
11
12
# File 'lib/emrpc/evented_api/pid.rb', line 10

def connections
  @connections
end

#killedObject

Returns the value of attribute killed.



10
11
12
# File 'lib/emrpc/evented_api/pid.rb', line 10

def killed
  @killed
end

#optionsObject

Returns the value of attribute options.



10
11
12
# File 'lib/emrpc/evented_api/pid.rb', line 10

def options
  @options
end

#uuidObject

Returns the value of attribute uuid.



10
11
12
# File 'lib/emrpc/evented_api/pid.rb', line 10

def uuid
  @uuid
end

Class Method Details

.new(*attributes) ⇒ Object

shorthand for console testing



19
20
21
22
23
24
25
26
27
28
# File 'lib/emrpc/evented_api/pid.rb', line 19

def self.new(*attributes)
  # We create random global const to workaround Marshal.dump issue:
  # >> Marshal.dump(Class.new.new)
  #    TypeError: can't dump anonymous class #<Class:0x5b5338>
  #
  const_set("DynamicPidClass#{rand(2**128).to_s(16).upcase}", Class.new {
    include Pid
    attr_accessor(*attributes)
  }).new
end

Instance Method Details

#==(other) ⇒ Object



154
155
156
# File 'lib/emrpc/evented_api/pid.rb', line 154

def ==(other)
  other.is_a?(Pid) && other.uuid == @uuid
end

#_send_dirty(*args) ⇒ Object

TODO: remove this in favor of using codec.rb



181
182
183
184
# File 'lib/emrpc/evented_api/pid.rb', line 181

def _send_dirty(*args)
  args._initialize_pids_recursively_d4d309bd!(self)
  send(*args)
end

#_uid(uuid = @uuid) ⇒ Object

shorter uuid for pretty output



159
160
161
# File 'lib/emrpc/evented_api/pid.rb', line 159

def _uid(uuid = @uuid)
  uuid && uuid[0,6]
end

#bind(addr) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/emrpc/evented_api/pid.rb', line 53

def bind(addr)
  raise "Pid is already binded!" if @_em_server_signature
  @_bind_address = addr.parsed_uri
  this = self
  @_em_server_signature = make_server_connection(@_bind_address, _protocol)  do |conn|
    conn.local_pid = this
    conn.address = addr
  end
end

#connect(addr, connected_callback = nil, disconnected_callback = nil) ⇒ Object

  1. Connect to the pid.

  2. When connection is established, asks for uuid.

  3. When uuid is received, triggers callback on the client.

(See Protocol for details)



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/emrpc/evented_api/pid.rb', line 67

def connect(addr, connected_callback = nil, disconnected_callback = nil)
  c = if addr.is_a?(Pid) && pid = addr
    LocalConnection.new(self, pid)
  else
    this = self
    make_client_connection(addr, _protocol)  do |conn|
      conn.local_pid = this
      conn.address = addr
    end
  end
  c.connected_callback    = connected_callback
  c.disconnected_callback = disconnected_callback
  c
end

#connection_established(pid, conn) ⇒ Object

TODO: When connecting to a spawned pid, we should transparantly discard TCP connection in favor of local connection.



103
104
105
106
107
# File 'lib/emrpc/evented_api/pid.rb', line 103

def connection_established(pid, conn)
  @connections[pid.uuid] ||= conn
  __send__(conn.connected_callback, pid)
  @connections[pid.uuid].remote_pid || pid # looks like hack, but it is not.
end

#connection_unbind(pid, conn) ⇒ Object



109
110
111
112
# File 'lib/emrpc/evented_api/pid.rb', line 109

def connection_unbind(pid, conn)
  @connections.delete(pid.uuid)
  __send__(conn.disconnected_callback, pid)
end

#connection_uuidsObject



141
142
143
# File 'lib/emrpc/evented_api/pid.rb', line 141

def connection_uuids
  (@connections || {}).keys
end

#disconnect(pid, disconnected_callback = nil) ⇒ Object



82
83
84
85
86
# File 'lib/emrpc/evented_api/pid.rb', line 82

def disconnect(pid, disconnected_callback = nil)
  c = @connections[pid.uuid]
  c.disconnected_callback = disconnected_callback if disconnected_callback
  c.close_connection_after_writing
end

#encode_b381b571_1ab2_5889_8221_855dbbc76242(ref) ⇒ Object



86
87
88
# File 'lib/emrpc/util/codec.rb', line 86

def encode_b381b571_1ab2_5889_8221_855dbbc76242(ref)
  @marshallable_pid ||= Marshallable.new(@uuid)
end

#find_pid(uuid) ⇒ Object



127
128
129
130
# File 'lib/emrpc/evented_api/pid.rb', line 127

def find_pid(uuid)
  return self if uuid == @uuid
  ((conn = @connections[uuid]) and conn.remote_pid) or raise "Pid #{_uid} was not found in a #{self.inspect}"
end

#initialize(*args, &blk) ⇒ Object



30
31
32
33
34
35
# File 'lib/emrpc/evented_api/pid.rb', line 30

def initialize(*args, &blk)
  @uuid = _random_uuid
  @options = {:uuid => @uuid}
  _common_init
  super(*args, &blk) rescue nil
end

#inspectObject



149
150
151
152
# File 'lib/emrpc/evented_api/pid.rb', line 149

def inspect
  return "#<#{pid_class_name}:#{_uid} KILLED>" if @killed
  "#<#{pid_class_name}:#{_uid} connected to #{connection_uuids.map{|u|_uid(u)}.inspect}>"
end

#killObject



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/emrpc/evented_api/pid.rb', line 88

def kill
  return if @killed
  if @_em_server_signature
    EventMachine.stop_server(@_em_server_signature)
  end
  @connections.each do |uuid, conn|
    conn.close_connection_after_writing
  end
  @connections.clear
  @killed = true
end

#killed?Boolean

Returns:

  • (Boolean)


123
124
125
# File 'lib/emrpc/evented_api/pid.rb', line 123

def killed?
  @killed
end

#marshal_dumpObject



132
133
134
# File 'lib/emrpc/evented_api/pid.rb', line 132

def marshal_dump
  @uuid
end

#marshal_load(uuid) ⇒ Object



136
137
138
139
# File 'lib/emrpc/evented_api/pid.rb', line 136

def marshal_load(uuid)
  _common_init
  @uuid = uuid
end

#pid_class_nameObject



145
146
147
# File 'lib/emrpc/evented_api/pid.rb', line 145

def pid_class_name
  "Pid"
end

#spawn(cls, *args, &blk) ⇒ Object



37
38
39
40
41
# File 'lib/emrpc/evented_api/pid.rb', line 37

def spawn(cls, *args, &blk)
  pid = cls.new(*args, &blk)
  connect(pid)
  pid
end

#tcp_spawn(addr, cls, *args, &blk) ⇒ Object



43
44
45
46
47
# File 'lib/emrpc/evented_api/pid.rb', line 43

def tcp_spawn(addr, cls, *args, &blk)
  pid = spawn(cls, *args, &blk)
  pid.bind(addr)
  pid
end

#thread_spawn(cls, *args, &blk) ⇒ Object



49
50
51
# File 'lib/emrpc/evented_api/pid.rb', line 49

def thread_spawn(cls, *args, &blk)
  # TODO: think about thread-safe passing messages back to sender.
end