def run(r, args = {})
Log.debug { "run entry, initialising stack to: " + r.to_s }
cleanup = args[:cleanup]
stack = Array.new
stack << r
while stack.size > 0 do
Log.debug { "stack size is #{stack.size}" }
Log.debug {
counter = 0
output = ""
for entry in stack.reverse do
output+= sprintf "%04d %s\n", counter, entry.to_s
counter+= 1
end
output
}
raise "bad stack" if stack.size > 1000
r = stack.pop
Log.debug { "running on stack entry #{r}" }
case r
when :calc_resolve
r = stack.pop
r.resolve_calculate
refres = r.referral_resolution?
p = (refres == true ? @progress_resolve : @progress_main)
p.call(:state => @state, :referral => r, :stage => :resolve)
stack << r
next
when :calc_answer
r = stack.pop
r.answer_calculate
refres = r.referral_resolution?
p = (refres == true ? @progress_resolve : @progress_main)
p.call(:state => @state, :referral => r, :stage => :answer)
r.cleanup(cleanup)
if @fast then
key = "#{r.qname}:#{r.qclass}:#{r.qtype}:#{r.server}:#{r.txt_ips_verbose}"
key.downcase!
Log.debug { "Fast mode cache store: #{key}" }
@answered[key] = r
end
unless r.server.nil? then
@seen[r.server.downcase] = [] unless @seen.has_key?(r.server)
@seen[r.server.downcase].concat(r.ips_as_array)
@seen[r.server.downcase].uniq!
end
next
else
refres = r.referral_resolution?
p = (refres == true ? @progress_resolve : @progress_main)
p.call(:state => @state, :referral => r, :stage => :start)
end
unless r.resolved? then
stack << r << :calc_resolve
stack.push(*r.resolve({}).reverse)
next
end
unless r.processed? then
stack << r << :calc_answer
children = r.process({})
if @fast then
Log.debug { "Checking #{r} for already completed children" }
newchildren = []
for c in children do
key = "#{c.qname}:#{c.qclass}:#{c.qtype}:#{c.server}:#{c.txt_ips_verbose}"
key.downcase!
Log.debug { "Fast mode cache lookup: #{key}" }
if @answered.key?(key) and (not c.noglue?) then
Log.debug { "Fast method - completed #{c}" }
r.replace_child(c, @answered[key])
refres = r.referral_resolution?
p = (refres == true ? @progress_resolve : @progress_main)
p.call(:state => @state, :referral => c, :stage => :answer_fast)
else
newchildren << c
end
end
children = newchildren
end
stack.push(*children.reverse)
next
end
raise "Fatal stack error at #{r} - size still #{stack.size}"
end
end