Skip to content

Commit

Permalink
Some initial work to try to make ManagerInterface not leak on disconn…
Browse files Browse the repository at this point in the history
…ect and

to support ManagerInterface#disconnect!
  • Loading branch information
eric authored and bklang committed Jul 13, 2010
1 parent b4e0913 commit 1613196
Showing 1 changed file with 74 additions and 16 deletions.
90 changes: 74 additions & 16 deletions lib/adhearsion/voip/asterisk/manager_interface.rb
Expand Up @@ -228,12 +228,13 @@ def connect!

def actions_connection_established
@actions_state = :connected
@actions_writer_thread = Thread.new(&method(:write_loop))
start_actions_writer_loop
end

def actions_connection_disconnected
@actions_state = :disconnected
ahn_log.ami.error "AMI connection for ACTION disconnected !!!"
clear_actions_connection
establish_actions_connection if @auto_reconnect
end

Expand All @@ -244,14 +245,23 @@ def events_connection_established
def events_connection_disconnected
@events_state = :disconnected
ahn_log.ami.error "AMI connection for EVENT disconnected !!!"
clear_events_connection
establish_events_connection if @auto_reconnect
end

def clear_actions_connection
stop_actions_writer_loop
clear_actions_connection_resources
disconnect_actions_connection
end

def clear_events_connection
disconnect_events_connection
end

def disconnect!
# PSEUDO CODE
# TODO: Go through all the waiting condition variables and raise an exception
#@write_queue << :STOP!
#raise NotImplementedError
clear_actions_connection
clear_events_connection
end

def dynamic
Expand Down Expand Up @@ -426,19 +436,33 @@ def check_action_name(name)
true
end

def write_loop
def start_actions_writer_loop
@actions_writer_thread = Thread.new(&method(:actions_writer_loop))
end

def stop_actions_writer_loop
if @actions_writer_thread
@write_queue << :STOP!
@actions_writer_thread.join
@actions_writer_thread = nil
end
end

def actions_writer_loop
loop do
next_action = @write_queue.shift
return :stopped if next_action.equal? :STOP!
register_action_with_metadata next_action

ahn_log.ami.debug "Sending AMI action: #{"\n>>> " + next_action.to_s.gsub(/(\r\n)+/, "\n>>> ")}"
@actions_connection.send_data next_action.to_s
# If it's "causal event" action, we must wait here until it's fully responded
next_action.response if next_action.has_causal_events?
begin
next_action = @write_queue.shift
return :stopped if next_action.equal? :STOP!
register_action_with_metadata next_action

ahn_log.ami.debug "Sending AMI action: #{"\n>>> " + next_action.to_s.gsub(/(\r\n)+/, "\n>>> ")}"
@actions_connection.send_data next_action.to_s
# If it's "causal event" action, we must wait here until it's fully responded
next_action.response if next_action.has_causal_events?
rescue Object => e
ahn_log.ami.debug "Error in AMI writer loop: #{e.class}: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
end
end
rescue => e
p e
end

##
Expand All @@ -464,6 +488,22 @@ def data_for_message_received_with_action_id(action_id)
end
end

# Give an error response to any outstanding messages -- they
# won't be completed now
def clear_actions_connection_resources
# Fail all outstanding messages and reset the message list
@sent_messages_lock.synchronize do
@sent_messages.each do |action_id, action|
error = ManagerInterfaceError.new
error.message = "Connection terminated to AMI server"

action.future_resource.resource = error
end

@sent_messages = {}
end
end

##
# Instantiates a new ManagerInterfaceActionsConnection and assigns it to @actions_connection.
#
Expand All @@ -478,6 +518,15 @@ def establish_actions_connection
login_actions
end

def disconnect_actions_connection
# Clean up the EventSocket we may have
if @actions_connection
@actions_connection.disconnect!
@actions_connection.join
@actions_connection = nil
end
end

##
# Instantiates a new ManagerInterfaceEventsConnection and assigns it to @events_connection.
#
Expand Down Expand Up @@ -506,6 +555,15 @@ def login_actions
end
end

def disconnect_events_connection
# Clean up the EventSocket we may have
if @events_connection
@events_connection.disconnect!
@events_connection.join
@events_connection = nil
end
end

##
# Since this method is always called after the login_actions method, an AuthenticationFailedException would have already
# been raised if the username/password were off. Because this is the only action we ever need to send on this socket,
Expand Down

0 comments on commit 1613196

Please sign in to comment.