--- rat/lonuserstate.pm 2009/11/16 20:26:04 1.128.2.3
+++ rat/lonuserstate.pm 2009/02/18 07:06:19 1.131
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Construct and maintain state and binary representation of course for user
#
-# $Id: lonuserstate.pm,v 1.128.2.3 2009/11/16 20:26:04 raeburn Exp $
+# $Id: lonuserstate.pm,v 1.131 2009/02/18 07:06:19 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -645,52 +645,92 @@ sub readmap {
my $uri;
$short=~s/\//\_/g;
unless ($uri=$cenv{'url'}) {
- &Apache::lonnet::logthis('WARNING: '.
+ &Apache::lonnet::logthis("WARNING: ".
"Could not load course $short.");
return ('',&mt('No course data available.'));;
}
@cond=('true:normal');
- unless (open(LOCKFILE,">$fn.db.lock")) {
- $errtext.='
'.&mt('Map not loaded - Lock file could not be opened when reading map:').' '.$fn.'.';
- $retfurl = '';
- return ($retfurl,$errtext);
- }
+ open(LOCKFILE,">$fn.db.lock");
my $lock=0;
- my $gotstate=0;
if (flock(LOCKFILE,LOCK_EX|LOCK_NB)) {
$lock=1;
- &unlink_tmpfiles($fn);
+ unlink($fn.'.db');
+ unlink($fn.'_symb.db');
+ unlink($fn.'.state');
+ unlink($fn.'parms.db');
}
undef %randompick;
undef %hiddenurl;
undef %encurl;
$retfrid='';
- my ($untiedhash,$untiedparmhash,$tiedhash,$tiedparmhash);
- if ($lock) {
- if (tie(%hash,'GDBM_File',"$fn.db",&GDBM_WRCREAT(),0640)) {
- $tiedhash = 1;
- if (tie(%parmhash,'GDBM_File',$fn.'_parms.db',&GDBM_WRCREAT(),0640)) {
- $tiedparmhash = 1;
- $gotstate = &build_tmp_hashes($uri,$fn,$short,\%cenv);
- unless ($gotstate) {
- &Apache::lonnet::logthis('Failed to write statemap at first attempt '.$fn.' for '.$uri.'.');
- }
- $untiedparmhash = untie(%parmhash);
- unless ($untiedparmhash) {
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not untie coursemap parmhash '.$fn.' for '.$uri.'.');
- }
- }
- $untiedhash = untie(%hash);
- unless ($untiedhash) {
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not untie coursemap hash '.$fn.' for '.$uri.'.');
- }
- }
- flock(LOCKFILE,LOCK_UN);
- }
- unless ($lock && $tiedhash && $tiedparmhash) {
+ if ($lock && (tie(%hash,'GDBM_File',"$fn.db",&GDBM_WRCREAT(),0640)) &&
+ (tie(%parmhash,'GDBM_File',$fn.'_parms.db',&GDBM_WRCREAT(),0640))) {
+ %hash=();
+ %parmhash=();
+ $errtext='';
+ $pc=0;
+ &clear_mapalias_count();
+ &processversionfile(%cenv);
+ my $furi=&Apache::lonnet::clutter($uri);
+ $hash{'src_0.0'}=&versiontrack($furi);
+ $hash{'title_0.0'}=&Apache::lonnet::metadata($uri,'title');
+ $hash{'ids_'.$furi}='0.0';
+ $hash{'is_map_0.0'}=1;
+ loadmap($uri,'0.0');
+ if (defined($hash{'map_start_'.$uri})) {
+ &Apache::lonnet::appenv({"request.course.id" => $short,
+ "request.course.fn" => $fn,
+ "request.course.uri" => $uri});
+ $env{'request.course.id'}=$short;
+ &traceroute('0',$hash{'map_start_'.$uri},'&');
+ &accinit($uri,$short,$fn);
+ &hiddenurls();
+ }
+ $errtext .= &get_mapalias_errors();
+# ------------------------------------------------------- Put versions into src
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^src_/) {
+ $hash{$key}=&putinversion($hash{$key});
+ } elsif ($key =~ /^(map_(?:start|finish|pc)_)(.*)/) {
+ my ($type, $url) = ($1,$2);
+ my $value = $hash{$key};
+ $hash{$type.&putinversion($url)}=$value;
+ }
+ }
+# ---------------------------------------------------------------- Encrypt URLs
+ foreach my $id (keys(%encurl)) {
+# $hash{'src_'.$id}=&Apache::lonenc::encrypted($hash{'src_'.$id});
+ $hash{'encrypted_'.$id}=1;
+ }
+# ----------------------------------------------- Close hashes to finally store
+# --------------------------------- Routine must pass this point, no early outs
+ $hash{'first_rid'}=$retfrid;
+ my ($mapid,$resid)=split(/\./,$retfrid);
+ $hash{'first_mapurl'}=$hash{'map_id_'.$mapid};
+ my $symb=&Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},$resid,$hash{'src_'.$retfrid});
+ $retfurl=&add_get_param($hash{'src_'.$retfrid},{ 'symb' => $symb });
+ if ($hash{'encrypted_'.$retfrid}) {
+ $retfurl=&Apache::lonenc::encrypted($retfurl,(&Apache::lonnet::allowed('adv') ne 'F'));
+ }
+ $hash{'first_url'}=$retfurl;
+ unless ((untie(%hash)) && (untie(%parmhash))) {
+ &Apache::lonnet::logthis("WARNING: ".
+ "Could not untie coursemap $fn for $uri.");
+ }
+# ---------------------------------------------------- Store away initial state
+ {
+ my $cfh;
+ if (open($cfh,">$fn.state")) {
+ print $cfh join("\n",@cond);
+ } else {
+ &Apache::lonnet::logthis("WARNING: ".
+ "Could not write statemap $fn for $uri.");
+ }
+ }
+ flock(LOCKFILE,LOCK_UN);
+ close(LOCKFILE);
+ } else {
# if we are here it is likely because we are already trying to
# initialize the course in another child, busy wait trying to
# tie the hashes for the next 90 seconds, if we succeed forward
@@ -699,113 +739,34 @@ sub readmap {
if ($lock) {
# Got the lock but not the DB files
flock(LOCKFILE,LOCK_UN);
- $lock = 0;
}
- if ($tiedhash) {
- unless($untiedhash) {
- untie(%hash);
- }
- }
- if ($tiedparmhash) {
- unless($untiedparmhash) {
- untie(%parmhash);
- }
- }
- &Apache::lonnet::logthis('WARNING: '.
- "Could not tie coursemap $fn for $uri.");
- $tiedhash = '';
- $tiedparmhash = '';
+ untie(%hash);
+ untie(%parmhash);
+ &Apache::lonnet::logthis("WARNING: ".
+ "Could not tie coursemap $fn for $uri.");
my $i=0;
while($i<90) {
$i++;
sleep(1);
- if (flock(LOCKFILE,LOCK_EX|LOCK_NB)) {
- $lock = 1;
- if (tie(%hash,'GDBM_File',"$fn.db",&GDBM_READER(),0640)) {
- $tiedhash = 1;
- if (tie(%parmhash,'GDBM_File',$fn.'_parms.db',&GDBM_READER(),0640)) {
- $tiedparmhash = 1;
- if (-e "$fn.state") {
- $retfurl='/adm/navmaps';
- &Apache::lonnet::appenv({"request.course.id" => $short,
- "request.course.fn" => $fn,
- "request.course.uri" => $uri});
- $untiedhash = untie(%hash);
- $untiedparmhash = untie(%parmhash);
- $gotstate = 1;
- last;
- }
- $untiedparmhash = untie(%parmhash);
- }
- $untiedhash = untie(%hash);
+ if (flock(LOCKFILE,LOCK_EX|LOCK_NB) &&
+ (tie(%hash,'GDBM_File',"$fn.db",&GDBM_READER(),0640))) {
+ if (tie(%parmhash,'GDBM_File',$fn.'_parms.db',&GDBM_READER(),0640)) {
+ $retfurl='/adm/navmaps';
+ &Apache::lonnet::appenv({"request.course.id" => $short,
+ "request.course.fn" => $fn,
+ "request.course.uri" => $uri});
+ untie(%hash);
+ untie(%parmhash);
+ last;
}
}
+ untie(%hash);
+ untie(%parmhash);
}
- if ($lock) {
- flock(LOCKFILE,LOCK_UN);
- $lock = 0;
- if ($tiedparmhash) {
- unless ($untiedparmhash) {
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not untie coursemap parmhash '.$fn.' for '.$uri.'.');
- }
- }
- if ($tiedparmhash) {
- unless ($untiedhash) {
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not untie coursemap hash '.$fn.' for '.$uri.'.');
- }
- }
- }
- }
- unless ($gotstate) {
- $lock = 0;
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not read statemap '.$fn.' for '.$uri.'.');
- &unlink_tmpfiles($fn);
- if (flock(LOCKFILE,LOCK_EX|LOCK_NB)) {
- $lock=1;
- }
- undef %randompick;
- undef %hiddenurl;
- undef %encurl;
- $retfrid='';
- if ($lock) {
- if (tie(%hash,'GDBM_File',"$fn.db",&GDBM_WRCREAT(),0640)) {
- if (tie(%parmhash,'GDBM_File',$fn.'_parms.db',&GDBM_WRCREAT(),0640)) {
- $gotstate = &build_tmp_hashes($uri,$fn,$short,\%cenv);
- unless ($gotstate) {
- &Apache::lonnet::logthis('WARNING: '.
- 'Failed to write statemap at second attempt '.$fn.' for '.$uri.'.');
- }
- unless (untie(%parmhash)) {
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not untie coursemap parmhash '.$fn.'.db for '.$uri.'.');
- }
- } else {
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not tie coursemap '.$fn.'__parms.db for '.$uri.'.');
- }
- unless (untie(%hash)) {
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not untie coursemap hash '.$fn.'.db for '.$uri.'.');
- }
- } else {
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not tie coursemap '.$fn.'.db for '.$uri.'.');
- }
- flock(LOCKFILE,LOCK_UN);
- $lock = 0;
- } else {
- &Apache::lonnet::logthis('WARNING: '.
- 'Could not obtain lock to tie coursemap hash '.$fn.'.db for '.$uri.'.');
- }
- }
- close(LOCKFILE);
- unless (($errtext eq '') || ($env{'request.course.uri'} =~ m{^/uploaded/})) {
- &Apache::lonmsg::author_res_msg($env{'request.course.uri'},
- $errtext);
+ flock(LOCKFILE,LOCK_UN);
+ close(LOCKFILE);
}
+ &Apache::lonmsg::author_res_msg($env{'request.course.uri'},$errtext);
# ------------------------------------------------- Check for critical messages
my @what=&Apache::lonnet::dump('critical',$env{'user.domain'},
@@ -818,91 +779,6 @@ sub readmap {
return ($retfurl,$errtext);
}
-sub build_tmp_hashes {
- my ($uri,$fn,$short,$cenvref) = @_;
- unless(ref($cenvref) eq 'HASH') {
- return;
- }
- my %cenv = %{$cenvref};
- my $gotstate = 0;
- %hash=();
- %parmhash=();
- $errtext='';
- $pc=0;
- &clear_mapalias_count();
- &processversionfile(%cenv);
- my $furi=&Apache::lonnet::clutter($uri);
- $hash{'src_0.0'}=&versiontrack($furi);
- $hash{'title_0.0'}=&Apache::lonnet::metadata($uri,'title');
- $hash{'ids_'.$furi}='0.0';
- $hash{'is_map_0.0'}=1;
- &loadmap($uri,'0.0');
- if (defined($hash{'map_start_'.$uri})) {
- &Apache::lonnet::appenv({"request.course.id" => $short,
- "request.course.fn" => $fn,
- "request.course.uri" => $uri});
- $env{'request.course.id'}=$short;
- &traceroute('0',$hash{'map_start_'.$uri},'&');
- &accinit($uri,$short,$fn);
- &hiddenurls();
- }
- $errtext .= &get_mapalias_errors();
-# ------------------------------------------------------- Put versions into src
- foreach my $key (keys(%hash)) {
- if ($key=~/^src_/) {
- $hash{$key}=&putinversion($hash{$key});
- } elsif ($key =~ /^(map_(?:start|finish|pc)_)(.*)/) {
- my ($type, $url) = ($1,$2);
- my $value = $hash{$key};
- $hash{$type.&putinversion($url)}=$value;
- }
- }
-# ---------------------------------------------------------------- Encrypt URLs
- foreach my $id (keys(%encurl)) {
-# $hash{'src_'.$id}=&Apache::lonenc::encrypted($hash{'src_'.$id});
- $hash{'encrypted_'.$id}=1;
- }
-# ----------------------------------------------- Close hashes to finally store
-# --------------------------------- Routine must pass this point, no early outs
- $hash{'first_rid'}=$retfrid;
- my ($mapid,$resid)=split(/\./,$retfrid);
- $hash{'first_mapurl'}=$hash{'map_id_'.$mapid};
- my $symb=&Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},$resid,$hash{'src_'.$retfrid});
- $retfurl=&add_get_param($hash{'src_'.$retfrid},{ 'symb' => $symb });
- if ($hash{'encrypted_'.$retfrid}) {
- $retfurl=&Apache::lonenc::encrypted($retfurl,(&Apache::lonnet::allowed('adv') ne 'F'));
- }
- $hash{'first_url'}=$retfurl;
-# ---------------------------------------------------- Store away initial state
- {
- my $cfh;
- if (open($cfh,">$fn.state")) {
- print $cfh join("\n",@cond);
- $gotstate = 1;
- } else {
- &Apache::lonnet::logthis("WARNING: ".
- "Could not write statemap $fn for $uri.");
- }
- }
- return $gotstate;
-}
-
-sub unlink_tmpfiles {
- my ($fn) = @_;
- if ($fn =~ m{^\Q$Apache::lonnet::perlvar{'lonUsersDir'}\E/tmp/}) {
- my @files = qw (.db _symb.db .state _parms.db);
- foreach my $file (@files) {
- if (-e $fn.$file) {
- unless (unlink($fn.$file)) {
- &Apache::lonnet::logthis("WARNING: ".
- "Could not unlink ".$fn.$file."");
- }
- }
- }
- }
- return;
-}
-
# ------------------------------------------------------- Evaluate state string
sub evalstate {
@@ -1002,37 +878,33 @@ of course for user.
This is part of the LearningOnline Network with CAPA project
described at http://www.lon-capa.org.
-=head1 HANDLER SUBROUTINE
-
-There is no handler subroutine.
-
-=head1 OTHER SUBROUTINES
+=head1 SUBROUTINES
-=over 4
+=over
-=item *
+=item loadmap()
-loadmap() : Loads map from disk
+Loads map from disk
-=item *
+=item simplify()
-simplify() : Simplify expression
+Simplify expression
-=item *
+=item traceroute()
-traceroute() : Build condition hash
+Build condition hash
-=item *
+=item accinit()
-accinit() : Cascading conditions, quick access, parameters
+Cascading conditions, quick access, parameters
-=item *
+=item readmap()
-readmap() : Read map and all submaps
+Read map and all submaps
-=item *
+=item evalstate()
-evalstate() : Evaluate state string
+Evaluate state string
=back