better error handling
This commit is contained in:
parent
0154d6292d
commit
9026140c4e
2 changed files with 89 additions and 97 deletions
|
|
@ -15,6 +15,11 @@ require 'news/newsrc'
|
||||||
require 'tempfile'
|
require 'tempfile'
|
||||||
require 'timeout'
|
require 'timeout'
|
||||||
|
|
||||||
|
class ArticleError < RuntimeError; end
|
||||||
|
class ReconnectError < ArticleError; end
|
||||||
|
class GroupInfoError < ArticleError; end
|
||||||
|
class BodyError < ArticleError; end
|
||||||
|
|
||||||
class Article
|
class Article
|
||||||
|
|
||||||
Debuglevel = 0
|
Debuglevel = 0
|
||||||
|
|
@ -41,25 +46,21 @@ def initialize(nntpservers, groupname, newsrc="~/.newsrc")
|
||||||
@connections[server]["newsrc"] = News::Newsrc.new("#{newsrc}.#{server}")
|
@connections[server]["newsrc"] = News::Newsrc.new("#{newsrc}.#{server}")
|
||||||
set_skip_ids(server, @connections[server]["newsrc"].marked_articles(@group))
|
set_skip_ids(server, @connections[server]["newsrc"].marked_articles(@group))
|
||||||
rescue SocketError
|
rescue SocketError
|
||||||
print "Connection to #{server} failed, removing from server list...\n"
|
print "Connection to #{server} failed\n"
|
||||||
@connections.delete(server)
|
del_server(server)
|
||||||
@serverlist.delete(server)
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def reconnect(server)
|
def reconnect(server)
|
||||||
print "Trying to reconnect to #{server}...\n"
|
|
||||||
begin
|
begin
|
||||||
@connections[server]["nntp"] = Net::NNTP.new(server)
|
@connections[server]["nntp"] = Net::NNTP.new(server)
|
||||||
rescue SocketError
|
rescue SocketError
|
||||||
print "Connection to #{server} failed, removing from server list...\n"
|
print "Reconnect to #{server} failed\n"
|
||||||
@connections.delete(server)
|
del_server(server)
|
||||||
@serverlist.delete(server)
|
raise ReconnectError
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
print "Succesfully reconnected to #{server}\n"
|
print "Succesfully reconnected to #{server}\n"
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add(messid, id, server, subject)
|
def add(messid, id, server, subject)
|
||||||
|
|
@ -75,29 +76,32 @@ def add(messid, id, server, subject)
|
||||||
@grouped = false
|
@grouped = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def del_server(server)
|
||||||
|
print "Removing server #{server} from list\n"
|
||||||
|
@connections.delete(server)
|
||||||
|
@serverlist.delete(server)
|
||||||
|
end
|
||||||
|
|
||||||
def get_articles(cachedir=false)
|
def get_articles(cachedir=false)
|
||||||
for server in @connections.keys
|
for server in @connections.keys
|
||||||
|
begin
|
||||||
first, last = get_group_info(server)
|
first, last = get_group_info(server)
|
||||||
return false if first == false
|
rescue ReconnectError, GroupInfoError
|
||||||
if first
|
del_server(server)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
if first <= last
|
||||||
@connections[server]["first"] = first ? first : 0
|
@connections[server]["first"] = first ? first : 0
|
||||||
@connections[server]["last"] = last ? last : 0
|
@connections[server]["last"] = last ? last : 0
|
||||||
else
|
else
|
||||||
print "Error selecting @group on server #{server}, removing from server list...\n"
|
print " First article has higher number than last article on server #{server}.\n"
|
||||||
@connections.delete(server)
|
del_server(server)
|
||||||
@serverlist.delete(server)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
read_cache(cachedir)
|
read_cache(cachedir)
|
||||||
for server in @connections.keys
|
for server in @connections.keys
|
||||||
print " reading articles from server: #{server}\n"
|
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"]}")
|
range = Set::IntSpan.new("#{@connections[server]["first"]}-#{@connections[server]["last"]}")
|
||||||
end
|
|
||||||
rangelist = rechunk_runlist(range.diff(@connections[server]["skip_ids"]).run_list)
|
rangelist = rechunk_runlist(range.diff(@connections[server]["skip_ids"]).run_list)
|
||||||
print "rangelist: #{rangelist}\n" if Debuglevel >1
|
print "rangelist: #{rangelist}\n" if Debuglevel >1
|
||||||
print "rangelist: #{rangelist.type.to_s}\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 =~ /^$/
|
unless rangelist == nil or rangelist =~ /^$/
|
||||||
for i in rangelist.split(',')
|
for i in rangelist.split(',')
|
||||||
print "i: #{i}\n" if Debuglevel > 1
|
print "i: #{i}\n" if Debuglevel > 1
|
||||||
|
begin
|
||||||
resp, subj_lines = get_xhdr(server, i, "subject")
|
resp, subj_lines = get_xhdr(server, i, "subject")
|
||||||
next unless resp
|
|
||||||
resp, messid_lines = get_xhdr(server, i, "message-id")
|
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 = {}
|
art = {}
|
||||||
subj_lines.collect{|x|
|
subj_lines.collect{|x|
|
||||||
|
|
@ -139,30 +146,27 @@ def get_group_info(server)
|
||||||
first = ""
|
first = ""
|
||||||
last = ""
|
last = ""
|
||||||
begin
|
begin
|
||||||
if timedout > 1
|
|
||||||
print "Too many timeouts! (get_group_info)\n"
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
timeout(30) do
|
timeout(30) do
|
||||||
begin
|
begin
|
||||||
resp, count, first, last, name = @connections[server]["nntp"].group(@group)
|
resp, count, first, last, name = @connections[server]["nntp"].group(@group)
|
||||||
rescue Net::NNTP::RuntimeError
|
rescue Net::NNTP::RuntimeError
|
||||||
print "Couldn't open group: #{@group}\n"
|
print "Got error \"#{$!}\" from #{server}\n"
|
||||||
print "Error: #{$!}\n"
|
raise GroupInfoError
|
||||||
return false
|
|
||||||
rescue Errno::EPIPE, Errno::ECONNRESET
|
rescue Errno::EPIPE, Errno::ECONNRESET
|
||||||
print "Caught Errno::EPIPE reading from server #{server}\n"
|
print "Caught Errno::EPIPE reading from server #{server}\n"
|
||||||
print "Error: #{$!}\n"
|
print "Error: #{$!}\n"
|
||||||
retry if reconnect(server)
|
reconnect(server)
|
||||||
|
retry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return first, last if resp
|
|
||||||
rescue TimeoutError
|
rescue TimeoutError
|
||||||
print "Time out, reconnecting to server\n"
|
|
||||||
timedout += 1
|
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
|
end
|
||||||
return false
|
return first, last
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_xhdr(server, range, header)
|
def get_xhdr(server, range, header)
|
||||||
|
|
@ -170,16 +174,12 @@ def get_xhdr(server, range, header)
|
||||||
resp = ""
|
resp = ""
|
||||||
lines = []
|
lines = []
|
||||||
begin
|
begin
|
||||||
if timedout > 1
|
|
||||||
print "Too many timeouts! (get_xhdr)\n"
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
timeout(180) do
|
timeout(180) do
|
||||||
begin
|
begin
|
||||||
resp, lines = @connections[server]["nntp"].xhdr(header, range)
|
resp, lines = @connections[server]["nntp"].xhdr(header, range)
|
||||||
unless resp.to_i >= 200 and resp.to_i < 300
|
unless resp.to_i >= 200 and resp.to_i < 300
|
||||||
print "got response #{resp} while reading group #{@group} from #{server}\n"
|
print "got response #{resp} while reading group #{@group} from #{server}\n"
|
||||||
return false
|
raise XhdrError
|
||||||
end
|
end
|
||||||
rescue Net::NNTP::RuntimeError
|
rescue Net::NNTP::RuntimeError
|
||||||
print "Caught Net::NNTP::RuntimeError reading from server #{server}\n"
|
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
|
rescue Errno::EPIPE, Errno::ECONNRESET
|
||||||
print "Caught Errno::EPIPE reading from server #{server}\n"
|
print "Caught Errno::EPIPE reading from server #{server}\n"
|
||||||
print "Error: #{$!}\n"
|
print "Error: #{$!}\n"
|
||||||
if reconnect(server)
|
reconnect(server)
|
||||||
return false unless get_group_info(server)
|
get_group_info(server)
|
||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
return resp, lines
|
return resp, lines
|
||||||
rescue TimeoutError
|
rescue TimeoutError
|
||||||
print "Time out, reconnecting to server\n"
|
print "Time out, reconnecting to server\n"
|
||||||
timedout += 1
|
timedout += 1
|
||||||
if reconnect(server)
|
raise TimeoutError, "Too many timeouts! (get_xhrd)\n" if timedout > 1
|
||||||
return false unless get_group_info(server)
|
reconnect(server)
|
||||||
|
get_group_info(server)
|
||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# if xhdr doesn't work, this should be used
|
# if xhdr doesn't work, this should be used
|
||||||
# for i in (range.diff(@connections[server]["skip_ids"]).elements)
|
# for i in (range.diff(@connections[server]["skip_ids"]).elements)
|
||||||
|
|
@ -240,10 +239,6 @@ def get_body(server, message)
|
||||||
messid = ""
|
messid = ""
|
||||||
list = []
|
list = []
|
||||||
begin
|
begin
|
||||||
if timedout > 1
|
|
||||||
print "Too many timeouts! (get_body)\n"
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
timeout(180) do
|
timeout(180) do
|
||||||
begin
|
begin
|
||||||
resp, id, messid, list = @connections[server]["nntp"].body(message)
|
resp, id, messid, list = @connections[server]["nntp"].body(message)
|
||||||
|
|
@ -254,22 +249,21 @@ def get_body(server, message)
|
||||||
rescue Errno::EPIPE, Errno::ECONNRESET
|
rescue Errno::EPIPE, Errno::ECONNRESET
|
||||||
print "Caught Errno::EPIPE reading from server #{server}\n"
|
print "Caught Errno::EPIPE reading from server #{server}\n"
|
||||||
print "Error: #{$!}\n"
|
print "Error: #{$!}\n"
|
||||||
if reconnect(server)
|
reconnect(server)
|
||||||
return false unless get_group_info(server)
|
get_group_info(server)
|
||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
return resp, id, messid, list
|
return resp, id, messid, list
|
||||||
rescue TimeoutError
|
rescue TimeoutError
|
||||||
print "Time out, reconnecting to server\n"
|
print "Time out, reconnecting to server\n"
|
||||||
timedout += 1
|
timedout += 1
|
||||||
if reconnect(server)
|
raise TimeoutError, "Too many timeouts! (get_body)\n" if timedout > 1
|
||||||
return false unless get_group_info(server)
|
reconnect(server)
|
||||||
|
get_group_info(server)
|
||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def get_group_body(subj)
|
def get_group_body(subj)
|
||||||
result = []
|
result = []
|
||||||
|
|
@ -293,8 +287,7 @@ def get_group_body(subj)
|
||||||
i += 1
|
i += 1
|
||||||
retry
|
retry
|
||||||
else
|
else
|
||||||
print "Message-id not on another server :( Skipping...\n"
|
raise BodyError, "Message-id not on another server\n"
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -325,8 +318,7 @@ def get_group_body_first(subj)
|
||||||
i += 1
|
i += 1
|
||||||
retry
|
retry
|
||||||
else
|
else
|
||||||
print "Message-id not on another server :( Skipping...\n"
|
raise BodyError, "Message-id not on another server\n"
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -356,8 +348,7 @@ def get_group_body_rest(subj, file=nil)
|
||||||
i += 1
|
i += 1
|
||||||
retry
|
retry
|
||||||
else
|
else
|
||||||
print "Message-id not on another server :( Skipping...\n"
|
raise BodyError, "Message-id not on another server\n"
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,6 @@ def get_multi(subj, group)
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
body = @articles.get_group_body_first(subj)
|
body = @articles.get_group_body_first(subj)
|
||||||
return false if body == false
|
|
||||||
if @articles.is_uuencoded(body) or @articles.is_yencoded(body)
|
if @articles.is_uuencoded(body) or @articles.is_yencoded(body)
|
||||||
file = Tempfile.new("riptmp", @config[group]["TEMPDIR"])
|
file = Tempfile.new("riptmp", @config[group]["TEMPDIR"])
|
||||||
body.collect{|x| file.print "#{x}\n"}
|
body.collect{|x| file.print "#{x}\n"}
|
||||||
|
|
@ -248,7 +247,6 @@ def get_multi(subj, group)
|
||||||
end
|
end
|
||||||
|
|
||||||
def output_data(subject, mode, filename="", body="")
|
def output_data(subject, mode, filename="", body="")
|
||||||
if mode
|
|
||||||
group = @articles.get_groupname
|
group = @articles.get_groupname
|
||||||
print " mode: #{mode}\n" if Debuglevel > 0
|
print " mode: #{mode}\n" if Debuglevel > 0
|
||||||
print " Filename: '#{filename}'\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.group_update_newsrc(subject)
|
||||||
@articles.save_newsrc unless @config[group].has_key?("-T") and @config[group]["-T"]
|
@articles.save_newsrc unless @config[group].has_key?("-T") and @config[group]["-T"]
|
||||||
end
|
end
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_ext(filename, mode)
|
def check_ext(filename, mode)
|
||||||
|
|
@ -303,10 +297,13 @@ end
|
||||||
for group in @config.keys.sort
|
for group in @config.keys.sort
|
||||||
print "Getting articles for #{group}\n"
|
print "Getting articles for #{group}\n"
|
||||||
@articles = Article.new(@config[group]["NNTPSERVER"], group, @config[group]["NEWSRCNAME"])
|
@articles = Article.new(@config[group]["NNTPSERVER"], group, @config[group]["NEWSRCNAME"])
|
||||||
if @articles.get_articles(@config[group]["CACHEDIR"]) == false
|
# begin
|
||||||
@articles.quit
|
@articles.get_articles(@config[group]["CACHEDIR"])
|
||||||
next
|
# rescue Article::
|
||||||
end
|
# print "Caught something: #{$!}\n"
|
||||||
|
# @articles.quit
|
||||||
|
# next
|
||||||
|
# end
|
||||||
|
|
||||||
unless FileTest.directory?("#{@config[group]["DATADIR"]}/#{group}") or
|
unless FileTest.directory?("#{@config[group]["DATADIR"]}/#{group}") or
|
||||||
Dir.mkdir("#{@config[group]["DATADIR"]}/#{group}", @config[group]["PERMISSION"].oct)
|
Dir.mkdir("#{@config[group]["DATADIR"]}/#{group}", @config[group]["PERMISSION"].oct)
|
||||||
|
|
@ -319,12 +316,16 @@ for group in @config.keys.sort
|
||||||
i =~ /#{@config[group]["-I"]}/
|
i =~ /#{@config[group]["-I"]}/
|
||||||
print "Match: #{i}\n" if Debuglevel > 0
|
print "Match: #{i}\n" if Debuglevel > 0
|
||||||
if @articles.group_is_complete(i)
|
if @articles.group_is_complete(i)
|
||||||
|
begin
|
||||||
if @articles.group_is_singlepart(i)
|
if @articles.group_is_singlepart(i)
|
||||||
mode, filename, body = get_single(i)
|
mode, filename, body = get_single(i)
|
||||||
elsif @articles.group_is_multipart(i)
|
elsif @articles.group_is_multipart(i)
|
||||||
mode, filename, body = get_multi(i, group)
|
mode, filename, body = get_multi(i, group)
|
||||||
end
|
end
|
||||||
output_data(i, mode, filename, body)
|
output_data(i, mode, filename, body) if mode != false
|
||||||
|
rescue Article::BodyError
|
||||||
|
next
|
||||||
|
end
|
||||||
else
|
else
|
||||||
print " Not complete: #{i}\n"
|
print " Not complete: #{i}\n"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue