public function get_maxima_available() { if ('unix' != stack_connection_helper::get_platform()) { return stack_string('healthunabletolistavail'); } $this->command = 'maxima --list-avail'; $rawresult = $this->call_maxima(''); return $rawresult; }
public function test_compute_miss_formed_command() { $connection = stack_connection_helper::make(); // This will induce a timeout on the CAS because we don't have a well formed CAS statement. $strin = 'cab:block([],print("[TimeStamp= [ 0 ];'; $return = $connection->compute($strin); $expected = array(); $this->assertEquals($return, $expected); }
protected function guess_maxima_command($path) { if ('default' == stack_connection_helper::get_maximaversion()) { throw new stack_exception("stack_cas_connection: maxima cannot be set to default on Windows platform. " . "Please choose an explicit version via the administration settings page."); } $cmd = $path . '/maxima.bat'; if (!is_readable($cmd)) { throw new stack_exception("stack_cas_connection: maxima launch script {$cmd} does not exist."); } return $cmd; }
public function compute($command) { $context = "Platform: " . stack_connection_helper::get_platform() . "\n"; $context .= "Maxima shell command: " . $this->command . "\n"; $context .= "Maxima initial command: " . $this->initcommand . "\n"; $context .= "Maxima timeout: " . $this->timeout; $this->debug->log('Context used', $context); $this->debug->log('Maxima command', $command); $rawresult = $this->call_maxima($command); $this->debug->log('CAS result', $rawresult); $unpackedresult = $this->unpack_raw_result($rawresult); $this->debug->log('Unpacked result as', print_r($unpackedresult, true)); if (!stack_connection_helper::check_stackmaxima_version($unpackedresult)) { stack_connection_helper::warn_about_version_mismatch($this->debug); } return $unpackedresult; }
protected function guess_maxima_command($path) { global $CFG; if (stack_connection_helper::get_platform() == 'unix-optimised') { // We are trying to use a Lisp snapshot of Maxima with all the // STACK libraries loaded. $lispimage = $CFG->dataroot . '/stack/maxima-optimised'; if (is_readable($lispimage)) { return $lispimage; } } if (is_readable('/Applications/Maxima.app/Contents/Resources/maxima.sh')) { // This is the path on Macs, if Maxima has been installed following // the instructions on Sourceforge. return '/Applications/Maxima.app/Contents/Resources/maxima.sh'; } // Default guess on Linux. return 'maxima'; }
public function compute($command) { $cached = $this->get_cached_result($command); if ($cached->result) { $this->debug->log('Maxima command', $command); $this->debug->log('Unpacked result found in the DB cache', print_r($cached->result, true)); if (!stack_connection_helper::check_stackmaxima_version($cached->result)) { stack_connection_helper::warn_about_version_mismatch($this->debug); // We could consider automatically purging the cache here. } return $cached->result; } $this->debug->log('Maxima command not found in the cache. Using the raw connection.'); $result = $this->rawconnection->compute($command); // Only add to the cache if we didn't timeout! if (!stack_connection_helper::did_cas_timeout($result)) { $this->add_to_cache($command, $result, $cached->key); } return $result; }
// If we have a linux machine, and we are testing the raw connection then we should // attempt to automatically create an optimized maxima image on the system. if ($config->platform === 'unix' and $genuinecascall) { echo $OUTPUT->heading(stack_string('healthautomaxopt'), 3); echo html_writer::tag('p', stack_string('healthautomaxoptintro')); list($message, $debug, $result) = stack_connection_helper::stackmaxima_auto_maxima_optimise($genuinedebug); $summary[] = array($result, $message); echo html_writer::tag('p', $message); echo output_debug(stack_string('debuginfo'), $debug); } // Test the version of the STACK libraries that Maxima is using. // When Maxima is being run pre-compiled (maxima-optimise) or on a server, // it is possible for the version of the Maxima libraries to get out of synch // with the qtype_stack code. echo $OUTPUT->heading(stack_string('healthchecksstackmaximaversion'), 3); list($message, $details, $result) = stack_connection_helper::stackmaxima_version_healthcheck(); $summary[] = array($result, stack_string($message, $details)); echo html_writer::tag('p', stack_string($message, $details)); // Test plots. output_cas_text(stack_string('healthcheckplots'), stack_string('healthcheckplotsintro'), get_string('healthchecksampleplots', 'qtype_stack')); // State of the cache. echo $OUTPUT->heading(stack_string('settingcasresultscache'), 3); $message = stack_string('healthcheckcache_' . $config->casresultscache); $summary[] = array(null, $message); echo html_writer::tag('p', $message); if ('db' == $config->casresultscache) { echo html_writer::tag('p', stack_string('healthcheckcachestatus', stack_cas_connection_db_cache::entries_count($DB))); echo $OUTPUT->single_button(new moodle_url($PAGE->url, array('clearcache' => 1, 'sesskey' => sesskey())), stack_string('clearthecache')); } echo '<hr />'; $tab = '';
public function instantiate() { if (null === $this->valid) { $this->validate(); } if (!$this->valid) { return false; } // Lazy instantiation - only do this once... // Empty session. Nothing to do. if ($this->instantiated || null === $this->session) { return true; } $connection = stack_connection_helper::make(); $results = $connection->compute($this->construct_maxima_command()); $this->debuginfo = $connection->get_debuginfo(); // Now put the information back into the correct slots. $session = $this->session; $newsession = array(); $newerrors = ''; $allfail = true; $i = 0; // We loop over each entry in the session, not over the result. // This way we can add an error for missing values. foreach ($session as $cs) { $gotvalue = false; if ('' == $cs->get_key()) { $key = 'dumvar' . $i; } else { $key = $cs->get_key(); } if (array_key_exists($i, $results)) { $allfail = false; // We at least got one result back from the CAS! $result = $results["{$i}"]; // GOCHA! Results have string represenations of numbers, not int.... if ('' != $result['error'] and false === strstr($result['error'], 'clipped')) { $cs->add_errors($result['error']); $cs->decode_maxima_errors($result['error']); $newerrors .= stack_maxima_format_casstring($cs->get_raw_casstring()); $newerrors .= ' ' . stack_string("stackCas_CASErrorCaused") . ' ' . $result['error'] . ' '; } if (array_key_exists('value', $result)) { $val = str_replace('QMCHAR', '?', $result['value']); $cs->set_value($val); $gotvalue = true; } else { $cs->add_errors(stack_string("stackCas_failedReturnOne")); } if (array_key_exists('display', $result)) { // Need to add this in here also because strings may contain question mark characters. $disp = str_replace('QMCHAR', '?', $result['display']); $cs->set_display($disp); } if (array_key_exists('valid', $result)) { $cs->set_valid($result['valid']); } if (array_key_exists('answernote', $result)) { $cs->set_answernote($result['answernote']); } if (array_key_exists('feedback', $result)) { $cs->set_feedback($result['feedback']); } } else { if (!$gotvalue) { $errstr = stack_string("stackCas_failedReturn") . ' ' . stack_maxima_format_casstring($cs->get_raw_casstring()); $cs->add_errors($errstr); $cs->set_answernote('CASFailedReturn'); $newerrors .= $errstr; } } $newsession[] = $cs; $i++; } $this->session = $newsession; if ('' != $newerrors) { $this->errors .= '<span class="error">' . stack_string('stackCas_CASError') . '</span>' . $newerrors; } if ($allfail) { $this->errors = '<span class="error">' . stack_string('stackCas_allFailed') . '</span>'; } $this->instantiated = true; }
/** * Initialises the database connection for the 'otherdb' cache type. * @return moodle_database the DB connection to use. */ protected static function get_other_db() { if (!is_null(self::$otherdb)) { return self::$otherdb; } $dboptions = array(); if (!empty(self::$config->cascachedbsocket)) { $dboptions['dbsocket'] = true; } self::$otherdb = moodle_database::get_driver_instance(self::$config->cascachedbtype, self::$config->cascachedblibrary); self::$otherdb->connect(self::$config->cascachedbhost, self::$config->cascachedbuser, self::$config->cascachedbpass, self::$config->cascachedbname, self::$config->cascachedbprefix, $dboptions); return self::$otherdb; }
protected function call_maxima($command) { global $CFG; $err = ''; $starttime = microtime(true); $request = curl_init($this->command); $postdata = 'input=' . urlencode($command) . '&timeout=' . $this->timeout * 1000 . '&ploturlbase=!ploturl!' . '&version=' . stack_connection_helper::get_required_stackmaxima_version(); curl_setopt($request, CURLOPT_POST, true); curl_setopt($request, CURLOPT_POSTFIELDS, $postdata); curl_setopt($request, CURLOPT_RETURNTRANSFER, true); curl_setopt($request, CURLOPT_HTTPAUTH, CURLAUTH_ANY); if (!empty($this->serveruserpass)) { curl_setopt($request, CURLOPT_USERPWD, $this->serveruserpass); } $ret = curl_exec($request); $timedout = false; // The servlet will return 416 if the evaluation hits the timelimit. if (curl_getinfo($request, CURLINFO_HTTP_CODE) != '200') { if (curl_getinfo($request, CURLINFO_HTTP_CODE) != '416') { throw new Exception('stack_cas_connection: MaximaPool error: ' . curl_getinfo($request, CURLINFO_HTTP_CODE)); } else { $timedout = true; } } // Did we get files? if (strpos(curl_getinfo($request, CURLINFO_CONTENT_TYPE), "text/plain") === false) { // We have to save the zip file on local disk before opening... // how come there is no core library solution to this!? // create temp file, save zip there. $ziptemp = $CFG->dataroot . "/stack/tmp/"; $ziptemp = tempnam($ziptemp, "zip"); $fp = fopen($ziptemp, "w"); fwrite($fp, $ret); fclose($fp); $zip = zip_open($ziptemp); $entry = zip_read($zip); // Read the entrys of the archive. while ($entry !== false) { // This one contains the output from maxima. if (zip_entry_name($entry) == 'OUTPUT') { zip_entry_open($zip, $entry); $ret = zip_entry_read($entry, zip_entry_filesize($entry)); zip_entry_close($entry); } else { $filename = $CFG->dataroot . "/stack/plots/" . zip_entry_name($entry); zip_entry_open($zip, $entry); $fp = fopen($filename, 'w'); $buffy = zip_entry_read($entry, 2048); while ($buffy != '') { fwrite($fp, $buffy); $buffy = zip_entry_read($entry, 2048); } fclose($fp); zip_entry_close($entry); } $entry = zip_read($zip); } zip_close($zip); // Clean up. unlink($ziptemp); } curl_close($request); $now = microtime(true); $this->debug->log('Timings', "Start: {$starttime}, End: {$now}, Taken = " . ($now - $starttime)); // Add sufficient closing ]'s to allow something to be un-parsed from the CAS. // WARNING: the string 'The CAS timed out' is used by the cache to serach for a timout occurance. if ($timedout) { $ret .= ' The CAS timed out. ] ] ] ]'; } return $ret; }