3600) { // Either cron has been running for more than an hour or the semaphore // was not reset due to a database error. watchdog('cdn_cron', 'CDN synchronization cron has been running for more than an hour and is most likely stuck.', WATCHDOG_ERROR); // Release CDN synchronization cron semaphore variable_del('cdn_cron_semaphore'); } else { // CDN synchronization cron is still running normally. watchdog('cdn_cron', 'Attempting to re-run CDN synchronization cron while it is already running.', WATCHDOG_WARNING); } } else { // Register shutdown callback register_shutdown_function('cdn_cron_cleanup'); // Lock CDN synchronization cron semaphore variable_set('cdn_cron_semaphore', time()); // Get the CDN integration configuration. $sync_method = variable_get('cdn_sync_method', 'ftp'); $sync_filters = variable_get('cdn_sync_filters', array()); $sync_method_settings = variable_get('cdn_sync_method_settings', FALSE); // Get the list of files, the unique settings for each file, and the // update settings for each file. list($files, $files_unique_settings, $files_update_setting) = _cdn_cron_get_files_to_sync($sync_filters); // Make all filenames unique. $files_unique = array_combine(array_keys($files), array_map('cdn_unique_filename', array_keys($files), $files_unique_settings)); // Store the files that are being synced in a variable, these URLs will be // used while updating files. variable_set('cdn_cron_files_syncing', $files_unique); // Update files if necessary. $files_updated = array_combine(array_keys($files), _cdn_cron_update_files_wrapper(array_keys($files), $files_update_setting)); // Perform the CDN synchronization using the configured method. Default to // the FTP method. require_once drupal_get_path('module', 'cdn') ."/sync_plugins/$sync_method.inc"; $sync_hook = $sync_method .'_cdn_cron_perform_sync'; timer_start('cdn_sync'); $stats = $sync_hook($files, $files_unique, $files_updated, _cdn_cron_init_stats(), $sync_method_settings); $timer = timer_stop('cdn_sync'); // Delete all temporary files in the cdn directory. $list = file_scan_directory(file_directory_path() .'/cdn', '.*'); array_map(create_function('$file', 'return file_delete($file->filename);'), $list); // Build message. $duration = round($timer['time'] / 1000, 1); extract($stats); $exists_kbytes = number_format($exists_bytes / 1024, 1); $uploaded_kbytes = number_format($uploaded_bytes / 1024, 1); $message = "
'. $time . $message ."\n"; ob_flush(); break; case 'console': default: print $time . $message ."\n"; break; } } } //---------------------------------------------------------------------------- // Private functions. /** * Generates the list of files that has to be sync, based on a file name * pattern, a list of ignored directories, a list of directories of which any * file will be included, and an exclude pattern. * * @param $filters * A set of filters, as specified in README.txt. * @return * An array of which the keys are filepaths and the values are filesizes. */ function _cdn_cron_get_files_to_sync($filters) { $files = array(); $files_unique_settings = array(); $files_update_settings = array(); foreach ($filters as $filter) { $newfiles = array(); foreach ($filter['paths'] as $path) { $newfiles = _cdn_cron_scan_directory($path, $filter['pattern'], $filter['ignored_dirs']); if (count($newfiles)) { // Get relative filepaths. $newfiles = array_combine(array_map('cdn_clean_filepath', array_keys($newfiles)), array_values($newfiles)); // For some unique methods, we have to store some extra parameters. $extra_params = FALSE; if ($filter['unique_method'] == 'md5 of mtimes') { $extra_params = array('path' => $path, 'files' => array_keys($newfiles)); } // Store the unique settings for each file. $unique_settings = array_fill( 0, count($newfiles), array( 'method' => $filter['unique_method'], 'where' => $filter['unique'], 'params' => $extra_params ) ); $files_unique_settings += array_combine(array_keys($newfiles), $unique_settings); // If desired, update the URLs that are embedded in the files. $update_settings = array_fill(0, count($newfiles), (isset($filter['update_urls_in_files']) && $filter['update_urls_in_files'] === TRUE) ? TRUE : FALSE); $files_update_settings += array_combine(array_keys($newfiles), $update_settings); $files += $newfiles; } } } return array($files, $files_unique_settings, $files_update_settings); } /** * Stolen from Drupal core. Simplified for CDN cron usage. Parameter order is * unchanged, so you can look at the official file_scan_directory() * documentation but think away the last parameters. * * @see file_scan_directory */ function _cdn_cron_scan_directory($dir, $pattern, $ignored_dirs = array('CVS')) { $files = array(); if (is_dir($dir) && $handle = opendir($dir)) { while ($file = readdir($handle)) { if (!in_array($file, $ignored_dirs) && $file[0] != '.') { if (is_dir("$dir/$file")) { $files += _cdn_cron_scan_directory("$dir/$file", $pattern, $ignored_dirs); } elseif (ereg($pattern, $file)) { $files["$dir/$file"] = filesize("$dir/$file"); } } } closedir($handle); } return $files; } /** * Initializes the stats array. * * @return * The stats array. */ function _cdn_cron_init_stats() { $stats = array( 'deletes' => 0, 'exists' => 0, 'exists_bytes' => 0, 'uploads' => 0, 'uploads_failed' => 0, 'uploaded_bytes' => 0, ); return $stats; } /** * Wrapper of cdn_update_file() for use only within cron mode. This function * simply calls cdn_update_file(), but also sets the $files_synced parameter. * @see cdn_update_file() * * @param $files * The list of files to be synchronized. * @param $update_setting * The update setting for each file. The key is the file path. * @return * The updated $files array, as updated by cdn_update_file(). */ function _cdn_cron_update_files_wrapper($files, $update_setting) { static $files_syncing = array(); if (empty($files_syncing)) { $files_syncing = variable_get('cdn_cron_files_syncing', array()); } $files_updated = array(); foreach ($files as $file) { if ($update_setting[$file]) { $files_updated[] = cdn_update_file($file, $files_syncing); } else { $files_updated[] = $file; } } return $files_updated; }