unsigned long WINAPI threadMain (void *param) #endif { ThreadInfo *thInfo = (ThreadInfo *)param; ThreadParser *thParser = 0; if (gRunInfo.verbose) printf("Thread #%d: starting\n", thInfo->fThreadNum); int docNum = gRunInfo.numInputFiles; // // 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) { if (gRunInfo.numParses == 0 || thInfo->fParses < gRunInfo.numParses) { thInfo->fInProgress = true; if (thParser == 0) thParser = new ThreadParser; docNum++; if (docNum >= gRunInfo.numInputFiles) docNum = 0; InFileInfo *fInfo = &gRunInfo.files[docNum]; if (gRunInfo.verbose ) printf("Thread #%d: parse %d starting file %s\n", thInfo->fThreadNum, thInfo->fParses, fInfo->fileName); 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; } 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, fInfo->fileName, thInfo->fParses, 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); } if (gRunInfo.reuseParser == false) { delete thParser; thParser = 0; } thInfo->fHeartBeat = true; thInfo->fParses++; thInfo->fInProgress = false; } else { ThreadFuncs::Sleep(1000); } } delete thParser; #ifdef HAVE_PTHREAD return; }
int main (int argc, char **argv) { parseCommandLine(argc, argv); // // Initialize the XML system. // try { XMLPlatformUtils::Initialize(); } catch (...) { fprintf(stderr, "Exception from XMLPlatfromUtils::Initialize.\n"); return 1; } /** 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. // ReadFilesIntoMemory(); // Initialize checksums to zero so we can check first parse and if // zero then we need to move first parse's checksum into array. This // is for the cse where we skip the initial parse. for (int n = 0; n < gRunInfo.numInputFiles; n++) { gRunInfo.files[n].checkSum = 0; } if (gRunInfo.doInitialParse) { // // While we are still single threaded, parse each of the documents // 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; int n; bool errors = false; int cksum; for (n = 0; n < gRunInfo.numInputFiles; n++) { char *fileName = gRunInfo.files[n].fileName; if (gRunInfo.verbose) printf("%s checksum is ", fileName); cksum = mainParser->parse(n); if (cksum == 0) { fprintf(stderr, "An error occurred while initially parsing %s\n", fileName); errors = true; }; gRunInfo.files[n].checkSum = cksum; if (gRunInfo.verbose ) printf("%x\n", cksum); 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; } } // // Fire off the requested number of parallel threads // if (gRunInfo.numThreads == 0) { clearFileInfoMemory(); exit(0); } gThreadInfo = new ThreadInfo[gRunInfo.numThreads]; int threadNum; for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) { gThreadInfo[threadNum].fThreadNum = threadNum; ThreadFuncs::startThread(threadMain, &gThreadInfo[threadNum]); } 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; } } } 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) // Tally up the total number of parses completed by each of the threads. // gRunInfo.stopNow = true; // set flag, which will cause worker threads to stop. // // Make sure all threads are done before terminate // for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) { while (gThreadInfo[threadNum].fInProgress == true) { ThreadFuncs::Sleep(1000); } if (gRunInfo.verbose) printf("Thread #%d: is finished.\n", threadNum); } // // We are done! Count the number of parse and terminate the program // double totalParsesCompleted = 0; for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) { totalParsesCompleted += gThreadInfo[threadNum].fParses; // printf("%f ", totalParsesCompleted); } if (gRunInfo.quiet == false) { 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(); clearFileInfoMemory(); delete [] gThreadInfo; printf("Test Run Successfully\n"); return 0; }