[LON-CAPA-cvs] cvs: loncom /interface lonprintout.pm

foxr lon-capa-cvs-allow@mail.lon-capa.org
Tue, 26 Feb 2008 10:46:15 -0000


This is a MIME encoded message

--foxr1204022775
Content-Type: text/plain

foxr		Tue Feb 26 05:46:15 2008 EDT

  Modified files:              
    /loncom/interface	lonprintout.pm 
  Log:
  BZ5631:
  1. Factored out calls to &Apache::lonnet::ssi into 
     local ssi_with_retries
  2. ssi_with_retries detects http errors and retries
     as many times as directed by the caller.
  3. ssi_with_retries will report errors that
     cannot be recovered within retries via a set of
     $ssi_ module global variables
  4. When output_data is rendering it's final page,
     if $ssi_error is set (indicating that at least 
     one rendering failed due to ssi retry exhaustion,
     An error message is delivered to the user rather than
     just blindly printing papers that may have missing resources.
  
  
  
--foxr1204022775
Content-Type: text/plain
Content-Disposition: attachment; filename="foxr-20080226054615.txt"

Index: loncom/interface/lonprintout.pm
diff -u loncom/interface/lonprintout.pm:1.514 loncom/interface/lonprintout.pm:1.515
--- loncom/interface/lonprintout.pm:1.514	Tue Jan 29 06:21:18 2008
+++ loncom/interface/lonprintout.pm	Tue Feb 26 05:46:14 2008
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Printout
 #
-# $Id: lonprintout.pm,v 1.514 2008/01/29 11:21:18 foxr Exp $
+# $Id: lonprintout.pm,v 1.515 2008/02/26 10:46:14 foxr Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -38,6 +38,7 @@
 use Apache::File();
 use Apache::lonnavmaps;
 use Apache::admannotations;
+use HTTP::Response;
 
 use LONCAPA::map();
 use POSIX qw(strftime);
@@ -49,6 +50,21 @@
 my %parmhash;
 my $resources_printed;
 
+# Global variables that describe errors in ssi calls detected  by ssi_with_retries.
+#
+
+my $ssi_error;			# True if there was an ssi error.
+my $ssi_last_error_resource;	# The resource URI that could not be fetched.
+my $ssi_last_error;		# The error text from the server. (e.g. 500 Server timed out).
+
+#
+#  Our ssi max retry count.
+#
+
+my $ssi_retry_count = 5;	# Some arbitrary value.
+
+
+
 # Fetch the contents of a resource, uninterpreted.
 # This is used here to fetch a latex file to be included
 # verbatim into the printout<
@@ -92,6 +108,68 @@
     return $result;
 }
 
+
+#
+#   ssi_with_retries - Does the server side include of a resource.
+#                      if the ssi call returns an error we'll retry it up to
+#                      the number of times requested by the caller.
+#                      If we still have a proble, no text is appended to the
+#                      output and we set some global variables.
+#                      to indicate to the caller an SSI error occured.  
+#                      All of this is supposed to deal with the issues described
+#                      in LonCAPA BZ 5631 see:
+#                      http://bugs.lon-capa.org/show_bug.cgi?id=5631
+#                      by informing the user that this happened.
+#
+# Parameters:
+#   resource   - The resource to include.  This is passed directly, without
+#                interpretation to lonnet::ssi.
+#   form       - The form hash parameters that guide the interpretation of the resource
+#                
+#   retries    - Number of retries allowed before giving up completely.
+# Returns:
+#   On success, returns the rendered resource identified by the resource parameter.
+# Side Effects:
+#   The following global variables can be set:
+#    ssi_error                - If an unrecoverable error occured this becomes true.
+#                               It is up to the caller to initialize this to false
+#                               if desired.
+#    ssi_last_error_resource  - If an unrecoverable error occured, this is the value
+#                               of the resource that could not be rendered by the ssi
+#                               call.
+#    ssi_last_error           - The error string fetched from the ssi response
+#                               in the event of an error.
+#
+sub ssi_with_retries {
+    my ($resource, $retries, %form) = @_;
+
+
+    my $ok = 0;			# True if we got a good response.
+    my $content;
+    my $response;
+
+    # Try to get the ssi done. within the retries count:
+
+    do {
+	($content, $response) = &Apache::lonnet::ssi($resource, %form);
+	$ok      = $response->is_success;
+	$retries--;
+    } while (!$ok && ($retries > 0));
+
+    # Two cases: ok is true we have valid data, if not, retries have been exhausted
+    # if ok is true, $response->content is what we want to return.. otherwise
+    # set the error information:
+
+    if ($ok) {
+	return $content;
+    } else {
+	$ssi_error               = 1;
+	$ssi_last_error_resource = $resource;
+	$ssi_last_error          = $response->code." ". $response->message;
+	return '';		# Nothing we can add to the printout that makes sense.
+    }
+}
+
 #
 #   printf_style_subst  item format_string repl
 #  
@@ -742,6 +820,7 @@
     $result =~ s/&(hearts|\#9829);/\\ensuremath\{\\heartsuit\}/g;
     $result =~ s/&(diams|\#9830);/\\ensuremath\{\\diamondsuit\}/g;
 #   Chemically useful 'things' contributed by Hon Kie (bug 4652).
+
     $result =~ s/&\#8636;/\\ensuremath\{\\leftharpoonup\}/g;
     $result =~ s/&\#8637;/\\ensuremath\{\\leftharpoondown\}/g;
     $result =~ s/&\#8640;/\\ensuremath\{\\rightharpoonup\}/g;
@@ -1251,7 +1330,7 @@
 		$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
 		$form{'rndseed'}=$rndseed;
 		$resources_printed .=$urlp.':';
-		$texversion=&Apache::lonnet::ssi($urlp,%form);
+		$texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form);
 	    }
 	    if((($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
 		($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) && 
@@ -1264,7 +1343,7 @@
 		$answerform{'problem_split'}=$parmhash{'problem_stream_switch'};
 		if ($urlp=~/\/res\//) {$env{'request.state'}='published';}
 		$resources_printed .= $urlp.':';
-		my $answer=&Apache::lonnet::ssi($urlp,%answerform);
+		my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
 		if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
 		    $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
 		} else {
@@ -1319,6 +1398,7 @@
 sub output_data {
     my ($r,$helper,$rparmhash) = @_;
     my %parmhash = %$rparmhash;
+    $ssi_error = 0;		# This will be set nonzero by failing ssi's.
     $resources_printed = '';
     my $do_postprocessing = 1;
     my $js = <<ENDPART;
@@ -1454,7 +1534,7 @@
 		&Apache::lonxml::clear_problem_counter();
 
 		$resources_printed .= $currentURL.':';
-		$texversion.=&Apache::lonnet::ssi($currentURL,%form);
+		$texversion.=&ssi_with_retries($currentURL,$ssi_retry_count, %form);
 
 		#  Add annotations if required:
 	    
@@ -1475,7 +1555,7 @@
 		    $form{'problemtype'}='exam';
 		}
 		$resources_printed .= $currentURL.':';
-		my $answer=&Apache::lonnet::ssi($currentURL,%form);
+		my $answer=&ssi_with_retries($currentURL,$ssi_retry_count, %form);
 		
 
 		if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
@@ -1536,7 +1616,7 @@
 		$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
 		if ($currentURL=~/\/syllabus$/) {$currentURL=~s/\/res//;}
 		$resources_printed .= $currentURL.':';
-		my $texversion=&Apache::lonnet::ssi($currentURL,%form);
+		my $texversion=&ssi_with_retries($currentURL, $ssi_retry_count, %form);
 		if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 		    my $annotation = &annotate($currentURL);
 		    $texversion    =~ s/(\\end{document})/$annotation$1/;
@@ -1617,7 +1697,7 @@
 		&& $urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) {
 		$resources_printed .= $urlp.':';
 		&Apache::lonxml::remember_problem_counter();
-		$texversion.=&Apache::lonnet::ssi($urlp,%form);
+		$texversion.=&ssi_with_retries($urlp, $ssi_retry_count, %form);
 		if ($urlp=~/\.page$/) {
 		    ($texversion,my $number_of_columns_page) = &page_cleanup($texversion);
 		    if ($number_of_columns_page > $number_of_columns) {$number_of_columns=$number_of_columns_page;} 
@@ -1634,7 +1714,7 @@
 		    $resources_printed .= $urlp.':';
 
 		    &Apache::lonxml::restore_problem_counter();
-		    my $answer=&Apache::lonnet::ssi($urlp,%answerform);
+		    my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
 
 		    if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
 			$texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
@@ -1689,7 +1769,7 @@
 		$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
 		if ($urlp=~/\/syllabus$/) {$urlp=~s/\/res//;}
 		$resources_printed .= $urlp.':';
-		my $texversion=&Apache::lonnet::ssi($urlp,%form);
+		my $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form);
 		if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 		    my $annotation = &annotate($urlp);
 		    $texversion =~ s/(\\end{document)/$annotation$1/;
@@ -1927,7 +2007,7 @@
 		    $urlp =~ s|^$Apache::lonnet::perlvar{'lonDocRoot'}||;
 		}
 		$resources_printed .= $urlp.':';
-		my $texversion=&Apache::lonnet::ssi($urlp,%form);
+		my $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form);
 		if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
 		   ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
 		    #  Don't permanently pervert %form:
@@ -1937,7 +2017,7 @@
 		    $answerform{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
 		    $answerform{'rndseed'}=$rndseed;
 		    $resources_printed .= $urlp.':';
-		    my $answer=&Apache::lonnet::ssi($urlp,%answerform);
+		    my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
 		    if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
 			$texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
 		    } else {
@@ -1954,7 +2034,8 @@
 			$texversion.='\vskip 1 mm '.$answer.'\end{document}';
 		    }
 		}
-                #this chunck is responsible for printing the path to problem
+                #this chunk is responsible for printing the path to problem
+
 		my $newurlp=$urlp;
 		if ($newurlp=~/~/) {$newurlp=~s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;}
 		$newurlp=&path_to_problem($newurlp,$LaTeXwidth);
@@ -1994,62 +2075,9 @@
 	#}
     }
 
-#-- writing .tex file in prtspool 
-    my $temp_file;
-    my $identifier = &Apache::loncommon::get_cgi_id();
-    my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout_$identifier.tex";
-    if (!($#print_array>0)) { 
-	unless ($temp_file = Apache::File->new('>'.$filename)) {
-	    $r->log_error("Couldn't open $filename for output $!");
-	    return SERVER_ERROR; 
-	}
-	print $temp_file $result;
-	my $begin=index($result,'\begin{document}',0);
-	my $inc=substr($result,0,$begin+16);
-    } else {
-	my $begin=index($result,'\begin{document}',0);
-	my $inc=substr($result,0,$begin+16);
-        for (my $i=0;$i<=$#print_array;$i++) {
-	    if ($i==0) {
-		$print_array[$i]=$result;
-	    } else {
-		$print_array[$i].='\end{document}';
-		$print_array[$i] = 
-		    &latex_corrections($number_of_columns,$print_array[$i],
-				       $selectionmade, 
-				       $helper->{'VARS'}->{'ANSWER_TYPE'});
-
-		my $anobegin=index($print_array[$i],'\setcounter{page}',0);
-		substr($print_array[$i],0,$anobegin)='';
-		$print_array[$i]=$inc.$print_array[$i];
-	    }
-	    my $temp_file;
-	    my $newfilename=$filename;
-	    my $num=$i+1;
-	    $newfilename =~s/\.tex$//; 
-	    $newfilename=sprintf("%s_%03d.tex",$newfilename, $num);
-	    unless ($temp_file = Apache::File->new('>'.$newfilename)) {
-		$r->log_error("Couldn't open $newfilename for output $!");
-		return SERVER_ERROR; 
-	    }
-	    print $temp_file $print_array[$i];
-	}
-    }
-    my $student_names='';
-    if ($#print_array>0) {
-	for (my $i=0;$i<=$#print_array;$i++) {
-	    $student_names.=$student_names[$i].'_ENDPERSON_';
-	}
-    } else {
-	if ($#student_names>-1) {
-	    $student_names=$student_names[0].'_ENDPERSON_';
-	} else {
-	    my $fullname = &get_name($env{'user.name'},$env{'user.domain'});
-	    $student_names=join(':',$env{'user.name'},$env{'user.domain'},
-				$env{'request.course.sec'},$fullname).
-				    '_ENDPERSON_'.'_END_';
-	}
-    }
+    # Set URLback if this is a construction space print so we can provide
+    # a link to the resource being edited.
+    #
 
     my $URLback=''; #link to original document
     if ($helper->{'VARS'}->{'construction'} eq '1') {
@@ -2060,34 +2088,123 @@
 	    $URLback=~s|^/~|/priv/|;
 	}
     }
-    # logic for now is too complex to trace if this has been defined
-    #  yet.
-    my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
-    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
-    &Apache::lonnet::appenv('cgi.'.$identifier.'.file'   => $filename,
-                            'cgi.'.$identifier.'.layout'  => $laystyle,
-                            'cgi.'.$identifier.'.numcol'  => $numberofcolumns,
-			    'cgi.'.$identifier.'.paper'  => $papersize,
-                            'cgi.'.$identifier.'.selection' => $selectionmade,
-			    'cgi.'.$identifier.'.tableofcontents' => $helper->{'VARS'}->{'TABLE_CONTENTS'},
-			    'cgi.'.$identifier.'.tableofindex' => $helper->{'VARS'}->{'TABLE_INDEX'},
-			    'cgi.'.$identifier.'.role' => $perm{'pav'},
-                            'cgi.'.$identifier.'.numberoffiles' => $#print_array,
-                            'cgi.'.$identifier.'.studentnames' => $student_names,
-                            'cgi.'.$identifier.'.backref' => $URLback,);
-    &Apache::lonnet::appenv("cgi.$identifier.user"    => $env{'user.name'},
-			    "cgi.$identifier.domain"  => $env{'user.domain'},
-			    "cgi.$identifier.courseid" => $cnum, 
-			    "cgi.$identifier.coursedom" => $cdom, 
-			    "cgi.$identifier.resources" => $resources_printed);
 
-    my $end_page = &Apache::loncommon::end_page();
-    $r->print(<<FINALEND);
+
+    # If there's been an unrecoverable SSI error, report it to the user
+    # otherwise, we can write the tex file.
+    #
+
+    if ($ssi_error) {
+	my $end_page = &Apache::loncommon::end_page();
+	$r->print(<<ERROR_END);
+<br />
+<h2>An unrecoverable error occured:</h2>
+<p>
+  I was not able to render one of the print resources ($ssi_last_error_resource) 
+due to an unrecoverable error communicating with a server:
+<br />
+$ssi_last_error;
+<br />
+</p>
+<p>
+I recommend that you try printing again later as this may mean the server was just 
+temporarily unavailable, or is down for maintenance.  If this error persists, then
+please contact your LonCAPA support folks for assistance and diagnosis. 
+<br />
+<br />
+We apologize for the inconvenience.
+</p>
+$end_page
+ERROR_END
+    } else {
+
+#-- writing .tex file in prtspool 
+	my $temp_file;
+	my $identifier = &Apache::loncommon::get_cgi_id();
+	my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout_$identifier.tex";
+	if (!($#print_array>0)) { 
+	    unless ($temp_file = Apache::File->new('>'.$filename)) {
+		$r->log_error("Couldn't open $filename for output $!");
+		return SERVER_ERROR; 
+	    }
+	    print $temp_file $result;
+	    my $begin=index($result,'\begin{document}',0);
+	    my $inc=substr($result,0,$begin+16);
+	} else {
+	    my $begin=index($result,'\begin{document}',0);
+	    my $inc=substr($result,0,$begin+16);
+	    for (my $i=0;$i<=$#print_array;$i++) {
+		if ($i==0) {
+		    $print_array[$i]=$result;
+		} else {
+		    $print_array[$i].='\end{document}';
+		    $print_array[$i] = 
+			&latex_corrections($number_of_columns,$print_array[$i],
+					   $selectionmade, 
+					   $helper->{'VARS'}->{'ANSWER_TYPE'});
+		    
+		    my $anobegin=index($print_array[$i],'\setcounter{page}',0);
+		    substr($print_array[$i],0,$anobegin)='';
+		    $print_array[$i]=$inc.$print_array[$i];
+		}
+		my $temp_file;
+		my $newfilename=$filename;
+		my $num=$i+1;
+		$newfilename =~s/\.tex$//; 
+		$newfilename=sprintf("%s_%03d.tex",$newfilename, $num);
+		unless ($temp_file = Apache::File->new('>'.$newfilename)) {
+		    $r->log_error("Couldn't open $newfilename for output $!");
+		    return SERVER_ERROR; 
+		}
+		print $temp_file $print_array[$i];
+	    }
+	    
+	}
+	my $student_names='';
+	if ($#print_array>0) {
+	    for (my $i=0;$i<=$#print_array;$i++) {
+		$student_names.=$student_names[$i].'_ENDPERSON_';
+	    }
+	} else {
+	    if ($#student_names>-1) {
+		$student_names=$student_names[0].'_ENDPERSON_';
+	    } else {
+		my $fullname = &get_name($env{'user.name'},$env{'user.domain'});
+		$student_names=join(':',$env{'user.name'},$env{'user.domain'},
+				    $env{'request.course.sec'},$fullname).
+					'_ENDPERSON_'.'_END_';
+	    }
+	}
+	
+	# logic for now is too complex to trace if this has been defined
+	#  yet.
+	my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+	my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+	&Apache::lonnet::appenv('cgi.'.$identifier.'.file'   => $filename,
+				'cgi.'.$identifier.'.layout'  => $laystyle,
+				'cgi.'.$identifier.'.numcol'  => $numberofcolumns,
+				'cgi.'.$identifier.'.paper'  => $papersize,
+				'cgi.'.$identifier.'.selection' => $selectionmade,
+				'cgi.'.$identifier.'.tableofcontents' => $helper->{'VARS'}->{'TABLE_CONTENTS'},
+				'cgi.'.$identifier.'.tableofindex' => $helper->{'VARS'}->{'TABLE_INDEX'},
+				'cgi.'.$identifier.'.role' => $perm{'pav'},
+				'cgi.'.$identifier.'.numberoffiles' => $#print_array,
+				'cgi.'.$identifier.'.studentnames' => $student_names,
+				'cgi.'.$identifier.'.backref' => $URLback,);
+	&Apache::lonnet::appenv("cgi.$identifier.user"    => $env{'user.name'},
+				"cgi.$identifier.domain"  => $env{'user.domain'},
+				"cgi.$identifier.courseid" => $cnum, 
+				"cgi.$identifier.coursedom" => $cdom, 
+				"cgi.$identifier.resources" => $resources_printed);
+	
+	my $end_page = &Apache::loncommon::end_page();
+	$r->print(<<FINALEND);
 <br />
 <meta http-equiv="Refresh" content="0; url=/cgi-bin/printout.pl?$identifier" />
 <a href="/cgi-bin/printout.pl?$identifier">Continue</a>
 $end_page
 FINALEND
+  }                                       # endif ssi errors.
 }
 
 
@@ -2285,6 +2402,8 @@
     if(-e $conversion_queuefile) {
 	unlink $conversion_queuefile;
     }
+    
+
     &output_data($r,$helper,\%parmhash);
     return OK;
 } 

--foxr1204022775--