source: icXML/icXML-devel/tests/src/MemHandlerTest/MemoryMonitor.cpp @ 2733

Last change on this file since 2733 was 2726, checked in by cameron, 7 years ago

Add original Xerces tests and samples directories

File size: 16.3 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: MemoryMonitor.cpp 833057 2009-11-05 15:25:10Z borisk $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26#include "MemoryMonitor.hpp"
27#if defined(XERCES_NEW_IOSTREAMS)
28#include <iostream>
29#include <fstream>
30#else
31#include <iostream.h>
32#include <fstream.h>
33#endif
34#include <assert.h>
35#include <xercesc/util/XercesDefs.hpp>
36#include <xercesc/util/OutOfMemoryException.hpp>
37#include <xercesc/dom/DOM.hpp>
38
39MemoryManager* MemoryMonitor::getExceptionMemoryManager()
40{
41  return this;
42}
43
44void* MemoryMonitor::allocate(XMLSize_t size)
45{
46    void *key = ::operator new(size);
47    fHashTable->put(key, (unsigned int)size);
48    return key;
49}
50
51void MemoryMonitor::deallocate(void* p)
52{
53    // if fHashTable doesn't contain p, then this memory manager
54    // didn't allocate that memory--a segfault waiting to happen...
55    assert(p == 0 || fHashTable->containsKey(p) != 0);
56    if (p != 0)
57    {
58        fHashTable->removeKey(p);
59        ::operator delete(p);
60    }
61}
62
63unsigned int MemoryMonitor::getTotalMemory()
64{
65    unsigned int total = 0;
66    ValueHashTableOfEnumerator<unsigned int> *memEnum =
67            new ValueHashTableOfEnumerator<unsigned int>(fHashTable);
68    while(memEnum->hasMoreElements()) {
69        total += memEnum->nextElement();
70    }
71    delete memEnum;
72    return total;
73}
74
75static void usage()
76{
77    XERCES_STD_QUALIFIER cout << "\nUsage:\n"
78            "    MemHandlerTest [options] <XML file | List file>\n\n"
79            "This program invokes the XercesDOMParser, DOMLSParser, SAXParser ,\n"
80            "and the SAX2XMLReader, and ensures that MemoryManagers set on these\n"
81            "domBuilders are called to delete just as many bytes as they allocate.\n"
82            "This is done for each XML file, and each file is processed\n"
83            "as many times as indicated.\n"
84            "Options:\n"
85            "    -l          Indicate the input file is a List File that has a list of xml files.\n"
86            "                Default to off (Input file is an XML file).\n"
87            "    -v=xxx      Validation scheme [always | never | auto*].\n"
88            "    -n          Enable namespace processing. Defaults to off.\n"
89            "    -s          Enable schema processing. Defaults to off.\n"
90            "    -f          Enable full schema constraint checking. Defaults to off.\n"
91            "    -r=n        Run file through domBuilders n times.\n"
92                    "    -?          Show this help.\n\n"
93            "  * = Default if not provided explicitly.\n"
94         << XERCES_STD_QUALIFIER endl;
95}
96
97class DOMLSParserHandler : public DOMErrorHandler
98{
99public:
100    DOMLSParserHandler() {};
101    ~DOMLSParserHandler() {};
102    bool handleError(const DOMError &error)
103    {
104        char *message = 0;
105        XERCES_STD_QUALIFIER cerr << "Error occurred in DOMBuilder!  Message:  " <<
106            (message = XMLString::transcode(error.getMessage())) << " of severity " << error.getSeverity() << "." << XERCES_STD_QUALIFIER endl;
107        XMLString::release(&message);
108        return true;
109    }
110};
111
112class SAXErrorHandler : public ErrorHandler
113{
114public:
115    SAXErrorHandler() {};
116    ~SAXErrorHandler() {};
117    void warning(const SAXParseException &exc )
118    {
119        char *message = 0;
120        XERCES_STD_QUALIFIER cerr << "SAX warning received!  Text:  " <<
121            (message = XMLString::transcode(exc.getMessage())) << "." << XERCES_STD_QUALIFIER endl;
122        XMLString::release(&message);
123    }
124    void error(const SAXParseException &exc )
125    {
126        char *message = 0;
127        XERCES_STD_QUALIFIER cerr << "SAX error received!  Text:  " <<
128            (message = XMLString::transcode(exc.getMessage())) << "." << XERCES_STD_QUALIFIER endl;
129        XMLString::release(&message);
130    }
131    void fatalError(const SAXParseException &exc )
132    {
133        char *message = 0;
134        XERCES_STD_QUALIFIER cerr << "SAX fatalError received!  Text:  " <<
135            (message = XMLString::transcode(exc.getMessage())) << "." << XERCES_STD_QUALIFIER endl;
136        XMLString::release(&message);
137    }
138
139    // no state so no body
140    void resetErrors() {};
141};
142
143/**
144 * This utility takes similar parameters as DOMCount,
145 * with similar meanings.  The only difference is that it runs
146 * the file(s) in question through a DOMParser, a DOMBuilder, a SAXParser and
147 * a SAX2XMLReader, setting options as appropriate.  It does this
148 * sequentially, n times per file with a single domBuilder
149 * object, and reports what it finds in terms of memory
150 * allocations/deallocations.
151 */
152
153int main (int argC,  char *argV[])
154{
155
156    MemoryMonitor *staticMemMonitor = new MemoryMonitor();
157
158    // Initialize the XML4C system
159    try
160    {
161        XMLPlatformUtils::Initialize(XMLUni::fgXercescDefaultLocale, 0, 0, staticMemMonitor);
162    }
163    catch (const XMLException& toCatch)
164    {
165         char *msg = XMLString::transcode(toCatch.getMessage());
166         XERCES_STD_QUALIFIER cerr << "Error during initialization! :\n"
167              << msg << XERCES_STD_QUALIFIER endl;
168         XMLString::release(&msg);
169         return 1;
170    }
171
172    // Check command line and extract arguments.
173    if (argC < 2)
174    {
175        usage();
176        return 1;
177    }
178
179    const char*                xmlFile = 0;
180    AbstractDOMParser::ValSchemes domBuilderValScheme = AbstractDOMParser::Val_Auto;
181    bool                       doNamespaces       = false;
182    bool                       doSchema           = false;
183    bool                       schemaFullChecking = false;
184    bool                       doList = false;
185    int                        numReps =1;
186
187    int argInd;
188    for (argInd = 1; argInd < argC; argInd++)
189    {
190        // Break out on first parm not starting with a dash
191        if (argV[argInd][0] != '-')
192            break;
193
194        // Watch for special case help request
195        if (!strcmp(argV[argInd], "-?"))
196        {
197            usage();
198            return 2;
199        }
200         else if (!strncmp(argV[argInd], "-v=", 3)
201              ||  !strncmp(argV[argInd], "-V=", 3))
202        {
203            const char* const parm = &argV[argInd][3];
204
205            if (!strcmp(parm, "never"))
206                domBuilderValScheme = AbstractDOMParser::Val_Never;
207            else if (!strcmp(parm, "auto"))
208                domBuilderValScheme = AbstractDOMParser::Val_Auto;
209            else if (!strcmp(parm, "always"))
210                domBuilderValScheme = AbstractDOMParser::Val_Always;
211            else
212            {
213                XERCES_STD_QUALIFIER cerr << "Unknown -v= value: " << parm << XERCES_STD_QUALIFIER endl;
214                return 2;
215            }
216        }
217         else if (!strcmp(argV[argInd], "-n")
218              ||  !strcmp(argV[argInd], "-N"))
219        {
220            doNamespaces = true;
221        }
222         else if (!strcmp(argV[argInd], "-s")
223              ||  !strcmp(argV[argInd], "-S"))
224        {
225            doSchema = true;
226        }
227         else if (!strcmp(argV[argInd], "-f")
228              ||  !strcmp(argV[argInd], "-F"))
229        {
230            schemaFullChecking = true;
231        }
232         else if (!strcmp(argV[argInd], "-l")
233              ||  !strcmp(argV[argInd], "-L"))
234        {
235            doList = true;
236        }
237         else if (!strncmp(argV[argInd], "-r=", 3)
238              ||  !strncmp(argV[argInd], "-R=", 3))
239        {
240            const char* const numStr = &argV[argInd][3];
241            XMLCh* numXStr = XMLString::transcode(numStr);
242            numReps = XMLString::parseInt(numXStr);
243            XMLString::release(&numXStr);
244        }
245         else
246        {
247            XERCES_STD_QUALIFIER cerr << "Unknown option '" << argV[argInd]
248                 << "', ignoring it\n" << XERCES_STD_QUALIFIER endl;
249        }
250    }
251
252    //
253    //  There should be only one and only one parameter left, and that
254    //  should be the file name.
255    //
256    if (argInd != argC - 1)
257    {
258        usage();
259        return 1;
260    }
261
262    // Instantiate the DOM domBuilder with its memory manager.
263    MemoryMonitor *domBuilderMemMonitor = new MemoryMonitor();
264    static const XMLCh gLS[] = { chLatin_L, chLatin_S, chNull };
265    DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(gLS);
266    DOMLSParser       *domBuilder = ((DOMImplementationLS*)impl)->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0, domBuilderMemMonitor);
267    DOMLSParserHandler domBuilderHandler;
268    domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMErrorHandler, &domBuilderHandler);
269
270    // Instantiate the SAX2 parser with its memory manager.
271    MemoryMonitor *sax2MemMonitor = new MemoryMonitor();
272    SAX2XMLReader *sax2parser = XMLReaderFactory::createXMLReader(sax2MemMonitor);
273    SAXErrorHandler saxErrorHandler;
274    sax2parser->setErrorHandler(&saxErrorHandler);
275
276    // Instantiate the SAX 1 parser with its memory manager.
277    MemoryMonitor *sax1MemMonitor = new MemoryMonitor();
278    SAXParser *saxParser = new (sax1MemMonitor) SAXParser(0, sax1MemMonitor);
279    saxParser->setErrorHandler(&saxErrorHandler);
280
281    // set features
282    domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMNamespaces, doNamespaces);
283    sax2parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, doNamespaces);
284    saxParser->setDoNamespaces(doNamespaces);
285
286    domBuilder->getDomConfig()->setParameter(XMLUni::fgXercesSchema, doSchema);
287    sax2parser->setFeature(XMLUni::fgXercesSchema, doSchema);
288    saxParser->setDoSchema(doSchema);
289
290    domBuilder->getDomConfig()->setParameter(XMLUni::fgXercesHandleMultipleImports, true);
291    sax2parser->setFeature(XMLUni::fgXercesHandleMultipleImports, true);
292    saxParser->setHandleMultipleImports (true);
293
294    domBuilder->getDomConfig()->setParameter(XMLUni::fgXercesSchemaFullChecking, schemaFullChecking);
295    sax2parser->setFeature(XMLUni::fgXercesSchemaFullChecking, schemaFullChecking);
296    saxParser->setValidationSchemaFullChecking(schemaFullChecking);
297
298    if (domBuilderValScheme == AbstractDOMParser::Val_Auto)
299    {
300        domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMValidateIfSchema, true);
301        sax2parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
302        sax2parser->setFeature(XMLUni::fgXercesDynamic, true);
303        saxParser->setValidationScheme(SAXParser::Val_Auto);
304    }
305    else if (domBuilderValScheme == AbstractDOMParser::Val_Never)
306    {
307        domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMValidate, false);
308        sax2parser->setFeature(XMLUni::fgSAX2CoreValidation, false);
309        saxParser->setValidationScheme(SAXParser::Val_Never);
310    }
311    else if (domBuilderValScheme == AbstractDOMParser::Val_Always)
312    {
313        domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMValidate, true);
314        sax2parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
315        sax2parser->setFeature(XMLUni::fgXercesDynamic, false);
316        saxParser->setValidationScheme(SAXParser::Val_Always);
317    }
318
319    // enable datatype normalization - default is off
320    domBuilder->getDomConfig()->setParameter(XMLUni::fgDOMDatatypeNormalization, true);
321
322    XERCES_STD_QUALIFIER ifstream fin;
323    bool more = true;
324
325    // the input is a list file
326    if (doList)
327        fin.open(argV[argInd]);
328
329    if (fin.fail()) {
330        XERCES_STD_QUALIFIER cerr <<"Cannot open the list file: " << argV[argInd] << XERCES_STD_QUALIFIER endl;
331        return 2;
332    }
333
334    while (more)
335    {
336        char fURI[1000];
337        //initialize the array to zeros
338        memset(fURI,0,sizeof(fURI));
339
340        if (doList) {
341            if (! fin.eof() ) {
342                fin.getline (fURI, sizeof(fURI));
343                if (!*fURI)
344                    continue;
345                else {
346                    xmlFile = fURI;
347                    XERCES_STD_QUALIFIER cerr << "==Parsing== " << xmlFile << XERCES_STD_QUALIFIER endl;
348                }
349            }
350            else
351                break;
352        }
353        else {
354            xmlFile = argV[argInd];
355            more = false;
356        }
357
358        // parse numReps times (in case we need it for some reason)
359        for (int i=0; i<numReps; i++)
360        {
361
362            XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc = 0;
363
364            try
365            {
366                // reset document pool
367                domBuilder->resetDocumentPool();
368
369                doc = domBuilder->parseURI(xmlFile);
370                if(doc && doc->getDocumentElement())
371                {
372                    XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList *list=NULL;
373                    if(doNamespaces)
374                        list=doc->getElementsByTagNameNS(doc->getDocumentElement()->getNamespaceURI(), doc->getDocumentElement()->getLocalName());
375                    else
376                        list=doc->getElementsByTagName(doc->getDocumentElement()->getNodeName());
377                    if(list==NULL)
378                        XERCES_STD_QUALIFIER cout << "getElementsByTagName didn't return a valid DOMNodeList." << XERCES_STD_QUALIFIER endl;
379                    else if(list->item(0)!=doc->getDocumentElement())
380                        XERCES_STD_QUALIFIER cout << "getElementsByTagName didn't find the root element." << XERCES_STD_QUALIFIER endl;
381                }
382                sax2parser->parse(xmlFile);
383                saxParser->parse(xmlFile);
384            }
385            catch (const OutOfMemoryException&)
386            {
387                XERCES_STD_QUALIFIER cerr << "OutOfMemoryException during parsing: '" << xmlFile << "'\n" << XERCES_STD_QUALIFIER endl;;
388                continue;
389            }
390            catch (const XMLException& toCatch)
391            {
392                char *msg = XMLString::transcode(toCatch.getMessage());
393                XERCES_STD_QUALIFIER cerr << "\nError during parsing: '" << xmlFile << "'\n"
394                    << "Exception message is:  \n"
395                    << msg << "\n" << XERCES_STD_QUALIFIER endl;
396                XMLString::release(&msg);
397                continue;
398            }
399            catch (const DOMException& toCatch)
400            {
401                const unsigned int maxChars = 2047;
402                XMLCh errText[maxChars + 1];
403
404                XERCES_STD_QUALIFIER cerr << "\nDOM Error during parsing: '" << xmlFile << "'\n"
405                    << "DOMException code is:  " << toCatch.code << XERCES_STD_QUALIFIER endl;
406
407                if (DOMImplementation::loadDOMExceptionMsg(toCatch.code, errText, maxChars))
408                {
409                    char * msg = XMLString::transcode(errText);
410                    XERCES_STD_QUALIFIER cerr << "Message is: " << msg << XERCES_STD_QUALIFIER endl;
411
412                    continue;
413                }
414            }
415            catch (...)
416            {
417                XERCES_STD_QUALIFIER cerr << "\nUnexpected exception during parsing: '" << xmlFile << "'\n";
418                continue;
419            }
420
421        }
422    }
423
424    //
425    //  Delete the domBuilder itself.  Must be done prior to calling Terminate, below.
426    //
427    domBuilder->release();
428    delete sax2parser;
429    delete saxParser;
430
431    XERCES_STD_QUALIFIER cout << "At destruction, domBuilderMemMonitor has " << domBuilderMemMonitor->getTotalMemory() << " bytes." << XERCES_STD_QUALIFIER endl;
432    XERCES_STD_QUALIFIER cout << "At destruction, sax2MemMonitor has " << sax2MemMonitor->getTotalMemory() << " bytes." << XERCES_STD_QUALIFIER endl;
433    XERCES_STD_QUALIFIER cout << "At destruction, sax1MemMonitor has " << sax1MemMonitor->getTotalMemory() << " bytes." << XERCES_STD_QUALIFIER endl;
434    delete domBuilderMemMonitor;
435    delete sax2MemMonitor;
436    delete sax1MemMonitor;
437
438    XMLPlatformUtils::Terminate();
439    XERCES_STD_QUALIFIER cout << "At destruction, staticMemMonitor has " << staticMemMonitor->getTotalMemory() << " bytes." << XERCES_STD_QUALIFIER endl;
440    delete staticMemMonitor;
441    return 0;
442}
Note: See TracBrowser for help on using the repository browser.