00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_VISX_EXPTDRIVER_CC_UTC20050626084017_DEFINED
00035 #define GROOVX_VISX_EXPTDRIVER_CC_UTC20050626084017_DEFINED
00036
00037 #include "visx/exptdriver.h"
00038
00039 #include "io/ioproxy.h"
00040 #include "io/ioutil.h"
00041 #include "io/readutils.h"
00042 #include "io/writeutils.h"
00043
00044 #include "nub/log.h"
00045 #include "nub/ref.h"
00046
00047 #include "tcl/eventloop.h"
00048 #include "tcl/interp.h"
00049
00050 #include "tcl-gfx/toglet.h"
00051 #include "tcl-io/tclprocwrapper.h"
00052
00053 #include "rutz/error.h"
00054 #include "rutz/fstring.h"
00055 #include "rutz/iter.h"
00056 #include "rutz/sfmt.h"
00057 #include "rutz/timeformat.h"
00058 #include "rutz/unixcall.h"
00059
00060 #include "visx/tlistutils.h"
00061
00062 #include <cstdlib>
00063 #include <cstring>
00064 #include <string>
00065 #include <sys/stat.h>
00066 #include <unistd.h>
00067
00068 #define GVX_DYNAMIC_TRACE_EXPR ExptDriver::tracer.status()
00069 #include "rutz/trace.h"
00070 #include "rutz/debug.h"
00071 GVX_DBG_REGISTER
00072
00073 using rutz::fstring;
00074
00075 rutz::tracer ExptDriver::tracer;
00076
00078
00079
00080
00082
00083 namespace
00084 {
00085 const io::version_id EXPTDRIVER_SVID = 6;
00086 }
00087
00089
00090
00091
00093
00094 class ExptDriver::Impl
00095 {
00096 private:
00097 Impl(const Impl&);
00098 Impl& operator=(const Impl&);
00099
00100 public:
00101 Impl() :
00102 interp(tcl::event_loop::interp()),
00103 widget(),
00104 hostname(""),
00105 subject(""),
00106 beginDate(""),
00107 endDate(""),
00108 autosaveFile("__autosave_file"),
00109 filePrefix("expt"),
00110 infoLog(),
00111 autosavePeriod(10),
00112 doWhenComplete(new tcl::ProcWrapper(interp)),
00113 numTrialsCompleted(0),
00114 createTime(rutz::time::wall_clock_now()),
00115 fileTimestamp(rutz::format_time(createTime, "%Y%b%d_%H%M%S"))
00116 {}
00117
00118 ~Impl() {}
00119
00120 void addLogInfo(const char* message)
00121 {
00122 const fstring date_string =
00123 rutz::format_time(rutz::time::wall_clock_now());
00124
00125 infoLog += rutz::sfmt("@%s %s\n",
00126 date_string.c_str(), message).c_str();
00127 }
00128
00129
00130
00131
00132
00133 tcl::interpreter interp;
00134
00135 nub::soft_ref<Toglet> widget;
00136
00137 fstring hostname;
00138 fstring subject;
00139 fstring beginDate;
00140 fstring endDate;
00141 fstring autosaveFile;
00142 fstring filePrefix;
00143
00144 std::string infoLog;
00145
00146 int autosavePeriod;
00147
00148 nub::ref<tcl::ProcWrapper> doWhenComplete;
00149
00150 unsigned int numTrialsCompleted;
00151
00152 rutz::time createTime;
00153 fstring fileTimestamp;
00154 };
00155
00157
00158
00159
00161
00162 ExptDriver::ExptDriver() :
00163 rep(new Impl)
00164 {
00165 GVX_TRACE("ExptDriver::ExptDriver");
00166
00167 rep->addLogInfo(tcl::event_loop::command_line().c_str());
00168 }
00169
00170 ExptDriver::~ExptDriver() throw()
00171 {
00172 GVX_TRACE("ExptDriver::~ExptDriver");
00173 delete rep;
00174 }
00175
00176 io::version_id ExptDriver::class_version_id() const
00177 {
00178 GVX_TRACE("ExptDriver::class_version_id");
00179 return EXPTDRIVER_SVID;
00180 }
00181
00182 void ExptDriver::read_from(io::reader& reader)
00183 {
00184 GVX_TRACE("ExptDriver::read_from");
00185
00186 reader.ensure_version_id("ExptDriver", 6,
00187 "Try cvs tag xml_conversion_20040526",
00188 SRC_POS);
00189
00190 reader.read_value("hostname", rep->hostname);
00191 reader.read_value("subject", rep->subject);
00192 reader.read_value("beginDate", rep->beginDate);
00193 reader.read_value("endDate", rep->endDate);
00194 reader.read_value("autosaveFile", rep->autosaveFile);
00195 reader.read_value("autosavePeriod", rep->autosavePeriod);
00196 {
00197 rutz::fstring tmp;
00198 reader.read_value("infoLog", tmp);
00199 rep->infoLog = tmp.c_str();
00200 }
00201 reader.read_owned_object("doWhenComplete", rep->doWhenComplete);
00202 reader.read_value("filePrefix", rep->filePrefix);
00203
00204 reader.read_base_class("ElementContainer",
00205 io::make_proxy<ElementContainer>(this));
00206 }
00207
00208 void ExptDriver::write_to(io::writer& writer) const
00209 {
00210 GVX_TRACE("ExptDriver::write_to");
00211
00212 writer.ensure_output_version_id("ExptDriver", EXPTDRIVER_SVID, 6,
00213 "Try groovx0.8a7", SRC_POS);
00214
00215 writer.write_value("hostname", rep->hostname);
00216 writer.write_value("subject", rep->subject);
00217 writer.write_value("beginDate", rep->beginDate);
00218 writer.write_value("endDate", rep->endDate);
00219 writer.write_value("autosaveFile", rep->autosaveFile);
00220 writer.write_value("autosavePeriod", rep->autosavePeriod);
00221 writer.write_value("infoLog", rutz::fstring(rep->infoLog.c_str()));
00222 writer.write_owned_object("doWhenComplete", rep->doWhenComplete);
00223 writer.write_value("filePrefix", rep->filePrefix);
00224
00225 writer.write_base_class("ElementContainer",
00226 io::make_const_proxy<ElementContainer>(this));
00227 }
00228
00229
00231
00232
00233
00235
00236 const nub::soft_ref<Toglet>& ExptDriver::getWidget() const
00237 {
00238 GVX_TRACE("ExptDriver::getWidget");
00239 return rep->widget;
00240 }
00241
00242 void ExptDriver::vxRun(Element& )
00243 {
00244 GVX_TRACE("currentElement");
00245 GVX_ASSERT(false);
00246 }
00247
00248 void ExptDriver::vxEndTrialHook()
00249 {
00250 GVX_TRACE("ExptDriver::vxEndTrialHook");
00251
00252 ++(rep->numTrialsCompleted);
00253
00254
00255
00256
00257 if ( rep->autosavePeriod <= 0 ||
00258 (rep->numTrialsCompleted % rep->autosavePeriod) != 0 ||
00259 rep->autosaveFile.is_empty() )
00260 return;
00261
00262 dbg_eval_nl(3, rep->autosaveFile.c_str());
00263 io::save_gvx(nub::ref<io::serializable>(this), rep->autosaveFile);
00264 }
00265
00266 void ExptDriver::vxAllChildrenFinished()
00267 {
00268 GVX_TRACE("ExptDriver::vxAllChildrenFinished");
00269
00270 nub::log( "ExptDriver::vxAllChildrenFinished" );
00271
00272 rep->addLogInfo("Experiment complete.");
00273
00274 vxHalt();
00275
00276 storeData();
00277
00278 nub::logging::add_obj_scope(*rep->doWhenComplete);
00279 rep->doWhenComplete->invoke("");
00280 nub::logging::remove_obj_scope(*rep->doWhenComplete);
00281
00282 nub::logging::remove_obj_scope(*this);
00283 }
00284
00286
00287
00288
00290
00291 const fstring& ExptDriver::getAutosaveFile() const
00292 {
00293 GVX_TRACE("ExptDriver::getAutosaveFile");
00294 return rep->autosaveFile;
00295 }
00296
00297 void ExptDriver::setAutosaveFile(const fstring& str)
00298 {
00299 GVX_TRACE("ExptDriver::setAutosaveFile");
00300 rep->autosaveFile = str;
00301 }
00302
00303 const fstring& ExptDriver::getFilePrefix() const
00304 {
00305 GVX_TRACE("ExptDriver::getFilePrefix");
00306 return rep->filePrefix;
00307 }
00308
00309 void ExptDriver::setFilePrefix(const fstring& str)
00310 {
00311 GVX_TRACE("ExptDriver::setFilePrefix");
00312 rep->filePrefix = str;
00313 }
00314
00315 void ExptDriver::claimLogFile() const
00316 {
00317 GVX_TRACE("ExptDriver::claimLogFile");
00318 nub::logging::set_log_filename
00319 (rutz::sfmt("%s_%s.log",
00320 rep->filePrefix.c_str(),
00321 rep->fileTimestamp.c_str()));
00322 }
00323
00324 int ExptDriver::getAutosavePeriod() const
00325 {
00326 GVX_TRACE("ExptDriver::getAutosavePeriod");
00327 return rep->autosavePeriod;
00328 }
00329
00330 void ExptDriver::setAutosavePeriod(int period)
00331 {
00332 GVX_TRACE("ExptDriver::setAutosavePeriod");
00333 rep->autosavePeriod = period;
00334 }
00335
00336 const char* ExptDriver::getInfoLog() const
00337 {
00338 GVX_TRACE("ExptDriver::getInfoLog");
00339 return rep->infoLog.c_str();
00340 }
00341
00342 fstring ExptDriver::getDoWhenComplete() const
00343 {
00344 GVX_TRACE("ExptDriver::getDoWhenComplete");
00345 return rep->doWhenComplete->fullSpec();
00346 }
00347
00348 void ExptDriver::setDoWhenComplete(const fstring& script)
00349 {
00350 GVX_TRACE("ExptDriver::setDoWhenComplete");
00351 rep->doWhenComplete->define("", script);
00352 }
00353
00354 void ExptDriver::setWidget(const nub::soft_ref<Toglet>& widg)
00355 {
00356 GVX_TRACE("ExptDriver::setWidget");
00357 rep->widget = widg;
00358 }
00359
00360 void ExptDriver::edBeginExpt()
00361 {
00362 GVX_TRACE("ExptDriver::edBeginExpt");
00363
00364 if (isComplete())
00365 {
00366 throw rutz::error("Can't begin experiment: "
00367 "there are no pending elements", SRC_POS);
00368 }
00369
00370 rep->addLogInfo("Beginning experiment.");
00371
00372 const fstring cwd = rutz::unixcall::getcwd();
00373
00374 rep->beginDate = rutz::format_time(rutz::time::wall_clock_now());
00375 rep->hostname = getenv("HOSTNAME");
00376 rep->subject = cwd;
00377 rep->numTrialsCompleted = 0;
00378
00379 nub::logging::reset();
00380 nub::logging::add_obj_scope(*this);
00381
00382 claimLogFile();
00383
00384 nub::log(rutz::sfmt("expt begin: %s", rep->beginDate.c_str()));
00385 nub::log(rutz::sfmt("hostname: %s", rep->hostname.c_str()));
00386 nub::log(rutz::sfmt("cwd: %s", cwd.c_str()));
00387 nub::log(rutz::sfmt("cmdline: %s",
00388 tcl::event_loop::command_line().c_str()));
00389
00390 currentElement()->vxRun(*this);
00391 }
00392
00393 void ExptDriver::edResumeExpt()
00394 {
00395 GVX_TRACE("ExptDriver::edResumeExpt");
00396
00397 if (isComplete())
00398 {
00399 throw rutz::error("Can't resume experiment: "
00400 "there are no pending elements", SRC_POS);
00401 }
00402
00403 currentElement()->vxRun(*this);
00404 }
00405
00406 #if 0
00407
00408
00409
00410
00411 void ExptDriver::pause()
00412 {
00413 GVX_TRACE("ExptDriver::pause");
00414
00415
00416
00417
00418 fstring pauseMsgCmd
00419 ("tk_messageBox -default ok -icon info "
00420 "-title \"Pause\" -type ok "
00421 "-message \"Experiment paused. Click OK to continue.\";\n");
00422
00423 vxHalt();
00424
00425 rep->addLogInfo("Experiment paused.");
00426
00427 rep->interp.eval(pauseMsgCmd);
00428
00429 tcl::interpreter::clear_event_queue();
00430
00431 rep->widget->fullClearscreen();
00432 rep->widget->fullClearscreen();
00433
00434 ::sleep(2);
00435
00436 rep->widget->fullClearscreen();
00437 rep->widget->fullClearscreen();
00438
00439 tcl::interpreter::clear_event_queue();
00440
00441 rep->addLogInfo("Resuming experiment.");
00442
00443 edResumeExpt();
00444 }
00445 #endif
00446
00447 namespace
00448 {
00449
00450
00451
00452 void renameFileIfExists(const fstring& fname)
00453 {
00454 struct stat buf;
00455
00456 if (stat(fname.c_str(), &buf) != 0)
00457 {
00458
00459 return;
00460 }
00461
00462 fstring newname = fname;
00463
00464 int i = 0;
00465
00466 while (stat(newname.c_str(), &buf) == 0)
00467 {
00468 newname = rutz::sfmt("%s.bkp%d", fname.c_str(), i++);
00469 }
00470
00471 rutz::unixcall::rename(fname.c_str(), newname.c_str());
00472 }
00473 }
00474
00475 void ExptDriver::storeData()
00476 {
00477 GVX_TRACE("ExptDriver::storeData");
00478
00479
00480
00481
00482 const rutz::time timestamp = rutz::time::wall_clock_now();
00483
00484 rep->endDate = rutz::format_time(timestamp);
00485
00486
00487 const fstring expt_filename =
00488 rutz::sfmt("%s_%s.gvx", rep->filePrefix.c_str(),
00489 rep->fileTimestamp.c_str());
00490 renameFileIfExists(expt_filename);
00491 io::save_gvx(nub::ref<io::serializable>(this), expt_filename.c_str());
00492 nub::log( rutz::sfmt("wrote file %s", expt_filename.c_str()) );
00493
00494
00495 const fstring resp_filename =
00496 rutz::sfmt("%s_%s.resp", rep->filePrefix.c_str(),
00497 rep->fileTimestamp.c_str());
00498 renameFileIfExists(resp_filename);
00499 TlistUtils::writeResponses(resp_filename.c_str());
00500 nub::log( rutz::sfmt("wrote file %s", resp_filename.c_str()) );
00501
00502
00503 const mode_t datafile_mode = S_IRUSR | S_IRGRP | S_IROTH;
00504
00505 rutz::unixcall::chmod(expt_filename.c_str(), datafile_mode);
00506 rutz::unixcall::chmod(resp_filename.c_str(), datafile_mode);
00507
00508 rep->addLogInfo("Experiment saved.");
00509 }
00510
00511 static const char __attribute__((used)) vcid_groovx_visx_exptdriver_cc_utc20050626084017[] = "$Id: exptdriver.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00512 #endif // !GROOVX_VISX_EXPTDRIVER_CC_UTC20050626084017_DEFINED