### Eclipse Workspace Patch 1.0
#P moodle
Index: lib/accesslib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/accesslib.php,v
retrieving revision 1.422
diff -u -r1.422 accesslib.php
--- lib/accesslib.php	12 Oct 2007 07:41:30 -0000	1.422
+++ lib/accesslib.php	13 Oct 2007 12:23:12 -0000
@@ -159,6 +159,7 @@
 
 $DIRTYCONTEXTS = null; // dirty contexts cache
 $ACCESS = array(); // cache of caps for cron user switching and has_capability for other users (==not $USER)
+$RDEFS = array(); // role definitions cache - helps a lot with mem usage in cron
 
 function get_role_context_caps($roleid, $context) {
     //this is really slow!!!! - do not use above course context level!
@@ -358,6 +359,7 @@
         // not-logged-in user or $USER object set up manually first time here
         load_all_capabilities();
         $ACCESS = array(); // reset the cache for other users too, the dirty contexts are empty now
+        $RDEFS = array();
     }
 
     // Load dirty contexts list if needed
@@ -371,6 +373,7 @@
         // and then cleanup any marks of dirtyness... at least from our short
         // term memory! :-)
         $ACCESS = array();
+        $RDEFS = array();
 
         if (defined('FULLME') && FULLME === 'cron') {
             load_user_accessdata($userid);
@@ -404,8 +407,7 @@
             error_log("loading access for context {$context->path} for $capability at {$context->contextlevel} {$context->id}");
             // $bt = debug_backtrace();
             // error_log("bt {$bt[0]['file']} {$bt[0]['line']}");
-            $USER->access = get_user_access_bycontext($USER->id, $context,
-                                                      $USER->access);
+            get_user_access_bycontext($USER->id, $context, $USER->access);
         }
         return has_capability_in_accessdata($capability, $context, $USER->access, $doanything);
     }
@@ -422,8 +424,7 @@
         error_log("loading access for context {$context->path} for $capability at {$context->contextlevel} {$context->id}");
         // $bt = debug_backtrace();
         // error_log("bt {$bt[0]['file']} {$bt[0]['line']}");
-        $ACCESS[$userid] = get_user_access_bycontext($userid, $context,
-                                                         $ACCESS[$userid]);
+        get_user_access_bycontext($userid, $context, $ACCESS[$userid]);
     }
     return has_capability_in_accessdata($capability, $context, $ACCESS[$userid], $doanything);
 }
@@ -1285,7 +1286,7 @@
  * @param $accessdata array  accessdata array
  *
  */
-function get_user_access_bycontext($userid, $context, $accessdata=NULL) {
+function get_user_access_bycontext($userid, $context, &$accessdata) {
 
     global $CFG;
 
@@ -1298,14 +1299,6 @@
      *   - below this user's RAs - limited to course level
      */
 
-    // Roles already in use in this context
-    if (is_null($accessdata)) {
-        $accessdata           = array(); // named list
-        $accessdata['ra']     = array();
-        $accessdata['rdef']   = array();
-        $accessdata['loaded'] = array();
-    }
-
     $base = "/" . SYSCONTEXTID;
 
     //
@@ -1394,22 +1387,27 @@
                     $wherelocalroles
             ORDER BY ctx.depth ASC, ctx.path DESC, rc.roleid ASC ";
 
+    $newrdefs = array();
     if ($rs = get_recordset_sql($sql)) {
         while ($rd = rs_fetch_next_record($rs)) {
             $k = "{$rd->path}:{$rd->roleid}";
-            $accessdata['rdef'][$k][$rd->capability] = $rd->permission;
+            if (!array_key_exists($k, $newrdefs)) {
+                $newrdefs[$k] = array();
+            }
+            $newrdefs[$k][$rd->capability] = $rd->permission;
         }
         rs_close($rs);
     } else {
         debugging('Bad SQL encountered!');
     }
 
-    // TODO: compact capsets?
+    compact_rdefs($newrdefs);
+    foreach ($newrdefs as $key=>$value) {
+        $accessdata['rdef'][$key] =& $newrdefs[$key];
+    }
 
     error_log("loaded {$context->path}");
     $accessdata['loaded'][] = $context->path;
-
-    return $accessdata;
 }
 
 /**
@@ -1475,7 +1473,7 @@
     return $accessdata;
 }
 
-/*
+/**
  * Load accessdata for a user
  * into the $ACCESS global
  *
@@ -1483,8 +1481,6 @@
  * to call it if you are about to run a BIG 
  * cron run across a bazillion users.
  *
- * TODO: share rdef tree to save mem
- *
  */ 
 function load_user_accessdata($userid) {
     global $ACCESS,$CFG;
@@ -1521,11 +1517,34 @@
     // for dirty timestamps in cron
     $accessdata['time'] = time();
 
-    $ACCESS[$userid] = $accessdata;  
+    $ACCESS[$userid] = $accessdata;
+    compact_rdefs($ACCESS[$userid]['rdef']);
+
     return true;
 }
 
 /**
+ * Use shared copy of role definistions stored in $RDEFS;
+ * @param array $rdefs array of role definitions in contexts
+ */
+function compact_rdefs(&$rdefs) {
+    global $RDEFS;
+
+    /*
+     * This is a basic sharing only, we could also
+     * use md5 sums of values. The main purpose is to
+     * reduce mem in cron jobs - many users in $ACCESS array.
+     */
+
+    foreach ($rdefs as $key => $value) {
+        if (!array_key_exists($key, $RDEFS)) {
+            $RDEFS[$key] = $rdefs[$key];
+        }
+        $rdefs[$key] =& $RDEFS[$key];
+    }
+}
+
+/**
  *  A convenience function to completely load all the capabilities 
  *  for the current user.   This is what gets called from login, for example.
  */
