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

matthew lon-capa-cvs@mail.lon-capa.org
Fri, 14 Feb 2003 21:02:05 -0000


matthew		Fri Feb 14 16:02:05 2003 EDT

  Modified files:              
    /loncom/interface	loncoursedata.pm 
  Log:
  Implemented caching scheme for &get_current_state().  This routine has not
  been tested for retrieval of data for a single symb.  It has been tested
  with the spreadsheet which requests all of the students current data.
  The cache file is prepended with the users name and domain in order to 
  prevent collisions between concurrent instructors.  The use of this function
  does not appreciably modify the performance of the spreadsheet.
  Added helper function &make_into_hash.
  
  
Index: loncom/interface/loncoursedata.pm
diff -u loncom/interface/loncoursedata.pm:1.46 loncom/interface/loncoursedata.pm:1.47
--- loncom/interface/loncoursedata.pm:1.46	Thu Feb 13 17:52:48 2003
+++ loncom/interface/loncoursedata.pm	Fri Feb 14 16:02:05 2003
@@ -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 @@
 
 =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 @@
 )
 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 @@
 
 ################################################
 ################################################
-
 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 ();