diff options
| author | Bent Bisballe Nyeng <deva@aasimon.org> | 2012-08-09 11:24:11 +0200 | 
|---|---|---|
| committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2012-08-09 11:24:11 +0200 | 
| commit | 40211cd5598c5349358e1d33b6353a4c729b17b3 (patch) | |
| tree | 8c2cf76aed3847cc4e1d74d3b1df50b662908eed | |
| parent | 24900ef2773fdcd3afc1f7598e2d2ab99e138d71 (diff) | |
Added SessionHeaderParser for faster session xml file content searching.
| -rw-r--r-- | server/src/Makefile.am | 2 | ||||
| -rw-r--r-- | server/src/sessionheaderparser.cc | 178 | ||||
| -rw-r--r-- | server/src/sessionheaderparser.h | 96 | ||||
| -rw-r--r-- | server/src/sessionserialiser.cc | 42 | 
4 files changed, 303 insertions, 15 deletions
| diff --git a/server/src/Makefile.am b/server/src/Makefile.am index bb172bd..c852eb0 100644 --- a/server/src/Makefile.am +++ b/server/src/Makefile.am @@ -57,6 +57,7 @@ pracrod_SOURCES = \  	semaphore.cc \  	server.cc \  	session.cc \ +	sessionheaderparser.cc \  	sessionparser.cc \  	sessionserialiser.cc \  	templatelist.cc \ @@ -121,6 +122,7 @@ EXTRA_DIST = \  	semaphore.h \  	server.h \  	session.h \ +	sessionheaderparser.h \  	sessionparser.h \  	sessionserialiser.h \  	template.h \ diff --git a/server/src/sessionheaderparser.cc b/server/src/sessionheaderparser.cc new file mode 100644 index 0000000..93bd80b --- /dev/null +++ b/server/src/sessionheaderparser.cc @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + *            sessionheaderparser.cc + * + *  Thu Aug  9 09:06:32 CEST 2012 + *  Copyright 2012 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of Pracro. + * + *  Pracro is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  Pracro is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Pracro; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "sessionheaderparser.h" + +/* +<session timestamp="1234567890" +         status="readonly"" +         id="12345" +         template="amd_forunders" +         patientid="0000000000"> +   ... +</session> +*/ + +#include <stdio.h> + +// For assert +#include <assert.h> + +// For open and friends +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +// For vprintf and friends +#include <stdarg.h> + +#include <errno.h> +#include <string.h> + +#include "debug.h" +#include "configuration.h" +#include "exception.h" + +void SessionHeaderParser::error(const char* fmt, ...) +{ +  ERR_LOG(session, "Error in SessionHeaderParser: "); + +  { +    va_list argp; +    va_start(argp, fmt); +    ERR_LOG_VA(session, fmt, argp); +    va_end(argp); + +    fprintf(stderr, "\n"); +  } + +  { +    char *p; +    va_list argp; +    va_start(argp, fmt); +    if(vasprintf(&p, fmt, argp) != -1) { +      throw Exception("Error in SessionHeaderParser: " + std::string(p)); +      free(p); +    } +    va_end(argp); +  } + +} + +SessionHeaderParser::SessionHeaderParser(std::string sessionfile) +{ +  done = false; + +  file = sessionfile; + +  DEBUG(session, "Using session file: %s\n", sessionfile.c_str()); + +  fd = open(sessionfile.c_str(), O_RDONLY); +  if(fd == -1) error("Could not open file %s", sessionfile.c_str()); +} + +SessionHeaderParser::~SessionHeaderParser() +{ +  if(fd != -1) close(fd); +} + +void SessionHeaderParser::startTag(std::string name, attributes_t &attr) +{ +  if(done) return; + +  if(name == "session") { +    done = true; +    if(attr.find("patientid") != attr.end()) patientid = attr["patientid"]; +    if(attr.find("template") != attr.end()) templ = attr["template"]; +  } else { +    throw Exception("Missing root tag 'session' - found '" + name + "'"); +  } +} + +int SessionHeaderParser::readData(char *data, size_t size) +{ +  if(done) return 0; // If done is true we already found what we were looking +                     //  for and can dismiss the rest of the document. + +  if(fd == -1) { +    ERR_LOG(session, "Invalid file descriptor.\n"); +    return 0; +  } +  ssize_t r = read(fd, data, size); +  if(r == -1) { +    ERR_LOG(session, "Could not read...%s\n", strerror(errno)); +    return 0; +  } +  return r; +} + +void SessionHeaderParser::parseError(const char *buf, size_t len, std::string error, int lineno) +{ +  if(done) return; // If done is true we already found what we were looking +                   //  for and can dismiss the rest of the document. + +  ERR_LOG(session, "SessionHeaderParser[%s] error at line %d: %s\n", +          file.c_str(), lineno, error.c_str()); +  ERR_LOG(session, "\tBuffer %u bytes: [", len); +  if(fwrite(buf, len, 1, stderr) != len) {} +  ERR_LOG(session, "]\n"); + +  char *slineno; +  if(asprintf(&slineno, " at line %d\n", lineno) != -1) { +    throw Exception(error + slineno); +    free(slineno); +  } +} + +std::string SessionHeaderParser::getPatientID() +{ +  return patientid; +} + +std::string SessionHeaderParser::getTemplate() +{ +  return templ; +} + +#ifdef TEST_SESSIONHEADERPARSER +//Additional dependency files +//deps: +//Required cflags (autoconf vars may be used) +//cflags: +//Required link options (autoconf vars may be used) +//libs: +#include "test.h" + +TEST_BEGIN; + +// TODO: Put some testcode here (see test.h for usable macros). +TEST_TRUE(false, "No tests yet!"); + +TEST_END; + +#endif/*TEST_SESSIONHEADERPARSER*/ diff --git a/server/src/sessionheaderparser.h b/server/src/sessionheaderparser.h new file mode 100644 index 0000000..a56215a --- /dev/null +++ b/server/src/sessionheaderparser.h @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + *            sessionheaderparser.h + * + *  Thu Aug  9 09:06:32 CEST 2012 + *  Copyright 2012 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of Pracro. + * + *  Pracro is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  Pracro is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Pracro; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#ifndef __PRACRO_SESSIONHEADERPARSER_H__ +#define __PRACRO_SESSIONHEADERPARSER_H__ + +#include "saxparser.h" + +/** + * Partial session parser. + * This class is used to parse only the first tag of a session xml file. + * The parser will run about 10 times faster than the one parsing the entire + * file (see the SessionParser class) and can be used to find a + * patientid/template match. + * This class inherits the SAXParser baseclass. + * Use the parse() method to run the parser, and collect the result via the + * getPatientID() and getTemplate() methods. + * If the file does not contain a session, or the file is not a valid xml file, + * an Exception is thrown. + */ +class SessionHeaderParser : public SAXParser { +public: +  /** +   * Constructor. +   * @param sessionfile A std::string containing the name of the file to parse. +   */ +  SessionHeaderParser(std::string sessionfile); + +  /** +   * Destructor. +   */ +  ~SessionHeaderParser(); + +  /** +   * Overloaded parser callback method. +   */ +  void startTag(std::string name, attributes_t &attr); + +  /** +   * Overloaded parser callback method. +   */ +  void parseError(const char *buf, size_t len, std::string error, int lineno); + +  /** +   * Get a pointer to the parsed macro. +   * NOTE: The allocated memory for the macro is owned by the parser, and will be +   * freed upon parser deletion. +   * @return A pointer to the macro or NULL on error. +   */ +  std::string getPatientID(); +  std::string getTemplate(); + +protected: +  /** +   * Overloaded parser callback method. +   */ +  int readData(char *data, size_t size); + +private: +  int fd; + +  bool done; +  +  std::string patientid; +  std::string templ; + +  std::string file; +  // Error callback function. +  void error(const char* fmt, ...); +}; + +#endif/*__PRACRO_SESSIONHEADERPARSER_H__*/ diff --git a/server/src/sessionserialiser.cc b/server/src/sessionserialiser.cc index 386a115..d5150ac 100644 --- a/server/src/sessionserialiser.cc +++ b/server/src/sessionserialiser.cc @@ -34,6 +34,7 @@  #include "journal.h"  #include "sessionparser.h" +#include "sessionheaderparser.h"  #include "database.h"  #include "xml_encode_decode.h" @@ -255,25 +256,36 @@ Session *SessionSerialiser::findFromTupple(const std::string &patientid,        DEBUG(sessionserialiser, "Is xml file\n"); -      // Load session file -      FILE *fp =  fopen(filename.c_str(), "r"); -      std::string xml; -      while(!feof(fp)) { -        char str[64]; -        memset(str, 0, sizeof(str)); -        fread(str, sizeof(str) - 1, 1, fp); -        xml += str; +      std::string pid; +      std::string tpl; + +      SessionHeaderParser p(filename); +      try { +        p.parse(); +        pid = p.getPatientID(); +        tpl = p.getTemplate(); +      } catch( ... ) { +        continue;        } -      fclose(fp); -      Session *session = loadStr(xml); +      if(patientid == pid && templ == tpl) { +        // Load session file +        FILE *fp =  fopen(filename.c_str(), "r"); +        std::string xml; +        while(!feof(fp)) { +          char str[64]; +          memset(str, 0, sizeof(str)); +          fread(str, sizeof(str) - 1, 1, fp); +          xml += str; +        } +        fclose(fp); + +        Session *session = loadStr(xml); -      DEBUG(sessionserialiser, "PatientID %s - Template %s\n",  -            session->patientid.c_str(), -            session->templ.c_str()); +        DEBUG(sessionserialiser, "PatientID %s - Template %s\n",  +              session->patientid.c_str(), +              session->templ.c_str()); -      if(session->patientid == patientid && -         session->templ == templ) {          closedir(dir);          unlink(filename.c_str());          return session; | 
