diff --git a/checkin_notes b/checkin_notes
index f4b0d1279d..0bdc10812d 100644
--- a/checkin_notes
+++ b/checkin_notes
@@ -8476,3 +8476,15 @@ Rom 29 Nov 2010
vboxwrapper.cpp
win_build/
vboxwrapper.vcproj
+
+David 29 Nov 2010
+ - add support for making wrappers for Rappture:
+ https://nanohub.org/infrastructure/rappture/
+
+ samples/
+ wrappture/
+ wrappture.cpp,h
+ wrappture_example.cpp
+ Makefile
+ wrapper/
+ wrapper.cpp
diff --git a/samples/wrapper/wrapper.cpp b/samples/wrapper/wrapper.cpp
index fdd2db9acb..bd4468559b 100644
--- a/samples/wrapper/wrapper.cpp
+++ b/samples/wrapper/wrapper.cpp
@@ -565,6 +565,9 @@ int main(int argc, char** argv) {
for (i=0; i.
+
+#include
+#include
+#include
+#ifdef _WIN32
+#include "boinc_win.h"
+#include "win_util.h"
+#else
+#include
+#include
+#include
+#include
+#include "procinfo.h"
+#endif
+
+#include "boinc_api.h"
+#include "diagnostics.h"
+#include "filesys.h"
+#include "parse.h"
+#include "str_util.h"
+#include "str_replace.h"
+#include "util.h"
+#include "error_numbers.h"
+
+#include "wrappture.h"
+
+#define POLL_PERIOD 1.0
+
+using std::vector;
+using std::string;
+
+struct TASK {
+ string application;
+ string stdin_filename;
+ string stdout_filename;
+ string stderr_filename;
+ string checkpoint_filename;
+ // name of task's checkpoint file, if any
+ string fraction_done_filename;
+ // name of file where app will write its fraction done
+ string command_line;
+ double weight;
+ // contribution of this task to overall fraction done
+ double final_cpu_time;
+ double starting_cpu;
+ // how much CPU time was used by tasks before this in the job file
+ bool suspended;
+ double wall_cpu_time;
+ // for estimating CPU time on Win98/ME and Mac
+#ifdef _WIN32
+ HANDLE pid_handle;
+ DWORD pid;
+ HANDLE thread_handle;
+ struct _stat last_stat; // mod time of checkpoint file
+#else
+ int pid;
+ struct stat last_stat;
+#endif
+ bool stat_first;
+ bool poll(int& status);
+ int run(int argc, char** argv);
+ void kill();
+ void stop();
+ void resume();
+ double cpu_time();
+ inline bool has_checkpointed() {
+ bool changed = false;
+ if (checkpoint_filename.size() == 0) return false;
+ struct stat new_stat;
+ int retval = stat(checkpoint_filename.c_str(), &new_stat);
+ if (retval) return false;
+ if (!stat_first && new_stat.st_mtime != last_stat.st_mtime) {
+ changed = true;
+ }
+ stat_first = false;
+ last_stat.st_mtime = new_stat.st_mtime;
+ return changed;
+ }
+ inline double fraction_done() {
+ if (fraction_done_filename.size() == 0) return 0;
+ FILE* f = fopen(fraction_done_filename.c_str(), "r");
+ if (!f) return 0;
+ double frac;
+ int n = fscanf(f, "%lf", &frac);
+ fclose(f);
+ if (n != 1) return 0;
+ if (frac < 0) return 0;
+ if (frac > 1) return 1;
+ return frac;
+ }
+};
+
+APP_INIT_DATA aid;
+double fraction_done, checkpoint_cpu_time;
+
+#ifdef _WIN32
+// CreateProcess() takes HANDLEs for the stdin/stdout.
+// We need to use CreateFile() to get them. Ugh.
+//
+HANDLE win_fopen(const char* path, const char* mode) {
+ SECURITY_ATTRIBUTES sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+
+ if (!strcmp(mode, "r")) {
+ return CreateFile(
+ path,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ &sa,
+ OPEN_EXISTING,
+ 0, 0
+ );
+ } else if (!strcmp(mode, "w")) {
+ return CreateFile(
+ path,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ &sa,
+ OPEN_ALWAYS,
+ 0, 0
+ );
+ } else if (!strcmp(mode, "a")) {
+ HANDLE hAppend = CreateFile(
+ path,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ &sa,
+ OPEN_ALWAYS,
+ 0, 0
+ );
+ SetFilePointer(hAppend, 0, NULL, FILE_END);
+ return hAppend;
+ } else {
+ return 0;
+ }
+}
+#endif
+
+void slash_to_backslash(char* p) {
+ while (1) {
+ char* q = strchr(p, '/');
+ if (!q) break;
+ *q = '\\';
+ }
+}
+
+int TASK::run(int argct, char** argvt) {
+ string stdout_path, stdin_path, stderr_path;
+ char app_path[1024], buf[256];
+
+ if (checkpoint_filename.size()) {
+ boinc_delete_file(checkpoint_filename.c_str());
+ }
+ if (fraction_done_filename.size()) {
+ boinc_delete_file(fraction_done_filename.c_str());
+ }
+
+ strcpy(buf, application.c_str());
+ char* p = strstr(buf, "$PROJECT_DIR");
+ if (p) {
+ p += strlen("$PROJECT_DIR");
+ sprintf(app_path, "%s%s", aid.project_dir, p);
+ } else {
+ boinc_resolve_filename(buf, app_path, sizeof(app_path));
+ }
+
+ // Append wrapper's command-line arguments to those in the job file.
+ //
+ for (int i=1; i"
+
+// the following runs in a thread and parses the app's stdout file,
+// looking for progress tags
+//
+void* parse_app_stdout(void*) {
+ char buf[8192];
+ FILE* f = boinc_fopen("rappture_stdout.txt", "r");
+
+ while (1) {
+ if (fgets(buf, sizeof(buf), f)) {
+ if (strstr(buf, PROGRESS_MARKER)) {
+ fraction_done = atof(buf+strlen(PROGRESS_MARKER))/100;
+ }
+ } else {
+ boinc_sleep(1.);
+ }
+ }
+}
+
+int create_parser_thread() {
+#ifdef _WIN32
+ DWORD parser_thread_id;
+ if (!CreateThread(NULL, 0, parse_app_stdout, 0, 0, &parser_thread_id)) {
+ return ERR_THREAD;
+ }
+#else
+ pthread_t parser_thread_handle;
+ pthread_attr_t thread_attrs;
+ pthread_attr_init(&thread_attrs);
+ pthread_attr_setstacksize(&thread_attrs, 16384);
+ int retval = pthread_create(
+ &parser_thread_handle, &thread_attrs, parse_app_stdout, NULL
+ );
+ if (retval) {
+ return ERR_THREAD;
+ }
+#endif
+ return 0;
+}
+
+int boinc_run_rappture_app(const char* program, const char* cmdline) {
+ TASK task;
+ int retval;
+ BOINC_OPTIONS options;
+
+ memset(&options, 0, sizeof(options));
+ options.main_program = true;
+ options.check_heartbeat = true;
+ options.handle_process_control = true;
+ boinc_init_options(&options);
+
+ memset(&task, 0, sizeof(task));
+ task.application = program;
+ task.command_line = cmdline;
+ task.stdout_filename = "rappture_stdout.txt";
+
+ retval = task.run(0, 0);
+ create_parser_thread();
+ while (1) {
+ int status;
+ if (task.poll(status)) {
+ if (status) {
+ boinc_finish(EXIT_CHILD_FAILED);
+ }
+ break;
+ }
+ poll_boinc_messages(task);
+ send_status_message(task, fraction_done, checkpoint_cpu_time);
+ boinc_sleep(POLL_PERIOD);
+ }
+ return 0;
+}
diff --git a/samples/wrappture/wrappture.h b/samples/wrappture/wrappture.h
new file mode 100644
index 0000000000..cf02f394ae
--- /dev/null
+++ b/samples/wrappture/wrappture.h
@@ -0,0 +1,18 @@
+// This file is part of BOINC.
+// http://boinc.berkeley.edu
+// Copyright (C) 2010 University of California
+//
+// BOINC is free software; you can redistribute it and/or modify it
+// under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// BOINC 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with BOINC. If not, see .
+
+extern int boinc_run_rappture_app(const char* program, const char* cmdline);
diff --git a/samples/wrappture/wrappture_example.cpp b/samples/wrappture/wrappture_example.cpp
new file mode 100644
index 0000000000..ecc922d94b
--- /dev/null
+++ b/samples/wrappture/wrappture_example.cpp
@@ -0,0 +1,107 @@
+// ----------------------------------------------------------------------
+// EXAMPLE: Fermi-Dirac function in C.
+//
+// This simple example shows how to use Rappture within a simulator
+// written in C.
+// ======================================================================
+// AUTHOR: Derrick Kearney, Purdue University
+// Copyright (c) 2004-2008 Purdue Research Foundation
+//
+// See the file "license.terms" for information on usage and
+// redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+// ======================================================================
+
+//#include "rappture.h"
+
+#include
+#include
+#include
+#include
+
+#include "error_numbers.h"
+#include "boinc_api.h"
+#include "wrappture.h"
+
+#define RPLIB_OVERWRITE 0
+struct RpLibrary{};
+RpLibrary* rpLibrary(char*){return NULL;}
+void rpGetString(RpLibrary*, const char*, const char**){}
+double rpConvertDbl(const char*, const char*, int*){return 0;}
+void rpPutString (RpLibrary*, const char*, const char*, int){}
+void rpResult(RpLibrary*);
+
+int main(int argc, char * argv[]) {
+
+ RpLibrary* lib = NULL;
+
+ const char* data = NULL;
+ char line[100];
+
+ double T = 0.0;
+ double Ef = 0.0;
+ double E = 0.0;
+ double dE = 0.0;
+ double kT = 0.0;
+ double Emin = 0.0;
+ double Emax = 0.0;
+ double f = 0.0;
+
+ int err = 0;
+
+ // create a rappture library from the file filePath
+ lib = rpLibrary(argv[1]);
+
+ if (lib == NULL) {
+ // cannot open file or out of memory
+ printf("FAILED creating Rappture Library\n");
+ return(1);
+ }
+
+
+ rpGetString(lib,"input.number(temperature).current",&data);
+ T = rpConvertDbl(data, "K", &err);
+ if (err) {
+ printf ("Error while retrieving input.number(temperature).current\n");
+ return(1);
+ }
+
+
+ rpGetString(lib,"input.number(Ef).current",&data);
+ Ef = rpConvertDbl(data, "eV", &err);
+ if (err) {
+ printf ("Error while retrieving input.number(Ef).current\n");
+ return(1);
+ }
+
+ kT = 8.61734e-5 * T;
+ Emin = Ef - 10*kT;
+ Emax = Ef + 10*kT;
+
+ E = Emin;
+ dE = 0.005*(Emax-Emin);
+
+ rpPutString ( lib,
+ "output.curve(f12).about.label",
+ "Fermi-Dirac Factor",
+ RPLIB_OVERWRITE );
+ rpPutString ( lib,
+ "output.curve(f12).xaxis.label",
+ "Fermi-Dirac Factor",
+ RPLIB_OVERWRITE );
+ rpPutString ( lib,
+ "output.curve(f12).yaxis.label",
+ "Energy",
+ RPLIB_OVERWRITE );
+ rpPutString ( lib,
+ "output.curve(f12).yaxis.units",
+ "eV",
+ RPLIB_OVERWRITE );
+
+ int retval = boinc_run_rappture_app("foobar.exe", "-kT 4.3");
+ if (retval == 0) {
+ boinc_finish(0);
+ rpResult(lib);
+ } else {
+ boinc_finish(EXIT_CHILD_FAILED);
+ }
+}