better error handling

This commit is contained in:
Ward Wouts 2002-07-03 22:18:40 +00:00
parent 0154d6292d
commit 9026140c4e
2 changed files with 89 additions and 97 deletions

View file

@ -15,6 +15,11 @@ require 'news/newsrc'
require 'tempfile'
require 'timeout'
class ArticleError < RuntimeError; end
class ReconnectError < ArticleError; end
class GroupInfoError < ArticleError; end
class BodyError < ArticleError; end
class Article
Debuglevel = 0
@ -41,25 +46,21 @@ def initialize(nntpservers, groupname, newsrc="~/.newsrc")
@connections[server]["newsrc"] = News::Newsrc.new("#{newsrc}.#{server}")
set_skip_ids(server, @connections[server]["newsrc"].marked_articles(@group))
rescue SocketError
print "Connection to #{server} failed, removing from server list...\n"
@connections.delete(server)
@serverlist.delete(server)
print "Connection to #{server} failed\n"
del_server(server)
end
}
end
def reconnect(server)
print "Trying to reconnect to #{server}...\n"
begin
@connections[server]["nntp"] = Net::NNTP.new(server)
rescue SocketError
print "Connection to #{server} failed, removing from server list...\n"
@connections.delete(server)
@serverlist.delete(server)
return false
print "Reconnect to #{server} failed\n"
del_server(server)
raise ReconnectError
end
print "Succesfully reconnected to #{server}\n"
return true
end
def add(messid, id, server, subject)
@ -75,29 +76,32 @@ def add(messid, id, server, subject)
@grouped = false
end
def del_server(server)
print "Removing server #{server} from list\n"
@connections.delete(server)
@serverlist.delete(server)
end
def get_articles(cachedir=false)
for server in @connections.keys
begin
first, last = get_group_info(server)
return false if first == false
if first
rescue ReconnectError, GroupInfoError
del_server(server)
next
end
if first <= last
@connections[server]["first"] = first ? first : 0
@connections[server]["last"] = last ? last : 0
else
print "Error selecting @group on server #{server}, removing from server list...\n"
@connections.delete(server)
@serverlist.delete(server)
print " First article has higher number than last article on server #{server}.\n"
del_server(server)
end
end
read_cache(cachedir)
for server in @connections.keys
print " reading articles from server: #{server}\n"
if @connections[server]["first"] > @connections[server]["last"]
print " First article has higher number than last article on server #{server}.\n"
print " Skipping...\n"
next
else
range = Set::IntSpan.new("#{@connections[server]["first"]}-#{@connections[server]["last"]}")
end
rangelist = rechunk_runlist(range.diff(@connections[server]["skip_ids"]).run_list)
print "rangelist: #{rangelist}\n" if Debuglevel >1
print "rangelist: #{rangelist.type.to_s}\n" if Debuglevel >1
@ -105,10 +109,13 @@ def get_articles(cachedir=false)
unless rangelist == nil or rangelist =~ /^$/
for i in rangelist.split(',')
print "i: #{i}\n" if Debuglevel > 1
begin
resp, subj_lines = get_xhdr(server, i, "subject")
next unless resp
resp, messid_lines = get_xhdr(server, i, "message-id")
next unless resp
rescue TimeoutError, ReconnectError, XhdrError, GroupInfoError
print "Caught: #{$!} reading from #{server}\n"
next
end
art = {}
subj_lines.collect{|x|
@ -139,30 +146,27 @@ def get_group_info(server)
first = ""
last = ""
begin
if timedout > 1
print "Too many timeouts! (get_group_info)\n"
return false
end
timeout(30) do
begin
resp, count, first, last, name = @connections[server]["nntp"].group(@group)
rescue Net::NNTP::RuntimeError
print "Couldn't open group: #{@group}\n"
print "Error: #{$!}\n"
return false
print "Got error \"#{$!}\" from #{server}\n"
raise GroupInfoError
rescue Errno::EPIPE, Errno::ECONNRESET
print "Caught Errno::EPIPE reading from server #{server}\n"
print "Error: #{$!}\n"
retry if reconnect(server)
reconnect(server)
retry
end
end
return first, last if resp
rescue TimeoutError
print "Time out, reconnecting to server\n"
timedout += 1
retry if reconnect(server)
raise TimeoutError, "Too many timeouts! (get_group_info)\n" if timedout > 1
print "Time out, reconnecting to server...\n"
reconnect(server)
retry
end
return false
return first, last
end
def get_xhdr(server, range, header)
@ -170,16 +174,12 @@ def get_xhdr(server, range, header)
resp = ""
lines = []
begin
if timedout > 1
print "Too many timeouts! (get_xhdr)\n"
return false
end
timeout(180) do
begin
resp, lines = @connections[server]["nntp"].xhdr(header, range)
unless resp.to_i >= 200 and resp.to_i < 300
print "got response #{resp} while reading group #{@group} from #{server}\n"
return false
raise XhdrError
end
rescue Net::NNTP::RuntimeError
print "Caught Net::NNTP::RuntimeError reading from server #{server}\n"
@ -187,22 +187,21 @@ def get_xhdr(server, range, header)
rescue Errno::EPIPE, Errno::ECONNRESET
print "Caught Errno::EPIPE reading from server #{server}\n"
print "Error: #{$!}\n"
if reconnect(server)
return false unless get_group_info(server)
reconnect(server)
get_group_info(server)
retry
end
end
end
return resp, lines
rescue TimeoutError
print "Time out, reconnecting to server\n"
timedout += 1
if reconnect(server)
return false unless get_group_info(server)
raise TimeoutError, "Too many timeouts! (get_xhrd)\n" if timedout > 1
reconnect(server)
get_group_info(server)
retry
end
end
end
# if xhdr doesn't work, this should be used
# for i in (range.diff(@connections[server]["skip_ids"]).elements)
@ -240,10 +239,6 @@ def get_body(server, message)
messid = ""
list = []
begin
if timedout > 1
print "Too many timeouts! (get_body)\n"
return false
end
timeout(180) do
begin
resp, id, messid, list = @connections[server]["nntp"].body(message)
@ -254,22 +249,21 @@ def get_body(server, message)
rescue Errno::EPIPE, Errno::ECONNRESET
print "Caught Errno::EPIPE reading from server #{server}\n"
print "Error: #{$!}\n"
if reconnect(server)
return false unless get_group_info(server)
reconnect(server)
get_group_info(server)
retry
end
end
end
return resp, id, messid, list
rescue TimeoutError
print "Time out, reconnecting to server\n"
timedout += 1
if reconnect(server)
return false unless get_group_info(server)
raise TimeoutError, "Too many timeouts! (get_body)\n" if timedout > 1
reconnect(server)
get_group_info(server)
retry
end
end
end
def get_group_body(subj)
result = []
@ -293,8 +287,7 @@ def get_group_body(subj)
i += 1
retry
else
print "Message-id not on another server :( Skipping...\n"
return false
raise BodyError, "Message-id not on another server\n"
end
end
end
@ -325,8 +318,7 @@ def get_group_body_first(subj)
i += 1
retry
else
print "Message-id not on another server :( Skipping...\n"
return false
raise BodyError, "Message-id not on another server\n"
end
end
end
@ -356,8 +348,7 @@ def get_group_body_rest(subj, file=nil)
i += 1
retry
else
print "Message-id not on another server :( Skipping...\n"
return false
raise BodyError, "Message-id not on another server\n"
end
end
end

View file

@ -224,7 +224,6 @@ def get_multi(subj, group)
return false
else
body = @articles.get_group_body_first(subj)
return false if body == false
if @articles.is_uuencoded(body) or @articles.is_yencoded(body)
file = Tempfile.new("riptmp", @config[group]["TEMPDIR"])
body.collect{|x| file.print "#{x}\n"}
@ -248,7 +247,6 @@ def get_multi(subj, group)
end
def output_data(subject, mode, filename="", body="")
if mode
group = @articles.get_groupname
print " mode: #{mode}\n" if Debuglevel > 0
print " Filename: '#{filename}'\n" if Debuglevel > 0
@ -266,10 +264,6 @@ def output_data(subject, mode, filename="", body="")
@articles.group_update_newsrc(subject)
@articles.save_newsrc unless @config[group].has_key?("-T") and @config[group]["-T"]
end
else
return false
end
return true
end
def check_ext(filename, mode)
@ -303,10 +297,13 @@ end
for group in @config.keys.sort
print "Getting articles for #{group}\n"
@articles = Article.new(@config[group]["NNTPSERVER"], group, @config[group]["NEWSRCNAME"])
if @articles.get_articles(@config[group]["CACHEDIR"]) == false
@articles.quit
next
end
# begin
@articles.get_articles(@config[group]["CACHEDIR"])
# rescue Article::
# print "Caught something: #{$!}\n"
# @articles.quit
# next
# end
unless FileTest.directory?("#{@config[group]["DATADIR"]}/#{group}") or
Dir.mkdir("#{@config[group]["DATADIR"]}/#{group}", @config[group]["PERMISSION"].oct)
@ -319,12 +316,16 @@ for group in @config.keys.sort
i =~ /#{@config[group]["-I"]}/
print "Match: #{i}\n" if Debuglevel > 0
if @articles.group_is_complete(i)
begin
if @articles.group_is_singlepart(i)
mode, filename, body = get_single(i)
elsif @articles.group_is_multipart(i)
mode, filename, body = get_multi(i, group)
end
output_data(i, mode, filename, body)
output_data(i, mode, filename, body) if mode != false
rescue Article::BodyError
next
end
else
print " Not complete: #{i}\n"
end