--- rat/lonuserstate.pm 2005/03/18 21:55:49 1.88 +++ rat/lonuserstate.pm 2006/02/23 08:38:54 1.99.2.1 @@ -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.88 2005/03/18 21:55:49 raeburn Exp $ +# $Id: lonuserstate.pm,v 1.99.2.1 2006/02/23 08:38:54 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -31,9 +31,8 @@ package Apache::lonuserstate; # ------------------------------------------------- modules used by this module use strict; -use Apache::Constants qw(:common :http); use HTML::TokeParser; -use Apache::lonnet(); +use Apache::lonnet; use Apache::loncommon(); use GDBM_File; use Apache::lonmsg; @@ -41,6 +40,7 @@ use Safe; use Safe::Hole; use Opcode; use Apache::lonenc; +use Fcntl qw(:flock); # ---------------------------------------------------- Globals for this package @@ -73,6 +73,7 @@ sub versiontrack { sub putinversion { my $uri=shift; + my $key=$env{'request.course.id'}.'_'.&Apache::lonnet::clutter($uri); if ($hash{'version_'.$uri}) { my $version=$hash{'version_'.$uri}; if ($version eq 'mostrecent') { return $uri; } @@ -81,6 +82,7 @@ sub putinversion { { return $uri; } $uri=~s/\.(\w+)$/\.$version\.$1/; } + &Apache::lonnet::do_cache_new('courseresversion',$key,&Apache::lonnet::declutter($uri),600); return $uri; } @@ -101,7 +103,7 @@ sub processversionfile { sub loadmap { my $uri=shift; - if ($hash{'map_pc_'.$uri}) { return OK; } + if ($hash{'map_pc_'.$uri}) { return; } $pc++; my $lpc=$pc; @@ -116,7 +118,7 @@ sub loadmap { unless (($fn=~/\.sequence$/) || ($fn=~/\.page$/)) { $errtext.="Invalid map: $fn\n"; - return OK; + return; } my $instr=&Apache::lonnet::getfile($fn); @@ -126,6 +128,7 @@ sub loadmap { # Successfully got file, parse it my $parser = HTML::TokeParser->new(\$instr); + $parser->attr_encoded(1); my $token; my $linkpc=0; @@ -138,7 +141,7 @@ sub loadmap { if ($token->[0] eq 'S') { if ($token->[1] eq 'resource') { # -------------------------------------------------------------------- Resource - + if ($token->[2]->{'type'} eq 'zombie') { next; } my $rid=$lpc.'.'.$token->[2]->{'id'}; $hash{'kind_'.$rid}='res'; @@ -161,7 +164,9 @@ sub loadmap { if ($token->[2]->{'external'} eq 'true') { # external $turi=~s/^http\:\/\//\/adm\/wrapper\/ext\//; } elsif ($turi=~/^\/*uploaded\//) { # uploaded - if (($embstyle eq 'img') || ($embstyle eq 'emb')) { + if (($embstyle eq 'img') + || ($embstyle eq 'emb') + || ($embstyle eq 'wrp')) { $turi='/adm/wrapper'.$turi; } elsif ($embstyle eq 'ssi') { #do nothing with these @@ -172,7 +177,9 @@ sub loadmap { my $mapdir=$uri; $mapdir=~s/[^\/]+$//; $turi=&Apache::lonnet::hreflocation($mapdir,$turi); - if (($embstyle eq 'img') || ($embstyle eq 'emb')) { + if (($embstyle eq 'img') + || ($embstyle eq 'emb') + || ($embstyle eq 'wrp')) { $turi='/adm/wrapper'.$turi; } } @@ -311,6 +318,8 @@ sub loadmap { sub simplify { my $expression=shift; +# (0&1) = 1 + $expression=~s/\(0\&(\d+)\)/$1/g; # (8)=8 $expression=~s/\((\d+)\)/$1/g; # 8&8=8 @@ -320,8 +329,8 @@ sub simplify { # (5&3)&4=5&3&4 $expression=~s/\((\d+)((?:\&\d+)+)\)\&(\d+\D)/$1$2\&$3/g; # (((5&3)|(4&6)))=((5&3)|(4&6)) - $expression=~ - s/\((\(\(\d+(?:\&\d+)*\)(?:\|\(\d+(?:\&\d+)*\))+\))\)/$1/g; +# $expression=~ +# s/\((\(\(\d+(?:\&\d+)*\)(?:\|\(\d+(?:\&\d+)*\))+\))\)/$1/g; # ((5&3)|(4&6))|(1&2)=(5&3)|(4&6)|(1&2) $expression=~ s/\((\(\d+(?:\&\d+)*\))((?:\|\(\d+(?:\&\d+)*\))+)\)\|(\(\d+(?:\&\d+)*\))/\($1$2\|$3\)/g; @@ -338,7 +347,14 @@ sub traceroute { my ($mapid,$resid)=split(/\./,$rid); my $symb=&Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},$resid,$hash{'src_'.$rid}); my $hidden=&Apache::lonnet::EXT('resource.0.hiddenresource',$symb); - if ($hdnflag || lc($hidden) eq 'yes') { $hiddenurl{$rid}=1; } + + if ($hdnflag || lc($hidden) eq 'yes') { + $hiddenurl{$rid}=1; + } + if (!$hdnflag && lc($hidden) eq 'no') { + delete($hiddenurl{$rid}); + } + my $encrypt=&Apache::lonnet::EXT('resource.0.encrypturl',$symb); if ($encflag || lc($encrypt) eq 'yes') { $encurl{$rid}=1; } if (($retfurl eq '') && ($hash{'src_'.$rid}) @@ -539,15 +555,21 @@ sub readmap { return 'No course data available.'; } @cond=('true:normal'); - #unlink($fn.'.db'); - #unlink($fn.'_symb.db'); - unlink($fn.'.state'); - unlink($fn.'parms.db'); + + open(LOCKFILE,">$fn.db.lock"); + my $lock=0; + if (flock(LOCKFILE,LOCK_EX|LOCK_NB)) { + $lock=1; + unlink($fn.'.db'); + unlink($fn.'_symb.db'); + unlink($fn.'.state'); + unlink($fn.'parms.db'); + } undef %randompick; undef %hiddenurl; undef %encurl; $retfurl=''; - if ((tie(%hash,'GDBM_File',"$fn.db",&GDBM_WRCREAT(),0640)) && + if ($lock && (tie(%hash,'GDBM_File',"$fn.db",&GDBM_WRCREAT(),0640)) && (tie(%parmhash,'GDBM_File',$fn.'_parms.db',&GDBM_WRCREAT(),0640))) { %hash=(); %parmhash=(); @@ -581,6 +603,7 @@ sub readmap { } # ----------------------------------------------- Close hashes to finally store # --------------------------------- Routine must pass this point, no early outs + $hash{'first_url'}=$retfurl; unless ((untie(%hash)) && (untie(%parmhash))) { &Apache::lonnet::logthis("WARNING: ". "Could not untie coursemap $fn for $uri."); @@ -594,13 +617,19 @@ sub readmap { &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 # them on to navmaps, if we fail, throw up the Could not init # course screen + if ($lock) { + # Got the lock but not the DB files + flock(LOCKFILE,LOCK_UN); + } untie(%hash); untie(%parmhash); &Apache::lonnet::logthis("WARNING: ". @@ -609,7 +638,8 @@ sub readmap { while($i<90) { $i++; sleep(1); - if ((tie(%hash,'GDBM_File',"$fn.db",&GDBM_READER(),0640))) { + 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, @@ -623,12 +653,14 @@ sub readmap { untie(%hash); untie(%parmhash); } + flock(LOCKFILE,LOCK_UN); + close(LOCKFILE); } - &Apache::lonmsg::author_res_msg($ENV{'request.course.uri'},$errtext); + &Apache::lonmsg::author_res_msg($env{'request.course.uri'},$errtext); # ------------------------------------------------- Check for critical messages - my @what=&Apache::lonnet::dump('critical',$ENV{'user.domain'}, - $ENV{'user.name'}); + my @what=&Apache::lonnet::dump('critical',$env{'user.domain'}, + $env{'user.name'}); if ($what[0]) { if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) { $retfurl='/adm/email?critical=display'; @@ -640,7 +672,7 @@ sub readmap { # ------------------------------------------------------- Evaluate state string sub evalstate { - my $fn=$ENV{'request.course.fn'}.'.state'; + my $fn=$env{'request.course.fn'}.'.state'; my $state=''; if (-e $fn) { my @conditions=(); @@ -672,7 +704,7 @@ sub evalstate { } } } - &Apache::lonnet::appenv('user.state.'.$ENV{'request.course.id'} => $state); + &Apache::lonnet::appenv('user.state.'.$env{'request.course.id'} => $state); return $state; } 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.