cargilld    2004/07/08 08:13:51

  Modified:    c/tests/ThreadTest ThreadTest.cpp
  Log:
  Various updates to ThreadTest from Khaled, Steve Dulin and myself including sax2 
support, grammar caching, and some debug support.
  
  Revision  Changes    Path
  1.34      +535 -235  xml-xerces/c/tests/ThreadTest/ThreadTest.cpp
  
  Index: ThreadTest.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/tests/ThreadTest/ThreadTest.cpp,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- ThreadTest.cpp    13 Feb 2004 13:23:17 -0000      1.33
  +++ ThreadTest.cpp    8 Jul 2004 15:13:51 -0000       1.34
  @@ -63,16 +63,24 @@
   #include <stdlib.h>
   #include <stdio.h>
   #include <string.h>
  +#include <ctype.h>
   #include <xercesc/parsers/SAXParser.hpp>
   #include <xercesc/parsers/XercesDOMParser.hpp>
   #include <xercesc/util/PlatformUtils.hpp>
   #include <xercesc/sax/HandlerBase.hpp>
   #include <xercesc/framework/MemBufInputSource.hpp>
   
  +#include <xercesc/sax2/SAX2XMLReader.hpp>
  +#include <xercesc/sax2/XMLReaderFactory.hpp>
  +#include <xercesc/sax2/Attributes.hpp>
  +#include <xercesc/sax2/DefaultHandler.hpp>
  +
   #include <xercesc/dom/DOM.hpp>
   
   #include <xercesc/framework/StdOutFormatTarget.hpp>
  -
  +#include <xercesc/internal/XMLGrammarPoolImpl.hpp>
  +#include <xercesc/internal/MemoryManagerImpl.hpp>
  +#include <xercesc/util/OutOfMemoryException.hpp>
   
   void clearFileInfoMemory();
   
  @@ -86,8 +94,6 @@
   #include "Windows.h"
   #include "process.h"
   
  -
  -
   typedef DWORD (WINAPI *ThreadFunc)(void *);
   
   class ThreadFuncs           // This class isolates OS dependent threading
  @@ -136,7 +142,6 @@
   
   extern "C" {
   
  -
   typedef void (*ThreadFunc)(void *);
   typedef void *(*pthreadfunc)(void *);
   
  @@ -181,13 +186,13 @@
       }
   
   }
  -}
  +
  +} // end of extern "C"
   #else
   #error This platform is not supported
   #endif
   
   
  -
   //------------------------------------------------------------------------------
   //
   //  struct InFileInfo   One of these structs will be set up for each file listed
  @@ -210,36 +215,6 @@
                                //   each file before the worker threads are started.
   };
   
  -//------------------------------------------------------------------------------
  -//
  -//  struct runInfo     Holds the info extracted from the command line.
  -//                     There is only one of these, and it is static, and
  -//                     unchanging once the command line has been parsed.
  -//                     During the test, the threads will access this info without
  -//                     any synchronization.
  -//
  -//------------------------------------------------------------------------------
  -const int MAXINFILES = 25;
  -struct RunInfo
  -{
  -    bool        quiet;
  -    bool        verbose;
  -    bool        stopNow;
  -    int         numThreads;
  -    bool        validating;
  -    bool        dom;
  -    bool        reuseParser;
  -    bool        inMemory;
  -    bool        dumpOnErr;
  -    bool        doSchema;
  -    bool        schemaFullChecking;
  -    bool        doNamespaces;
  -    bool        doInitialParse;
  -    int         totalTime;
  -    int         numInputFiles;
  -    InFileInfo  files[MAXINFILES];
  -};
  -
   
   //------------------------------------------------------------------------------
   //
  @@ -251,11 +226,11 @@
   //------------------------------------------------------------------------------
   struct ThreadInfo
   {
  -    bool    fHeartBeat;            // Set true by the thread each time it finishes
  -                                   //   parsing a file.
  -    bool    fInProgress;           // Set to false by the thread when parse in 
progress
  -    unsigned int     fParses;      // Number of parses completed.
  -    int              fThreadNum;   // Identifying number for this thread.
  +    bool            fHeartBeat;   // Set true by the thread each time it finishes
  +                                  //   parsing a file.
  +    bool            fInProgress;  // Set to false by the thread when parse in 
progress
  +    unsigned int    fParses;      // Number of parses completed.
  +    int             fThreadNum;   // Identifying number for this thread.
       ThreadInfo() {
           fHeartBeat = false;
           fInProgress = false;
  @@ -265,6 +240,41 @@
   };
   
   
  +XERCES_CPP_NAMESPACE_USE
  +//------------------------------------------------------------------------------
  +//
  +//  struct runInfo     Holds the info extracted from the command line.
  +//                     There is only one of these, and it is static, and
  +//                     unchanging once the command line has been parsed.
  +//                     During the test, the threads will access this info without
  +//                     any synchronization.
  +//
  +//------------------------------------------------------------------------------
  +const int MAXINFILES = 25;
  +struct RunInfo
  +{    
  +    bool                            doGrammarCaching;    
  +    bool                            quiet;
  +    bool                            verbose;
  +    bool                            stopNow;        
  +    bool                            dom;    
  +    bool                            sax;    
  +    bool                            reuseParser;
  +    bool                            inMemory;
  +    bool                            dumpOnErr;
  +    bool                            doSchema;
  +    bool                            schemaFullChecking;
  +    bool                            doNamespaces;
  +    bool                            doInitialParse;    
  +    bool                            doNamespacePrefixes;  // SAX2    
  +    SAXParser::ValSchemes           valScheme;
  +    int                             numThreads;
  +    int                             totalTime;
  +    int                             numInputFiles;
  +    unsigned int                    numParses;
  +    InFileInfo                      files[MAXINFILES];
  +};
  +
   //
   //------------------------------------------------------------------------------
   //
  @@ -274,8 +284,61 @@
   RunInfo         gRunInfo;
   ThreadInfo      *gThreadInfo;
   
  +/** Grammar caching thread testing */
  +MemoryManager*  gpMemMgr = 0;
  +XMLGrammarPool* gp = 0;
   
  -XERCES_CPP_NAMESPACE_USE
  +// Routines which maybe helpful for debugging
  +static void printString(const XMLCh *str)
  +{
  +    char *s = XMLString::transcode(str);
  +    printf("%s", s);
  +    delete s;
  +}
  +
  +#define CHARS_PER_LINE           40
  +#define BYTES_PER_LINE           16
  +
  +/*
  + * DumpLine: Dump out a buffer (address and length) to stderr.
  + */
  +static void DumpLine(char* address, int length) {
  +    int i, c, charCount=0;
  +    if (length % 4) length += 4;
  +    fprintf(stderr, "%8.8p: ", address);
  +    for (i=0; i < length/4; ++i) {
  +        fprintf(stderr, "%8.8X ", ((int*)address)[i]);
  +        charCount += 9;
  +    }
  +    for (i=charCount; i < CHARS_PER_LINE; ++i) {
  +        putc(' ', stderr);
  +    }
  +    fprintf(stderr, "| ");
  +    for (i=0; i < length; ++i) {
  +        c = address[i];
  +        c = (isprint(c) ? c : '.');
  +        fprintf(stderr, "%c", c);
  +    }
  +    fprintf(stderr, "\n");
  +}
  +
  +/*
  + * dump: dump out a buffer (address and length) to stderr by dumping out
  + *       a line at a time (DumpLine), until the buffer is written out.
  + */
  +
  +static void dump(void* generalAddress, int length) {
  +    int curr = 0;
  +    char* address = (char*) generalAddress;
  +    while (&address[curr] < &address[length-BYTES_PER_LINE]) {
  +        DumpLine(&address[curr], BYTES_PER_LINE);
  +        curr += BYTES_PER_LINE;
  +    }
  +    if (curr < length) {
  +        DumpLine(&address[curr], length-curr);
  +    }
  +    fflush(stderr);
  +}
   
   //------------------------------------------------------------------------------
   //
  @@ -287,16 +350,17 @@
   //                       in different threads.
   //
   //-------------------------------------------------------------------------------
  -class ThreadParser: public HandlerBase
  -{
  -private:
  -    int           fCheckSum;
  -    SAXParser*    fSAXParser;
  -    XercesDOMParser*    fXercesDOMParser;
  -    XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * fDoc;
   
  -
  -public:                               //  This is the API used by the rest of the 
test program
  +class ThreadParser
  +{
  +public:
  +    class SAXHandler;
  +    class SAX2Handler;
  +    SAXHandler*     fSAXHandler;
  +    SAX2Handler*    fSAX2Handler;
  +    ErrorHandler*   fDOMErrorHandler;
  +    
  +    //  This is the API used by the rest of the test program
       ThreadParser();
       ~ThreadParser();
   
  @@ -305,84 +369,197 @@
                                         //  return the XML checksum, or
                                         //  0 if a parse error occurred.
   
  +    int getCheckSum() {
  +        return fCheckSum;
  +    };
  +
       int reCheck();                    // Try to compute the checksum again.
                                         //  for DOM, re-walk the tree.
                                         //  for SAX, can't do, just return previous 
value.
   
       void domPrint();                  //   including any children.  Default (no 
param)
                                          //   version dumps the entire document.
  -
  -private:
  -    ThreadParser(const ThreadParser &); // No copy constructor
  -    const ThreadParser & operator =(const ThreadParser &); // No assignment.
  -
       void  addToCheckSum(const XMLCh *chars, int len=-1);
  -    void  domCheckSum(const DOMNode *);
  -
  -
  -public:                               // Not really public,
  -                                      //  These are the SAX call-back functions
  -                                      //  that this class implements.
  -    void startElement(const XMLCh* const name, AttributeList& attributes);
  +    
  +    //  These are the SAX call-back functions that this class implements. Can be 
used
  +    //  for SAX and SAX2.
       void characters(const XMLCh* const chars, const unsigned int length) {
  -        addToCheckSum(chars, length);};
  +        addToCheckSum(chars, length);
  +    };
  +    
       void ignorableWhitespace(const XMLCh* const chars, const unsigned int length) {
  -        addToCheckSum(chars, length);};
  -    void resetDocument() {};
  +        addToCheckSum(chars, length);
  +    };
  +    
  +    void resetDocument() {
  +    };
   
       void warning(const SAXParseException& exception)     {
           fprintf(stderr, "*** Warning ");
  -        throw exception;};
  +        fflush(stderr);
  +        throw exception;
  +    };
   
       void error(const SAXParseException& exception)       {
           fprintf(stderr, "*** Error ");
  -        throw exception;};
  +        fflush(stderr);
  +        throw exception;
  +    };
   
       void fatalError(const SAXParseException& exception)  {
           fprintf(stderr, "***** Fatal error ");
  -        throw exception;};
  -};
  +        fflush(stderr);
  +        throw exception;
  +    };
  +
  +    // Create a nested class that can inherit from HandlerBase
  +    // for SAX startElement callbacks.
  +    class SAXHandler :  public HandlerBase
  +    {
  +    public:
  +        ThreadParser* SAXInstance;
  +
  +        void startElement(const XMLCh* const name, AttributeList& attributes);
  +    };
  +
  +    // Create a nested class that can inherit from DefaultHandler
  +    // for SAX2 startElement callbacks.
  +    class SAX2Handler :  public DefaultHandler
  +    {
  +    public:
  +        ThreadParser* SAX2Instance;
  +
  +        void startElement(const XMLCh* const uri,
  +                          const XMLCh* const localname,
  +                          const XMLCh* const qname,
  +                          const Attributes& attributes);
  +    };
  +
  +private:
  +    int                                             fCheckSum;
  +    SAXParser*                                      fSAXParser;
  +    SAX2XMLReader*                                  fSAX2Parser;
  +    XercesDOMParser*                                fXercesDOMParser;
  +    XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *    fDoc;
   
   
  +    ThreadParser(const ThreadParser &); // No copy constructor
  +    const ThreadParser & operator =(const ThreadParser &); // No assignment.
  +
  +    void  domCheckSum(const DOMNode *);
  +};
   
   //
   //  ThreadParser constructor.  Invoked by the threads of the test program
   //                              to create parsers.
   //
   ThreadParser::ThreadParser()
  -{
  -    fSAXParser = 0;
  +{   
  +    fSAXParser       = 0;
  +    fSAX2Parser      = 0;
       fXercesDOMParser = 0;
  -    fDoc       = 0;
  +    fSAXHandler      = 0;
  +    fSAX2Handler     = 0;
  +    fDOMErrorHandler = 0;    
  +    fDoc             = 0;
  +    fCheckSum        = 0;
  +
       if (gRunInfo.dom) {
           // Set up to use a DOM parser
  -        fXercesDOMParser = new XercesDOMParser;
  -        fXercesDOMParser->setDoValidation(gRunInfo.validating);
  +        /** Grammar caching thread testing */
  +        if (gp) {
  +            fXercesDOMParser = new XercesDOMParser(0, 
XMLPlatformUtils::fgMemoryManager, gp);
  +            fXercesDOMParser->cacheGrammarFromParse(true);
  +            fXercesDOMParser->useCachedGrammarInParse(true);
  +        }        
  +        else {
  +            fXercesDOMParser = new XercesDOMParser;
  +        }
  +        switch (gRunInfo.valScheme) {
  +            case SAXParser::Val_Never:
  +                fXercesDOMParser->setValidationScheme(XercesDOMParser::Val_Never);
  +                break;
  +            case SAXParser::Val_Auto:
  +                fXercesDOMParser->setValidationScheme(XercesDOMParser::Val_Auto);
  +                break;
  +            default: //SAXParser::Val_Always:
  +                fXercesDOMParser->setValidationScheme(XercesDOMParser::Val_Always);
  +                break;
  +        }        
           fXercesDOMParser->setDoSchema(gRunInfo.doSchema);
           
fXercesDOMParser->setValidationSchemaFullChecking(gRunInfo.schemaFullChecking);
           fXercesDOMParser->setDoNamespaces(gRunInfo.doNamespaces);
  -        fXercesDOMParser->setErrorHandler(this);
  +        fDOMErrorHandler = (ErrorHandler*) new HandlerBase();
  +        fXercesDOMParser->setErrorHandler(fDOMErrorHandler);
       }
  -    else
  -    {
  -        // Set up to use a SAX parser.
  -        fSAXParser = new SAXParser;
  -        fSAXParser->setDoValidation(gRunInfo.validating);
  +
  +    else if (gRunInfo.sax) {
  +        // Set up to use a SAX1 parser.
  +        /** Grammar caching thread testing */
  +        if (gp) {
  +            fSAXParser = new SAXParser(0, XMLPlatformUtils::fgMemoryManager, gp);
  +            fSAXParser->cacheGrammarFromParse(true);
  +            fSAXParser->useCachedGrammarInParse(true);
  +        }        
  +        else {
  +            fSAXParser = new SAXParser();
  +        }
  +        fSAXParser->setValidationScheme(gRunInfo.valScheme);
           fSAXParser->setDoSchema(gRunInfo.doSchema);
           fSAXParser->setValidationSchemaFullChecking(gRunInfo.schemaFullChecking);
           fSAXParser->setDoNamespaces(gRunInfo.doNamespaces);
  -        fSAXParser->setDocumentHandler(this);
  -        fSAXParser->setErrorHandler(this);
  +        fSAXHandler = new ThreadParser::SAXHandler();
  +        fSAXHandler->SAXInstance = this;
  +        fSAXParser->setDocumentHandler(fSAXHandler);
  +        fSAXParser->setErrorHandler(fSAXHandler);
       }
   
  -}
  -
  +    else { 
  +        // Set up to use a SAX2 parser.
  +        /** Grammar caching thread testing */
  +        if (gp) {            
  +            fSAX2Parser = XMLReaderFactory::createXMLReader(gpMemMgr, gp);
  +            fSAX2Parser->setFeature(XMLUni::fgXercesCacheGrammarFromParse,true);
  +            fSAX2Parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse,true);
  +        }
  +        else {
  +            fSAX2Parser = XMLReaderFactory::createXMLReader();
  +        }
   
  +        
fSAX2Parser->setFeature(XMLUni::fgSAX2CoreNameSpaces,(gRunInfo.doNamespaces));
  +        fSAX2Parser->setFeature(XMLUni::fgXercesSchema,(gRunInfo.doSchema));
  +        
fSAX2Parser->setFeature(XMLUni::fgXercesSchemaFullChecking,(gRunInfo.schemaFullChecking));
  +
  +        switch (gRunInfo.valScheme) {
  +            case SAXParser::Val_Never:
  +                fSAX2Parser->setFeature(XMLUni::fgSAX2CoreValidation, false);
  +                break;
  +            case SAXParser::Val_Auto:
  +                fSAX2Parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
  +                fSAX2Parser->setFeature(XMLUni::fgXercesDynamic, true);
  +                break;
  +            default: //SAXParser::Val_Always:
  +                fSAX2Parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
  +                fSAX2Parser->setFeature(XMLUni::fgXercesDynamic, false);
  +                break;
  +        }            
  +        
  +        
fSAX2Parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes,(gRunInfo.doNamespacePrefixes));
        
  +        fSAX2Handler = new ThreadParser::SAX2Handler();
  +        fSAX2Handler->SAX2Instance = this;
  +        fSAX2Parser->setContentHandler(fSAX2Handler);
  +        fSAX2Parser->setErrorHandler(fSAX2Handler);
  +    }
  +}
   
   ThreadParser::~ThreadParser()
   {
  -     delete fSAXParser;
  +     delete fSAXParser;          
  +     delete fSAX2Parser;
        delete fXercesDOMParser;
  +     delete fSAXHandler;
  +     delete fSAX2Handler;     
  +     delete fDOMErrorHandler;
   }
   
   //------------------------------------------------------------------------
  @@ -415,37 +592,47 @@
                   fXercesDOMParser->parse(*mbis);
               else
                   fXercesDOMParser->parse(fInfo->fileName);
  -            XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* doc = 
fXercesDOMParser->getDocument();
  -            domCheckSum(doc);
  +            fDoc = fXercesDOMParser->getDocument();
  +            domCheckSum(fDoc);
           }
  -        else
  -        {
  -            // Do a SAX parse
  +        else if (gRunInfo.sax) {
  +            // Do a SAX1 parse
               if (gRunInfo.inMemory)
                   fSAXParser->parse(*mbis);
               else
                   fSAXParser->parse(fInfo->fileName);
           }
  +        else {
  +            // Do a SAX2 parse
  +            if (gRunInfo.inMemory)
  +                fSAX2Parser->parse(*mbis);
  +            else
  +                fSAX2Parser->parse(fInfo->fileName);
  +        }
  +    }
  +    catch (const OutOfMemoryException&)
  +    {
  +         fprintf(stderr, " during parsing: %s\n OutOfMemoryException.\n", 
fInfo->fileName);        
  +         errors = true;
       }
  -
       catch (const XMLException& e)
       {
           char *exceptionMessage = XMLString::transcode(e.getMessage());
  -        fprintf(stderr, " during parsing: %s \n Exception message is: %s \n",
  +        fprintf(stderr, " during parsing: %s\n Exception message is: %s\n",
               fInfo->fileName, exceptionMessage);
           XMLString::release(&exceptionMessage);
           errors = true;
       }
       catch (const DOMException& toCatch)
       {
  -        fprintf(stderr, " during parsing: %s \n DOMException code is: %i \n",
  +        fprintf(stderr, " during parsing: %s\n DOMException code is: %i\n",
               fInfo->fileName, toCatch.code);
           errors = true;
       }
       catch (const SAXParseException& e)
       {
           char *exceptionMessage = XMLString::transcode(e.getMessage());
  -        fprintf(stderr, " during parsing: %s \n Exception message is: %s \n",
  +        fprintf(stderr, " during parsing: %s\n Exception message is: %s\n",
               fInfo->fileName, exceptionMessage);
           XMLString::release(&exceptionMessage);
           errors = true;
  @@ -457,8 +644,10 @@
       }
   
       delete mbis;
  -    if (errors)
  +    if (errors) {
  +        fflush(stderr);
           return 0;  // if errors occurred, return zero as if checksum = 0;
  +    }
       return fCheckSum;
   }
   
  @@ -494,25 +683,47 @@
   
   
   //
  -// startElement - our SAX handler callback function for element starts.
  -//                update the document checksum with the element name
  +// startElement - our SAX handler callback function for startElement.
  +//                Update the document checksum with the element name
   //                and any attribute names and values.
   //
  -void ThreadParser::startElement(const XMLCh *const name, AttributeList &attributes)
  + void ThreadParser::SAXHandler::startElement(const XMLCh *const name, AttributeList 
&attributes)
   {
  -    addToCheckSum(name);
  -
  +    SAXInstance->addToCheckSum(name);
       int n = attributes.getLength();
       int i;
       for (i=0; i<n; i++)
       {
           const XMLCh *attNam = attributes.getName(i);
  -        addToCheckSum(attNam);
  +        SAXInstance->addToCheckSum(attNam);
           const XMLCh *attVal = attributes.getValue(i);
  -        addToCheckSum(attVal);
  +        SAXInstance->addToCheckSum(attVal);
       }
   }
   
  +//
  +// startElement - our SAX2 handler callback function for startElement.
  +//                Update the document checksum with the element name
  +//                and any attribute names and values.
  +//
  +
  +void ThreadParser::SAX2Handler::startElement(const XMLCh *const uri,
  +                              const XMLCh *const localname,
  +                              const XMLCh *const qname,
  +                              const Attributes& attributes)
  +{
  +    SAX2Instance->addToCheckSum(localname);
  +
  +    int n = attributes.getLength();
  +    int i;
  +    for (i=0; i<n; i++)
  +    {
  +        const XMLCh *attNam = attributes.getQName(i);
  +        SAX2Instance->addToCheckSum(attNam);
  +        const XMLCh *attVal = attributes.getValue(i);
  +        SAX2Instance->addToCheckSum(attVal);
  +    }
  +}
   
   //
   // domCheckSum  -  Compute the check sum for a DOM node.
  @@ -543,7 +754,6 @@
               break;
           }
   
  -
       case DOMNode::ATTRIBUTE_NODE:
           {
               s = node->getNodeName();  // The attribute name
  @@ -554,7 +764,6 @@
               break;
           }
   
  -
       case DOMNode::TEXT_NODE:
       case DOMNode::CDATA_SECTION_NODE:
           {
  @@ -619,13 +828,6 @@
       printf("End DOMPrint\n");
   }
   
  -static void printString(const XMLCh *str)
  -{
  -    char *s = XMLString::transcode(str);
  -    printf("%s", s);
  -    delete s;
  -}
  -
   //----------------------------------------------------------------------
   //
   //   parseCommandLine   Read through the command line, and save all
  @@ -640,49 +842,79 @@
   
   void parseCommandLine(int argc, char **argv)
   {
  +    gRunInfo.doGrammarCaching = false;     
       gRunInfo.quiet = false;               // Set up defaults for run.
       gRunInfo.verbose = false;
  -    gRunInfo.numThreads = 2;
  -    gRunInfo.validating = false;
  -    gRunInfo.doSchema = false;
  -    gRunInfo.schemaFullChecking = false;
  -    gRunInfo.doNamespaces = false;
  -    gRunInfo.doInitialParse = false;
  +    gRunInfo.stopNow = false;            
       gRunInfo.dom = false;
  +    gRunInfo.sax = true;    
       gRunInfo.reuseParser = false;
       gRunInfo.inMemory = false;
       gRunInfo.dumpOnErr = false;
  +    gRunInfo.doSchema = false;
  +    gRunInfo.schemaFullChecking = false;
  +    gRunInfo.doNamespaces = false;
  +    gRunInfo.doInitialParse = false;
  +    gRunInfo.doNamespacePrefixes = false;    
  +    
  +    gRunInfo.valScheme = SAXParser::Val_Auto;
  +    gRunInfo.numThreads = 2;
       gRunInfo.totalTime = 0;
       gRunInfo.numInputFiles = 0;
  +    gRunInfo.numParses = 0;
   
       try             // Use exceptions for command line syntax errors.
       {
           int argnum = 1;
  -        while (argnum < argc)
  -        {
  +        while (argnum < argc) {
               if (strcmp(argv[argnum], "-quiet") == 0)
                   gRunInfo.quiet = true;
               else if (strcmp(argv[argnum], "-verbose") == 0)
                   gRunInfo.verbose = true;
  -            else if (strcmp(argv[argnum], "-v") == 0)
  -                gRunInfo.validating = true;
  +            else if (strncmp(argv[argnum], "-v=", 3) == 0) {
  +                const char* const parm = &argv[argnum][3];
  +                if (!strcmp(parm, "never"))
  +                    gRunInfo.valScheme = SAXParser::Val_Never;
  +                else if (!strcmp(parm, "auto"))
  +                    gRunInfo.valScheme = SAXParser::Val_Auto;
  +                else if (!strcmp(parm, "always"))
  +                    gRunInfo.valScheme = SAXParser::Val_Always;
  +                else {
  +                    fprintf(stderr, "Unrecognized -v option \"%s\"\n", parm);       
              
  +                    throw 1;
  +                }
  +            }
  +            else if (strcmp(argv[argnum], "-v") == 0) {
  +                fprintf(stderr, "Please note the -v option has been changed to 
-v=[always | never | auto]\n");
  +                fprintf(stderr, "ThreadTest will continue with -v=always\n");
  +                gRunInfo.valScheme = SAXParser::Val_Always;
  +            }
               else if (strcmp(argv[argnum], "-s") == 0)
                   gRunInfo.doSchema = true;
               else if (strcmp(argv[argnum], "-f") == 0)
                   gRunInfo.schemaFullChecking = true;
               else if (strcmp(argv[argnum], "-n") == 0)
  -                gRunInfo.doNamespaces = true;
  +                gRunInfo.doNamespaces = true;            
  +            else if (strcmp(argv[argnum], "-p") == 0)
  +                gRunInfo.doNamespacePrefixes = true;         
               else if (!strncmp(argv[argnum], "-parser=", 8)) {
  -                const char* const parm = &argv[argnum][8];
  -
  +                const char* const parm = &argv[argnum][8];                
                   if (!strcmp(parm, "dom")) {
                       gRunInfo.dom = true;
  +                    gRunInfo.sax = false;
                   }
                   else if (!strcmp(parm, "sax")) {
                       gRunInfo.dom = false;
  +                    gRunInfo.sax = true;                    
                   }
  -                else
  +                else if (!strcmp(parm, "sax2")) {
  +                    gRunInfo.dom = false;
  +                    gRunInfo.sax = false;
  +                }                
  +                else {
  +                    fprintf(stderr, "Unrecognized -parser option \"%s\"\n", parm);  
                  
                       throw 1;
  +                }
               }
               else if (strcmp(argv[argnum], "-init") == 0)
                   gRunInfo.doInitialParse = true;
  @@ -692,35 +924,53 @@
                   gRunInfo.dumpOnErr = true;
               else if (strcmp(argv[argnum], "-mem") == 0)
                   gRunInfo.inMemory = true;
  -            else if (strcmp(argv[argnum], "-threads") == 0)
  -            {
  +            else if (strcmp(argv[argnum], "-threads") == 0) {
                   ++argnum;
  -                if (argnum >= argc)
  +                if (argnum >= argc) {
  +                    fprintf(stderr, "Invalid -threads option (missing # of 
threads)\n");
                       throw 1;
  +                }
                   gRunInfo.numThreads = atoi(argv[argnum]);
  -                if (gRunInfo.numThreads < 0)
  +                if (gRunInfo.numThreads < 0) {
  +                    fprintf(stderr, "Invalid -threads option (negative # of 
threads)\n");
                       throw 1;
  +                }
               }
  -            else if (strcmp(argv[argnum], "-time") == 0)
  -            {
  +            else if (strcmp(argv[argnum], "-time") == 0) {
                   ++argnum;
  -                if (argnum >= argc)
  +                if (argnum >= argc) {
  +                    fprintf(stderr, "Invalid -time option (missing time value)\n");
                       throw 1;
  +                }
                   gRunInfo.totalTime = atoi(argv[argnum]);
  -                if (gRunInfo.totalTime < 1)
  +                if (gRunInfo.totalTime < 1) {
  +                    fprintf(stderr, "Invalid -time option (time value < 1)\n");
                       throw 1;
  +                }
  +            }            
  +            else if (strcmp(argv[argnum], "-gc") == 0)
  +                gRunInfo.doGrammarCaching = true;            
  +            else if (strcmp(argv[argnum], "-parses") == 0) {
  +                ++argnum;
  +                if (argnum >= argc) {
  +                    fprintf(stderr, "Invalid -parses option (missing # of 
parses)\n");
  +                    throw 1;
  +                }
  +                int temp = atoi(argv[argnum]);
  +                if (temp < 0) {
  +                    fprintf(stderr, "Invalid -parses option (negative # of 
parses)\n");
  +                    throw 1;
  +                }
  +                gRunInfo.numParses = temp;
               }
  -            else  if (argv[argnum][0] == '-')
  -            {
  +            else  if (argv[argnum][0] == '-') {
                   fprintf(stderr, "Unrecognized command line option.  Scanning 
\"%s\"\n",
                       argv[argnum]);
                   throw 1;
               }
  -            else
  -            {
  +            else {
                   gRunInfo.numInputFiles++;
  -                if (gRunInfo.numInputFiles >= MAXINFILES)
  -                {
  +                if (gRunInfo.numInputFiles >= MAXINFILES) {
                       fprintf(stderr, "Too many input files.  Limit is %d\n", 
MAXINFILES);
                       throw 1;
                   }
  @@ -730,30 +980,35 @@
           }
   
           // We've made it through the command line.
  -        //  Verify that at least one input file to be parsed was specified.
  -        if (gRunInfo.numInputFiles == 0)
  -        {
  +        // Verify that at least one input file to be parsed was specified.
  +        if (gRunInfo.numInputFiles == 0) {
               fprintf(stderr, "No input XML file specified on command line.\n");
               throw 1;
           };
   
  -
  +        if (gRunInfo.numParses && gRunInfo.totalTime) {
  +            fprintf(stderr, "Both -parses nnn and -time nnn were specified. 
Ignoring -time nnn.\n");
  +        }
       }
       catch (int)
       {
  -        fprintf(stderr, "usage:  threadtest [-v] [-threads nnn] [-time nnn] 
[-quiet] [-verbose] xmlfile...\n"
  -            "     -v             Use validating parser.  Non-validating is 
default.\n"
  +        fprintf(stderr, "usage:  ThreadTest [-v] [-threads nnn] [-time nnn] 
[-quiet] [-verbose] xmlfile...\n"            
  +            "     -v=xxx         Validation scheme [always | never | auto].  
Default is AUTO.\n"
               "     -n             Enable namespace processing. Defaults to off.\n"
               "     -s             Enable schema processing. Defaults to off.\n"
               "     -f             Enable full schema constraint checking. Defaults 
to off.\n"
  -            "     -parser=xxx    Parser Type [dom | sax].  Default is SAX.\n"
  +            "     -parser=xxx    Parser Type [dom | sax | sax2].  Default is SAX 
(SAX1).\n"
  +            "     -p             Enable namespace prefixes. Defaults to off.\n"
  +            "                    (Only used with -parser=sax2, ignored 
otherwise.)\n"
               "     -quiet         Suppress periodic status display.\n"
               "     -verbose       Display extra messages.\n"
               "     -reuse         Retain and reuse parser.  Default creates new for 
each parse.\n"
               "     -threads nnn   Number of threads.  Default is 2.\n"
               "     -time nnn      Total time to run, in seconds.  Default is 
forever.\n"
  +            "     -parses nnn    Run for nnn parses instead of time.  Default is to 
use time\n"
               "     -dump          Dump DOM tree on error.\n"
               "     -mem           Read files into memory once only, and parse them 
from there.\n"
  +            "     -gc            Enable grammar caching (i.e. grammar cached and 
used in subsequent parses). Defaults to off.\n"
               "     -init          Perform an initial parse of the file(s) before 
starting up the individual threads.\n\n"
               );
           exit(1);
  @@ -834,7 +1089,6 @@
   unsigned long WINAPI threadMain (void *param)
   #else
   extern "C" {
  -
   void threadMain (void *param)
   #endif
   {
  @@ -850,66 +1104,74 @@
       // Each time through this loop, one file will be parsed and its checksum
       // computed and compared with the precomputed value for that file.
       //
  -    while (gRunInfo.stopNow == false)
  -    {
  -
  -        thInfo->fInProgress = true;
  +    while (gRunInfo.stopNow == false) {
  +        if (gRunInfo.numParses == 0 || thInfo->fParses < gRunInfo.numParses) {
  +            thInfo->fInProgress = true;
   
  -        if (thParser == 0)
  -            thParser = new ThreadParser;
  +            if (thParser == 0)
  +                thParser = new ThreadParser;
   
  -        docNum++;
  +            docNum++;
   
  -        if (docNum >= gRunInfo.numInputFiles)
  -            docNum = 0;
  +            if (docNum >= gRunInfo.numInputFiles)
  +                docNum = 0;
   
  -        InFileInfo *fInfo = &gRunInfo.files[docNum];
  +            InFileInfo *fInfo = &gRunInfo.files[docNum];
   
  -        if (gRunInfo.verbose )
  -            printf("Thread #%d: starting file %s\n", thInfo->fThreadNum, 
fInfo->fileName);
  -
  -
  -        int checkSum = 0;
  -        checkSum = thParser->parse(docNum);
  +            if (gRunInfo.verbose )
  +                printf("Thread #%d: parse %d starting file %s\n", 
thInfo->fThreadNum, thInfo->fParses, fInfo->fileName);
   
  -        // For the case where we skip the preparse we will have nothing to
  -        // compare the first parse's results to ... so if this looks like first
  -        // parse move the checkSum back into the gRunInfo data for this file.
  +            int checkSum = 0;
  +                           
  +            checkSum = thParser->parse(docNum);
  +
  +            // For the case where we skip the preparse we will have nothing to
  +            // compare the first parse's results to ... so if this looks like first
  +            // parse move the checkSum back into the gRunInfo data for this file.
   
  -        if (gRunInfo.files[docNum].checkSum == 0)
  -        {
  -           gRunInfo.files[docNum].checkSum = checkSum;
  -        }
  +            if (gRunInfo.files[docNum].checkSum == 0) {
  +                gRunInfo.files[docNum].checkSum = checkSum;
  +            }
  +            else if (checkSum != gRunInfo.files[docNum].checkSum) {
  +                if (checkSum == 0) {
  +                    // parse returns 0 if there was an error so do this to get the 
real
  +                    // checksum value
  +                    checkSum = thParser->getCheckSum();
  +                }
  +                fprintf(stderr, "\nThread %d: Parse Check sum error on file  \"%s\" 
for parse # %d.  Expected %x,  got %x\n",
  +                    thInfo->fThreadNum, thInfo->fParses, fInfo->fileName, 
fInfo->checkSum, checkSum);
   
  -        if (checkSum != gRunInfo.files[docNum].checkSum)
  -        {
  -            fprintf(stderr, "\nThread %d: Parse Check sum error on file  \"%s\".  
Expected %x,  got %x\n",
  -                thInfo->fThreadNum, fInfo->fileName, fInfo->checkSum, checkSum);
  +                 double totalParsesCompleted = 0;
  +                for (int threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) 
{
  +                    totalParsesCompleted += gThreadInfo[threadNum].fParses;         
       
  +                }
  +                fprintf(stderr, "Total number of parses completed is %f.\n", 
totalParsesCompleted);
  +            
  +                // Revisit - let the loop continue to run?
  +                int secondTryCheckSum = thParser->reCheck();
  +                fprintf(stderr, "   Retry checksum is %x\n", secondTryCheckSum);
  +                if (gRunInfo.dumpOnErr && gRunInfo.dom) {
  +                    thParser->domPrint();
  +                }
  +                fflush(stdout);
  +                fflush(stderr);
  +                clearFileInfoMemory();
  +                exit(-1);
  +            }
   
  -            // Revisit - let the loop continue to run?
  -            int secondTryCheckSum = thParser->reCheck();
  -            fprintf(stderr, "   Retry checksum is %x\n", secondTryCheckSum);
  -            if (gRunInfo.dumpOnErr) {
  -               if (gRunInfo.dom)
  -                  thParser->domPrint();
  +            if (gRunInfo.reuseParser == false) {
  +                delete thParser;
  +                thParser = 0;
               }
  -            fflush(stdout);
  -            clearFileInfoMemory();
  -            exit(-1);
  -        }
   
  -        if (gRunInfo.reuseParser == false)
  -        {
  -            delete thParser;
  -            thParser = 0;
  +            thInfo->fHeartBeat = true;
  +            thInfo->fParses++;
  +            thInfo->fInProgress = false;
  +        }
  +        else {
  +            ThreadFuncs::Sleep(1000); 
           }
  -
  -
  -        thInfo->fHeartBeat = true;
  -        thInfo->fParses++;
  -        thInfo->fInProgress = false;
       }
  -
       delete thParser;
   #ifdef PLATFORM_WIN32
       return 0;
  @@ -920,8 +1182,6 @@
   }
   
   
  -
  -
   //----------------------------------------------------------------------
   //
   //   main
  @@ -948,6 +1208,17 @@
       }
   
   
  +    /** Grammar caching thread testing */
  +    // Initialize memory manger and grammar pool
  +    // set doInitialParse to true so that the first parse will cache the
  +    // grammar and it'll be used in subsequent parses
  +    
  +    if (gRunInfo.doSchema == true && gRunInfo.doNamespaces == true && 
gRunInfo.doGrammarCaching == true) {
  +        gpMemMgr = new MemoryManagerImpl();
  +        gp = new XMLGrammarPoolImpl(gpMemMgr);
  +        gRunInfo.doInitialParse = true;
  +    }    
  +
       //
       // If we will be parsing from memory, read each of the input files
       //  into memory now.
  @@ -966,7 +1237,7 @@
       {
       //
       // While we are still single threaded, parse each of the documents
  -    //  once, to check for errors, and to note the checksum.
  +    // once, to check for errors, and to note the checksum.
       // Blow off the rest of the test if there are errors.
       //
           ThreadParser *mainParser = new ThreadParser;
  @@ -982,8 +1253,7 @@
   
               cksum = mainParser->parse(n);
   
  -            if (cksum == 0)
  -            {
  +            if (cksum == 0) {
                   fprintf(stderr, "An error occurred while initially parsing %s\n",
                       fileName);
                   errors = true;
  @@ -992,13 +1262,18 @@
               gRunInfo.files[n].checkSum = cksum;
               if (gRunInfo.verbose )
                   printf("%x\n", cksum);
  -            if (gRunInfo.dumpOnErr && errors) {
  -                if (gRunInfo.dom)
  -                    mainParser->domPrint();
  +            if (gRunInfo.dumpOnErr && errors && gRunInfo.dom) {
  +                mainParser->domPrint();
               }
   
           }
           delete mainParser;
  +
  +        if (errors) {
  +            fprintf(stderr, "Quitting due to error incurred during initial 
parse\n");
  +            clearFileInfoMemory();
  +            return 1;
  +        }
       }
   
       //
  @@ -1018,38 +1293,53 @@
           gThreadInfo[threadNum].fThreadNum = threadNum;
           ThreadFuncs::startThread(threadMain, &gThreadInfo[threadNum]);
       }
  -
  -    //
  -    //  Loop, watching the heartbeat of the worker threads.
  -    //    Each second, display "+" when all threads have completed a parse
  -    //                 display "." if some thread hasn't since previous "+"
  -    //
  -
  -    unsigned long startTime = XMLPlatformUtils::getCurrentMillis();
  -    int elapsedSeconds = 0;
  -    while (gRunInfo.totalTime == 0 || gRunInfo.totalTime > elapsedSeconds)
  -    {
  -        ThreadFuncs::Sleep(1000);
  -        if (gRunInfo.quiet == false && gRunInfo.verbose == false)
  -        {
  -            char c = '+';
  -            int threadNum;
  -            for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
  -            {
  -                if (gThreadInfo[threadNum].fHeartBeat == false)
  -                {
  -                    c = '.';
  -                    break;
  -                };
  -            }
  -            fputc(c, stdout);
  -            fflush(stdout);
  -            if (c == '+')
  -                for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
  -                    gThreadInfo[threadNum].fHeartBeat = false;
  +        
  +    if (gRunInfo.numParses)
  +    {
  +        bool notDone;
  +        while (true)
  +        {
  +            ThreadFuncs::Sleep(1000);            
  +            notDone = false;
  +           
  +            for (threadNum = 0; threadNum < gRunInfo.numThreads; threadNum++) {
  +                if (gThreadInfo[threadNum].fParses < gRunInfo.numParses)            
                        
  +                    notDone = true;
  +            }
  +            if (notDone == false) {                
  +                break;
  +            }
           }
  -        elapsedSeconds = (XMLPlatformUtils::getCurrentMillis() - startTime) / 1000;
  -    };
  +    }
  +    else
  +    {
  +        //
  +        //  Loop, watching the heartbeat of the worker threads.
  +        //    Each second, display "+" when all threads have completed a parse
  +        //                 display "." if some thread hasn't since previous "+"
  +        //
  +
  +        unsigned long startTime = XMLPlatformUtils::getCurrentMillis();
  +        int elapsedSeconds = 0;
  +        while (gRunInfo.totalTime == 0 || gRunInfo.totalTime > elapsedSeconds) {
  +            ThreadFuncs::Sleep(1000);
  +            if (gRunInfo.quiet == false && gRunInfo.verbose == false) {
  +                char c = '+';                
  +                for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) {
  +                    if (gThreadInfo[threadNum].fHeartBeat == false) {
  +                        c = '.';
  +                        break;
  +                    }
  +                }
  +                fputc(c, stdout);
  +                fflush(stdout);
  +                if (c == '+')
  +                    for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++)
  +                        gThreadInfo[threadNum].fHeartBeat = false;
  +            }
  +            elapsedSeconds = (XMLPlatformUtils::getCurrentMillis() - startTime) / 
1000;
  +        }
  +    }
   
       //
       //  Time's up, we are done.  (We only get here if this was a timed run)
  @@ -1066,7 +1356,6 @@
           }
           if (gRunInfo.verbose)
               printf("Thread #%d: is finished.\n", threadNum);
  -
       }
   
       //
  @@ -1080,8 +1369,19 @@
       }
   
       if (gRunInfo.quiet == false) {
  -        double parsesPerMinute = totalParsesCompleted / (double(gRunInfo.totalTime) 
/ double(60));
  -        printf("\n%8.1f parses per minute.\n", parsesPerMinute);
  +        if (gRunInfo.numParses) {
  +            printf("\n%8.0f total parses were completed.\n", totalParsesCompleted);
  +        }
  +        else {
  +            double parsesPerMinute = totalParsesCompleted / 
(double(gRunInfo.totalTime) / double(60));
  +            printf("\n%8.2f parses per minute.\n", parsesPerMinute);
  +        }
  +    }
  +    
  +    // delete grammar pool and memory manager
  +    if (gp) {
  +        delete gp;    
  +        delete gpMemMgr;    
       }
   
       XMLPlatformUtils::Terminate();
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to