示例#1
0
文件: values.php 项目: rair/yacs
 /**
  * retrieve date of last value update
  *
  * @param string the id of the value to be retrieved
  * @return string modification date, or '0000-00-00'
  */
 public static function get_stamp($id)
 {
     global $context;
     // get one attribute of the record
     if ($item = Values::get_record($id)) {
         $item = $item['edit_date'];
     } else {
         $item = NULL_DATE;
     }
     return $item;
 }
示例#2
0
文件: sql.php 项目: rair/yacs
 /**
  * purge idle space
  *
  * This function OPTIMIZEs tables that may create overheads because of
  * frequent deletions, including: cache, links, members, messages,
  * notifications, values, versions, visits.
  *
  * Last purge is recorded as value 'sql.tick'.
  *
  * @param boolean optional TRUE to not report on any error
  * @return a string to be displayed in resulting page, if any
  */
 public static function purge($silent = FALSE)
 {
     global $context;
     // useless if we don't have a valid database connection
     if (!$context['connection']) {
         return;
     }
     // remember start time
     $stamp = get_micro_time();
     // get date of last tick
     include_once $context['path_to_root'] . 'shared/values.php';
     $record = Values::get_record('sql.tick', NULL_DATE);
     // wait at least 8 hours = 24*3600 seconds between ticks
     if (isset($record['edit_date'])) {
         $target = SQL::strtotime($record['edit_date']) + 8 * 3600;
     } else {
         $target = time();
     }
     // request to be delayed
     if ($target > time()) {
         return 'shared/sql.php: wait until ' . gmdate('r', $target) . ' GMT' . BR;
     }
     // recover unused bytes
     $query = 'OPTIMIZE TABLE ' . SQL::table_name('cache') . ', ' . SQL::table_name('links') . ', ' . SQL::table_name('members') . ', ' . SQL::table_name('messages') . ', ' . SQL::table_name('notifications') . ', ' . SQL::table_name('values') . ', ' . SQL::table_name('versions') . ', ' . SQL::table_name('visits');
     $result = SQL::query($query, $silent);
     // remember tick date and resulting text
     Values::set('sql.tick', 'purge');
     // compute execution time
     $time = round(get_micro_time() - $stamp, 2);
     // report on work achieved
     if ($result) {
         return 'shared/sql.php: unused bytes have been recovered (' . $time . ' seconds)' . BR;
     } else {
         return 'shared/sql.php: nothing to recover (' . $time . ' seconds)' . BR;
     }
 }
示例#3
0
文件: cron.php 项目: rair/yacs
    // do the job and provide feed-back to user
    $context['text'] = Hooks::include_scripts('hourly');
    echo $context['text'];
    // remember tick date and resulting text
    Values::set('cron.hourly', $context['text']);
    // log outcome of script execution in debug mode
    if ($context['with_debug'] == 'Y') {
        Logger::remember('cron.php: hourly processing', $context['text'], 'debug');
    }
}
//
// daily jobs
//
echo 'Checking daily jobs...' . BR;
// get date of last run
$record = Values::get_record('cron.daily', NULL_DATE);
// wait at least 1 day = 86400 seconds between runs
if (isset($record['edit_date'])) {
    $target = SQL::strtotime($record['edit_date']) + 86400;
} else {
    $target = time();
}
// request to be delayed
if ($target > time()) {
    echo 'Wait until ' . gmdate('r', $target) . ' GMT' . BR;
} else {
    Values::set('cron.daily', 'running...');
    // do the job and provide feed-back to user
    $context['text'] = Hooks::include_scripts('daily');
    echo $context['text'];
    // remember tick date and resulting text
示例#4
0
文件: mailer.php 项目: rair/yacs
 /**
  * process deferred messages
  *
  * Most often, the server has to stay below a given rate of messages,
  * for example 50 messages per hour.
  *
  * Of course, any lively community will feature bursts of activity and of
  * messages, therefore the need for a shaping mechanism.
  *
  * YACS implements a leaking bucket algorithm to take care of messages sent
  * previously:
  *
  * 1. Initially, the bucket is empty.
  *
  * 2. New messages are queued in the database, to be processed asynchronously.
  *
  * 3. On background ticks, the bucket is decremented. If the bucket becomes
  * empty, and if some messages have been queued, a couple of them are sent, and
  * the bucket is incremented accordingly.
  *
  * Bucket content is managed as value 'bucket.content' saved in the database.
  *
  * The bucket size is given by parameter $context['mail_hourly_maximum'], set
  * in the configuration panel for system parameters.
  *
  * This parameter has a default value of 50, meaning YACS will not send more
  * than 50 messages per hour.
  *
  * Background processing is either added to regular page generation or delegated
  * to an external sub-system (e.g., cron). In case of a large site, we recommend
  * to use the second solution, even if this adds additional setup steps. Your
  * choice will be recorded in the configuration panel for system parameters.
  *
  * @see control/configure.php
  *
  * The number of messages sent on each tick can go up to the bucket size if
  * background processing is external. Else it is one fourth of bucket size, to
  * minimize impact on watching surfer.
  *
  * @see cron.php
  */
 public static function tick_hook()
 {
     global $context;
     // email services have to be activated
     if (!isset($context['with_email']) || $context['with_email'] != 'Y') {
         return;
     }
     // useless if we don't have a valid database connection
     if (!$context['connection']) {
         return;
     }
     // remember start time
     $start = get_micro_time();
     // get bucket size --force it if set to 0
     if (!isset($context['mail_hourly_maximum']) || $context['mail_hourly_maximum'] < 5) {
         $context['mail_hourly_maximum'] = 50;
     }
     // get record related to last tick
     include_once $context['path_to_root'] . 'shared/values.php';
     $bucket = Values::get_record('mailer.bucket.content', 0);
     $bucket['value'] = intval($bucket['value']);
     // some content to leak
     if ($bucket['value'] > 0) {
         // date of last stamp
         if (isset($bucket['edit_date'])) {
             $stamp = SQL::strtotime($bucket['edit_date']);
         } else {
             $stamp = time() - 3600;
         }
         // leak is maximum after one hour
         $leak = intval($context['mail_hourly_maximum'] * (time() - $stamp) / 3600);
         // preserve previous value until actual leak
         if ($leak < 1) {
             return;
         }
         // actual leak
         $bucket['value'] = max(0, $bucket['value'] - $leak);
     }
     // process some messages only when bucket is empty
     $count = 0;
     if ($bucket['value'] < 1) {
         // reduced speed if on-line processing
         if (isset($_SERVER['REMOTE_ADDR'])) {
             $slice = intval($context['mail_hourly_maximum'] / 4);
         } else {
             $slice = intval($context['mail_hourly_maximum']);
         }
         // get some messages, if any
         $query = "SELECT * FROM " . SQL::table_name('messages') . " ORDER BY edit_date LIMIT 0, " . $slice;
         if ($result = SQL::query($query)) {
             // process every message
             while ($item = SQL::fetch($result)) {
                 Mailer::process($item['recipient'], $item['subject'], $item['message'], $item['headers']);
                 // purge the queue
                 $query = 'DELETE FROM ' . SQL::table_name('messages') . ' WHERE id = ' . $item['id'];
                 SQL::query($query);
                 // fill the bucket
                 $bucket['value'] += 1;
                 $count++;
                 // take care of time
                 if (!($count % 50)) {
                     // ensure enough execution time
                     Safe::set_time_limit(30);
                 }
             }
             // close connection
             Mailer::close();
         }
     }
     // remember new state of the bucket
     Values::set('mailer.bucket.content', $bucket['value']);
     // compute execution time
     $time = round(get_micro_time() - $start, 2);
     // report on work achieved
     if ($count > 1) {
         return 'shared/mailer.php: ' . $count . ' messages have been processed (' . $time . ' seconds)' . BR;
     } elseif ($count == 1) {
         return 'shared/mailer.php: 1 message has been processed (' . $time . ' seconds)' . BR;
     } elseif ($bucket['value']) {
         return 'shared/mailer.php: delaying messages (' . $time . ' seconds)' . BR;
     } else {
         return 'shared/mailer.php: nothing to do (' . $time . ' seconds)' . BR;
     }
 }