aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortradke <tradke@83718e91-0e4f-0410-abf4-91180603181f>2007-08-29 12:34:48 +0000
committertradke <tradke@83718e91-0e4f-0410-abf4-91180603181f>2007-08-29 12:34:48 +0000
commitfd620c91b16ec633407d347b40315546464a45d4 (patch)
tree29182b72fe9301397439b2a32850d6281969e34d
parentf087ca19300df86166e298c305d42143ad67704d (diff)
- register callbacks for the Publish API
these callbacks collect published information and send it to an external RDF information service - use the Publish API to periodically announce simulation metadata runtime information git-svn-id: http://svn.cactuscode.org/arrangements/CactusUtils/Formaline/trunk@132 83718e91-0e4f-0410-abf4-91180603181f
-rw-r--r--interface.ccl104
-rw-r--r--param.ccl5
-rw-r--r--schedule.ccl14
-rw-r--r--src/make.code.defn2
-rw-r--r--src/rdf.cc271
-rw-r--r--src/rdf.hh47
-rw-r--r--src/rdf_publisher.cc309
7 files changed, 640 insertions, 112 deletions
diff --git a/interface.ccl b/interface.ccl
index fa8779b..71e356e 100644
--- a/interface.ccl
+++ b/interface.ccl
@@ -6,7 +6,7 @@ IMPLEMENTS: Formaline
# for HTTP_Port()
USES INCLUDE HEADER: http_Content.h
-USES INCLUDE HEADER: Announce.h
+USES INCLUDE HEADER: Publish.h
@@ -31,6 +31,108 @@ PROVIDES FUNCTION UniqueSimulationID \
LANGUAGE C
+#############
+# Publish API
+#############
+CCTK_INT FUNCTION PublishBoolean (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_INT IN level, \
+ CCTK_INT IN value, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishInt (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_INT IN level, \
+ CCTK_INT IN value, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishReal (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_INT IN level, \
+ CCTK_REAL IN value, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishString (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_INT IN level, \
+ CCTK_STRING IN value, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishTable (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_INT IN level, \
+ CCTK_INT IN table, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN name)
+USES FUNCTION PublishBoolean
+USES FUNCTION PublishInt
+USES FUNCTION PublishReal
+USES FUNCTION PublishString
+USES FUNCTION PublishTable
+
+##########################
+# Publish registration API
+##########################
+CCTK_INT FUNCTION PublishBoolean_Register( \
+ CCTK_INT CCTK_FPOINTER IN publish_cb (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_POINTER IN cb_data, \
+ CCTK_INT IN level, \
+ CCTK_INT IN value, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN thorn), \
+ CCTK_POINTER IN cb_data, \
+ CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishInt_Register( \
+ CCTK_INT CCTK_FPOINTER IN publish_cb (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_POINTER IN cb_data, \
+ CCTK_INT IN level, \
+ CCTK_INT IN value, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN thorn), \
+ CCTK_POINTER IN cb_data, \
+ CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishReal_Register( \
+ CCTK_INT CCTK_FPOINTER IN publish_cb (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_POINTER IN cb_data, \
+ CCTK_INT IN level, \
+ CCTK_REAL IN value, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN thorn), \
+ CCTK_POINTER IN cb_data, \
+ CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishString_Register( \
+ CCTK_INT CCTK_FPOINTER IN publish_cb (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_POINTER IN cb_data, \
+ CCTK_INT IN level, \
+ CCTK_STRING IN value, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN thorn), \
+ CCTK_POINTER IN cb_data, \
+ CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishTable_Register( \
+ CCTK_INT CCTK_FPOINTER IN publish_cb (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_POINTER IN cb_data, \
+ CCTK_INT IN level, \
+ CCTK_INT IN table, \
+ CCTK_STRING IN key, \
+ CCTK_STRING IN thorn), \
+ CCTK_POINTER IN cb_data, \
+ CCTK_STRING IN name)
+
+USES FUNCTION PublishBoolean_Register
+USES FUNCTION PublishInt_Register
+USES FUNCTION PublishReal_Register
+USES FUNCTION PublishString_Register
+USES FUNCTION PublishTable_Register
+
+CCTK_INT FUNCTION PublishBoolean_Unregister (CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishInt_Unregister (CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishReal_Unregister (CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishString_Unregister (CCTK_STRING IN name)
+CCTK_INT FUNCTION PublishTable_Unregister (CCTK_STRING IN name)
+
+USES FUNCTION PublishBoolean_Unregister
+USES FUNCTION PublishInt_Unregister
+USES FUNCTION PublishReal_Unregister
+USES FUNCTION PublishString_Unregister
+USES FUNCTION PublishTable_Unregister
+
+
# Return a pointer to an unmodifiable C string
# which contains a unique ID for this run
diff --git a/param.ccl b/param.ccl
index 1598231..e505332 100644
--- a/param.ccl
+++ b/param.ccl
@@ -14,6 +14,11 @@ REAL update_interval "Update interval for the meta information (in seconds)" STE
0:* :: ""
} 600.0
+INT publish_level "Importance level for meta data to be published via the Publish API" STEERABLE=always
+{
+ 0:10 :: "the lower the level the more important the meta data to be published"
+} 1
+
INT timeout "Timeout for sending meta information to a server (in seconds)" STEERABLE=always
{
1:* :: "a positive value"
diff --git a/schedule.ccl b/schedule.ccl
index a9f84fb..5b897eb 100644
--- a/schedule.ccl
+++ b/schedule.ccl
@@ -19,8 +19,12 @@ if (collect_metadata)
OPTIONS: meta
} "Print the build and simulation ids"
-
-
+ SCHEDULE Formaline_RegisterPublishRDF_Callbacks IN RegisterPublishCallbacks
+ {
+ LANG: C
+ OPTIONS: meta
+ } "Register RDF callbacks for the Publish API"
+
SCHEDULE Formaline_RegisterWarnings AT wragh
{
LANG: C
@@ -45,4 +49,10 @@ if (collect_metadata)
OPTIONS: global
} "Put some meta information about the current run into permanent storage"
+ SCHEDULE Formaline_UnregisterPublishRDF_Callbacks IN UnregisterPublishCallbacks
+ {
+ LANG: C
+ OPTIONS: meta
+ } "Unregister RDF callbacks for the Publish API"
+
}
diff --git a/src/make.code.defn b/src/make.code.defn
index a195bbc..f00f745 100644
--- a/src/make.code.defn
+++ b/src/make.code.defn
@@ -2,7 +2,7 @@
# $Header$
# Source files in this directory
-SRCS = announce.cc file.cc id.cc multistorage.cc output_source.c portal.cc rdf.cc senddata.cc storage.cc thornlist.cc
+SRCS = announce.cc file.cc id.cc multistorage.cc output_source.c portal.cc rdf.cc rdf_publisher.cc senddata.cc storage.cc thornlist.cc
# Subdirectories containing source files
SUBDIRS =
diff --git a/src/rdf.cc b/src/rdf.cc
index 286ba59..c7dd7c2 100644
--- a/src/rdf.cc
+++ b/src/rdf.cc
@@ -21,8 +21,10 @@
#include "cctk.h"
#include "cctk_Parameters.h"
#include "cctk_Version.h"
-#include "util_String.h"
#include "util_Network.h"
+#include "util_String.h"
+
+#include "Publish.h"
#include "rdf.hh"
#include "senddata.hh"
@@ -31,17 +33,19 @@
namespace Formaline
{
-
using namespace std;
-
+ // the jobID is shared between this source file and PublishAsRDF.cc
+ string jobID;
+
+
// NUM_RDF_ENTRIES must match the size of the
// Formaline::rdf_hostname and Formaline::rdf_port parameter arrays
int const NUM_RDF_ENTRIES = 5;
// Number of space chars for indentation
- int const NUM_INDENT_SPACES = 2;
+ // int const NUM_INDENT_SPACES = 2;
@@ -57,52 +61,6 @@ namespace Formaline
cGH const * const cctkGH)
: storage (st)
{
- //
- // RDF/XML document header with some namespace definitions
- //
- msgbuf
- << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl
- << "<!DOCTYPE owl [" << endl
- << "\t<!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>" << endl
- << "\t<!ENTITY xsd 'http://www.w3.org/2001/XMLSchema#'>" << endl
- << "\t<!ENTITY cctk 'http://www.gac-grid.org/project-products/Software/InformationService/InformationProducer/CactusRDFProducer/2006/08/cctk-schema#'>" << endl
-#if 0
- << "\t<!ENTITY cctk 'http://www.aei.mpg.de/~tradke/cctk-schema#'>" << endl
- << "\t<!ENTITY cctk 'http://www.cct.lsu.edu/~dstark/cctk/0.1/'>" << endl
- << "<!--" << endl
- << "\t<!ENTITY dc 'http://purl.org/dc/elements/1.1/'>" << endl
- << "\t<!ENTITY doap 'http://usefulinc.com/ns/doap#'>" << endl
- << "\t<!ENTITY foaf 'http://xmlns.com/foaf/0.1/'>" << endl
- << "\t<!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>" << endl
- << "\t<!ENTITY form 'http://www.aei.mpg.de/form#'>" << endl
- << "-->" << endl
-#endif
- << "]>" << endl
- << "<rdf:RDF xmlns:rdf=\"&rdf;\"" << endl
- << "\txmlns:xsd=\"&xsd;\"" << endl
- << "\txmlns:cctk=\"&cctk;\"" << endl
- << ">" << endl
-#if 0
- << "<!--" << endl
- << "\txmlns:dc=\"&dc;\"" << endl
- << "\txmlns:doap=\"&doap;\"" << endl
- << "\txmlns:foaf=\"&foaf;\"" << endl
- << "\txmlns:rdfs=\"&rdfs;\"" << endl
- << "\txmlns:form=\"&form;\"" << endl
- << "-->" << endl
- << "" << endl
- << "<!-- lessons learned so far" << endl
- << " " << endl
- << " * although it would be better to use rdf:ID as relative URIs for objects" << endl
- << " (because they are enforced to be unique), rdf:about must be used instead" << endl
- << " because the value of a relative rdf:about URI may contain special" << endl
- << " characters (such as '/') whereas rdf:ID must not" << endl
- << "-->" << endl
-#endif
- << endl
- << endl;
-
-
// set the unique ID for this simulation
jobID = clean (string (id));
@@ -113,13 +71,8 @@ namespace Formaline
case initial: Initial (); break;
case update:
case final: Update (cctkGH); break;
- default: assert (0 && "invalid state");
+ default: assert (0); // invalid state
}
-
- //
- // close the RDF/XML document
- //
- msgbuf << endl << "</rdf:RDF>" << endl;
}
void rdf::Initial (void)
@@ -173,10 +126,27 @@ namespace Formaline
if (pbsJobname) {
msgbuf << "\tcctk:pbsJobname=\"" << clean (pbsJobname) << "\"" << endl;
}
+ const char* pbsHost = getenv ("PBS_O_HOST");
+ if (pbsHost) {
+ // fix incomplete and/or strange PBS headnode hostnames
+ if (strncmp(pbsHost, "peyote", 6) == 0) {
+ pbsHost = "peyote.aei.mpg.de";
+ } else if (strcmp(pbsHost, "master.ic") == 0) {
+ pbsHost = "belladonna.aei.mpg.de";
+ } else if (strcmp(pbsHost, "damiana.damiana.admin") == 0) {
+ pbsHost = "damiana.aei.mpg.de";
+ }
+ msgbuf << "\tcctk:pbsHost=\"" << clean (pbsHost) << "\"" << endl;
+ }
msgbuf << "\tcctk:cwd=\"" << cwd << "\">" << endl
- << "\t<cctk:nProcs rdf:datatype=\"&xsd;integer\">" << nprocs << "</cctk:nProcs>" << endl
- << "\t<cctk:compiledAt rdf:datatype=\"&xsd;datetime\">" << compiled_at << "</cctk:compiledAt>" << endl
- << "\t<cctk:startedAt rdf:datatype=\"&xsd;datetime\">" << started_at << "</cctk:startedAt>" << endl;
+ << "\t<cctk:nProcs rdf:datatype=\"&xsd;integer\">"
+ << nprocs << "</cctk:nProcs>" << endl
+ << "\t<cctk:compiledAt rdf:datatype=\"&xsd;datetime\">"
+ << compiled_at << "</cctk:compiledAt>" << endl
+ << "\t<cctk:startedAt rdf:datatype=\"&xsd;datetime\">"
+ << started_at << "</cctk:startedAt>" << endl
+ << "\t<cctk:lastModified rdf:datatype=\"&xsd;datetime\">"
+ << started_at << "</cctk:lastModified>" << endl;
//
// metadata as references to other nodes
@@ -235,7 +205,8 @@ namespace Formaline
// skip parameters that belong to inactive thorns
const bool is_active = CCTK_IsThornActive (thornname);
- msgbuf << "\t<cctk:active rdf:datatype=\"&xsd;boolean\">" << (is_active ? "true" : "false") << "</cctk:active>" << endl;
+ msgbuf << "\t<cctk:active rdf:datatype=\"&xsd;boolean\">"
+ << (is_active ? "true" : "false") << "</cctk:active>" << endl;
// loop over all parameters of this thorn (if it is active)
if (is_active) {
@@ -244,7 +215,8 @@ namespace Formaline
const cParamData* pdata = NULL;
// get the first/next parameter
- const int ierr = CCTK_ParameterWalk (first, thornname,&fullname,&pdata);
+ const int ierr = CCTK_ParameterWalk (first, thornname,
+ &fullname, &pdata);
assert (ierr >= 0);
if (ierr > 0) break;
@@ -309,7 +281,7 @@ namespace Formaline
}
break;
- default: assert (0 and "invalid parameter type");
+ default: assert (0); // invalid parameter type
} // switch (pdata->type)
@@ -318,7 +290,8 @@ namespace Formaline
<< pdata->thorn << "/" << cleanURI (pdata->name) << "\""
<< endl
<< "\tcctk:name=\"" << fullname <<"\">" << endl
- << "\t<cctk:value rdf:datatype=\"&xsd;" << paramdatatype <<"\">" << paramvaluebuf.str() << "</cctk:value>" << endl
+ << "\t<cctk:value rdf:datatype=\"&xsd;" << paramdatatype
+ << "\">" << paramvaluebuf.str() << "</cctk:value>" << endl
<< "</cctk:" << paramtype << ">" << endl;
} // if (pdata->n_set or list_all_parameters)
@@ -347,27 +320,78 @@ namespace Formaline
}
}
- char* currentdatebuf = Util_CurrentDateTime ();
- const string currentdate (clean (currentdatebuf));
- free (currentdatebuf);
+ if (CCTK_IsFunctionAliased ("PublishBoolean")) {
+#ifndef PUBLISH_LEVEL_NOTICE
+#define PUBLISH_LEVEL_NOTICE 2
+#endif
+ const int retval = PublishBoolean (cctkGH, PUBLISH_LEVEL_NOTICE,
+ get_state() == final ? 1 : 0,
+ "Finished", "Runtime Info");
+ if (retval < 0) {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Failed to publish runtime information (error code %d)",
+ retval);
+ }
+ }
+
+ // check if there was anything published
+ if (rdfPublishList.empty()) return;
- // update counter which is incremented for each Update() call
- static int update_counter = 0;
- update_counter++;
+ char* rundatebuf = Util_CurrentDateTime ();
+ const string started_at (clean (rundatebuf));
- msgbuf
-<< "<cctk:Simulation rdf:about=\"#" << jobID << "\">" << endl
-<< "\t<cctk:updateInfo rdf:resource=\"#UpdateInfo/" << update_counter << "\"/>" << endl
-<< "</cctk:Simulation>" << endl << endl
-<< "<cctk:UpdateInfo rdf:about=\"#UpdateInfo/" << update_counter << "\">" << endl
-<< "\t<cctk:iteration rdf:datatype=\"&xsd;integer\">" << cctkGH->cctk_iteration << "</cctk:iteration>" << endl
-<< "\t<cctk:time rdf:datatype=\"&xsd;double\">" << cctkGH->cctk_time << "</cctk:time>" << endl
-<< "\t<cctk:datetime rdf:datatype=\"&xsd;datetime\">" << currentdate << "</cctk:datetime>" << endl;
-
- if (get_state() == final) {
- msgbuf << "\t<cctk:terminated rdf:datatype=\"&xsd;boolean\">yes</cctk:terminated>" << endl;
+ static int publishedItems = 0;
+ msgbuf << "<cctk:Simulation rdf:about=\"#" << jobID << "\">" << endl
+ << "\t<cctk:lastModified rdf:datatype=\"&xsd;datetime\">"
+ << started_at << "</cctk:lastModified>" << endl;
+ for (size_t i = 0; i < rdfPublishList.size(); i++) {
+ msgbuf << "\t<cctk:publish rdf:resource=\"#Publish/"
+ << (publishedItems + i) << "\"/>" << endl;
+ }
+ msgbuf << "</cctk:Simulation>" << endl << endl;
+ for (size_t i = 0; i < rdfPublishList.size(); i++, publishedItems++) {
+ const rdfPublishItem& item = rdfPublishList[i];
+ msgbuf << "<cctk:Publish rdf:about=\"#Publish/"
+ << publishedItems << "\">" << endl
+ << "\t<cctk:datetime rdf:datatype=\"&xsd;datetime\">"
+ << item.datetime << "</cctk:datetime>" << endl
+ << "\t<cctk:key>" << item.key << "</cctk:key>" << endl;
+ if (not item.name.empty()) {
+ msgbuf << "\t<cctk:name>" << item.name << "</cctk:name>" << endl;
+ }
+ if (item.hasCCTKinfo) {
+ msgbuf << "\t<cctk:time>" << item.cctk_time << "</cctk:time>" << endl;
+ msgbuf << "\t<cctk:iteration>" << item.cctk_iteration
+ << "</cctk:iteration>" << endl;
+ }
+ ostringstream tablebuf;
+ if (item.isTable) {
+ for (size_t j = 0; j < item.table.size(); j++) {
+ const rdfTableEntry& entry = item.table[j];
+ msgbuf << "\t<cctk:tableEntry rdf:resource=\"#Publish/"
+ << publishedItems << "/" << j << "\"/>" << endl;
+ tablebuf << "<cctk:TableEntry rdf:about=\"#Publish/"
+ << publishedItems << "/" << j << "\">" << endl
+ << "\t<cctk:key>" << entry.key << "</cctk:key>" << endl
+ << "\t<cctk:value";
+ if (not entry.value.type.empty()) {
+ tablebuf << " rdf:datatype=\"&xsd;" << entry.value.type << "\"";
+ }
+ tablebuf << ">" << entry.value.value << "</cctk:value>" << endl
+ << "</cctk:TableEntry>" << endl;
+ }
+ } else {
+ msgbuf << "\t<cctk:value";
+ if (not item.scalar.type.empty()) {
+ msgbuf << " rdf:datatype=\"&xsd;" << item.scalar.type << "\"";
+ }
+ msgbuf << ">" << item.scalar.value << "</cctk:value>" << endl;
+ }
+ msgbuf << "</cctk:Publish>" << endl;
+ msgbuf << tablebuf.str();
}
- msgbuf << "</cctk:UpdateInfo>" << endl;
+
+ rdfPublishList.clear();
}
@@ -375,9 +399,57 @@ namespace Formaline
~ rdf ()
{
DECLARE_CCTK_PARAMETERS;
-
- // Create the data string
- string const msgstr = msgbuf.str();
+
+ // check if anything needs to be done
+ if (msgbuf.str().empty()) return;
+
+ // RDF/XML document header with some namespace definitions
+ const string header =
+"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+"<!DOCTYPE owl [\n"
+"\t<!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n"
+"\t<!ENTITY xsd 'http://www.w3.org/2001/XMLSchema#'>\n"
+"\t<!ENTITY cctk 'http://www.gac-grid.org/project-products/Software/InformationService/InformationProducer/CactusRDFProducer/2006/08/cctk-schema#'>\n"
+
+#if 0
+ << "\t<!ENTITY cctk 'http://www.aei.mpg.de/~tradke/cctk-schema#'>" << endl
+ << "\t<!ENTITY cctk 'http://www.cct.lsu.edu/~dstark/cctk/0.1/'>" << endl
+ << "<!--" << endl
+ << "\t<!ENTITY dc 'http://purl.org/dc/elements/1.1/'>" << endl
+ << "\t<!ENTITY doap 'http://usefulinc.com/ns/doap#'>" << endl
+ << "\t<!ENTITY foaf 'http://xmlns.com/foaf/0.1/'>" << endl
+ << "\t<!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>" << endl
+ << "\t<!ENTITY form 'http://www.aei.mpg.de/form#'>" << endl
+ << "-->" << endl
+#endif
+"]>\n"
+"<rdf:RDF xmlns:rdf=\"&rdf;\"\n"
+"\txmlns:xsd=\"&xsd;\"\n"
+"\txmlns:cctk=\"&cctk;\"\n"
+">\n"
+#if 0
+ << "<!--" << endl
+ << "\txmlns:dc=\"&dc;\"" << endl
+ << "\txmlns:doap=\"&doap;\"" << endl
+ << "\txmlns:foaf=\"&foaf;\"" << endl
+ << "\txmlns:rdfs=\"&rdfs;\"" << endl
+ << "\txmlns:form=\"&form;\"" << endl
+ << "-->" << endl
+ << "" << endl
+ << "<!-- lessons learned so far" << endl
+ << " " << endl
+ << " * although it would be better to use rdf:ID as relative URIs for objects" << endl
+ << " (because they are enforced to be unique), rdf:about must be used instead" << endl
+ << " because the value of a relative rdf:about URI may contain special" << endl
+ << " characters (such as '/') whereas rdf:ID must not" << endl
+ << "-->" << endl
+#endif
+"\n\n";
+
+ // RDF/XML document footer
+ const string footer = "\n</rdf:RDF>\n";
+
+ const int len = header.length() + msgbuf.str().length() + footer.length();
// Loop over all destinations
for (int i = 0; i < NUM_RDF_ENTRIES; i++) {
@@ -389,19 +461,17 @@ namespace Formaline
ostringstream databuf;
databuf
<< (get_state() == initial ? "PUT" : "POST")
-<< " /context/CactusSimulations/" << jobID << " HTTP/1.0\r\n"
+<< " /context/CactusSimulations/" << jobID;
+// if (get_state() != initial) databuf << "?action=update";
+ databuf << " HTTP/1.0\r\n"
<< "Host: " << rdf_hostname[i] << "\r\n"
<< "Content-Type: application/rdf+xml\r\n"
-<< "Content-Length: " << msgstr.length() << "\r\n"
-<< "\r\n"
-<< msgstr
-<< "\r\n"
-<< "\r\n";
- string const datastr = databuf.str();
+<< "Content-Length: " << len << "\r\n\r\n"
+<< header << msgbuf.str() << footer << "\r\n\r\n";
// Send the data
- SendData (rdf_hostname[i], rdf_port[i], datastr);
-
+ SendData (rdf_hostname[i], rdf_port[i], databuf.str());
+
}
} // loop over all destinations
}
@@ -412,6 +482,8 @@ namespace Formaline
store (char const * const key,
bool const value)
{
+ const void* dummy = &dummy;
+ dummy = &key; dummy = &value;
#if 0
ostringstream valuebuf;
valuebuf << (value ? "true" : "false");
@@ -447,6 +519,8 @@ namespace Formaline
store (char const * const key,
CCTK_INT const value)
{
+ const void* dummy = &dummy;
+ dummy = &key; dummy = &value;
#if 0
ostringstream valuebuf;
valuebuf << value;
@@ -482,6 +556,8 @@ namespace Formaline
store (char const * const key,
CCTK_REAL const value)
{
+ const void* dummy = &dummy;
+ dummy = &key; dummy = &value;
#if 0
int const prec = numeric_limits<CCTK_REAL>::digits10;
ostringstream valuebuf;
@@ -518,6 +594,8 @@ namespace Formaline
store (char const * const key,
char const * const value)
{
+ const void* dummy = &dummy;
+ dummy = &key; dummy = &value;
#if 0
// don't store keys with empty string values
if (not *value) return;
@@ -552,10 +630,8 @@ namespace Formaline
}
-
- string rdf::
+ string
clean (string const & txt)
- const
{
ostringstream buf;
@@ -573,9 +649,8 @@ namespace Formaline
}
- string rdf::
+ string
cleanURI (string const & uri)
- const
{
const string allowed_charset ("-_.!~*'()/");
ostringstream buf;
diff --git a/src/rdf.hh b/src/rdf.hh
index cef3f5e..2ea3cd0 100644
--- a/src/rdf.hh
+++ b/src/rdf.hh
@@ -7,6 +7,7 @@
#include <sstream>
#include <string>
+#include <vector>
#include "storage.hh"
@@ -15,6 +16,41 @@
namespace Formaline
{
+ typedef struct {
+ std::string type;
+ std::string value;
+ } rdfScalarValue;
+
+ typedef struct {
+ std::string key;
+ rdfScalarValue value;
+ } rdfTableEntry;
+
+ typedef struct {
+ std::string datetime;
+ bool hasCCTKinfo;
+ CCTK_REAL cctk_time;
+ int cctk_iteration;
+ std::string name;
+ std::string key;
+// classes (with constructors) are not allowed as members of a union
+// union value {
+ rdfScalarValue scalar;
+ std::vector<rdfTableEntry> table;
+// }
+ bool isTable;
+ } rdfPublishItem;
+
+ // buffer to keep RDF metadata until the next Update() call
+ extern std::vector<rdfPublishItem> rdfPublishList;
+
+ // the jobID string
+ extern std::string jobID;
+
+ std::string clean (std::string const & txt);
+
+ std::string cleanURI (std::string const & uri);
+
class rdf : public storage
@@ -49,18 +85,9 @@ namespace Formaline
private:
- std::string jobID;
-
- std::string
- clean (std::string const & txt)
- const;
-
- std::string
- cleanURI (std::string const & uri)
- const;
-
void Initial (void);
void Update (cGH const * cctkGH);
+
};
diff --git a/src/rdf_publisher.cc b/src/rdf_publisher.cc
new file mode 100644
index 0000000..fd17707
--- /dev/null
+++ b/src/rdf_publisher.cc
@@ -0,0 +1,309 @@
+// $Header$
+
+#include <cassert>
+#include <string>
+#include <iostream>
+
+#include "util_Table.h"
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Parameters.h"
+
+#include "Publish.h"
+
+#include "rdf.hh"
+
+
+using std::endl;
+
+namespace Formaline
+{
+
+// buffer of published RDF metadata since the last Update() call
+std::vector<rdfPublishItem> rdfPublishList;
+
+
+static rdfPublishItem* CreateNewItem (CCTK_POINTER_TO_CONST cctkGH,
+ CCTK_POINTER data,
+ CCTK_INT level,
+ CCTK_STRING name,
+ CCTK_STRING key,
+ bool isTable)
+{
+ DECLARE_CCTK_PARAMETERS;
+
+ // prevent compiler warnings about unused parameters
+ data = &data;
+
+ assert (key and *key);
+ assert (level >= 0);
+ rdfPublishItem* item = NULL;
+ if (level <= publish_level) {
+ rdfPublishItem newItem;
+ rdfPublishList.push_back (newItem);
+ item = &rdfPublishList.back();
+ char* currentdate = Util_CurrentDateTime ();
+ item->datetime = clean (currentdate);
+ free (currentdate);
+ item->hasCCTKinfo = cctkGH != NULL;
+ if (item->hasCCTKinfo) {
+ const cGH* _cctkGH = (const cGH*) cctkGH;
+ item->cctk_time = _cctkGH->cctk_time;
+ item->cctk_iteration = _cctkGH->cctk_iteration;
+ }
+ if (name and *name) item->name = clean (name);
+ item->key = clean (key);
+ item->isTable = isTable;
+ }
+ return item;
+}
+
+static CCTK_INT PublishBooleanAsRDF (CCTK_POINTER_TO_CONST cctkGH,
+ CCTK_POINTER data,
+ CCTK_INT level,
+ CCTK_INT value,
+ CCTK_STRING key,
+ CCTK_STRING name)
+{
+ rdfPublishItem* item = CreateNewItem (cctkGH, data, level, name, key, false);
+ if (item) {
+ item->scalar.value = value ? "true" : "false";
+ item->scalar.type = "boolean";
+ }
+
+ return (item ? 1 : 0);
+}
+
+
+static CCTK_INT PublishIntAsRDF (CCTK_POINTER_TO_CONST cctkGH,
+ CCTK_POINTER data,
+ CCTK_INT level,
+ CCTK_INT value,
+ CCTK_STRING key,
+ CCTK_STRING name)
+{
+ rdfPublishItem* item = CreateNewItem (cctkGH, data, level, name, key, false);
+ if (item) {
+ std::ostringstream buf;
+ buf << value;
+ item->scalar.value = buf.str();
+ item->scalar.type = "int";
+ }
+
+ return (item ? 1 : 0);
+}
+
+
+static CCTK_INT PublishRealAsRDF (CCTK_POINTER_TO_CONST cctkGH,
+ CCTK_POINTER data,
+ CCTK_INT level,
+ CCTK_REAL value,
+ CCTK_STRING key,
+ CCTK_STRING name)
+{
+ rdfPublishItem* item = CreateNewItem (cctkGH, data, level, name, key, false);
+ if (item) {
+ std::ostringstream buf;
+ buf << value;
+ item->scalar.value = buf.str();
+ item->scalar.type = "double";
+ }
+
+ return (item ? 1 : 0);
+}
+
+
+static CCTK_INT PublishStringAsRDF (CCTK_POINTER_TO_CONST cctkGH,
+ CCTK_POINTER data,
+ CCTK_INT level,
+ CCTK_STRING value,
+ CCTK_STRING key,
+ CCTK_STRING name)
+{
+ rdfPublishItem* item = CreateNewItem (cctkGH, data, level, name, key, false);
+ if (item) {
+ item->scalar.value = clean (value);
+ item->scalar.type = "string";
+ }
+
+ return (item ? 1 : 0);
+}
+
+
+static CCTK_INT PublishTableAsRDF (CCTK_POINTER_TO_CONST cctkGH,
+ CCTK_POINTER data,
+ CCTK_INT level,
+ CCTK_INT table,
+ CCTK_STRING key,
+ CCTK_STRING name)
+{
+ rdfPublishItem* item = CreateNewItem (cctkGH, data, level, name, key, true);
+ if (not item) return 0;
+
+ const int maxkeylen = Util_TableQueryMaxKeyLength (table);
+ if (maxkeylen <= 0) return (-1);
+ char* userkey = new char[maxkeylen + 1];
+
+ int iterator;
+ for (iterator = Util_TableItCreate (table);
+ Util_TableItQueryIsNonNull (iterator) > 0;
+ Util_TableItAdvance (iterator)) {
+ CCTK_INT typecode, n_elements = -1;
+
+ Util_TableItQueryKeyValueInfo (iterator, maxkeylen + 1, userkey,
+ &typecode, &n_elements);
+ if (n_elements <= 0) {
+ CCTK_VWarn (3, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "No value provided for user key '%s' in table to be "
+ "published with key '%s'", userkey, key);
+ continue;
+ }
+ if (n_elements > 1 and
+ (typecode == CCTK_VARIABLE_INT or typecode == CCTK_VARIABLE_REAL)) {
+ CCTK_VWarn (3, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Array value not supported for user key '%s' in table to "
+ "be published with key '%s'", userkey, key);
+ continue;
+ } else if (typecode != CCTK_VARIABLE_CHAR and
+ typecode != CCTK_VARIABLE_INT and
+ typecode != CCTK_VARIABLE_REAL) {
+ CCTK_VWarn (3, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Unsupported datatype '%s' for value with user key '%s' "
+ "in table to be published with key '%s'",
+ CCTK_VarTypeName (typecode), userkey, key);
+ continue;
+ }
+
+ rdfTableEntry newEntry;
+ item->table.push_back (newEntry);
+ rdfTableEntry* entry = &item->table.back();
+ entry->key = clean (userkey);
+ std::ostringstream buf;
+ if (typecode == CCTK_VARIABLE_CHAR) {
+ char *buffer = new char[n_elements + 1];
+ Util_TableGetString (table, n_elements + 1, buffer, userkey);
+ entry->value.value = buffer;
+ delete[] buffer;
+ } else if (typecode == CCTK_VARIABLE_INT) {
+ CCTK_INT int_value;
+ Util_TableGetInt (table, &int_value, userkey);
+ buf << int_value;
+ entry->value.value = buf.str();
+ entry->value.type = "int";
+ } else if (typecode == CCTK_VARIABLE_REAL) {
+ CCTK_REAL real_value;
+ Util_TableGetReal (table, &real_value, userkey);
+ buf << real_value;
+ entry->value.value = buf.str();
+ entry->value.type = "double";
+ } else {
+ assert (0);
+ }
+ }
+ Util_TableItDestroy (iterator);
+ delete[] userkey;
+
+ return 1;
+}
+
+
+static void ParameterSetNotify (void *unused,
+ const char *thorn,
+ const char *parameter,
+ const char *new_value)
+{
+ unused = &unused;
+
+ const char *name = "Set Parameter";
+ std::string key(thorn); key.append ("::"); key.append (parameter);
+
+ int type;
+ const void* data = CCTK_ParameterGet (parameter, thorn, &type);
+
+ if (type == PARAMETER_KEYWORD || type == PARAMETER_STRING ||
+ type == PARAMETER_SENTENCE)
+ {
+ if (CCTK_IsFunctionAliased ("PublishString"))
+ {
+ PublishString (NULL, 0, *(const char *const *) data, key.c_str(), name);
+ }
+ }
+ else if (type == PARAMETER_BOOLEAN)
+ {
+ if (CCTK_IsFunctionAliased ("PublishBoolean"))
+ {
+ PublishBoolean (NULL, 0, *(const CCTK_INT *) data, key.c_str(), name);
+ }
+ }
+ else if (type == PARAMETER_INT)
+ {
+ if (CCTK_IsFunctionAliased ("PublishInt"))
+ {
+ PublishInt (NULL, 0, *(const CCTK_INT *) data, key.c_str(), name);
+ }
+ }
+ else if (type == PARAMETER_REAL)
+ {
+ if (CCTK_IsFunctionAliased ("PublishReal"))
+ {
+ PublishReal (NULL, 0, *(const CCTK_REAL *) data, key.c_str(), name);
+ }
+ } else {
+ assert (0 and "invalid parameter type");
+ }
+}
+
+
+extern "C"
+void Formaline_RegisterPublishRDF_Callbacks (void)
+{
+ int registered = 0;
+
+#define REGISTER_RDF_CALLBACKS(type) \
+ if (CCTK_IsFunctionAliased ("Publish" #type "_Register")) { \
+ if (Publish##type##_Register (Publish##type##AsRDF, NULL, \
+ "Publish as RDF")) { \
+ CCTK_WARN (0, "Failed to register Publish" #type " callback"); \
+ } \
+ registered++; \
+ }
+ // we don't have a valid cctkGH yet
+ if (CCTK_MyProc (NULL) == 0) {
+ REGISTER_RDF_CALLBACKS (Boolean);
+ REGISTER_RDF_CALLBACKS (Int);
+ REGISTER_RDF_CALLBACKS (Real);
+ REGISTER_RDF_CALLBACKS (String);
+ REGISTER_RDF_CALLBACKS (Table);
+ if (registered) {
+ if (CCTK_ParameterSetNotifyRegister (ParameterSetNotify, NULL,
+ CCTK_THORNSTRING, NULL, NULL)) {
+ CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Couldn't register parameter set notify callback");
+ }
+ } else {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Couldn't register Publish RDF callbacks because no thorn "
+ "provides Publish register API aliases functions");
+ }
+ }
+}
+
+extern "C"
+void Formaline_UnregisterPublishRDF_Callbacks (CCTK_ARGUMENTS)
+{
+#define UNREGISTER_RDF_CALLBACKS(type) \
+ if (CCTK_IsFunctionAliased ("Publish" #type "_Unregister")) { \
+ Publish##type##_Unregister ("Publish as RDF"); \
+ }
+ if (CCTK_MyProc (cctkGH) == 0) {
+ CCTK_ParameterSetNotifyUnregister (CCTK_THORNSTRING);
+ UNREGISTER_RDF_CALLBACKS (Boolean);
+ UNREGISTER_RDF_CALLBACKS (Int);
+ UNREGISTER_RDF_CALLBACKS (Real);
+ UNREGISTER_RDF_CALLBACKS (String);
+ UNREGISTER_RDF_CALLBACKS (Table);
+ }
+}
+
+
+} // namespace Formaline