From 97a1dc47e8e6a127a4c08e9a6cf8923009ca335f Mon Sep 17 00:00:00 2001
From: Oliver Bock <oliver.bock@aei.mpg.de>
Date: Fri, 11 Apr 2008 15:26:27 +0200
Subject: [PATCH] Refactored the BOINC client/application communication layer

* Now there's a generic and science application specific (e.g. shared memory handling) part
* The actual shared memory indentifier now has to be passed during initialize() instead of being hard-coded
* All this might eventually allow us to incorporate some portions of this API into something more general like a generic graphics toolkit
---
 BOINCClientAdapter.cpp  | 81 ++++++++++++++-----------------------
 BOINCClientAdapter.h    | 76 +++++++++++++----------------------
 EinsteinS5R3Adapter.cpp | 66 ++++++++++++++++++++++++++++++
 EinsteinS5R3Adapter.h   | 89 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 211 insertions(+), 101 deletions(-)
 create mode 100644 EinsteinS5R3Adapter.cpp
 create mode 100644 EinsteinS5R3Adapter.h

diff --git a/BOINCClientAdapter.cpp b/BOINCClientAdapter.cpp
index deaf9fa..901e2ce 100644
--- a/BOINCClientAdapter.cpp
+++ b/BOINCClientAdapter.cpp
@@ -2,24 +2,32 @@
 
 BOINCClientAdapter::BOINCClientAdapter()
 {
-	m_WUSkyPosRightAscension = 0.0;
-	m_WUSkyPosDeclination = 0.0;
-	m_WUFractionDone = 0.0;
-	m_WUCPUTime = 0.0;
-	
-    m_SharedMemoryAreaAvailable = false;
-    
-	readUserInfo();
-	readSharedMemoryArea();
+	m_Initialized = false;
+	m_SharedMemoryAreaAvailable = false;
 }
 
 BOINCClientAdapter::~BOINCClientAdapter()
 {
 }
 
-void BOINCClientAdapter::refresh()
+void BOINCClientAdapter::initialize(string sharedMemoryIdentifier)
 {
+	m_SharedMemoryAreaIdentifier = sharedMemoryIdentifier;
+	
+	readUserInfo();
 	readSharedMemoryArea();
+	
+	m_Initialized = true;
+}
+
+void BOINCClientAdapter::refresh()
+{
+	if(m_Initialized) {
+		readSharedMemoryArea();
+	}
+	else {
+		cerr << "The BOINC Client Adapter has not yet been initialized!";
+	}
 }
 
 void BOINCClientAdapter::readUserInfo()
@@ -28,35 +36,16 @@ void BOINCClientAdapter::readUserInfo()
 	boinc_get_init_data(m_UserData);
 }
 
-/**
- * \todo This should be more flexible as the shared memory area's
- * contents are very likely to change over time, i.e. when a new
- * application (and/or search method) is implemented!
- * \note We might use the factory method pattern here
- */
 void BOINCClientAdapter::readSharedMemoryArea()
 {
 	// check if we already have a pointer
 	if(m_SharedMemoryAreaAvailable) {
-
-		// parse the current contents (see notes above!)
-		if(4 != sscanf(m_SharedMemoryArea,
-			  		"<graphics_info>\n"
-			  		"  <skypos_rac>%lf</skypos_rac>\n"
-			  		"  <skypos_dec>%lf</skypos_dec>\n"
-			  		"  <fraction_done>%lf</fraction_done>\n"
-			  		"  <cpu_time>%lf</cpu_time>\n",
-			  		&m_WUSkyPosRightAscension,
-			  		&m_WUSkyPosDeclination,
-			  		&m_WUFractionDone,
-			  		&m_WUCPUTime))
-		{		 
-			cerr << "Incompatible shared memory data encountered!" << endl;
-	  }
+		// load contents
+		m_SharedMemoryAreaContents = string(m_SharedMemoryArea);
 	}
 	// the shared memory area's not available, try to get a pointer to it
 	else {
-	   m_SharedMemoryArea = (char*) boinc_graphics_get_shmem(EAH_SHMEM_APP_NAME);
+	   m_SharedMemoryArea = (char*) boinc_graphics_get_shmem(m_SharedMemoryAreaIdentifier.c_str());
 	    
 	    if(m_SharedMemoryArea) {
 	    	// fine, get the contents recursively
@@ -65,14 +54,22 @@ void BOINCClientAdapter::readSharedMemoryArea()
 	    }
 	    else {
 	    	// bad luck
+	    	m_SharedMemoryAreaContents = "";
 	        m_SharedMemoryAreaAvailable = false;
 	    }
 	}
 }
 
+string BOINCClientAdapter::applicationInformation() const
+{
+	return m_SharedMemoryAreaContents;
+}
+
 string BOINCClientAdapter::coreVersion() const
 {
 	stringstream buffer;
+	
+	// build common version string
 	buffer	<< m_UserData.major_version << "."
 			<< m_UserData.minor_version << "."
 			<< m_UserData.release;
@@ -149,23 +146,3 @@ double BOINCClientAdapter::wuDiskBound() const
 {
 	return m_UserData.rsc_disk_bound;
 }
-
-double BOINCClientAdapter::wuSkyPosRightAscension() const
-{
-	return m_WUSkyPosRightAscension;
-}
-
-double BOINCClientAdapter::wuSkyPosDeclination() const
-{
-	return m_WUSkyPosDeclination;
-}
-
-double BOINCClientAdapter::wuFractionDone() const
-{
-	return m_WUFractionDone;
-}
-
-double BOINCClientAdapter::wuCPUTime() const
-{
-	return m_WUCPUTime;
-}
diff --git a/BOINCClientAdapter.h b/BOINCClientAdapter.h
index 7bd07a8..449c072 100644
--- a/BOINCClientAdapter.h
+++ b/BOINCClientAdapter.h
@@ -11,16 +11,10 @@
 using namespace std;
 
 /**
- * This is the common name tag used to identify the shared memory area
- * provided by the \b Einstein\@Home application
- */
-#define EAH_SHMEM_APP_NAME "EinsteinHS"
-
-/**
- * \brief Adapter class which facilitates all communications with the BOINC client
+ * \brief Adapter class which facilitates communications with the BOINC client
  * 
- * This adapter class can be used to query the BOINC core client as well as the \b Einstein\@Home
- * application for informational data.
+ * This adapter class can be used to query the BOINC core client for information
+ * about the user and the running science application instance.
  * 
  * \author Oliver Bock\n
  * Max-Planck-Institute for Gravitational Physics\n
@@ -34,13 +28,22 @@ public:
 	
 	/// Destructor
 	virtual ~BOINCClientAdapter();
+
+	/**
+	 * \brief Initializes the BOINC client adapter instance
+	 * 
+	 * This method has to be called first, otherwise no data will be returned when requested!
+	 */
+	void initialize(string sharedMemoryIdentifier);
 	
 	/**
 	 * \brief Refreshes dynamic data (e.g. search information)
 	 * 
-	 * You want to call this method periodically to refresh any volatile client information
+	 * You want to call this method periodically to refresh any volatile client information.
+	 * Please make sure that you call initialize() first!
 	 * 	
-	 * \see AbstractGraphicsEngine::refreshBOINCInformation()
+	 * \see AbstractGraphicsEngine::refreshBOINCInformation
+	 * \see initialize
 	 */
 	void refresh();
 	
@@ -119,36 +122,14 @@ public:
     double wuFPOpsBound() const;
     double wuMemoryBound() const;
     double wuDiskBound() const;
-
-    /**
-	 * \brief Retrieves the right ascension of the currently searched sky position
-	 * 
-	 * \return The right ascension (in radians)
-	 */
-    double wuSkyPosRightAscension() const;
     
     /**
-	 * \brief Retrieves the declination of the currently searched sky position
-	 * 
-	 * \return The right ascension (in radians)
-	 */
-    double wuSkyPosDeclination() const;
-    
-    /**
-     * \brief Retrieves the completion fraction of the currently active work unit
-     * 
-     * \return The completion fraction (range 0-1)
-     */    
-    double wuFractionDone() const;
-    
-    /**
-     * \brief Retrieves the amount of CPU time consumed for the currently active work unit
-     * during the active session
+     * \brief Retrieves information provided by the running science application
      * 
-     * \return The accumulated CPU time consumed during this work unit session (in seconds)
+     * \return The application specific information string (i.e. XML)
      */
-    double wuCPUTime() const;
-	
+    string applicationInformation() const;
+
 private:
     /**
      * \brief Fetch the contents of \c init_data.xml
@@ -171,9 +152,18 @@ private:
 	 */
 	void readSharedMemoryArea();
 	
+	/// State flag which indicates whether the adapter instance is ready to be used
+	bool m_Initialized;
+	
+	/// Name tag used to identify the shared memory area provided by the \b Einstein\@Home application
+	string m_SharedMemoryAreaIdentifier;
+	
 	/// Pointer to the shared memory area
 	char *m_SharedMemoryArea;
 	
+	/// The contents of the shared memory area after the last refresh
+	string m_SharedMemoryAreaContents;
+	
 	/// Flag to indicate whether the shared memory area is available or not
 	bool m_SharedMemoryAreaAvailable;
 	
@@ -183,18 +173,6 @@ private:
 	 * It contains initial information about the current work unit computation session.
 	 */
 	APP_INIT_DATA m_UserData;
-	
-	/// Right ascension of the currently searched sky position
-	double m_WUSkyPosRightAscension;
-	
-	/// Declination of the currently searched sky position
-	double m_WUSkyPosDeclination;
-	
-	/// The completion fraction of the active work unit
-	double m_WUFractionDone;
-	
-	/// Amount of CPU time consumed for the work unit during the active session
-	double m_WUCPUTime;
 };
 
 #endif /*BOINCCLIENTADAPTER_H_*/
diff --git a/EinsteinS5R3Adapter.cpp b/EinsteinS5R3Adapter.cpp
new file mode 100644
index 0000000..5df4e36
--- /dev/null
+++ b/EinsteinS5R3Adapter.cpp
@@ -0,0 +1,66 @@
+#include "EinsteinS5R3Adapter.h"
+
+EinsteinS5R3Adapter::EinsteinS5R3Adapter(BOINCClientAdapter *boincClient)
+{
+	this->boincClient = boincClient;
+	
+	m_WUSkyPosRightAscension = 0.0;
+	m_WUSkyPosDeclination = 0.0;
+	m_WUFractionDone = 0.0;
+	m_WUCPUTime = 0.0;
+}
+
+EinsteinS5R3Adapter::~EinsteinS5R3Adapter()
+{
+}
+
+void EinsteinS5R3Adapter::refresh()
+{
+	boincClient->refresh();
+	parseApplicationInformation();
+}
+
+void EinsteinS5R3Adapter::parseApplicationInformation()
+{
+	// get updated application information
+	string info = boincClient->applicationInformation();
+	
+	// do we have any data?
+	if(info.length() > 0) {
+		
+		// parse data into members
+		if(4 != sscanf(info.c_str(),
+			  		"<graphics_info>\n"
+			  		"  <skypos_rac>%lf</skypos_rac>\n"
+			  		"  <skypos_dec>%lf</skypos_dec>\n"
+			  		"  <fraction_done>%lf</fraction_done>\n"
+			  		"  <cpu_time>%lf</cpu_time>\n",
+			  		&m_WUSkyPosRightAscension,
+			  		&m_WUSkyPosDeclination,
+			  		&m_WUFractionDone,
+			  		&m_WUCPUTime))
+		{		 
+			cerr << "Incompatible shared memory data encountered!" << endl;
+		}
+	}
+}
+
+double EinsteinS5R3Adapter::wuSkyPosRightAscension() const
+{
+	return m_WUSkyPosRightAscension;
+}
+
+double EinsteinS5R3Adapter::wuSkyPosDeclination() const
+{
+	return m_WUSkyPosDeclination;
+}
+
+double EinsteinS5R3Adapter::wuFractionDone() const
+{
+	return m_WUFractionDone;
+}
+
+double EinsteinS5R3Adapter::wuCPUTime() const
+{
+	return m_WUCPUTime;
+}
diff --git a/EinsteinS5R3Adapter.h b/EinsteinS5R3Adapter.h
new file mode 100644
index 0000000..f7e0d0b
--- /dev/null
+++ b/EinsteinS5R3Adapter.h
@@ -0,0 +1,89 @@
+#ifndef EINSTEINS5R3ADAPTER_H_
+#define EINSTEINS5R3ADAPTER_H_
+
+#include <string>
+
+#include "BOINCClientAdapter.h"
+
+using namespace std;
+
+/**
+ * \brief Adapter class which facilitates communications with the \b Einstein\@Home S5R3 application
+ * 
+ * This adapter class can be used to query the \b Einstein\@Home S5R3 application
+ * for informational data about the current work unit like search details and progress.
+ * 
+ * \author Oliver Bock\n
+ * Max-Planck-Institute for Gravitational Physics\n
+ * Hannover, Germany
+ */
+class EinsteinS5R3Adapter
+{
+public:
+	/**
+	 * Constructor
+	 * 
+	 * \param boincClient Pointer to the general BOINC client adapter instance
+	 */
+	EinsteinS5R3Adapter(BOINCClientAdapter* boincClient);
+	
+	/// Destructor
+	virtual ~EinsteinS5R3Adapter();
+	
+	/**
+	 * \brief Refreshes dynamic data (e.g. search information)
+	 * 
+	 * You want to call this method periodically to refresh any volatile application information
+	 * 	
+	 * \see AbstractGraphicsEngine::refreshBOINCInformation
+	 */
+	void refresh();
+	
+    /**
+	 * \brief Retrieves the right ascension of the currently searched sky position
+	 * 
+	 * \return The right ascension (in radians)
+	 */
+    double wuSkyPosRightAscension() const;
+    
+    /**
+	 * \brief Retrieves the declination of the currently searched sky position
+	 * 
+	 * \return The right ascension (in radians)
+	 */
+    double wuSkyPosDeclination() const;
+    
+    /**
+     * \brief Retrieves the completion fraction of the currently active work unit
+     * 
+     * \return The completion fraction (range 0-1)
+     */    
+    double wuFractionDone() const;
+    
+    /**
+     * \brief Retrieves the amount of CPU time consumed for the currently active work unit
+     * during the active session
+     * 
+     * \return The accumulated CPU time consumed during this work unit session (in seconds)
+     */
+    double wuCPUTime() const;
+    
+private:
+	void parseApplicationInformation();
+	
+	BOINCClientAdapter *boincClient;
+	
+	/// Right ascension of the currently searched sky position
+	double m_WUSkyPosRightAscension;
+	
+	/// Declination of the currently searched sky position
+	double m_WUSkyPosDeclination;
+	
+	/// The completion fraction of the active work unit
+	double m_WUFractionDone;
+	
+	/// Amount of CPU time consumed for the work unit during the active session
+	double m_WUCPUTime;	
+};
+
+#endif /*EINSTEINS5R3ADAPTER_H_*/
-- 
GitLab