lib/echi-converter.rb in echi-converter-0.1.1 vs lib/echi-converter.rb in echi-converter-0.2.0
- old
+ new
@@ -1,9 +1,10 @@
require 'rubygems'
require 'active_record'
require 'faster_csv'
require 'net/ftp'
+require 'net/smtp'
require 'fileutils'
class Logger
#Change the logging format to include a timestamp
def format_message(severity, timestamp, progname, msg)
@@ -32,10 +33,11 @@
begin
ActiveRecord::Base.establish_connection(YAML::load(File.open(databaseconfig)))
@log.info "Successfully connected to the database"
rescue => err
@log.fatal "Could not connect to the database - " + err
+ send_email_alert "DATABASE"
end
end
#Method to open our application log
def initiate_logger
@@ -53,10 +55,50 @@
when 'DEBUG'
@log.level = Logger::DEBUG
end
end
+ #Method to send alert emails
+ def send_email_alert reason
+ begin
+ Net::SMTP.start(@config["smtp_server"], @config["smtp_port"]) do |smtp|
+ smtp.open_message_stream('donotreply@echi-converter.rubyforge.org', [@config["alert_email_address"]]) do |f|
+ f.puts "From: donotreply@echi-converter.rubyforge.org"
+ f.puts "To: " + @config['alert_email_address']
+ f.puts "Subject: ECHI-Converter Failure"
+ case reason
+ when "DATABASE"
+ f.puts "Failed to connect to the database."
+ when "FTP"
+ f.puts "Failed to connect to the ftp server."
+ end
+ f.puts " "
+ f.puts "Please check the ECHI-Converter environment as soon as possible."
+ end
+ end
+ rescue => err
+ @log.warn err
+ end
+ end
+
+ #Set the working directory to copy processed files to, if it does not exist creat it
+ #Directory names based on year/month so as not to exceed 5K files in a single directory
+ def set_directory working_directory
+ time = Time.now
+ directory_year = working_directory + "/../files/processed/" + time.year.to_s
+ directory_month = directory_year + "/" + time.month.to_s
+
+ if File.exists?(directory_month) == false
+ if File.exists?(directory_year) == false
+ Dir.mkdir(directory_year)
+ end
+ Dir.mkdir(directory_month)
+ end
+
+ return directory_month
+ end
+
#Method for parsing the various datatypes from the ECH file
def dump_binary type, length
case type
when 'int'
#Process integers, assigning appropriate profile based on length
@@ -114,65 +156,68 @@
echi_log.filename = filename
echi_log.filenumber = filenumber
echi_log.version = fileversion
end
- bool_cnt = 0
- record_cnt = 0
- while @binary_file.eof == FALSE do
- @log.debug '<====================START RECORD ' + record_cnt.to_s + ' ====================>'
- echi_record = EchiRecord.new
- @echi_schema["fields"].each do | field |
- #We handle the 'boolean' fields differently, as they are all encoded as bits in a single 8-bit byte
- if field["type"] == 'bool'
- if bool_cnt == 0
- bytearray = dump_binary field["type"], field["length"]
- end
- #Ensure we parse the bytearray and set the appropriate flags
- #We need to make sure the entire array is not nil, in order to do Y/N
- #if Nil we then set all no
- if bytearray != nil
- if bytearray.slice(bool_cnt,1) == 1
- value = 'Y'
- else
+ #Perform a transaction for each file, including the log table
+ #in order to commit as one atomic action upon success
+ EchiRecord.transaction do
+ bool_cnt = 0
+ @record_cnt = 0
+ while @binary_file.eof == FALSE do
+ @log.debug '<====================START RECORD ' + @record_cnt.to_s + ' ====================>'
+ echi_record = EchiRecord.new
+ @echi_schema["fields"].each do | field |
+ #We handle the 'boolean' fields differently, as they are all encoded as bits in a single 8-bit byte
+ if field["type"] == 'bool'
+ if bool_cnt == 0
+ bytearray = dump_binary field["type"], field["length"]
+ end
+ #Ensure we parse the bytearray and set the appropriate flags
+ #We need to make sure the entire array is not nil, in order to do Y/N
+ #if Nil we then set all no
+ if bytearray != nil
+ if bytearray.slice(bool_cnt,1) == 1
+ value = 'Y'
+ else
+ value = 'N'
+ end
+ else
value = 'N'
end
- else
- value = 'N'
+ bool_cnt += 1
+ if bool_cnt == 8
+ bool_cnt = 0
+ end
+ else
+ #Process 'standard' fields
+ value = dump_binary field["type"], field["length"]
+ @log.debug field["name"] + " { type => #{field["type"]} & length => #{field["length"]} } value => " + value.to_s
end
- bool_cnt += 1
- if bool_cnt == 8
- bool_cnt = 0
- end
- else
- #Process 'standard' fields
- value = dump_binary field["type"], field["length"]
- @log.debug field["name"] + " { type => #{field["type"]} & length => #{field["length"]} } value => " + value.to_s
+ echi_record[field["name"]] = value
end
- echi_record[field["name"]] = value
- end
- echi_record.save
+ echi_record.save
- #Scan past the end of line record
- @binary_file.read(1)
- @log.debug '<====================STOP RECORD ' + record_cnt.to_s + ' ====================>'
- record_cnt += 1
+ #Scan past the end of line record
+ @binary_file.read(1)
+ @log.debug '<====================STOP RECORD ' + @record_cnt.to_s + ' ====================>'
+ @record_cnt += 1
+ end
+ @binary_file.close
end
- @binary_file.close
#Move the file to the processed directory
- destination_directory = @workingdirectory + '/../files/processed/'
- FileUtils.mv(echi_file, destination_directory)
+ FileUtils.mv(echi_file, @processeddirectory)
if @config["echi_process_log"] == "Y"
#Finish logging the details on the file
- echi_log.records = record_cnt
+ echi_log.records = @record_cnt
echi_log.processed_at = Time.now
echi_log.save
end
- return record_cnt
+ return @record_cnt
end
def connect_ftpsession
#Open ftp connection
begin
@@ -186,10 +231,11 @@
@log.fatal "SSH currently not supported, please use FTP for accessing the ECHI server"
exit
end
rescue => err
@log.fatal "Could not connect with the FTP server - " + err
+ send_email_alert "FTP"
return -1
end
return ftp_session
end
@@ -208,11 +254,13 @@
ftp_session = 0
end
end
if ftp_session != 0
begin
- ftp_session.chdir(@config["echi_ftp_directory"])
+ if @config["echi_ftp_directory"] != nil
+ ftp_session.chdir(@config["echi_ftp_directory"])
+ end
files = ftp_session.list('chr*')
file_cnt = 0
files.each do | file |
#ACTION: Need to detect which OS we are running on and then parse the ftp data appropriately
file_data = file.split(' ')
@@ -247,49 +295,52 @@
echi_log.filename = filename
#echi_log.filenumber = filenumber
#echi_log.version = fileversion
end
- record_cnt = 0
- FasterCSV.foreach(echi_file) do |row|
- if row != nil
- @log.debug '<====================START RECORD ' + record_cnt.to_s + ' ====================>'
- echi_record = EchiRecord.new
- cnt = 0
- @echi_schema["fields"].each do | field |
- if field["type"] == "bool" || field["type"] == "bool_int"
- case row[cnt]
- when "0"
- echi_record[field["name"]] = "N"
- when "1"
- echi_record[field["name"]] = "Y"
- end
- @log.debug field["name"] + ' == ' + row[cnt]
- else
- echi_record[field["name"]] = row[cnt]
- if row[cnt] != nil
+ #Perform a transaction for each file, including the log table
+ #in order to commit as one atomic action upon success
+ EchiRecord.transaction do
+ @record_cnt = 0
+ FasterCSV.foreach(echi_file) do |row|
+ if row != nil
+ @log.debug '<====================START RECORD ' + @record_cnt.to_s + ' ====================>'
+ echi_record = EchiRecord.new
+ cnt = 0
+ @echi_schema["fields"].each do | field |
+ if field["type"] == "bool" || field["type"] == "bool_int"
+ case row[cnt]
+ when "0"
+ echi_record[field["name"]] = "N"
+ when "1"
+ echi_record[field["name"]] = "Y"
+ end
@log.debug field["name"] + ' == ' + row[cnt]
+ else
+ echi_record[field["name"]] = row[cnt]
+ if row[cnt] != nil
+ @log.debug field["name"] + ' == ' + row[cnt]
+ end
end
+ cnt += 1
end
- cnt += 1
+ echi_record.save
+ @log.debug '<====================STOP RECORD ' + @record_cnt.to_s + ' ====================>'
+ @record_cnt += 1
end
- echi_record.save
- @log.debug '<====================STOP RECORD ' + record_cnt.to_s + ' ====================>'
- record_cnt += 1
end
end
#Move the file to the processed directory
- destination_directory = @workingdirectory + '/../files/processed/' + filename
- FileUtils.mv(echi_file, destination_directory)
+ FileUtils.mv(echi_file, @processeddirectory)
if @config["echi_process_log"] == "Y"
#Finish logging the details on the file
- echi_log.records = record_cnt
+ echi_log.records = @record_cnt
echi_log.processed_at = Time.now
echi_log.save
end
- return record_cnt
+ return @record_cnt
end
require @workingdirectory + '/echi-converter/version.rb'