--- loncom/interface/loncoursedata.pm 2003/02/13 22:52:48 1.46 +++ loncom/interface/loncoursedata.pm 2003/02/14 21:02:05 1.47 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # (Publication Handler # -# $Id: loncoursedata.pm,v 1.46 2003/02/13 22:52:48 matthew Exp $ +# $Id: loncoursedata.pm,v 1.47 2003/02/14 21:02:05 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -1498,11 +1498,36 @@ sub CheckForResidualDownload { =pod +=item &make_into_hash($values); + +Returns a reference to a hash as described by $values. $values is +assumed to be the result of + join(':',map {&Apache::lonnet::escape($_)} %orighash; + +This is a helper function for get_current_state. + +=cut + +################################################ +################################################ +sub make_into_hash { + my $values = shift; + my %tmp = map { &Apache::lonnet::unescape($_); } + split(':',$values); + return \%tmp; +} + + +################################################ +################################################ + +=pod + =item &get_current_state($sname,$sdom,$symb,$courseid); -Retrive the current status of a students performance. $sname and +Retrieve the current status of a students performance. $sname and $sdom are the only required parameters. If $symb is undef the results -of a &Apache::lonnet::currentdump() will be returned. +of an &Apache::lonnet::currentdump() will be returned. If $courseid is undef it will be retrieved from the environment. The return structure is based on &Apache::lonnet::currentdump. If @@ -1520,8 +1545,6 @@ If $symb is specified, a hash of ) is returned. -Eventually this routine will cache the results locally. - If no data is found for $symb, or if the student has not performance data, an empty list is returned. @@ -1529,23 +1552,95 @@ an empty list is returned. ################################################ ################################################ - sub get_current_state { - my ($sname,$sdom,$symb,$courseid)=@_; - return undef if (! defined($sname) || ! defined($sdom)); + my ($sname,$sdom,$symb,$courseid,$forcedownload)=@_; + return () if (! defined($sname) || ! defined($sdom)); + # $courseid = $ENV{'request.course.id'} if (! defined($courseid)); - # For a first pass, just get a currentdump and return the requested - # results - my @tmp = &Apache::lonnet::currentdump($courseid,$sdom,$sname); - if (! ((scalar(@tmp) > 0) && ($tmp[0] !~ /^error:/)) ) { - &Apache::lonnet::logthis('error getting data for '.$sname.':'.$sdom. - 'in course '.$courseid); - return (); + # + my $cachefilename = $Apache::lonnet::tmpdir.$ENV{'user.name'}.'_'. + $ENV{'user.domain'}.'_'. + $courseid.'_student_data.db'; + my %cache; + # + my %student_data; # return values go here + # + my $updatetime = 0; + my $key = &Apache::lonnet::escape($sname).':'. + &Apache::lonnet::escape($sdom).':'; + # Open the cache file + if (tie(%cache,'GDBM_File',$cachefilename,&GDBM_READER(),0640)) { + if (exists($cache{$key.'time'})) { + $updatetime = $cache{$key.'time'}; +# &Apache::lonnet::logthis('got updatetime of '.$updatetime); + } + untie(%cache); + } + # timestamp/devalidation + my $modifiedtime = 1; + # Take whatever steps are neccessary at this point to give $modifiedtime a + # new value + # + if (($updatetime < $modifiedtime) || + (defined($forcedownload) && $forcedownload)) { +# &Apache::lonnet::logthis("loading data"); + # Get all the students current data + my $time_of_retrieval = time; + my @tmp = &Apache::lonnet::currentdump($courseid,$sdom,$sname); + if ((scalar(@tmp) > 0) && ($tmp[0] =~ /^error:/)) { + &Apache::lonnet::logthis('error getting data for '. + $sname.':'.$sdom.' in course '.$courseid. + ':'.$tmp[0]); + return (); + } + %student_data = @tmp; + # + # Store away the data + # + # The cache structure is colon deliminated. + # $uname:$udom:time => timestamp + # $uname:$udom:$symb => $parm1:$val1:$parm2:$val2 ... + # + # BEWARE: The colons are NOT escaped so can search with escaped + # keys instead of unescaping every key. + # + if (tie(%cache,'GDBM_File',$cachefilename,&GDBM_WRCREAT(),0640)) { +# &Apache::lonnet::logthis("writing data"); + while (my ($current_symb,$param_hash) = each(%student_data)) { + my @Parameters = %{$param_hash}; + my $value = join(':',map { &Apache::lonnet::escape($_); } + @Parameters); + # Store away the values + $cache{$key.&Apache::lonnet::escape($symb)}=$value; + } + $cache{$key.'time'}=$time_of_retrieval; + untie(%cache); + } + } else { +# &Apache::lonnet::logthis('retrieving cached data '); + if (tie(%cache,'GDBM_File',$cachefilename,&GDBM_READER(),0640)) { + if (defined($symb)) { + my $searchkey = $key.&Apache::lonnet::escape($symb); + if (exists($cache{$searchkey})) { + $student_data{$symb} = &make_into_hash($cache{$searchkey}); + } + } else { + my $searchkey = '^'.$key.'(.*)$';#' + while (my ($testkey,$params)=each(%cache)) { + if ($testkey =~ /$searchkey/) { # \Q \E? May be necc. + $student_data{&Apache::lonnet::unescape($1)} = + &make_into_hash($params); + } + } + } + untie(%cache); + } } - my %student_data = @tmp; if (! defined($symb)) { +# &Apache::lonnet::logthis("returning all data"); return %student_data; } elsif (exists($student_data{$symb})) { +# &Apache::lonnet::logthis("returning data for symb=".$symb); return %{$student_data{$symb}}; } else { return ();