KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > thread > Test


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2001 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  * if any, must include the following acknowledgment:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowledgment may appear in the software itself,
24  * if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Xerces" and "Apache Software Foundation" must
27  * not be used to endorse or promote products derived from this
28  * software without prior written permission. For written
29  * permission, please contact apache\@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  * nor may "Apache" appear in their name, without prior written
33  * permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation, and was
51  * originally based on software copyright (c) 1999, International
52  * Business Machines, Inc., http://www.ibm.com . For more information
53  * on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  */

56
57 /**
58  * $Id: Test.java,v 1.2 2005/01/26 08:28:45 jkjome Exp $
59  *
60  * This program is a straight port of xerces/c/tests/ThreadTest.cpp
61  * No particular effort has been made to make it more java-like (who cares
62  * besides a few biggots? ;-)
63  *
64  * @author Andy Heninger, IBM (C++ version)
65  * @author Arnaud Le Hors, IBM
66  */

67
68 package thread;
69
70 import java.io.FileInputStream JavaDoc;
71 import java.io.FileNotFoundException JavaDoc;
72 import java.io.IOException JavaDoc;
73 import java.io.InputStreamReader JavaDoc;
74 import java.io.StringReader JavaDoc;
75
76 import org.enhydra.apache.xerces.parsers.DOMParser;
77 import org.enhydra.apache.xerces.parsers.SAXParser;
78 import org.w3c.dom.Document JavaDoc;
79 import org.w3c.dom.NamedNodeMap JavaDoc;
80 import org.w3c.dom.Node JavaDoc;
81 import org.xml.sax.AttributeList JavaDoc;
82 import org.xml.sax.HandlerBase JavaDoc;
83 import org.xml.sax.InputSource JavaDoc;
84 import org.xml.sax.SAXException JavaDoc;
85 import org.xml.sax.SAXParseException JavaDoc;
86
87 public class Test {
88
89
90 //------------------------------------------------------------------------------
91
//
92
// struct InFileInfo One of these structs will be set up for each file listed
93
// on the command line. Once set, the data is unchanging
94
// and can safely be referenced by the test threads without
95
// use of synchronization.
96
//
97
//------------------------------------------------------------------------------
98
class InFileInfo
99 {
100     public String JavaDoc fileName;
101     public String JavaDoc fileContent; // If doing an in-memory parse, this field points
102
// to an allocated string containing the entire file
103
// contents. Otherwise it's 0.
104
int checkSum; // The XML checksum. Set up by the main thread for
105
// each file before the worker threads are started.
106
}
107
108 //------------------------------------------------------------------------------
109
//
110
// struct runInfo Holds the info extracted from the command line.
111
// There is only one of these, and it is static, and
112
// unchanging once the command line has been parsed.
113
// During the test, the threads will access this info without
114
// any synchronization.
115
//
116
//------------------------------------------------------------------------------
117
final int MAXINFILES = 25;
118 class RunInfo
119 {
120     boolean quiet;
121     boolean verbose;
122     int numThreads;
123     boolean validating;
124     boolean dom;
125     boolean reuseParser;
126     boolean inMemory;
127     boolean dumpOnErr;
128     int totalTime;
129     int numInputFiles;
130     InFileInfo files[] = new InFileInfo[MAXINFILES];
131 }
132
133
134 //------------------------------------------------------------------------------
135
//
136
// struct threadInfo Holds information specific to an individual thread.
137
// One of these is set up for each thread in the test.
138
// The main program monitors the threads by looking
139
// at the status stored in these structs.
140
//
141
//------------------------------------------------------------------------------
142
class ThreadInfo
143 {
144     boolean fHeartBeat; // Set true by the thread each time it finishes
145
// parsing a file.
146
int fParses; // Number of parses completed.
147
int fThreadNum; // Identifying number for this thread.
148

149     ThreadInfo() {
150         fHeartBeat = false;
151         fParses = 0;
152         fThreadNum = -1;
153     }
154 }
155
156
157 //
158
//------------------------------------------------------------------------------
159
//
160
// Global Data
161
//
162
//------------------------------------------------------------------------------
163
RunInfo gRunInfo = new RunInfo();
164 ThreadInfo gThreadInfo[];
165
166
167
168 //------------------------------------------------------------------------------
169
//
170
// class ThreadParser Bundles together a SAX parser and the SAX handlers
171
// and contains the API that the rest of this test
172
// program uses for creating parsers and doing parsing.
173
//
174
// Multiple instances of this class can operate concurrently
175
// in different threads.
176
//
177
//-------------------------------------------------------------------------------
178
class ThreadParser extends HandlerBase JavaDoc
179 {
180     private int fCheckSum;
181     private SAXParser fSAXParser;
182     private DOMParser fDOMParser;
183
184
185     // Not really public,
186
// These are the SAX call-back functions
187
// that this class implements.
188
public void characters(char chars[], int start, int length) {
189         addToCheckSum(chars, start, length);}
190     public void ignorableWhitespace(char chars[], int start, int length) {
191         addToCheckSum(chars, start, length);}
192
193     public void warning(SAXParseException JavaDoc ex) {
194         System.err.print("*** Warning "+
195                          ex.getMessage());}
196
197     public void error(SAXParseException JavaDoc ex) {
198         System.err.print("*** Error "+
199                          ex.getMessage());}
200
201     public void fatalError(SAXParseException JavaDoc ex) {
202         System.err.print("***** Fatal error "+
203                          ex.getMessage());}
204
205 //
206
// ThreadParser constructor. Invoked by the threads of the test program
207
// to create parsers.
208
//
209
ThreadParser()
210 {
211     if (gRunInfo.dom) {
212         // Set up to use a DOM parser
213
fDOMParser = new org.enhydra.apache.xerces.parsers.DOMParser();
214         try {
215             fDOMParser.setFeature( "http://xml.org/sax/features/validation",
216                                    gRunInfo.validating);
217         }
218         catch (Exception JavaDoc e) {}
219         fDOMParser.setErrorHandler(this);
220     }
221     else
222     {
223         // Set up to use a SAX parser.
224
fSAXParser = new org.enhydra.apache.xerces.parsers.SAXParser();
225         try {
226             fSAXParser.setFeature( "http://xml.org/sax/features/validation",
227                                    gRunInfo.validating);
228         }
229         catch (Exception JavaDoc e) {}
230         fSAXParser.setDocumentHandler(this);
231         fSAXParser.setErrorHandler(this);
232     }
233
234 }
235
236 //------------------------------------------------------------------------
237
//
238
// parse - This is the method that is invoked by the rest of
239
// the test program to actually parse an XML file.
240
//
241
// @param fileNum is an index into the gRunInfo.files array.
242
// @return the XML checksum, or 0 if a parse error occured.
243
//
244
//------------------------------------------------------------------------
245
int parse(int fileNum)
246 {
247     InputSource JavaDoc mbis = null;
248     InFileInfo fInfo = gRunInfo.files[fileNum];
249
250     fCheckSum = 0;
251
252     if (gRunInfo.inMemory) {
253         mbis = new InputSource JavaDoc(new StringReader JavaDoc(fInfo.fileContent));
254     }
255
256     try
257     {
258         if (gRunInfo.dom) {
259             // Do a DOM parse
260
if (gRunInfo.inMemory)
261                 fDOMParser.parse(mbis);
262             else
263                 fDOMParser.parse(fInfo.fileName);
264             Document JavaDoc doc = fDOMParser.getDocument();
265             domCheckSum(doc);
266         }
267         else
268         {
269             // Do a SAX parse
270
if (gRunInfo.inMemory)
271                 fSAXParser.parse(mbis);
272             else
273                 fSAXParser.parse(fInfo.fileName);
274         }
275     }
276
277     catch (SAXException JavaDoc e)
278     {
279         String JavaDoc exceptionMessage = e.getMessage();
280         System.err.println(" during parsing: " + fInfo.fileName +
281                            " Exception message is: " + exceptionMessage);
282     }
283     catch (IOException JavaDoc e)
284     {
285         String JavaDoc exceptionMessage = e.getMessage();
286         System.err.println(" during parsing: " + fInfo.fileName +
287                            " Exception message is: " + exceptionMessage);
288     }
289
290     return fCheckSum;
291 }
292
293
294 //
295
// addToCheckSum - private function, used within ThreadParser in
296
// computing the checksum of the XML file.
297
//
298
private void addToCheckSum(char chars[], int start, int len)
299 {
300     // String with character count.
301
int i;
302     for (i=start; i<len; i++)
303         fCheckSum = fCheckSum*5 + chars[i];
304 }
305
306 //
307
// addToCheckSum - private function, used within ThreadParser in
308
// computing the checksum of the XML file.
309
//
310
private void addToCheckSum(String JavaDoc chars)
311 {
312     int i;
313     int len = chars.length();
314     for (i=0; i<len; i++)
315         fCheckSum = fCheckSum*5 + chars.charAt(i);
316 }
317
318
319
320 //
321
// startElement - our SAX handler callback function for element starts.
322
// update the document checksum with the element name
323
// and any attribute names and values.
324
//
325
public void startElement(String JavaDoc name, AttributeList JavaDoc attributes)
326 {
327     addToCheckSum(name);
328
329     int n = attributes.getLength();
330     int i;
331     for (i=0; i<n; i++)
332     {
333         String JavaDoc attNam = attributes.getName(i);
334         addToCheckSum(attNam);
335         String JavaDoc attVal = attributes.getValue(i);
336         addToCheckSum(attVal);
337     }
338 }
339
340
341 //
342
// domCheckSum - Compute the check sum for a DOM node.
343
// Works recursively - initially called with a document node.
344
//
345
public void domCheckSum(Node JavaDoc node)
346 {
347     String JavaDoc s;
348     Node JavaDoc child;
349     NamedNodeMap JavaDoc attributes;
350
351     switch (node.getNodeType() )
352     {
353     case Node.ELEMENT_NODE:
354         {
355             s = node.getNodeName(); // the element name
356

357             attributes = node.getAttributes(); // Element's attributes
358
int numAttributes = attributes.getLength();
359             int i;
360             for (i=0; i<numAttributes; i++)
361                 domCheckSum(attributes.item(i));
362
363             addToCheckSum(s); // Content and Children
364
for (child=node.getFirstChild(); child!=null; child=child.getNextSibling())
365                 domCheckSum(child);
366
367             break;
368         }
369
370
371     case Node.ATTRIBUTE_NODE:
372         {
373             s = node.getNodeName(); // The attribute name
374
addToCheckSum(s);
375             s = node.getNodeValue(); // The attribute value
376
if (s != null)
377                 addToCheckSum(s);
378             break;
379         }
380
381
382     case Node.TEXT_NODE:
383     case Node.CDATA_SECTION_NODE:
384         {
385             s = node.getNodeValue();
386             addToCheckSum(s);
387             break;
388         }
389
390     case Node.ENTITY_REFERENCE_NODE:
391     case Node.DOCUMENT_NODE:
392         {
393             // For entity references and the document, nothing is dirctly
394
// added to the checksum, but we do want to process the chidren nodes.
395
//
396
for (child=node.getFirstChild(); child!=null; child=child.getNextSibling())
397                 domCheckSum(child);
398             break;
399         }
400     }
401 }
402
403
404 //
405
// Recompute the checksum. Meaningful only for DOM, will tell us whether
406
// a failure is transient, or whether the DOM data is permanently corrupted.
407
// for DOM, re-walk the tree.
408
// for SAX, can't do, just return previous value.
409
//
410
public int reCheck()
411 {
412     if (gRunInfo.dom) {
413         fCheckSum = 0;
414         Document JavaDoc doc = fDOMParser.getDocument();
415         domCheckSum(doc);
416     }
417     return fCheckSum;
418 }
419
420 //
421
// domPrint - Dump the contents of a DOM document.
422
// For debugging failures, when all else fails.
423
//
424
public void domPrint()
425 {
426     System.out.println("Begin DOMPrint ...");
427     if (gRunInfo.dom)
428         domPrint(fDOMParser.getDocument());
429     System.out.println("End DOMPrint");
430 }
431
432 //
433
// domPrint - Dump the contents of a DOM node.
434
// For debugging failures, when all else fails.
435
// Works recursively - initially called with a document node.
436
//
437
void domPrint(Node JavaDoc node)
438 {
439
440     String JavaDoc s;
441     Node JavaDoc child;
442     NamedNodeMap JavaDoc attributes;
443
444     switch (node.getNodeType() )
445     {
446     case Node.ELEMENT_NODE:
447         {
448             System.out.print("<");
449             System.out.print(node.getNodeName()); // the element name
450

451             attributes = node.getAttributes(); // Element's attributes
452
int numAttributes = attributes.getLength();
453             int i;
454             for (i=0; i<numAttributes; i++) {
455                 domPrint(attributes.item(i));
456             }
457             System.out.print(">");
458
459             for (child=node.getFirstChild(); child!=null; child=child.getNextSibling())
460                 domPrint(child);
461
462             System.out.print("</");
463             System.out.print(node.getNodeName());
464             System.out.print(">");
465             break;
466         }
467
468
469     case Node.ATTRIBUTE_NODE:
470         {
471             System.out.print(" ");
472             System.out.print(node.getNodeName()); // The attribute name
473
System.out.print("= \"");
474             System.out.print(node.getNodeValue()); // The attribute value
475
System.out.print("\"");
476             break;
477         }
478
479
480     case Node.TEXT_NODE:
481     case Node.CDATA_SECTION_NODE:
482         {
483             System.out.print(node.getNodeValue());
484             break;
485         }
486
487     case Node.ENTITY_REFERENCE_NODE:
488     case Node.DOCUMENT_NODE:
489         {
490             // For entity references and the document, nothing is dirctly
491
// printed, but we do want to process the chidren nodes.
492
//
493
for (child=node.getFirstChild(); child!=null; child=child.getNextSibling())
494                 domPrint(child);
495             break;
496         }
497     }
498 }
499
500 } // class ThreadParser
501

502
503 //----------------------------------------------------------------------
504
//
505
// parseCommandLine Read through the command line, and save all
506
// of the options in the gRunInfo struct.
507
//
508
// Display the usage message if the command line
509
// is no good.
510
//
511
// Probably ought to be a member function of RunInfo.
512
//
513
//----------------------------------------------------------------------
514

515 void parseCommandLine(String JavaDoc argv[])
516 {
517     gRunInfo.quiet = false; // Set up defaults for run.
518
gRunInfo.verbose = false;
519     gRunInfo.numThreads = 2;
520     gRunInfo.validating = false;
521     gRunInfo.dom = false;
522     gRunInfo.reuseParser = false;
523     gRunInfo.inMemory = false;
524     gRunInfo.dumpOnErr = false;
525     gRunInfo.totalTime = 0;
526     gRunInfo.numInputFiles = 0;
527
528     try // Use exceptions for command line syntax errors.
529
{
530         int argnum = 0;
531         int argc = argv.length;
532         while (argnum < argc)
533         {
534             if (argv[argnum].equals("-quiet"))
535                 gRunInfo.quiet = true;
536             else if (argv[argnum].equals("-verbose"))
537                 gRunInfo.verbose = true;
538             else if (argv[argnum].equals("-v"))
539                 gRunInfo.validating = true;
540             else if (argv[argnum].equals("-dom"))
541                 gRunInfo.dom = true;
542             else if (argv[argnum].equals("-reuse"))
543                 gRunInfo.reuseParser = true;
544             else if (argv[argnum].equals("-dump"))
545                 gRunInfo.dumpOnErr = true;
546             else if (argv[argnum].equals("-mem"))
547                 gRunInfo.inMemory = true;
548             else if (argv[argnum].equals("-threads"))
549             {
550                 ++argnum;
551                 if (argnum >= argc)
552                     throw new Exception JavaDoc();
553                 try {
554                     gRunInfo.numThreads = Integer.parseInt(argv[argnum]);
555                 }
556                 catch (NumberFormatException JavaDoc e) {
557                     throw new Exception JavaDoc();
558                 }
559                 if (gRunInfo.numThreads < 0)
560                     throw new Exception JavaDoc();
561             }
562             else if (argv[argnum].equals("-time"))
563             {
564                 ++argnum;
565                 if (argnum >= argc)
566                     throw new Exception JavaDoc();
567                 try {
568                     gRunInfo.totalTime = Integer.parseInt(argv[argnum]);
569                 }
570                 catch (NumberFormatException JavaDoc e) {
571                     throw new Exception JavaDoc();
572                 }
573                 if (gRunInfo.totalTime < 1)
574                     throw new Exception JavaDoc();
575             }
576             else if (argv[argnum].charAt(0) == '-')
577             {
578                 System.err.println("Unrecognized command line option. Scanning"
579                                    + " \"" + argv[argnum] + "\"");
580                 throw new Exception JavaDoc();
581             }
582             else
583             {
584                 gRunInfo.numInputFiles++;
585                 if (gRunInfo.numInputFiles >= MAXINFILES)
586                 {
587                     System.err.println("Too many input files. Limit is "
588                                        + MAXINFILES);
589                     throw new Exception JavaDoc();
590                 }
591                 gRunInfo.files[gRunInfo.numInputFiles-1] = new InFileInfo();
592                 gRunInfo.files[gRunInfo.numInputFiles-1].fileName = argv[argnum];
593             }
594             argnum++;
595         }
596
597         // We've made it through the command line.
598
// Verify that at least one input file to be parsed was specified.
599
if (gRunInfo.numInputFiles == 0)
600         {
601             System.err.println("No input XML file specified on command line.");
602             throw new Exception JavaDoc();
603         };
604
605
606     }
607     catch (Exception JavaDoc e)
608     {
609         System.err.print("usage: java thread.Test [-v] [-threads nnn] [-time nnn] [-quiet] [-verbose] xmlfile...\n" +
610             " -v Use validating parser. Non-validating is default. \n" +
611             " -dom Use a DOM parser. Default is SAX. \n" +
612             " -quiet Suppress periodic status display. \n" +
613             " -verbose Display extra messages. \n" +
614             " -reuse Retain and reuse parser. Default creates new for each parse.\n" +
615             " -threads nnn Number of threads. Default is 2. \n" +
616             " -time nnn Total time to run, in seconds. Default is forever.\n" +
617             " -dump Dump DOM tree on error.\n" +
618             " -mem Read files into memory once only, and parse them from there.\n"
619             );
620         System.exit(1);
621     }
622 }
623
624
625 //---------------------------------------------------------------------------
626
//
627
// ReadFilesIntoMemory For use when parsing from memory rather than
628
// reading the files each time, here is the code that
629
// reads the files into local memory buffers.
630
//
631
// This function is only called once, from the main
632
// thread, before all of the worker threads are started.
633
//
634
//---------------------------------------------------------------------------
635
void ReadFilesIntoMemory()
636 {
637     int fileNum;
638     InputStreamReader JavaDoc fileF;
639     char chars[] = new char[1024];
640     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
641
642     if (gRunInfo.inMemory)
643     {
644         for (fileNum = 0; fileNum <gRunInfo.numInputFiles; fileNum++)
645         {
646             InFileInfo fInfo = gRunInfo.files[fileNum];
647             buf.setLength(0);
648             try {
649                 FileInputStream JavaDoc in = new FileInputStream JavaDoc( fInfo.fileName );
650                 fileF = new InputStreamReader JavaDoc(in);
651                 int len = 0;
652                 while ((len = fileF.read(chars, 0, chars.length)) > 0) {
653                     buf.append(chars, 0, len);
654                 }
655                 fInfo.fileContent = buf.toString();
656                 fileF.close();
657             }
658             catch (FileNotFoundException JavaDoc e) {
659                 System.err.print("File not found: \"" +
660                                  fInfo.fileName + "\".");
661                 System.exit(-1);
662             }
663             catch (IOException JavaDoc e) {
664                 System.err.println("Error reading file \"" +
665                                    fInfo.fileName + "\".");
666                 System.exit(-1);
667             }
668         }
669     }
670 }
671
672
673
674 //----------------------------------------------------------------------
675
//
676
// threadMain The main function for each of the swarm of test threads.
677
// Run in an infinite loop, parsing each of the documents
678
// given on the command line in turn.
679
//
680
// There is no return from this fuction, and no graceful
681
// thread termination. Threads are stuck running here
682
// until the OS shuts them down as a consequence of the
683
// main thread of the process (which never calls this
684
// function) exiting.
685
//
686
//----------------------------------------------------------------------
687

688
689 class thread extends Thread JavaDoc {
690
691     ThreadInfo thInfo;
692
693     thread (ThreadInfo param) {
694         thInfo = param;
695     }
696
697     public void run()
698 {
699     ThreadParser thParser = null;
700
701     if (gRunInfo.verbose)
702         System.out.println("Thread " + thInfo.fThreadNum + ": starting");
703
704     int docNum = gRunInfo.numInputFiles;
705
706     //
707
// Each time through this loop, one file will be parsed and its checksum
708
// computed and compared with the precomputed value for that file.
709
//
710
while (true)
711     {
712
713         if (thParser == null)
714             thParser = new ThreadParser();
715
716         docNum++;
717
718         if (docNum >= gRunInfo.numInputFiles)
719             docNum = 0;
720
721         InFileInfo fInfo = gRunInfo.files[docNum];
722
723         if (gRunInfo.verbose )
724             System.out.println("Thread " + thInfo.fThreadNum +
725                                ": starting file " + fInfo.fileName);
726
727
728         int checkSum = 0;
729         checkSum = thParser.parse(docNum);
730
731         if (checkSum != gRunInfo.files[docNum].checkSum)
732         {
733             System.err.println("\nThread " + thInfo.fThreadNum +
734                                ": Parse Check sum error on file \"" +
735                                fInfo.fileName + "\". Expected " +
736                                fInfo.checkSum + ", got " + checkSum);
737
738             // Revisit - let the loop continue to run?
739
int secondTryCheckSum = thParser.reCheck();
740             System.err.println(" Retry checksum is " + secondTryCheckSum);
741             if (gRunInfo.dumpOnErr)
742                 thParser.domPrint();
743             System.out.flush();
744             System.exit(-1);
745         }
746
747         if (gRunInfo.reuseParser == false)
748         {
749             thParser = null;
750         }
751
752
753         thInfo.fHeartBeat = true;
754         thInfo.fParses++;
755     }
756 } // run():void
757

758 } // class thread
759

760
761 //----------------------------------------------------------------------
762
//
763
// main
764
//
765
//----------------------------------------------------------------------
766

767 void run(String JavaDoc argv[])
768 {
769     parseCommandLine(argv);
770
771     //
772
// If we will be parsing from memory, read each of the input files
773
// into memory now.
774
//
775
ReadFilesIntoMemory();
776
777
778     //
779
// While we are still single threaded, parse each of the documents
780
// once, to check for errors, and to note the checksum.
781
// Blow off the rest of the test if there are errors.
782
//
783
ThreadParser mainParser = new ThreadParser();
784     int n;
785     boolean errors = false;
786     int cksum;
787
788
789     for (n = 0; n < gRunInfo.numInputFiles; n++)
790     {
791         String JavaDoc fileName = gRunInfo.files[n].fileName;
792         if (gRunInfo.verbose)
793             System.out.print(fileName + " checksum is ");
794
795         cksum = mainParser.parse(n);
796
797         if (cksum == 0)
798         {
799             System.err.println("An error occured while initially parsing" +
800                                fileName);
801             errors = true;
802         }
803
804         gRunInfo.files[n].checkSum = cksum;
805         if (gRunInfo.verbose )
806             System.out.println(cksum);
807         if (gRunInfo.dumpOnErr && errors)
808             mainParser.domPrint();
809
810     }
811     if (errors)
812         System.exit(1);
813
814     //
815
// Fire off the requested number of parallel threads
816
//
817

818     if (gRunInfo.numThreads == 0)
819         return;
820
821     gThreadInfo = new ThreadInfo[gRunInfo.numThreads];
822
823     int threadNum;
824     for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
825     {
826         gThreadInfo[threadNum] = new ThreadInfo();
827         gThreadInfo[threadNum].fThreadNum = threadNum;
828         thread t = new thread(gThreadInfo[threadNum]);
829         t.start();
830     }
831
832     //
833
// Loop, watching the heartbeat of the worker threads.
834
// Each second, display "+" when all threads have completed a parse
835
// display "." if some thread hasn't since previous "+"
836
//
837

838     long startTime = System.currentTimeMillis();
839     long elapsedSeconds = 0;
840     while (gRunInfo.totalTime == 0 || gRunInfo.totalTime > elapsedSeconds)
841     {
842         try {
843             Thread.sleep(1000);
844         }
845         catch (InterruptedException JavaDoc e) {
846             // nobody would dare!! :-)
847
}
848         if (gRunInfo.quiet == false && gRunInfo.verbose == false)
849         {
850             char c = '+';
851             for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
852             {
853                 if (gThreadInfo[threadNum].fHeartBeat == false)
854                 {
855                     c = '.';
856                     break;
857                 }
858             }
859             System.out.print(c);
860             System.out.flush();
861             if (c == '+')
862                 for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
863                     gThreadInfo[threadNum].fHeartBeat = false;
864         }
865         elapsedSeconds = (System.currentTimeMillis() - startTime) / 1000;
866     };
867
868     //
869
// Time's up, we are done. (We only get here if this was a timed run)
870
// Tally up the total number of parses completed by each of the threads.
871
// To Do: Run the main thread at higher priority, so that the worker threads
872
// won't make much progress while we are adding up the results.
873
//
874
double totalParsesCompleted = 0;
875     for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
876     {
877         totalParsesCompleted += gThreadInfo[threadNum].fParses;
878         // printf("%f ", totalParsesCompleted);
879
}
880
881     double parsesPerMinute =
882         totalParsesCompleted / (((double)gRunInfo.totalTime) / ((double)60));
883     System.out.println("\n" + parsesPerMinute + " parses per minute.");
884
885     // The threads are still running; we just return
886
// and leave it to the operating sytem to kill them.
887
//
888
System.exit(0);
889 }
890
891 static public void main(String JavaDoc argv[]) {
892     Test test = new Test();
893     test.run(argv);
894 }
895
896 } // class Test
897
Popular Tags