echi-converter 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -61,8 +61,21 @@
61
61
 
62
62
  * Major enhancement(s):
63
63
  * Minor enhancement(s):
64
- * Removed some extraneous comments to the log and added others
64
+ * Removed some extraneous comments to the log
65
65
  * Added 'standard' schema definitions for revision 12 & 13 to the config directory
66
66
  * Bug fix(es):
67
67
  * Fixed bug #14020 issue with binary offset
68
- * In binary handling properly insert a Y/N for the booleans
68
+ * In binary handling properly insert a Y/N for the booleans
69
+
70
+ == 0.2.0 2007-10-21
71
+
72
+ * Major enhancement(s):
73
+ * FR#14853 - Added support for ActiveRecord transactions on a per file basis
74
+ * Minor enhancement(s):
75
+ * FR#14855 - Store processed files in a year/month directory structure based on processed date (ie - 2007/10)
76
+ * If the 'echi_ftp_directory' option in application.yml is left blank/nil, the system will not attempt a change directory
77
+ * The system now builds the files to process array from the to_process directory instead of the ftp list, to allow for better recovery if a failure occurs
78
+ * FR#14997 - Added support for sending email alerts if ECHI fails to connect to either the database or an ftp server
79
+ * Bug fix(es):
80
+ * Fixed bug #14585 requiring Hoe for the install
81
+ * Will now properly toggle between the standard schema and the Presence schema (ie - override ActiveRecord defaults)
data/Manifest.txt CHANGED
@@ -6,6 +6,7 @@ Rakefile
6
6
  lib/main.rb
7
7
  lib/echi-converter/version.rb
8
8
  lib/database.rb
9
+ lib/database_presence.rb
9
10
  lib/main.rb
10
11
  lib/echi-converter.rb
11
12
  scripts/txt2html
data/Rakefile CHANGED
@@ -79,6 +79,7 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
79
79
  ['activesupport', '>=1.4.2'],
80
80
  ['daemons', '>=1.0.7'],
81
81
  ['fastercsv', '>=1.2.0'],
82
+ ['hoe', '>=1.2.2'],
82
83
  ['rake', '>=0.7.3']
83
84
  ]
84
85
  #p.spec_extras = {} # A hash of extra values to set in the gemspec.
@@ -3,10 +3,10 @@
3
3
  #Connection details for the Avaya CMS/ECHI host
4
4
  echi_host: localhost
5
5
  echi_port: 22
6
- echi_username: your_uname
7
- echi_password: your_passwd
6
+ echi_username: anonymous
7
+ echi_password:
8
8
  echi_connect_type: ftp #only ftp supported now, possible for ssh in the future
9
- echi_ftp_directory: /Users/ftp/anonymous
9
+ echi_ftp_directory: #/Users/ftp/anonymous #If blank/nil, the system will not do a CD at the start
10
10
  echi_ftp_retry: 3
11
11
  echi_ftp_delete: N #to not delete the files off of the FTP server set to N
12
12
  echi_schema: extended_version13.yml
@@ -35,6 +35,12 @@ log_number: 10
35
35
  #The size of each individual log file
36
36
  log_length: 10240000
37
37
 
38
+ #Email address to send alerts to, specifically failures to connect to the DB or FTP servers
39
+ #currently does not support an SMTP server that requires authentication
40
+ alert_email_address: jgoecke@presenceco.com
41
+ smtp_server: mail.presenceco.com
42
+ smtp_port: 25
43
+
38
44
  #Special settings for a specific application database
39
45
  pco_process: N #Set to yes or no if running with a PCO database
40
46
  pco_record_tablename: PCO_ECHIRECORD
@@ -34,6 +34,7 @@ files_to_copy:
34
34
  - name: examples/extended_version12/chr0003
35
35
  - name: examples/extended_version12/chr0003.txt
36
36
  - name: lib/database.rb
37
+ - name: lib/database_presence.rb
37
38
  - name: lib/echi-converter.rb
38
39
  - name: lib/main.rb
39
40
  - name: lib/echi-converter/version.rb
@@ -41,6 +42,7 @@ files_to_copy:
41
42
 
42
43
  files_to_upgrade:
43
44
  - name: lib/database.rb
45
+ - name: lib/database_presence.rb
44
46
  - name: lib/echi-converter.rb
45
47
  - name: lib/main.rb
46
48
  - name: lib/echi-converter/version.rb
data/lib/database.rb CHANGED
@@ -1,25 +1,5 @@
1
1
  class EchiRecord < ActiveRecord::Base
2
- #Determine our working directory
3
- workingdirectory = File.expand_path(File.dirname(__FILE__))
4
- #Open the configuration file
5
- configfile = workingdirectory + '/../config/application.yml'
6
- config = YAML::load(File.open(configfile))
7
-
8
- if config["pco_process"] == 'Y'
9
- set_table_name config["pco_record_tablename"]
10
- set_sequence_name config["pco_record_seqname"]
11
- end
12
2
  end
13
3
 
14
4
  class EchiLog < ActiveRecord::Base
15
- #Determine our working directory
16
- workingdirectory = File.expand_path(File.dirname(__FILE__))
17
- #Open the configuration file
18
- configfile = workingdirectory + '/../config/application.yml'
19
- config = YAML::load(File.open(configfile))
20
-
21
- if config["pco_process"] == 'Y'
22
- set_table_name @config["pco_log_tablename"]
23
- set_sequence_name @config["pco_log_seqname"]
24
- end
25
5
  end
@@ -0,0 +1,9 @@
1
+ class EchiRecord < ActiveRecord::Base
2
+ set_table_name config["pco_record_tablename"]
3
+ set_sequence_name config["pco_record_seqname"]
4
+ end
5
+
6
+ class EchiLog < ActiveRecord::Base
7
+ set_table_name @config["pco_log_tablename"]
8
+ set_sequence_name @config["pco_log_seqname"]
9
+ end
@@ -2,6 +2,7 @@ require 'rubygems'
2
2
  require 'active_record'
3
3
  require 'faster_csv'
4
4
  require 'net/ftp'
5
+ require 'net/smtp'
5
6
  require 'fileutils'
6
7
 
7
8
  class Logger
@@ -34,6 +35,7 @@ module EchiConverter
34
35
  @log.info "Successfully connected to the database"
35
36
  rescue => err
36
37
  @log.fatal "Could not connect to the database - " + err
38
+ send_email_alert "DATABASE"
37
39
  end
38
40
  end
39
41
 
@@ -55,6 +57,46 @@ module EchiConverter
55
57
  end
56
58
  end
57
59
 
60
+ #Method to send alert emails
61
+ def send_email_alert reason
62
+ begin
63
+ Net::SMTP.start(@config["smtp_server"], @config["smtp_port"]) do |smtp|
64
+ smtp.open_message_stream('donotreply@echi-converter.rubyforge.org', [@config["alert_email_address"]]) do |f|
65
+ f.puts "From: donotreply@echi-converter.rubyforge.org"
66
+ f.puts "To: " + @config['alert_email_address']
67
+ f.puts "Subject: ECHI-Converter Failure"
68
+ case reason
69
+ when "DATABASE"
70
+ f.puts "Failed to connect to the database."
71
+ when "FTP"
72
+ f.puts "Failed to connect to the ftp server."
73
+ end
74
+ f.puts " "
75
+ f.puts "Please check the ECHI-Converter environment as soon as possible."
76
+ end
77
+ end
78
+ rescue => err
79
+ @log.warn err
80
+ end
81
+ end
82
+
83
+ #Set the working directory to copy processed files to, if it does not exist creat it
84
+ #Directory names based on year/month so as not to exceed 5K files in a single directory
85
+ def set_directory working_directory
86
+ time = Time.now
87
+ directory_year = working_directory + "/../files/processed/" + time.year.to_s
88
+ directory_month = directory_year + "/" + time.month.to_s
89
+
90
+ if File.exists?(directory_month) == false
91
+ if File.exists?(directory_year) == false
92
+ Dir.mkdir(directory_year)
93
+ end
94
+ Dir.mkdir(directory_month)
95
+ end
96
+
97
+ return directory_month
98
+ end
99
+
58
100
  #Method for parsing the various datatypes from the ECH file
59
101
  def dump_binary type, length
60
102
  case type
@@ -116,61 +158,64 @@ module EchiConverter
116
158
  echi_log.version = fileversion
117
159
  end
118
160
 
119
- bool_cnt = 0
120
- record_cnt = 0
121
- while @binary_file.eof == FALSE do
122
- @log.debug '<====================START RECORD ' + record_cnt.to_s + ' ====================>'
123
- echi_record = EchiRecord.new
124
- @echi_schema["fields"].each do | field |
125
- #We handle the 'boolean' fields differently, as they are all encoded as bits in a single 8-bit byte
126
- if field["type"] == 'bool'
127
- if bool_cnt == 0
128
- bytearray = dump_binary field["type"], field["length"]
129
- end
130
- #Ensure we parse the bytearray and set the appropriate flags
131
- #We need to make sure the entire array is not nil, in order to do Y/N
132
- #if Nil we then set all no
133
- if bytearray != nil
134
- if bytearray.slice(bool_cnt,1) == 1
135
- value = 'Y'
136
- else
161
+ #Perform a transaction for each file, including the log table
162
+ #in order to commit as one atomic action upon success
163
+ EchiRecord.transaction do
164
+ bool_cnt = 0
165
+ @record_cnt = 0
166
+ while @binary_file.eof == FALSE do
167
+ @log.debug '<====================START RECORD ' + @record_cnt.to_s + ' ====================>'
168
+ echi_record = EchiRecord.new
169
+ @echi_schema["fields"].each do | field |
170
+ #We handle the 'boolean' fields differently, as they are all encoded as bits in a single 8-bit byte
171
+ if field["type"] == 'bool'
172
+ if bool_cnt == 0
173
+ bytearray = dump_binary field["type"], field["length"]
174
+ end
175
+ #Ensure we parse the bytearray and set the appropriate flags
176
+ #We need to make sure the entire array is not nil, in order to do Y/N
177
+ #if Nil we then set all no
178
+ if bytearray != nil
179
+ if bytearray.slice(bool_cnt,1) == 1
180
+ value = 'Y'
181
+ else
182
+ value = 'N'
183
+ end
184
+ else
137
185
  value = 'N'
138
186
  end
139
- else
140
- value = 'N'
141
- end
142
- bool_cnt += 1
143
- if bool_cnt == 8
144
- bool_cnt = 0
187
+ bool_cnt += 1
188
+ if bool_cnt == 8
189
+ bool_cnt = 0
190
+ end
191
+ else
192
+ #Process 'standard' fields
193
+ value = dump_binary field["type"], field["length"]
194
+ @log.debug field["name"] + " { type => #{field["type"]} & length => #{field["length"]} } value => " + value.to_s
145
195
  end
146
- else
147
- #Process 'standard' fields
148
- value = dump_binary field["type"], field["length"]
149
- @log.debug field["name"] + " { type => #{field["type"]} & length => #{field["length"]} } value => " + value.to_s
196
+ echi_record[field["name"]] = value
150
197
  end
151
- echi_record[field["name"]] = value
152
- end
153
- echi_record.save
198
+ echi_record.save
154
199
 
155
- #Scan past the end of line record
156
- @binary_file.read(1)
157
- @log.debug '<====================STOP RECORD ' + record_cnt.to_s + ' ====================>'
158
- record_cnt += 1
200
+ #Scan past the end of line record
201
+ @binary_file.read(1)
202
+ @log.debug '<====================STOP RECORD ' + @record_cnt.to_s + ' ====================>'
203
+ @record_cnt += 1
204
+ end
205
+ @binary_file.close
159
206
  end
160
- @binary_file.close
161
207
 
162
208
  #Move the file to the processed directory
163
- destination_directory = @workingdirectory + '/../files/processed/'
164
- FileUtils.mv(echi_file, destination_directory)
209
+ FileUtils.mv(echi_file, @processeddirectory)
165
210
 
166
211
  if @config["echi_process_log"] == "Y"
167
212
  #Finish logging the details on the file
168
- echi_log.records = record_cnt
213
+ echi_log.records = @record_cnt
169
214
  echi_log.processed_at = Time.now
170
215
  echi_log.save
171
216
  end
172
217
 
173
- return record_cnt
218
+ return @record_cnt
174
219
  end
175
220
 
176
221
  def connect_ftpsession
@@ -188,6 +233,7 @@ module EchiConverter
188
233
  end
189
234
  rescue => err
190
235
  @log.fatal "Could not connect with the FTP server - " + err
236
+ send_email_alert "FTP"
191
237
  return -1
192
238
  end
193
239
  return ftp_session
@@ -210,7 +256,9 @@ module EchiConverter
210
256
  end
211
257
  if ftp_session != 0
212
258
  begin
213
- ftp_session.chdir(@config["echi_ftp_directory"])
259
+ if @config["echi_ftp_directory"] != nil
260
+ ftp_session.chdir(@config["echi_ftp_directory"])
261
+ end
214
262
  files = ftp_session.list('chr*')
215
263
  file_cnt = 0
216
264
  files.each do | file |
@@ -249,47 +297,50 @@ def process_ascii filename
249
297
  #echi_log.version = fileversion
250
298
  end
251
299
 
252
- record_cnt = 0
253
- FasterCSV.foreach(echi_file) do |row|
254
- if row != nil
255
- @log.debug '<====================START RECORD ' + record_cnt.to_s + ' ====================>'
256
- echi_record = EchiRecord.new
257
- cnt = 0
258
- @echi_schema["fields"].each do | field |
259
- if field["type"] == "bool" || field["type"] == "bool_int"
260
- case row[cnt]
261
- when "0"
262
- echi_record[field["name"]] = "N"
263
- when "1"
264
- echi_record[field["name"]] = "Y"
265
- end
266
- @log.debug field["name"] + ' == ' + row[cnt]
267
- else
268
- echi_record[field["name"]] = row[cnt]
269
- if row[cnt] != nil
300
+ #Perform a transaction for each file, including the log table
301
+ #in order to commit as one atomic action upon success
302
+ EchiRecord.transaction do
303
+ @record_cnt = 0
304
+ FasterCSV.foreach(echi_file) do |row|
305
+ if row != nil
306
+ @log.debug '<====================START RECORD ' + @record_cnt.to_s + ' ====================>'
307
+ echi_record = EchiRecord.new
308
+ cnt = 0
309
+ @echi_schema["fields"].each do | field |
310
+ if field["type"] == "bool" || field["type"] == "bool_int"
311
+ case row[cnt]
312
+ when "0"
313
+ echi_record[field["name"]] = "N"
314
+ when "1"
315
+ echi_record[field["name"]] = "Y"
316
+ end
270
317
  @log.debug field["name"] + ' == ' + row[cnt]
318
+ else
319
+ echi_record[field["name"]] = row[cnt]
320
+ if row[cnt] != nil
321
+ @log.debug field["name"] + ' == ' + row[cnt]
322
+ end
271
323
  end
324
+ cnt += 1
272
325
  end
273
- cnt += 1
326
+ echi_record.save
327
+ @log.debug '<====================STOP RECORD ' + @record_cnt.to_s + ' ====================>'
328
+ @record_cnt += 1
274
329
  end
275
- echi_record.save
276
- @log.debug '<====================STOP RECORD ' + record_cnt.to_s + ' ====================>'
277
- record_cnt += 1
278
330
  end
279
331
  end
280
332
 
281
333
  #Move the file to the processed directory
282
- destination_directory = @workingdirectory + '/../files/processed/' + filename
283
- FileUtils.mv(echi_file, destination_directory)
334
+ FileUtils.mv(echi_file, @processeddirectory)
284
335
 
285
336
  if @config["echi_process_log"] == "Y"
286
337
  #Finish logging the details on the file
287
- echi_log.records = record_cnt
338
+ echi_log.records = @record_cnt
288
339
  echi_log.processed_at = Time.now
289
340
  echi_log.save
290
341
  end
291
342
 
292
- return record_cnt
343
+ return @record_cnt
293
344
  end
294
345
 
295
346
  require @workingdirectory + '/echi-converter/version.rb'
@@ -1,8 +1,8 @@
1
1
  module EchiConverter #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 1
5
- TINY = 1
4
+ MINOR = 2
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/main.rb CHANGED
@@ -11,7 +11,11 @@ configfile = @workingdirectory + '/../config/application.yml'
11
11
  @config = YAML::load(File.open(configfile))
12
12
 
13
13
  #Load ActiveRecord Models
14
- require @workingdirectory + '/database.rb'
14
+ if @config["pco_process"] == 'Y'
15
+ require @workingdirectory + '/database_presence.rb'
16
+ else
17
+ require @workingdirectory + '/database.rb'
18
+ end
15
19
 
16
20
  #Load the configured schema
17
21
  schemafile = @workingdirectory + "/../config/" + @config["echi_schema"]
@@ -29,12 +33,21 @@ end
29
33
 
30
34
  loop do
31
35
  #Process the files
32
- files = fetch_ftp_files
33
- files.each do | file |
34
- if @config["echi_format"] == 'BINARY'
35
- record_cnt = convert_binary_file file
36
- elsif @config["echi_format"] == 'ASCII'
37
- record_cnt = process_ascii file
36
+ ftp_files = fetch_ftp_files
37
+ #Grab filenames from the to_process directory after an FTP fetch, so if the
38
+ #system fails it may pick up where it left off
39
+ to_process_dir = @workingdirectory + "/../files/to_process/"
40
+
41
+ #Establish where to copy the processed files to
42
+ @processeddirectory = set_directory(@workingdirectory)
43
+
44
+ Dir.entries(to_process_dir).each do | file |
45
+ if file != "." && file != ".."
46
+ if @config["echi_format"] == 'BINARY'
47
+ record_cnt = convert_binary_file file
48
+ elsif @config["echi_format"] == 'ASCII'
49
+ record_cnt = process_ascii file
50
+ end
38
51
  end
39
52
  @log.info "Processed file #{file} with #{record_cnt.to_s} records"
40
53
  end
data/website/index.html CHANGED
@@ -33,7 +33,7 @@
33
33
  <h1>ECHI Converter</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/echi-converter"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/echi-converter" class="numbers">0.1.1</a>
36
+ <a href="http://rubyforge.org/projects/echi-converter" class="numbers">0.2.0</a>
37
37
  </div>
38
38
  <h1>&#x2192; &#8216;echi-converter&#8217;</h1>
39
39
 
@@ -61,7 +61,7 @@
61
61
  <li>Generate your schema via ActiveRecord Migrations</li>
62
62
  <li>Fetch Binary or <span class="caps">ASCII CSV</span> files from the Avaya <span class="caps">CMS</span> platform via <span class="caps">FTP</span></li>
63
63
  <li>Convert from the defined Binary format to <span class="caps">ASCII</span></li>
64
- <li>Insert the records into the defined database table</li>
64
+ <li>Insert the records into the defined database table using database transactions, via ActiveRecord, on a per file basis to support recovery on failure</li>
65
65
  <li>Change schema structure via <span class="caps">YML</span> configuration file to accommodate various releases of the <span class="caps">ECHI</span> format</li>
66
66
  </ol>
67
67
 
@@ -86,6 +86,7 @@
86
86
  <li><a href="http://daemons.rubyforge.org/">Daemons v1.0.7+</a></li>
87
87
  <li><a href="http://fastercsv.rubyforge.org/">FasterCSV v1.2.0+</a></li>
88
88
  <li><a href="http://rake.rubyforge.org/">Rake v0.7.3+</a></li>
89
+ <li><a href="http://rubyforge.org/projects/seattlerb/">Hoe v1.2.2+</a></li>
89
90
  </ol>
90
91
 
91
92
 
@@ -175,6 +176,12 @@
175
176
  </ol>
176
177
 
177
178
 
179
+ <h2>Screencast</h2>
180
+
181
+
182
+ <p>You may view the screencast on howto install and use the <span class="caps">ECHI</span>-Converter <a href="http://www.screencast.com/t/lQQkIVkUZMr">here</a>.</p>
183
+
184
+
178
185
  <h2>Forum</h2>
179
186
 
180
187
 
@@ -201,7 +208,7 @@
201
208
 
202
209
  <p>Comments are welcome. Send an email to <a href="mailto:jason@goecke.net">jason [at] goecke.net</a>.</p>
203
210
  <p class="coda">
204
- <a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, 17th September 2007<br>
211
+ <a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, 23rd October 2007<br>
205
212
  Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
206
213
  </p>
207
214
  </div>
data/website/index.txt CHANGED
@@ -20,7 +20,7 @@ The utility provides the following capabilities:
20
20
  # Generate your schema via ActiveRecord Migrations
21
21
  # Fetch Binary or ASCII CSV files from the Avaya CMS platform via FTP
22
22
  # Convert from the defined Binary format to ASCII
23
- # Insert the records into the defined database table
23
+ # Insert the records into the defined database table using database transactions, via ActiveRecord, on a per file basis to support recovery on failure
24
24
  # Change schema structure via YML configuration file to accommodate various releases of the ECHI format
25
25
 
26
26
  # Table names:
@@ -37,6 +37,7 @@ h2. Requirements
37
37
  # "Daemons v1.0.7+":http://daemons.rubyforge.org/
38
38
  # "FasterCSV v1.2.0+":http://fastercsv.rubyforge.org/
39
39
  # "Rake v0.7.3+":http://rake.rubyforge.org/
40
+ # "Hoe v1.2.2+":http://rubyforge.org/projects/seattlerb/
40
41
 
41
42
 
42
43
  h2. Installing
@@ -97,6 +98,9 @@ Items to be done to move this out of alpha stage:
97
98
 
98
99
  # 'echi-converter create' works fine with OSX/Linux, need to test validate with a Win32 platform, therefore currently recommended to only run on a Linux/OSX platform, could use "VMWare":http://www.vmware.com to do this on Windows.
99
100
 
101
+ h2. Screencast
102
+
103
+ You may view the screencast on howto install and use the ECHI-Converter "here":http://www.screencast.com/t/lQQkIVkUZMr.
100
104
 
101
105
  h2. Forum
102
106
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: echi-converter
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.1
7
- date: 2007-09-17 00:00:00 -07:00
6
+ version: 0.2.0
7
+ date: 2007-10-23 00:00:00 -07:00
8
8
  summary: ECHI Conversion Utility - Provides a utility to fetch Avaya CMS / ECHI binary files, convert them and insert into a database table via ActiveRecord
9
9
  require_paths:
10
10
  - lib
@@ -37,6 +37,7 @@ files:
37
37
  - lib/main.rb
38
38
  - lib/echi-converter/version.rb
39
39
  - lib/database.rb
40
+ - lib/database_presence.rb
40
41
  - lib/echi-converter.rb
41
42
  - scripts/txt2html
42
43
  - setup.rb