001 package EVolve; 002 003 /* EVolve - an Extensible Software Visualization Framework 004 * Copyright (C) 2001-2002 Qin Wang 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Library General Public 008 * License as published by the Free Software Foundation; either 009 * version 2 of the License, or (at your option) any later version. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Library General Public License for more details. 015 * 016 * You should have received a copy of the GNU Library General Public 017 * License along with this library; if not, write to the 018 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 019 * Boston, MA 02111-1307, USA. 020 */ 021 022 /* 023 * EVolve is distributed at http://www.sable.mcgill.ca/EVolve/ 024 */ 025 026 import java.io.IOException; 027 import java.io.RandomAccessFile; 028 import java.util.ArrayList; 029 import java.util.Iterator; 030 import java.util.NoSuchElementException; 031 import java.util.TreeMap; 032 033 import javax.swing.JFileChooser; 034 035 import EVolve.data.DataSource; 036 import EVolve.data.ElementDefinition; 037 import EVolve.data.Entity; 038 import EVolve.data.EntityBuilder; 039 import EVolve.data.Event; 040 import EVolve.data.EventBuilder; 041 import EVolve.data.FieldDefinition; 042 import EVolve.exceptions.DataProcessingException; 043 import EVolve.exceptions.EVolveException; 044 045 public class PMCPentiumSource implements DataSource { 046 047 private final String dsourceName = "PMCPentiumSource"; 048 private String fn = null; // data file name 049 private long LastBytecode; 050 private long eventCounter; 051 052 053 private int PMC_COUNTER_NUM = 2; // For Pentinum, Change to 4 for Athlon 054 private static int TAIL_LEN = 45; // The length of the last line of the trace file, where the amount of the events is recorded 055 private RandomAccessFile file; 056 057 private EntityBuilder EVolveEventTypeBuilder; // Give the type of an event for Evolve: GC or Ordinary interval 058 059 060 private EntityBuilder hardwareEventNameBuilder; // Give the names of the events 061 private EntityBuilder hardwareEventDescBuilder; // Give the descriptions of the events 062 private EntityBuilder hardwareEventIDBuilder; // Give the IDs of the events 063 private EntityBuilder byteCodeIntervalBuilder; // Give the default interval 064 065 private EventBuilder hardwareEvent_1; 066 private EventBuilder hardwareEvent_2; 067 private EventBuilder cycleEvent; 068 069 private FieldDefinition[] EVolveEventType = new FieldDefinition[PMC_COUNTER_NUM+1]; // EVolve Type, GC or Interval 070 private FieldDefinition[] intervalBytecodeNumStart= new FieldDefinition[PMC_COUNTER_NUM+1]; // Start point 071 private FieldDefinition[] intervalBytecodeNumEnd= new FieldDefinition[PMC_COUNTER_NUM+1]; // End point 072 private FieldDefinition[] intervalEventsVal= new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles 073 074 075 /* 076 private FieldDefinition[] intervalEventsDes = new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles 077 private FieldDefinition[] intervalEventsName= new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles 078 private FieldDefinition[] intervalEventsID= new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles 079 */ 080 private EventBuilder semiGCBuilder; 081 private FieldDefinition GCBytecodeNum; 082 private FieldDefinition[] GCEventsID= new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles 083 private FieldDefinition[] GCEventsName= new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles 084 private FieldDefinition[] GCEventsDes = new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles 085 private FieldDefinition[] GCEventsAllGCVal= new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles for all GC phases 086 private FieldDefinition[] GCEventsRootScanGCVal= new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles for GC phase 1 087 private FieldDefinition[] GCEventsCopyGCVal= new FieldDefinition[PMC_COUNTER_NUM+1]; // Events plus Cycles for GC phase 2 088 089 private int[] countedEvents = new int[PMC_COUNTER_NUM+1]; 090 091 092 093 094 private ElementDefinition[] definition; 095 private int definitionCounter; 096 097 private TreeMap EVTypeMap; 098 private TreeMap IDMap; 099 private TreeMap nameMap; 100 private TreeMap descMap; 101 //private TreeMap defIntMap; 102 private TreeMap intervalMap; 103 private TreeMap GCMap; 104 private ArrayList TotalList; 105 private Iterator ItTotalList; 106 107 108 109 private String[] eventName; 110 private String[] eventDescription; 111 private String[] hardEventType; 112 113 private int totalEventNum, interEventNum,gcEventNum; 114 115 // private InstructionAnalyzeRunner runner; 116 117 public void init() throws EVolveException { 118 String lastName = fn; 119 LastBytecode = 0; 120 eventCounter = 0; 121 fn = Scene.getDataFileName(); 122 //runner = Scene.getToolsManager().getInstructionAnalyzeRunner(); 123 if (fn == null) { 124 JFileChooser fc = new JFileChooser(Scene.getUIManager().getLastDataDir()); 125 if (fc.showOpenDialog(Scene.getFrame()) == JFileChooser.APPROVE_OPTION) { 126 try { 127 file = new RandomAccessFile(fc.getSelectedFile(), "r"); 128 fn = fc.getSelectedFile().getName(); 129 Scene.setDataFilename(fc.getSelectedFile().getPath()); 130 Scene.getUIManager().setLastDataDir(fc.getSelectedFile().getPath()); 131 Scene.setDataFilename(null); 132 } catch (IOException e) { 133 throw new EVolveException("File loading failed."); 134 } 135 } else { 136 fn = lastName; 137 throw new EVolveException("File loading canceled."); 138 } 139 } else { 140 try { 141 file = new RandomAccessFile(fn, "r"); 142 } catch (IOException e) { 143 throw new EVolveException("File loading failed."); 144 } 145 } 146 147 // Get the length of the file 148 readLength(); 149 150 initEventNameDesc(); 151 } 152 153 public String getFileName() { 154 return fn; 155 } 156 157 public String getName() { 158 return dsourceName; 159 } 160 161 // Read the length of the file to get the event number 162 private void readLength()throws EVolveException { 163 // Skip to the end of the file 164 int trials = 1; 165 166 try { 167 long lenOfFile = file.length(); 168 file.seek(lenOfFile-TAIL_LEN); 169 String eventNumStr = file.readLine(); 170 if (eventNumStr.length() < TAIL_LEN-2 ) { 171 eventNumStr = file.readLine(); 172 } 173 174 // Try to skip all the illegal letters 175 while (eventNumStr.indexOf("ALL") != 0) { 176 trials++; 177 file.seek(lenOfFile-TAIL_LEN*trials); 178 while (eventNumStr.indexOf("ALL") != 0) { 179 eventNumStr = file.readLine(); 180 if (eventNumStr == null) break; 181 } 182 183 } 184 185 186 // Read the number of events 187 int start = eventNumStr.indexOf(' ')+1; 188 eventNumStr = eventNumStr.substring(start); 189 //start= eventNumStr.indexOf(' ') ; 190 //String InterStr= eventNumStr.substring(0,start); 191 String InterStr= eventNumStr.substring(0,20); 192 InterStr = InterStr.substring(2); 193 InterStr = InterStr.trim(); 194 interEventNum = Integer.valueOf(InterStr).intValue(); 195 eventNumStr = eventNumStr.substring(23); 196 eventNumStr= eventNumStr.trim(); 197 gcEventNum = Integer.valueOf(eventNumStr).intValue(); 198 totalEventNum = interEventNum+gcEventNum; 199 //System.out.println("total="+totalEventNum); 200 } catch (IOException e) { 201 throw new EVolveException("FILE CHECKING FAILED"); 202 } 203 } 204 205 // Initlize the Event names and description, The XX item of these array is for the No XX event in PMc 206 // Event 257 is saved for the cycles 207 private void initEventNameDesc(){ 208 eventName = new String[258]; 209 eventDescription = new String[258]; 210 211 212 int i; 213 for (i=0; i<258;i++) { 214 eventName[i] = "UNDEFINED PENTIUM EVENT"; 215 eventDescription[i] = "UNDEFINED PENTIUM EVENT"; 216 } 217 218 // Set the value 219 220 eventName[40] = "L2_IFETCH"; 221 eventDescription[40] = "L2 cache instruction fetches"; 222 223 eventName[41] = "L2_LD"; 224 eventDescription[41] = "L2 cache data load"; 225 226 eventName[42] = "L2_ST"; 227 eventDescription[42] = "L2 cache data store"; 228 229 eventName[44] = "L2_LINES_IN"; 230 eventDescription[44] = "Number of Lines allocated in L2"; 231 232 eventName[67] = "DATA_MEM_REFS"; 233 eventDescription[67] = "All loads from and store to any memory type"; 234 235 eventName[69] = "DCU_LINE_IN"; 236 eventDescription[69] = "L1 Data Cache Miss"; 237 238 eventName[72] = "DCU_MISS_OUTSTANDING"; 239 eventDescription[72] = "Weighted num. of cycles whiel DCU miss is outstanding"; 240 241 eventName[121] = "CPU_CLK_UNHALTED"; 242 eventDescription[121] = "Num. of cycles during the processor us not halted"; 243 244 eventName[128] = "IFU_IFETCH"; 245 eventDescription[128] = "Num. of instruction fetched"; 246 247 eventName[129] = "IFU_IFETCH_MISS"; 248 eventDescription[128] = "Num. of instruction fetch miss"; 249 250 eventName[133] = "ITLB_MISS"; 251 eventDescription[133] = "Num. of ITLB miss"; 252 253 eventName[134] = "IFU_MEM_STALL"; 254 eventDescription[134] = "Num. of cycles instruction fetch is stalled"; 255 256 eventName[162] = "RESOURCE_STALLS"; 257 eventDescription[162] = "Num. of cycles during ehich there is a resource related stall"; 258 259 eventName[192] = "INSTRUCTION_RETIRED"; 260 eventDescription[192] = "Instructions have been executed to the end"; 261 262 eventName[196] = "BR_INSTRUCTION_RETIRED"; 263 eventDescription[196] = "Number of branch Instructions retired"; 264 265 eventName[197] = "BR_MISS_PRED_RETIRED"; 266 eventDescription[197] = "Number of mispredict branch Instructions retired"; 267 268 eventName[201] = "BR_TAKEN_RETIRED"; 269 eventDescription[201] = "Number of taken branch Instructions retired"; 270 271 eventName[202] = "BR_MISS_PRED_TAKEN_RETIRED"; 272 eventDescription[202] = "Number of taken mispredict branch Instructions retired"; 273 274 eventName[224] = "BR_IN_DECODED"; 275 eventDescription[224] = "Number of branch Instructions decoded"; 276 277 eventName[226] = "BTB_MISS"; 278 eventDescription[226] = "Number of branch for which BTB did not produce a prediction"; 279 280 eventName[257] = "CYCLE"; 281 eventDescription[257] = "Executed Cycles"; 282 283 284 hardEventType = new String[2]; 285 hardEventType[0] = "Interval"; 286 hardEventType[1] = "GC_Cycle"; 287 } 288 289 290 public void startBuildDefinition() throws DataProcessingException { 291 String[] propertySum = {"time","sum"}; 292 String[] propertyCount = {"time","count","Dotplot time"}; 293 String[] propertyAmount = {"amount"}; 294 String[] propertyCoordinate = {"coordinate","time"}; 295 String[] propertyIndicator = {"indicator"}; 296 String[] propertyBytecode = {"bytecode" }; 297 String[] propertyEventValue = {"eventvalue"}; 298 int i; 299 int Id1, Id2; 300 301 definition = new ElementDefinition[5]; 302 303 EVolveEventTypeBuilder = new EntityBuilder("EventType", "Type of the Event for EVovle"); 304 definition[0] = EVolveEventTypeBuilder.buildDefinition(); 305 306 byteCodeIntervalBuilder = new EntityBuilder("DefaultInterval", "The default bytecode Interval"); 307 definition[1] = byteCodeIntervalBuilder.buildDefinition(); 308 309 try { 310 file.seek(0); 311 312 String line; 313 // Skip the beginning text 314 for (i=0; i<5;i++ ) { 315 file.readLine(); 316 } 317 line = file.readLine(); 318 line = line.trim(); 319 Id1 = Integer.valueOf(line).intValue(); 320 line = file.readLine(); 321 line = line.trim(); 322 Id2 = Integer.valueOf(line).intValue(); 323 324 } catch (IOException e) { 325 throw new DataProcessingException("File processing failed."); 326 } 327 328 329 // Build Interval Event for event 1 330 hardwareEvent_1 = new EventBuilder(eventName[Id1], eventDescription[Id1]); 331 EVolveEventType[0] = hardwareEvent_1.buildReferenceDefinition("Type",EVolveEventTypeBuilder,null,"Type of this record"); 332 intervalBytecodeNumStart[0] = hardwareEvent_1.buildValueDefinition("Bytecode Start", propertyBytecode, "Bytecode sequence startpoint"); 333 intervalBytecodeNumEnd[0] = hardwareEvent_1.buildValueDefinition("Bytecode End", propertyBytecode, "Bytecode sequence endpoint"); 334 intervalEventsVal[0] = hardwareEvent_1.buildValueDefinition("Number of Event "+eventName[Id1], propertyEventValue, "Occurence Number of Event"+eventName[Id1]); 335 definition[2] = hardwareEvent_1.buildDefinition(); 336 337 // Build Interval Event for event 2 338 hardwareEvent_2 = new EventBuilder(eventName[Id2], eventDescription[Id2]); 339 EVolveEventType[1] = hardwareEvent_2.buildReferenceDefinition("Type",EVolveEventTypeBuilder,null,"Type of this record"); 340 intervalBytecodeNumStart[1] = hardwareEvent_2.buildValueDefinition("Bytecode Start", propertyBytecode, "Bytecode sequence startpoint"); 341 intervalBytecodeNumEnd[1] = hardwareEvent_2.buildValueDefinition("Bytecode End", propertyBytecode, "Bytecode sequence endpoint"); 342 intervalEventsVal[1] = hardwareEvent_2.buildValueDefinition("Number of Event "+eventName[Id2], propertyEventValue, "Occurence Number of Event"+eventName[Id2]); 343 definition[3] = hardwareEvent_2.buildDefinition(); 344 345 // Build Interval Event for cycle 346 cycleEvent = new EventBuilder(eventName[257], eventDescription[257]); 347 EVolveEventType[2] = cycleEvent.buildReferenceDefinition("Type",EVolveEventTypeBuilder,null,"Type of this record"); 348 intervalBytecodeNumStart[2] = cycleEvent.buildValueDefinition("Bytecode Start", propertyBytecode, "Bytecode sequence startpoint"); 349 intervalBytecodeNumEnd[2] = cycleEvent.buildValueDefinition("Bytecode End", propertyBytecode, "Bytecode sequence endpoint"); 350 intervalEventsVal[2] = cycleEvent.buildValueDefinition("Number of Event "+eventName[257], propertyEventValue, "Occurence Number of Event"+eventName[257]); 351 definition[4] = cycleEvent.buildDefinition(); 352 definitionCounter = -1; 353 } 354 355 public ElementDefinition getNextDefinition() throws DataProcessingException { 356 definitionCounter++; 357 if (definitionCounter < definition.length) { 358 return definition[definitionCounter]; 359 } else { 360 return null; 361 } 362 } 363 364 private String getSub(String line, int part) { 365 int start = line.indexOf('\t') + 1; 366 int i = 1; 367 while (i < part) { 368 start = line.indexOf('\t', start) + 1; 369 i++; 370 } 371 int end = line.indexOf('\t', start); 372 if (end == -1) { 373 return line.substring(start); 374 } else { 375 return line.substring(start, end); 376 } 377 } 378 379 public void startBuildEntity() throws DataProcessingException { 380 String line; 381 try { 382 file.seek(0); 383 // Skip the beginning text 384 for (int i=0; i<5;i++ ) { 385 file.readLine(); 386 } 387 388 EVTypeMap = new TreeMap(); 389 IDMap = new TreeMap(); 390 descMap = new TreeMap(); 391 nameMap = new TreeMap(); 392 intervalMap = new TreeMap(); 393 GCMap = new TreeMap(); 394 TotalList = new ArrayList(); 395 396 } catch (IOException e) { 397 throw new DataProcessingException("File processing failed."); 398 } 399 400 // Read the entities here 401 int Id; 402 try { 403 Entity newVal = null; 404 for (int i=0; i<PMC_COUNTER_NUM;i++ ) { 405 406 line = file.readLine(); 407 line = line.trim(); 408 Id = Integer.valueOf(line).intValue(); 409 countedEvents[i] = Id; 410 411 } 412 line="257"; 413 countedEvents[PMC_COUNTER_NUM] = 257; 414 String str = "CYCLE"; 415 String str2 = "Executed Cycles"; 416 417 418 EVolveEventTypeBuilder.newEntity(hardEventType[0]); 419 //EVolveEventTypeBuilder.newEntity("Interval"); 420 newVal = EVolveEventTypeBuilder.buildEntity(); 421 EVTypeMap.put(hardEventType[0],newVal); 422 TotalList.add(newVal); 423 424 EVolveEventTypeBuilder.newEntity(hardEventType[1]); 425 //EVolveEventTypeBuilder.newEntity("GarbageCollection"); 426 newVal = EVolveEventTypeBuilder.buildEntity(); 427 EVTypeMap.put(hardEventType[1],newVal); 428 TotalList.add(newVal); 429 430 // For the interval 431 line = file.readLine(); 432 line = line.trim(); 433 byteCodeIntervalBuilder.newEntity(line); 434 newVal = byteCodeIntervalBuilder.buildEntity(); 435 TotalList.add(newVal); 436 437 } catch (IOException e) { 438 throw new DataProcessingException("File processing failed."); 439 } 440 441 ItTotalList = TotalList.iterator(); 442 } 443 444 445 public Entity getNextEntity() throws DataProcessingException { 446 Entity returnVal = null; 447 448 try { 449 returnVal = (Entity)ItTotalList.next(); 450 return returnVal; 451 452 } catch (NoSuchElementException e) { 453 returnVal = null; 454 return returnVal; 455 } 456 } 457 458 public long getTotalNumberOfEvents() { 459 return totalEventNum * 3 ; 460 } 461 462 public long getNumberOfEvents(String definitionName) { 463 464 // if (definitionName.equalsIgnoreCase("HardwareEventCount")) 465 return totalEventNum; 466 //else 467 // return 0; 468 } 469 470 public void startBuildEvent() throws DataProcessingException { 471 eventCounter = 0; 472 LastBytecode = 0; 473 try { 474 file.seek(0); 475 // Skip the beginning text 476 for (int i=0; i<5;i++ ) { 477 file.readLine(); 478 } 479 // Skip the first three lines for the entities 480 for (int i=0; i<PMC_COUNTER_NUM+1;i++ ) { 481 file.readLine(); 482 } 483 } catch (IOException e) { 484 throw new DataProcessingException("File processing failed."); 485 } 486 } 487 488 public Event getNextEvent() throws DataProcessingException { 489 490 eventCounter++; 491 try { 492 493 494 if ((eventCounter%3) == 2) return hardwareEvent_2.buildEvent(); 495 else if ((eventCounter%3) == 0) return cycleEvent.buildEvent(); 496 497 Event returnVal = null; 498 String line = file.readLine(); 499 500 /* Now Event Counter % 3 == 1 */ 501 while ((returnVal == null) && (line != null)) { 502 line = line.trim(); 503 if (line.length() < 2) 504 { 505 line = file.readLine(); 506 continue; 507 } 508 char ch = line.charAt(0); 509 510 if (ch == 'I') { // This is an Interval Event 511 hardwareEvent_1.newEvent(); 512 hardwareEvent_2.newEvent(); 513 cycleEvent.newEvent(); 514 515 hardwareEvent_1.addReferenceField(EVolveEventType[0],(Entity)EVTypeMap.get(hardEventType[0])); // Inteval 516 hardwareEvent_2.addReferenceField(EVolveEventType[1],(Entity)EVTypeMap.get(hardEventType[0])); // Inteval 517 cycleEvent.addReferenceField(EVolveEventType[2],(Entity)EVTypeMap.get(hardEventType[0])); // Inteval 518 519 String bytecodeStr = getSub(line, 1); 520 bytecodeStr = bytecodeStr.trim(); 521 int val = Integer.valueOf(bytecodeStr).intValue(); // Currently use integer, should be changed into long long int later 522 hardwareEvent_1.addValueField(intervalBytecodeNumStart[0],LastBytecode); 523 hardwareEvent_1.addValueField(intervalBytecodeNumEnd[0],val); 524 hardwareEvent_2.addValueField(intervalBytecodeNumStart[1],LastBytecode); 525 hardwareEvent_2.addValueField(intervalBytecodeNumEnd[1],val); 526 cycleEvent.addValueField(intervalBytecodeNumStart[2],LastBytecode); 527 cycleEvent.addValueField(intervalBytecodeNumEnd[2],val); 528 529 LastBytecode = val; 530 531 String evtValStr = getSub(line, 2); 532 evtValStr = evtValStr.trim(); 533 long evtVal = Long.valueOf(evtValStr).longValue(); 534 hardwareEvent_1.addValueField(intervalEventsVal[0],evtVal); 535 536 evtValStr = getSub(line, 3); 537 evtValStr = evtValStr.trim(); 538 evtVal = Long.valueOf(evtValStr).longValue(); 539 hardwareEvent_2.addValueField(intervalEventsVal[1],evtVal); 540 541 evtValStr = getSub(line, 4); 542 evtValStr = evtValStr.trim(); 543 evtVal = Long.valueOf(evtValStr).longValue(); 544 cycleEvent.addValueField(intervalEventsVal[2],evtVal); 545 returnVal = hardwareEvent_1.buildEvent(); 546 547 } else if (ch == 'G') { // This is a GC Event 548 549 hardwareEvent_1.newEvent(); 550 hardwareEvent_2.newEvent(); 551 cycleEvent.newEvent(); 552 553 hardwareEvent_1.addReferenceField(EVolveEventType[0],(Entity)EVTypeMap.get(hardEventType[1])); // GC 554 hardwareEvent_2.addReferenceField(EVolveEventType[1],(Entity)EVTypeMap.get(hardEventType[1])); // GC 555 cycleEvent.addReferenceField(EVolveEventType[2],(Entity)EVTypeMap.get(hardEventType[1])); // GC 556 557 String bytecodeStr = getSub(line, 1); 558 bytecodeStr = bytecodeStr.trim(); 559 int val = Integer.valueOf(bytecodeStr).intValue(); // Currently use integer, should be changed into long long int later 560 hardwareEvent_1.addValueField(intervalBytecodeNumStart[0],LastBytecode); 561 hardwareEvent_1.addValueField(intervalBytecodeNumEnd[0],val); 562 hardwareEvent_2.addValueField(intervalBytecodeNumStart[1],LastBytecode); 563 hardwareEvent_2.addValueField(intervalBytecodeNumEnd[1],val); 564 cycleEvent.addValueField(intervalBytecodeNumStart[2],LastBytecode); 565 cycleEvent.addValueField(intervalBytecodeNumEnd[2],val); 566 567 LastBytecode = val; 568 569 String evtValStr = getSub(line, 2); 570 evtValStr = evtValStr.trim(); 571 long evtVal = Long.valueOf(evtValStr).longValue(); 572 hardwareEvent_1.addValueField(intervalEventsVal[0],evtVal); 573 574 evtValStr = getSub(line, 3); 575 evtValStr = evtValStr.trim(); 576 evtVal = Long.valueOf(evtValStr).longValue(); 577 hardwareEvent_2.addValueField(intervalEventsVal[1],evtVal); 578 579 evtValStr = getSub(line, 4); 580 evtValStr = evtValStr.trim(); 581 evtVal = Long.valueOf(evtValStr).longValue(); 582 cycleEvent.addValueField(intervalEventsVal[2],evtVal); 583 returnVal = hardwareEvent_1.buildEvent(); 584 } 585 586 if (returnVal == null) { 587 line = file.readLine(); 588 } 589 } 590 return returnVal; 591 } catch (IOException e) { 592 throw new DataProcessingException("File processing failed."); 593 } 594 } 595 596 }