Skip to content
Snippets Groups Projects
Commit ce4c13d2 authored by Oliver Bock's avatar Oliver Bock
Browse files

Using SAX style parsing instead of XPath searches

* SAX requires less memory
* Performance doesn't differ apparently
* Also: improved error handling
* Also: moved from stdlib to stream conversions
parent a90a54a4
No related branches found
No related tags found
No related merge requests found
...@@ -19,9 +19,8 @@ ...@@ -19,9 +19,8 @@
***************************************************************************/ ***************************************************************************/
#include "EinsteinRadioAdapter.h" #include "EinsteinRadioAdapter.h"
#include "Libxml2Adapter.h"
#include <cstdlib> #include <sstream>
const string EinsteinRadioAdapter::SharedMemoryIdentifier = "EinsteinRadio"; const string EinsteinRadioAdapter::SharedMemoryIdentifier = "EinsteinRadio";
...@@ -29,7 +28,7 @@ EinsteinRadioAdapter::EinsteinRadioAdapter(BOINCClientAdapter *boincClient) : ...@@ -29,7 +28,7 @@ EinsteinRadioAdapter::EinsteinRadioAdapter(BOINCClientAdapter *boincClient) :
m_WUTemplatePowerSpectrum(POWERSPECTRUM_BINS, 0) m_WUTemplatePowerSpectrum(POWERSPECTRUM_BINS, 0)
{ {
this->boincClient = boincClient; this->boincClient = boincClient;
m_xmlIFace = new Libxml2Adapter(); m_xmlReader = NULL;
m_WUSkyPosRightAscension = 0.0; m_WUSkyPosRightAscension = 0.0;
m_WUSkyPosDeclination = 0.0; m_WUSkyPosDeclination = 0.0;
...@@ -39,7 +38,8 @@ EinsteinRadioAdapter::EinsteinRadioAdapter(BOINCClientAdapter *boincClient) : ...@@ -39,7 +38,8 @@ EinsteinRadioAdapter::EinsteinRadioAdapter(BOINCClientAdapter *boincClient) :
EinsteinRadioAdapter::~EinsteinRadioAdapter() EinsteinRadioAdapter::~EinsteinRadioAdapter()
{ {
if(m_xmlIFace) delete m_xmlIFace; if(m_xmlReader) xmlFreeTextReader(m_xmlReader);
xmlCleanupParser();
} }
void EinsteinRadioAdapter::refresh() void EinsteinRadioAdapter::refresh()
...@@ -50,58 +50,68 @@ void EinsteinRadioAdapter::refresh() ...@@ -50,58 +50,68 @@ void EinsteinRadioAdapter::refresh()
void EinsteinRadioAdapter::parseApplicationInformation() void EinsteinRadioAdapter::parseApplicationInformation()
{ {
string spectrumString;
// get updated application information // get updated application information
string info = boincClient->applicationInformation(); string info = boincClient->applicationInformation();
// do we have any data? // do we have any data?
if(info.length() > 0) { if(info.length() > 0) {
string temp; int result = 0;
// TODO: SAX-style xmlReader could be an alternative to this (wrt performance)! // prepare conversion stream
stringstream converter;
// parse data into members converter.precision(3);
m_xmlIFace->setXmlDocument(info, "http://einstein.phys.uwm.edu"); converter.exceptions(ios_base::badbit | ios_base::failbit);
temp = m_xmlIFace->getSingleNodeContentByXPath("/graphics_info/skypos_rac");
m_WUSkyPosRightAscension = strtod(temp.c_str(), NULL); if(!m_xmlReader) {
temp = m_xmlIFace->getSingleNodeContentByXPath("/graphics_info/skypos_dec"); // set up SAX style XML reader (create instance)
m_WUSkyPosDeclination = strtod(temp.c_str(), NULL); m_xmlReader = xmlReaderForMemory(info.c_str(),
temp = m_xmlIFace->getSingleNodeContentByXPath("/graphics_info/dispersion"); info.length(),
m_WUDispersionMeasure = strtod(temp.c_str(), NULL); "http://einstein.phys.uwm.edu",
temp = m_xmlIFace->getSingleNodeContentByXPath("/graphics_info/orb_radius"); "UTF-8",
m_WUTemplateOrbitalRadius = strtod(temp.c_str(), NULL); 0);
temp = m_xmlIFace->getSingleNodeContentByXPath("/graphics_info/orb_period"); if(!m_xmlReader) {
m_WUTemplateOrbitalPeriod = strtod(temp.c_str(), NULL); cerr << "Error creating XML reader for shared memory data!" << endl;
temp = m_xmlIFace->getSingleNodeContentByXPath("/graphics_info/orb_phase"); return;
m_WUTemplateOrbitalPhase = strtod(temp.c_str(), NULL); }
spectrumString = m_xmlIFace->getSingleNodeContentByXPath("/graphics_info/power_spectrum"); }
temp = m_xmlIFace->getSingleNodeContentByXPath("/graphics_info/fraction_done"); else {
m_WUFractionDone = strtod(temp.c_str(), NULL); // set up SAX style XML reader (reusing existing instance)
temp = m_xmlIFace->getSingleNodeContentByXPath("/graphics_info/cpu_time"); if(xmlReaderNewMemory(m_xmlReader,
m_WUCPUTime = strtod(temp.c_str(), NULL); info.c_str(),
info.length(),
// TODO: make sure parsing worked flawlessly (only spectrum is checked below!) "http://einstein.phys.uwm.edu",
"UTF-8",
0))
{
cerr << "Error updating XML reader for shared memory data!" << endl;
return;
}
}
// parse XML fragment and process nodes
result = xmlTextReaderRead(m_xmlReader);
while (result == 1) {
processXmlNode(m_xmlReader, converter);
result = xmlTextReaderRead(m_xmlReader);
}
// convert radians to degrees // convert radians to degrees
m_WUSkyPosRightAscension *= 180/PI; m_WUSkyPosRightAscension *= 180/PI;
m_WUSkyPosDeclination *= 180/PI; m_WUSkyPosDeclination *= 180/PI;
// deserialize power spectrum data // deserialize power spectrum data
if(spectrumString.length() == POWERSPECTRUM_BIN_BYTES) { if(m_WUTemplatePowerSpectrumString.length() == POWERSPECTRUM_BIN_BYTES) {
int spectrumBinValue; int spectrumBinValue;
// prepare hex to int conversion stream ;
istringstream spectrumBinStream;
spectrumBinStream.exceptions(ios_base::badbit | ios_base::failbit);
// iterate over all bins // iterate over all bins
for(int i = 0, j = 0; i < POWERSPECTRUM_BIN_BYTES; i += 2, ++j) { for(int i = 0, j = 0; i < POWERSPECTRUM_BIN_BYTES; i += 2, ++j) {
try { try {
spectrumBinStream.str(spectrumString.substr(i, 2)); converter.clear();
converter.str(m_WUTemplatePowerSpectrumString.substr(i, 2));
// convert hex bin value to integer // convert hex bin value to integer
spectrumBinStream >> hex >> spectrumBinValue; converter >> hex >> spectrumBinValue;
// store bin power value // store bin power value
m_WUTemplatePowerSpectrum.at(j) = (unsigned char) spectrumBinValue; m_WUTemplatePowerSpectrum.at(j) = (unsigned char) spectrumBinValue;
spectrumBinStream.clear();
} }
catch(ios_base::failure) { catch(ios_base::failure) {
cerr << "Error processing power spectrum shared memory data!" << endl; cerr << "Error processing power spectrum shared memory data!" << endl;
...@@ -116,6 +126,75 @@ void EinsteinRadioAdapter::parseApplicationInformation() ...@@ -116,6 +126,75 @@ void EinsteinRadioAdapter::parseApplicationInformation()
} }
} }
void EinsteinRadioAdapter::processXmlNode(const xmlTextReaderPtr xmlReader, stringstream& converter)
{
// we only parse element nodes
if(xmlTextReaderNodeType(xmlReader) != XML_READER_TYPE_ELEMENT) return;
// buffers (will be deallocated automatically)
const xmlChar *nodeName = NULL, *nodeValue = NULL;
// get element node's name
nodeName = xmlTextReaderConstLocalName(xmlReader);
if (nodeName == NULL) {
cerr << "Error parsing XML node (invalid name)" << endl;
return;
}
// move to node's text content (child node) or return if unavailable
if(! (xmlTextReaderRead(m_xmlReader) && xmlTextReaderHasValue(xmlReader))) {
return;
}
// get text node's value
nodeValue = xmlTextReaderConstValue(xmlReader);
if (nodeValue == NULL) {
cerr << "Error parsing XML node (invalid value)" << endl;
return;
}
try {
// prepare converter stream
converter.clear();
converter.str("");
converter << nodeValue;
// assign node value to respective data member
if(xmlStrEqual(nodeName, BAD_CAST("skypos_rac"))) {
converter >> fixed >> m_WUSkyPosRightAscension;
}
else if(xmlStrEqual(nodeName, BAD_CAST("skypos_dec"))) {
converter >> fixed >> m_WUSkyPosDeclination;
}
else if(xmlStrEqual(nodeName, BAD_CAST("dispersion"))) {
converter >> fixed >> m_WUDispersionMeasure;
}
else if(xmlStrEqual(nodeName, BAD_CAST("orb_radius"))) {
converter >> fixed >> m_WUTemplateOrbitalRadius;
}
else if(xmlStrEqual(nodeName, BAD_CAST("orb_period"))) {
converter >> fixed >> m_WUTemplateOrbitalPeriod;
}
else if(xmlStrEqual(nodeName, BAD_CAST("orb_phase"))) {
converter >> fixed >> m_WUTemplateOrbitalPhase;
}
else if(xmlStrEqual(nodeName, BAD_CAST("power_spectrum"))) {
converter >> m_WUTemplatePowerSpectrumString;
}
else if(xmlStrEqual(nodeName, BAD_CAST("fraction_done"))) {
converter >> fixed >> m_WUFractionDone;
}
else if(xmlStrEqual(nodeName, BAD_CAST("cpu_time"))) {
converter >> fixed >> m_WUCPUTime;
}
}
catch(ios_base::failure) {
cerr << "Error converting XML reader node content!" << endl;
}
}
double EinsteinRadioAdapter::wuSkyPosRightAscension() const double EinsteinRadioAdapter::wuSkyPosRightAscension() const
{ {
return m_WUSkyPosRightAscension; return m_WUSkyPosRightAscension;
......
...@@ -25,8 +25,9 @@ ...@@ -25,8 +25,9 @@
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <libxml/xmlreader.h>
#include "BOINCClientAdapter.h" #include "BOINCClientAdapter.h"
#include "XMLProcessorInterface.h"
using namespace std; using namespace std;
...@@ -150,11 +151,25 @@ private: ...@@ -150,11 +151,25 @@ private:
*/ */
void parseApplicationInformation(); void parseApplicationInformation();
/**
* \brief Processes single element nodes found by the XML parser
*
* This method can sort of resembles the callback method used in conjunction with SAX parsers.
* It's called to process single XML nodes (in our case element nodes only) encountered
* during XML document (tree) traversal.
*
* \param xmlReader The pointer to the current xmlReader instance
* \param converter Reference to an existing string stream for value/type conversion
*
* \see parseApplicationInformation()
*/
void processXmlNode(const xmlTextReaderPtr xmlReader, stringstream& converter);
/// Pointer to the (parent) BOINC client adapter /// Pointer to the (parent) BOINC client adapter
BOINCClientAdapter *boincClient; BOINCClientAdapter *boincClient;
/// Pointer to the XML processor /// Pointer to the XML reader (SAX style)
XMLProcessorInterface* m_xmlIFace; xmlTextReaderPtr m_xmlReader;
/// Right ascension of the currently searched sky position (in degrees) /// Right ascension of the currently searched sky position (in degrees)
double m_WUSkyPosRightAscension; double m_WUSkyPosRightAscension;
...@@ -174,7 +189,10 @@ private: ...@@ -174,7 +189,10 @@ private:
/// Initial orbital phase of the currently active template /// Initial orbital phase of the currently active template
double m_WUTemplateOrbitalPhase; double m_WUTemplateOrbitalPhase;
/// Power spectrum of the currently active template /// Power spectrum of the currently active template (string)
string m_WUTemplatePowerSpectrumString;
/// Power spectrum of the currently active template (values)
vector<unsigned char> m_WUTemplatePowerSpectrum; vector<unsigned char> m_WUTemplatePowerSpectrum;
/// The completion fraction of the active work unit /// The completion fraction of the active work unit
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment