--- admin.php 2009/04/01 09:30:42 1.60 +++ admin.php 2009/04/14 17:08:44 1.61 @@ -125,6 +125,11 @@ $string['privilegedserverips']='Privileged server IPs'; $string['configprivilegedserverips']='A comma-separated list of numerical IP addresses for OU servers that have privileged access to web services or other back-end communication.'; +$string['logbatchfolder']='Log batch folder'; +$string['configlogbatchfolder']='Disk folder used to batch up log inserts, specified as an absolute path. Leave blank to disable log insert batching. If specified, this must be on a local (not networked) disk, and must already exist.'; +$string['logbatchtime']='Log batch time'; +$string['configlogbatchtime']='Time in seconds to group log inserts into batches. (Note: In periods of low activity, inserts might be delayed longer because the batch insert only happens when there is another log request.)'; + $string['perflogview'] = 'Performance logs'; $string['exportdisk'] = 'Bulk DVD Export'; $string['sitemapgen'] = 'SEO Sitemap Generator'; --- server.php 2009/04/01 09:30:42 1.63 +++ server.php 2009/04/14 17:08:44 1.64 @@ -360,6 +360,14 @@ get_string('configmemcachedpconn', 'admin'), 0, array( '0' => get_string('no'), '1' => get_string('yes')))); +// ou-specific begins +$temp->add(new admin_setting_configtext('logbatchfolder', + get_string('logbatchfolder', 'admin'), + get_string('configlogbatchfolder','admin'),'')); +$temp->add(new admin_setting_configtext('logbatchtime', + get_string('logbatchtime', 'admin'), + get_string('configlogbatchtime','admin'),'30')); +// ou-specific ends $ADMIN->add('server', $temp); if ($CFG->dbfamily === 'mysql') { --- ou_lib.php 2009/03/03 10:50:38 1.6 +++ ou_lib.php 2009/04/14 17:08:44 1.7 @@ -136,4 +136,95 @@ return true; } + +/** + * For use with very frequent SQL inserts. Batches them up into a file in + * local filesystem which is inserted in a single transaction after a number + * of seconds (when a future insert happens). + * + * @param string $table Name of table (unique identifier for type of insert) + * @param string $sql SQL of insert command + */ +function ou_run_batched_insert($table, $sql) { + global $CFG, $db; + + // If not enabled, run SQL statement directly + if (empty($CFG->logbatchfolder) || empty($CFG->logbatchtime)) { + if(!$db->Execute($sql)) { + debugging("Insert into $table failed [$sql]"); + } + return; + } + + // Otherwise batch together inserts over a period of time using filesystem + $logtimefile = $CFG->logbatchfolder . '/' . $table . '.time'; + $logbatchfile = $CFG->logbatchfolder . '/' . $table . '.batch'; + + // Open batch file (this should lock it) + if ($handle = fopen($logbatchfile, 'a+')) { + // Get modified time of time file and create it if it doesn't exist + if (!($modified = @filemtime($logtimefile))) { + file_put_contents($logtimefile, + 'This file tracks when update batch was last applied'); + $modified = time(); + } + + // See how long since we've updated + if (time() - $modified < $CFG->logbatchtime) { + // It isn't long since we updated, so just add the current + // function call to the file + fwrite($handle, strlen($sql) . ':' . $sql); + fclose($handle); + return; + } else { + // It's a while since we updated, so read the whole file and + // update it. First read the data + touch($logtimefile); + fseek($handle, 0); + $size = filesize($logbatchfile); + if($size > 0) { + $data = fread($handle, $size); + // Clear and close the file now so it doesn't stay locked long + ftruncate($handle, 0); + } else { + $data = ''; + } + fclose($handle); + + // Start batch + begin_sql(); + + // Process the data + while($data !== '') { + // Get data chunk + $colon = strpos($data, ':'); + if($colon === false) { + debugging('Error: invalid log batch format'); + break; + } + $bytes = (int)substr($data, 0, $colon); + $batchsql = substr($data, $colon + 1, $bytes); + $data = (string)substr($data, $colon + 1 + $bytes); + + // Execute SQL + if(!$db->Execute($batchsql)) { + debugging("Insert into $table failed [$batchsql]"); + } + } + + // Finally don't forget to actually log *this* request too + if(!$db->Execute($sql)) { + debugging("Insert into $table failed [$sql]"); + } + + // Finish batch + commit_sql(); + } + } else { + debugging('Failed to open log batch file'); + if(!$db->Execute($sql)) { + debugging("Insert into $table failed [$sql]"); + } + } +} ?> --- datalib.php 2009/03/17 16:28:52 1.103 +++ datalib.php 2009/04/14 17:08:44 1.104 @@ -2249,7 +2248,11 @@ } $sql ='INSERT INTO '. $CFG->prefix .'log (time, userid, course, ip, module, cmid, action, url, info) VALUES (' . "'$timenow', '$userid', '$courseid', '$REMOTE_ADDR', '$module', '$cm', '$action', '$url', '$info')"; - +// ou-specific begins + ou_run_batched_insert('log', $sql); + return; +// ou-specific ends + $result = $db->Execute($sql); // MDL-11893, alert $CFG->supportemail if insert into log failed