Class: CorosyncCommander::Execution

Inherits:
Object
  • Object
show all
Defined in:
lib/corosync_commander/execution.rb,
lib/corosync_commander/execution/message.rb

Defined Under Namespace

Classes: Message

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cc, id, recipients, command, args) ⇒ Execution

Returns a new instance of Execution.



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/corosync_commander/execution.rb', line 11

def initialize(cc, id, recipients, command, args)
	@cc = cc
	@id = id
	@recipients = Corosync::CPG::MemberList.new(recipients)
	@command = command
	@args = args

	@queue = Queue.new

	@pending_members = nil

	@responses = []
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



8
9
10
# File 'lib/corosync_commander/execution.rb', line 8

def args
  @args
end

#commandObject (readonly)

Returns the value of attribute command.



7
8
9
# File 'lib/corosync_commander/execution.rb', line 7

def command
  @command
end

#idObject (readonly)

Returns the value of attribute id.



5
6
7
# File 'lib/corosync_commander/execution.rb', line 5

def id
  @id
end

#pending_membersObject (readonly)

Returns the value of attribute pending_members.



9
10
11
# File 'lib/corosync_commander/execution.rb', line 9

def pending_members
  @pending_members
end

#queueObject (readonly)

Returns the value of attribute queue.



4
5
6
# File 'lib/corosync_commander/execution.rb', line 4

def queue
  @queue
end

#recipientsObject (readonly)

Returns the value of attribute recipients.



6
7
8
# File 'lib/corosync_commander/execution.rb', line 6

def recipients
  @recipients
end

Instance Method Details

#discardObject

This is just so that we can remove the queue from execution_queues and avoid running unnecessary code on receipt of message/confchg



86
87
88
89
90
91
92
# File 'lib/corosync_commander/execution.rb', line 86

def discard
	@cc.execution_queues.sync_synchronize(:EX) do
		@cc.execution_queues.delete(@id)
	end
	@queue.clear
	@queue = []
end

#get_responseCorosyncCommander::Execution::Message

Gets the next response message from the queue. This is used internally and is probably not what you want. See #response



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/corosync_commander/execution.rb', line 97

def get_response
	return if !@queue.is_a?(Queue) # we've called `clear`

	while @pending_members.nil?
		if Thread.current.object_id == @cc.dispatch_thread.object_id then
			raise StandardError, "Deadlock! Can not call wait for responses on callback thread."
		end
		message = @queue.shift

		next if message.type == 'leave' # we havent received the echo, so we dont care yet

		raise RuntimeError, "Received unexpected response while waiting for echo" if message.type != 'echo'

		# CorosyncCommander#cpg_message sets the content to the list of cpg members at the time the echo was received
		@pending_members = @recipients.size == 0 ? message.content.dup : message.content & @recipients
	end

	return if @pending_members.size == 0

	message = @queue.shift

	@pending_members.delete message.sender
	if @pending_members.size == 0 then
		self.discard
	end

	return if message.type == 'leave' # we already did @pending_members.delete above

	message
end

#responseCorosyncCommander::Execution::Message Also known as: next

Gets the next response, blocking if none has been returned yet. This will also raise an exception if the remote process raised an exception. This can be tested by calling ‘exception.is_a?(CorosyncCommander::RemoteException)`

Returns:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/corosync_commander/execution.rb', line 28

def response
	response = get_response

	return nil if response.nil?

	if response.type == 'exception'
		e_class = Kernel.const_get(response.content[0])
		e_class = StandardError if e_class.nil? or !(e_class <= Exception) # The remote node might have types we don't have. So if we don't have them use StandardError
		e = e_class.new(response.content[1] + " (CorosyncCommander::RemoteException@#{response.sender})")
		e.set_backtrace(response.content[2])
		e.extend(CorosyncCommander::RemoteException)
		e.sender = response.sender
		raise e
	end

	response
end

#to_enum(*ignore) {|response, sender| ... } ⇒ Enumerator

Provides an enumerator that can be looped through. Will raise an exception if the remote node generated an exception. Can be verified by calling ‘is_a?(CorosyncCommander::RemoteException)`. Restarting the enumerator will not restart from the first response, it will continue on to the next.

Parameters:

  • ignore (Exception, Boolean)

    List of exception classes to suppress. ‘true` for all

Yield Parameters:

  • response (Object)

    The response generated by the remote command.

  • sender (Corosync::CPG::Member)

    The node which generated the response.

Returns:

  • (Enumerator)


54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/corosync_commander/execution.rb', line 54

def to_enum(*ignore)
	ignore = [Exception] if ignore.size == 1 and ignore[0] == true

	Enumerator.new do |block|
		begin
			while response = self.response do
				block.yield response.sender, response.content
			end
		rescue CorosyncCommander::RemoteException => e
			retry if ignore.find {|extype| e.is_a?(extype)}
			raise e
		end
	end
end

#wait(ignore_exception = false) ⇒ Boolean

Wait for all responses to come in, but discard them. Useful to block waiting for the remote commands to finish when you dont care about the result.

Parameters:

  • ignore_exception (Boolean) (defaults to: false)

    Whether to ignore remote exceptions, or raise them. If ‘true`, remote exceptions will not raise an exception here.

Returns:

  • (Boolean)

    Returns ‘true` if no exceptions were raised, `false` otherwise.



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/corosync_commander/execution.rb', line 73

def wait(ignore_exception = false)
	success = true
	begin
		while response do end
	rescue CorosyncCommander::RemoteException => e
		success = false
		retry if ignore_exception
		raise e
	end
	success
end