代码拉取完成,页面将自动刷新
#!/usr/bin/env php
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2024 The Cacti Group |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License |
| as published by the Free Software Foundation; either version 2 |
| of the License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/
if (function_exists('pcntl_async_signals')) {
pcntl_async_signals(true);
} else {
declare(ticks = 100);
}
ini_set('output_buffering', 'Off');
require(__DIR__ . '/include/cli_check.php');
require_once(CACTI_PATH_LIBRARY . '/poller.php');
require_once(CACTI_PATH_LIBRARY . '/boost.php');
require_once(CACTI_PATH_LIBRARY . '/dsstats.php');
require_once(CACTI_PATH_LIBRARY . '/rrdcheck.php');
require_once(CACTI_PATH_LIBRARY . '/rrd.php');
/* get the boost polling cycle */
$max_run_duration = read_config_option('boost_rrd_update_max_runtime');
/* process calling arguments */
$parms = $_SERVER['argv'];
array_shift($parms);
$debug = false;
$forcerun = false;
$verbose = false;
$child = false;
/* for releasing lock on SIGNAL */
$current_lock = false;
global $child, $next_run_time, $archive_table, $current_lock;
if (cacti_sizeof($parms)) {
foreach ($parms as $parameter) {
if (strpos($parameter, '=')) {
list($arg, $value) = explode('=', $parameter);
} else {
$arg = $parameter;
$value = '';
}
switch ($arg) {
case '--child':
$child = $value;
break;
case '-d':
case '--debug':
$debug = true;
break;
case '-f':
case '--force':
$forcerun = true;
cacti_log('WARNING: Boost Poller forced by command line.', false, 'BOOST');
break;
case '--verbose':
$verbose = true;
break;
case '--version':
case '-V':
case '-v':
display_version();
exit;
case '--help':
case '-H':
case '-h':
display_help();
exit;
default:
print 'ERROR: Invalid Parameter ' . $parameter . "\n\n";
display_help();
exit;
}
}
}
/* install signal handlers for UNIX only */
if (function_exists('pcntl_signal')) {
pcntl_signal(SIGTERM, 'sig_handler');
pcntl_signal(SIGINT, 'sig_handler');
}
/* take time and log performance data */
$start = microtime(true);
$start_time = time();
$rrd_updates = -1;
/* let's give this script lot of time to run for ever */
ini_set('max_execution_time', '0');
boost_memory_limit();
if ($child == false) {
$current_time = time();
/* find out if it's time to collect device information
* support both old and new formats.
*/
$boost_last_run_time = read_config_option('boost_last_run_time') ?? ($current_time - 3600);
if (!is_numeric($boost_last_run_time)) {
$last_run_time = strtotime($boost_last_run_time);
} elseif (empty($boost_last_run_time)) {
$last_run_time = time() - 3600;
} else {
$last_run_time = $boost_last_run_time;
}
$boost_next_run_time = read_config_option('boost_next_run_time');
if (!empty($boost_next_run_time) && !is_numeric($boost_next_run_time)) {
$next_run_time = strtotime($boost_next_run_time);
} elseif (empty($boost_next_run_time)) {
$next_run_time = time() + 3600;
} else {
$next_run_time = $boost_next_run_time;
}
$seconds_offset = read_config_option('boost_rrd_update_interval') * 60;
$run_now = boost_time_to_run($forcerun, $current_time, $last_run_time, $next_run_time);
if ($run_now) {
/**
* Check to see if the boost log is enabled and the file exists and
* is writable. If it does not exist, create an empty file.
*/
$debug_log = read_config_option('path_boost_log');
if ($debug_log != '') {
if (!file_exists($debug_log)) {
if (is_writable(dirname($debug_log))) {
touch($debug_log);
} else {
cacti_log(sprintf('WARNING: Boost Debug Log %s is not writable. Change the path to a writable location', $debug_log), false, 'BOOST');
}
}
}
/**
* Check to see if there are any poller items to process and if not
* exit cleanly
*/
$poller_items = db_fetch_row('SELECT * FROM poller_output_boost LIMIT 1');
if (!cacti_sizeof($poller_items)) {
exit(0);
}
/* we will warn if the process is taking extra long */
if (!register_process_start('boost', 'master', $config['poller_id'], read_config_option('boost_rrd_update_max_runtime') * 3)) {
exit(0);
}
boost_debug('Time to Run Boost, Force Run is ' . ($forcerun ? 'true!':'false.'));
/* Check if processes are running and kill them */
boost_kill_running_processes();
/* Truncate the rrd_update_counter table */
db_execute('TRUNCATE TABLE poller_output_boost_processes');
/* Prepare the boost distribution */
$continue = boost_prepare_process_table();
/* Launch the boost children */
if ($continue) {
/* Allow mysql to flush the rename transaction */
sleep(7);
boost_launch_children();
/* Wait for all processes to continue */
while ($running = boost_processes_running()) {
boost_debug(sprintf('%s Processes Running, Sleeping for 2 seconds.', $running));
sleep(2);
}
/* tell the main poller that we are done */
set_config_option('boost_poller_status', 'complete - end time:' . date('Y-m-d H:i:s'));
/* Finish processing post */
set_config_option('boost_last_run_time', $current_time);
/* output all the rrd data to the rrd files */
$rrd_updates = db_fetch_cell('SELECT SUM(status) FROM poller_output_boost_processes');
if ($rrd_updates > 0) {
boost_log_statistics($rrd_updates);
$next_run_time = $current_time + $seconds_offset;
} elseif ($rrd_updates == -1) {
boost_log_statistics(0);
$next_run_time = $current_time + $seconds_offset;
} else { /* rollback last run time */
set_config_option('boost_last_run_time', $last_run_time);
}
if ($rrd_updates > 0) {
/* cleanup - remove empty arch tables*/
$tables = db_fetch_assoc("SELECT table_name AS name
FROM information_schema.tables
WHERE TABLE_SCHEMA = SCHEMA()
AND TABLE_NAME LIKE 'poller_output_boost_arch_%'");
if (cacti_sizeof($tables)) {
foreach ($tables as $table) {
db_execute('DROP TABLE IF EXISTS ' . $table['name']);
}
}
dsstats_boost_bottom();
rrdcheck_boost_bottom();
api_plugin_hook('boost_poller_bottom');
}
}
unregister_process('boost', 'master', $config['poller_id'], getmypid());
/* log the end time of the process */
set_config_option('boost_last_end_time', time());
} else {
set_config_option('boost_poller_status', 'complete');
}
/* store the next run time so that people understand */
if ($rrd_updates > 0 || $rrd_updates == -1) {
if (empty($next_run_time)) {
$next_run_time = time() + $seconds_offset;
}
set_config_option('boost_next_run_time', $next_run_time);
}
boost_purge_cached_png_files($forcerun);
exit(0);
} else {
/* we will warn if the process is taking extra long */
if (!register_process_start('boost', 'child', $child, read_config_option('boost_rrd_update_max_runtime') * 3)) {
exit(0);
}
/* output all the rrd data to the rrd files */
$rrd_updates = boost_output_rrd_data($child);
db_execute_prepared('INSERT INTO poller_output_boost_processes
(status) VALUES (?)',
array($rrd_updates));
boost_log_child_statistics($rrd_updates, $child);
unregister_process('boost', 'child', $child);
exit(0);
}
function sig_handler($signo) {
global $child, $config, $current_lock;
$rrdtool_version = read_config_option('rrdtool_version');
switch ($signo) {
case SIGTERM:
case SIGINT:
cacti_log('WARNING: Boost Poller terminated by user', false, 'BOOST');
/* tell the main poller that we are done */
set_config_option('boost_poller_status', 'terminated - end time:' . date('Y-m-d H:i:s'));
if ($child) {
unregister_process('boost', 'child', $child, getmypid());
} else {
unregister_process('boost', 'master', $config['poller_id'], getmypid());
}
exit;
break;
default:
/* ignore all other signals */
}
if (cacti_version_compare(get_rrdtool_version(), '1.5', '<')) {
if ($current_lock !== false && $child) {
db_execute("SELECT RELEASE_LOCK('boost.single_ds.$current_lock')");
} elseif (!$child) {
db_execute("SELECT RELEASE_ALL_LOCKS()");
}
}
}
function boost_kill_running_processes() {
$processes = db_fetch_assoc_prepared('SELECT *
FROM processes
WHERE tasktype = "boost"
AND pid != ?',
array(getmypid()));
if (cacti_sizeof($processes)) {
foreach ($processes as $p) {
cacti_log(sprintf('WARNING: Killing Boost %s PID %d due to another boost process starting.', ucfirst($p['taskname']), $p['pid']), false, 'BOOST');
posix_kill($p['pid'], SIGTERM);
unregister_process($p['tasktype'], $p['taskname'], $p['taskid'], $p['pid']);
}
}
}
function boost_processes_running() {
$running = db_fetch_cell('SELECT COUNT(*)
FROM processes
WHERE tasktype = "boost"
AND taskname = "child"');
return $running;
}
function boost_prepare_process_table() {
global $start_time, $archive_table, $max_run_duration, $config, $database_default, $debug, $get_memory, $memory_used;
boost_debug('Parallel Process Setup Begins.');
$boost_poller_status = read_config_option('boost_poller_status');
if (!$boost_poller_status) {
$boost_poller_status = 'not started';
}
/* detect a process that has overrun it's warning time */
if (substr_count($boost_poller_status, 'running')) {
$status_array = explode(':', $boost_poller_status);
if (!empty($status_array[1])) {
$previous_start_time = strtotime($status_array[1]);
/* if the runtime was exceeded, allow the next process to run */
if ($previous_start_time + $max_run_duration < $start_time) {
cacti_log('WARNING: Detected Poller Boost Overrun, Possible Boost Poller Crash', false, 'BOOST SVR');
admin_email(__('Cacti System Warning'), __('WARNING: Detected Poller Boost Overrun, Possible Boost Poller Crash', 'BOOST SVR'));
}
}
}
/* if the poller is not running, or has never run, start */
/* mark the boost server as running */
set_config_option('boost_poller_status', 'running - start time:' . date('Y-m-d H:i:s'));
$delayed_inserts = db_fetch_row("SHOW STATUS LIKE 'Not_flushed_delayed_rows'");
while (cacti_sizeof($delayed_inserts) && $delayed_inserts['Value']) {
cacti_log('BOOST WAIT: Waiting 1s for delayed inserts are made' , true, 'SYSTEM');
usleep(1000000);
$delayed_inserts = db_fetch_row("SHOW STATUS LIKE 'Not_flushed_delayed_rows'");
}
$time = time();
/* split poller_output_boost */
$archive_table = 'poller_output_boost_arch_' . $time;
$interim_table = 'poller_output_boost_' . $time;
db_execute("CREATE TABLE $interim_table LIKE poller_output_boost");
db_execute("RENAME TABLE poller_output_boost TO $archive_table, $interim_table TO poller_output_boost");
db_execute("ANALYZE TABLE $archive_table");
$arch_tables = boost_get_arch_table_names($archive_table);
if (!cacti_sizeof($arch_tables)) {
cacti_log('ERROR: Failed to retrieve archive table name - check poller', false, 'BOOST');
return false;
}
$total_rows = 0;
foreach ($arch_tables as $table) {
$total_rows += db_fetch_cell_prepared('SELECT TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = SCHEMA()
AND TABLE_NAME = ?',
array($table));
}
if ($total_rows == 0) {
boost_debug('ERROR: Failed to retrieve any rows from archive tables');
cacti_log('ERROR: Failed to retrieve any rows from archive tables', false, 'BOOST');
return false;
}
db_execute('CREATE TABLE IF NOT EXISTS poller_output_boost_local_data_ids (
local_data_id int unsigned default "0",
process_handler int unsigned default "0",
PRIMARY KEY (local_data_id),
INDEX process_handler(process_handler))
ENGINE=InnoDB');
db_execute('TRUNCATE poller_output_boost_local_data_ids');
foreach ($arch_tables as $table) {
db_execute("INSERT IGNORE INTO poller_output_boost_local_data_ids
(local_data_id)
SELECT DISTINCT local_data_id
FROM $table");
}
$data_ids = db_fetch_cell('SELECT
COUNT(local_data_id)
FROM poller_output_boost_local_data_ids');
$processes = read_config_option('boost_parallel');
boost_debug("Data Sources:$data_ids, Concurrent Processes:$processes");
$data_ids_per_process = ceil($data_ids / $processes);
$count = 1;
while ($count <= $processes) {
db_execute_prepared('UPDATE poller_output_boost_local_data_ids
SET process_handler = ?
WHERE process_handler = 0
LIMIT ' . $data_ids_per_process,
array($count));
$count++;
}
boost_debug('Parallel Process Setup Complete. Ready to spawn children.');
return true;
}
function boost_launch_children() {
global $config, $debug;
$processes = read_config_option('boost_parallel');
if (empty($processes)) {
$processes = 1;
}
$php_binary = read_config_option('path_php_binary');
$boost_log = read_config_option('path_boost_log');
$redirect_args = '';
if ($boost_log != '') {
if (!is_writable($boost_log)) {
boost_debug("WARNING: Boost log '$boost_log' is not writable!");
cacti_log("WARNING: Boost log '$boost_log' is not writable!", false, 'BOOST');
} else {
$redirect_args = '>> ' . $boost_log;
}
}
boost_debug("About to launch $processes processes.");
for ($i = 1; $i <= $processes; $i++) {
boost_debug('Launching Boost Process Number ' . $i);
cacti_log('NOTE: Launching Boost Process Number ' . $i, false, 'BOOST', POLLER_VERBOSITY_MEDIUM);
exec_background($php_binary, CACTI_PATH_BASE . '/poller_boost.php --child=' . $i . ($debug ? ' --debug':''), $redirect_args);
}
sleep(2);
}
function boost_time_to_run($forcerun, $current_time, $last_run_time, $next_run_time) {
$run_now = false;
boost_debug('Checking if Boost is ready to run.');
if ((read_config_option('boost_rrd_update_enable') == 'on') || $forcerun) {
/* turn on the system level updates as that is what dictates "on/off" */
if (!$forcerun && read_config_option('boost_rrd_update_system_enable') != 'on') {
set_config_option('boost_rrd_update_system_enable', 'on');
}
$seconds_offset = read_config_option('boost_rrd_update_interval') * 60;
/* Initialize seconds offset, if not set to 2 hours */
if (empty($seconds_offset)) {
$seconds_offset = 120;
set_config_option('boost_rrd_update_interval', 120);
}
boost_debug('Last Runtime was ' . date('Y-m-d H:i:s', $last_run_time) . " ($last_run_time).");
boost_debug('Next Runtime is ' . date('Y-m-d H:i:s', $next_run_time) . " ($next_run_time).");
/* determine the next start time */
if (empty($last_run_time)) {
/* since the poller has never run before, let's fake it out */
$next_run_time = $current_time + $seconds_offset;
set_config_option('boost_last_run_time', $current_time);
set_config_option('boost_next_run_time', $next_run_time);
$run_now = false;
} else {
$next_run_time = $last_run_time + $seconds_offset;
if ($current_time >= $next_run_time) {
$run_now = true;
set_config_option('boost_next_run_time', $next_run_time);
}
}
/* determine if you must output boost table now */
$current_records = boost_get_total_rows();
$max_records = read_config_option('boost_rrd_update_max_records');
boost_debug('Records Found:' . $current_records . ', Max Threshold:' . $max_records . '.');
if ($current_records > $max_records) {
$run_now = true;
set_config_option('boost_next_run_time', $next_run_time);
}
if ($forcerun) {
$run_now = true;
set_config_option('boost_next_run_time', $next_run_time);
}
} else {
$pollers = db_fetch_cell('SELECT COUNT(*) FROM pollers WHERE disabled = ""');
if ($pollers > 1) {
boost_debug('Someone attempted to disable boost through there are multiple Data Collectors Defined!');
set_config_option('boost_rrd_update_system_enable', 'on');
} elseif (read_config_option('boost_rrd_update_system_enable') == 'on') {
/* turn off the system level updates, we want to disable */
set_config_option('boost_rrd_update_system_enable', '');
}
/* we are force to run until boost is finished */
$rows = boost_get_total_rows();
if ($rows > 0) {
$run_now = true;
}
}
return $run_now;
}
function boost_output_rrd_data($child) {
global $start, $archive_table, $max_run_duration, $config, $database_default, $debug, $get_memory, $memory_used;
$rrd_updates = 0;
$rrdtool_pipe = rrd_init();
$runtime_exceeded = false;
/* let's set and track memory usage will we */
if (!function_exists('memory_get_peak_usage')) {
$get_memory = true;
$memory_used = memory_get_usage();
} else {
$get_memory = false;
}
boost_debug("Processing RRRtool Output for Boost Process $child");
$arch_tables = boost_get_arch_table_names($archive_table);
if (!cacti_sizeof($arch_tables)) {
cacti_log('ERROR: Failed to retrieve archive table name', false, 'BOOST');
return false;
}
$total_rows = 0;
foreach ($arch_tables as $table) {
$total_rows += db_fetch_cell_prepared("SELECT COUNT(at.local_data_id)
FROM $table AS at
INNER JOIN poller_output_boost_local_data_ids AS bpt
ON at.local_data_id = bpt.local_data_id
AND bpt.process_handler = ?",
array($child));
}
if ($total_rows == 0) {
return false;
}
boost_debug("Processes:$child, TotalRows:$total_rows");
$max_per_select = read_config_option('boost_rrd_update_max_records_per_select');
$data_ids = db_fetch_cell_prepared('SELECT
COUNT(local_data_id)
FROM poller_output_boost_local_data_ids
WHERE process_handler = ?',
array($child));
$passes = ceil($total_rows / $max_per_select);
$ids_per_pass = ceil($data_ids / $passes);
$curpass = 1;
while ($data_ids > 0) {
boost_debug("Processing $curpass of $passes for Boost Process $child");
$last_id = db_fetch_cell_prepared("SELECT MAX(local_data_id)
FROM (
SELECT local_data_id
FROM poller_output_boost_local_data_ids
WHERE process_handler = ?
ORDER BY local_data_id ASC
LIMIT $ids_per_pass
) AS result",
array($child));
if (empty($last_id)) {
break;
}
boost_process_local_data_ids($last_id, $child, $rrdtool_pipe);
$curpass++;
$data_ids = db_fetch_cell_prepared('SELECT *
FROM poller_output_boost_local_data_ids
WHERE process_handler = ?',
array($child));
if (((time() - $start) > $max_run_duration) && (!$runtime_exceeded)) {
cacti_log('WARNING: RRD On Demand Updater Exceeded Runtime Limits. Continuing to Process!!!', false, 'BOOST');
$runtime_exceeded = true;
}
}
boost_debug("Processing Complete for Boost Process $child. It took $curpass passed to complete.");
/* log memory usage */
if (function_exists('memory_get_peak_usage')) {
set_config_option('boost_peak_memory_' . $child, memory_get_peak_usage());
} else {
set_config_option('boost_peak_memory_' . $child, $memory_used);
}
rrd_close($rrdtool_pipe);
return $total_rows;
}
/* boost_process_local_data_ids - grabs data from the 'poller_output' table and feeds the *completed*
results to RRDTool for processing
@arg $last_id - the last id to process
@arg $child - the current process
@arg $rrdtool_pipe - the socket that has been opened for the RRDtool operation */
function boost_process_local_data_ids($last_id, $child, $rrdtool_pipe) {
global $config, $archive_table, $boost_sock, $boost_timeout, $debug, $get_memory, $memory_used, $current_lock;
/* cache this call as it takes time */
static $archive_tables = false;
static $rrdtool_version = null;
include_once(CACTI_PATH_LIBRARY . '/rrd.php');
/* suppress warnings */
if (defined('E_DEPRECATED')) {
error_reporting(E_ALL ^ E_DEPRECATED);
} else {
error_reporting(E_ALL);
}
/* gather, repair if required and cache the rrdtool version */
if ($rrdtool_version === null) {
$rrdtool_ins_version = get_installed_rrdtool_version();
$rrdtool_version = get_rrdtool_version();
if ($rrdtool_ins_version != $rrdtool_version) {
boost_debug('NOTE: Updating Stored RRDtool version to installed version ' . $rrdtool_ins_version);
cacti_log('NOTE: Updating Stored RRDtool version to installed version ' . $rrdtool_ins_version, false, 'BOOST');
set_config_option('rrdtool_version', $rrdtool_ins_version);
$rrdtool_version = $rrdtool_ins_version;
}
}
/* install the boost error handler */
set_error_handler('boost_error_handler');
/* load system variables needed */
$upd_string_len = read_config_option('boost_rrd_update_string_length');
$rrd_update_interval = read_config_option('boost_rrd_update_interval');
$data_ids_to_get = read_config_option('boost_rrd_update_max_records_per_select');
if ($archive_tables === false) {
$archive_tables = boost_get_arch_table_names($archive_table);
}
if ($archive_tables === false) {
boost_debug('Failed to determine archive tables');
cacti_log('Failed to determine archive tables', false, 'BOOST');
return 0;
}
if (!cacti_sizeof($rrd_field_names)) {
$rrd_field_names = array_rekey(
db_fetch_assoc_prepared('SELECT ' . SQL_NO_CACHE . '
CONCAT(data_template_id, "_", data_name) AS keyname, data_source_names AS data_source_name
FROM poller_data_template_field_mappings'),
'keyname', array('data_source_name'));
}
$query_string = 'SELECT * FROM (';
$query_string_suffix = 'ORDER BY local_data_id ASC, timestamp ASC, rrd_name ASC';
$sub_query_string = '';
foreach ($archive_tables as $table) {
$sub_query_string .= ($sub_query_string != '' ? ' UNION ALL ':'') .
" SELECT $table.local_data_id, dl.data_template_id, UNIX_TIMESTAMP(time) AS timestamp, rrd_name, output
FROM $table
INNER JOIN poller_output_boost_local_data_ids AS bpt
ON $table.local_data_id = bpt.local_data_id
INNER JOIN data_local AS dl
ON $table.local_data_id = dl.id
WHERE bpt.local_data_id <= $last_id
AND bpt.process_handler = $child";
}
$query_string = $query_string . $sub_query_string . ') t ' . $query_string_suffix;
boost_timer('get_records', BOOST_TIMER_START);
$results = db_fetch_assoc($query_string);
boost_timer('get_records', BOOST_TIMER_END);
/* log memory */
if ($get_memory) {
$cur_memory = memory_get_usage();
if ($cur_memory > $memory_used) {
$memory_used = $cur_memory;
}
}
if (cacti_sizeof($results)) {
/* create an array keyed off of each .rrd file */
$local_data_id = -1;
$time = -1;
$buflen = 0;
$outarray = array();
$locked = false;
$last_update = -1;
$reset_template = true;
$unused_data_source_names = array();
/* we are going to blow away all record if ok */
$vals_in_buffer = 0;
boost_timer('results_cycle', BOOST_TIMER_START);
/* go through each poller_output_boost entries and process */
foreach ($results as $item) {
if ($local_data_id == $item['local_data_id'] && cacti_sizeof($unused_data_source_names) && isset($unused_data_source_names[$item['rrd_name']])) {
continue;
}
$item['timestamp'] = trim($item['timestamp']);
if (!$locked) {
/* acquire lock in order to prevent race conditions, only a problem pre-rrdtool 1.5 */
if (cacti_version_compare($rrdtool_version, '1.5', '<')) {
while (!db_fetch_cell("SELECT GET_LOCK('boost.single_ds." . $item['local_data_id'] . "', 1)")) {
usleep(50000);
}
}
$current_lock = $item['local_data_id'];
$locked = true;
}
/**
* if the local_data_id changes, we need to flush the buffer
* and discover the template for the next RRDfile.
*/
if ($local_data_id != $item['local_data_id']) {
$unused_data_source_names = array_rekey(
db_fetch_assoc_prepared('SELECT DISTINCT dtr.data_source_name, dtr.data_source_name
FROM data_template_rrd AS dtr
LEFT JOIN graph_templates_item AS gti
ON dtr.id = gti.task_item_id
WHERE dtr.local_data_id = ?
AND gti.task_item_id IS NULL',
array($item['local_data_id'])),
'data_source_name', 'data_source_name'
);
if (cacti_sizeof($unused_data_source_names) && isset($unused_data_source_names[$item['rrd_name']])) {
continue;
}
$reset_template = true;
if (isset($nt_rrd_field_names)) {
unset($nt_rrd_field_names);
}
/* release the previous lock */
if (cacti_version_compare($rrdtool_version, '1.5', '<')) {
db_execute("SELECT RELEASE_LOCK('boost.single_ds.$local_data_id')");
}
$current_lock = false;
/* acquire lock in order to prevent race conditions, only a problem pre-rrdtool 1.5 */
if (cacti_version_compare($rrdtool_version, '1.5', '<')) {
while (!db_fetch_cell("SELECT GET_LOCK('boost.single_ds." . $item['local_data_id'] . "', 1)")) {
usleep(50000);
}
}
$current_lock = $item['local_data_id'];
/* update the rrd for the previous local_data_id */
if ($vals_in_buffer) {
/* place the latest update at the end of the output array */
$outarray[] = $tv_tmpl;
/* new process output function */
boost_process_output($local_data_id, $outarray, $rrd_path, $rrd_tmplp, $rrdtool_pipe);
$buflen = 0;
$vals_in_buffer = 0;
$outarray = array();
}
/* reset the rrd file path and templates, assume non multi output */
boost_timer('rrd_filename_and_template', BOOST_TIMER_START);
$rrd_data = boost_get_rrd_filename_and_template($item['local_data_id']);
$rrd_tmpl = $rrd_data['rrd_template'];
$template_len = strlen($rrd_tmpl);
/**
* take the template and turn into an associative array of
* data source names with a default of 'U' for each value
* and creating the first value to include the timestamp.
* We will use this for missing data detection.
*/
$rrd_tmplp = array_fill_keys(array_values(explode(':', $rrd_tmpl)), 'U');
$rrd_tmplpts = array('timestamp' => '') + $rrd_tmplp;
$rrd_path = $rrd_data['rrd_path'];
boost_timer('rrd_filename_and_template', BOOST_TIMER_END);
if (cacti_version_compare(get_rrdtool_version(), '1.5', '<')) {
boost_timer('rrd_lastupdate', BOOST_TIMER_START);
$last_update = boost_rrdtool_get_last_update_time($rrd_path, $rrdtool_pipe);
boost_timer('rrd_lastupdate', BOOST_TIMER_END);
} else {
boost_timer('rrd_lastupdate', BOOST_TIMER_START);
$last_update = 0;
boost_timer('rrd_lastupdate', BOOST_TIMER_END);
}
$local_data_id = $item['local_data_id'];
$time = $item['timestamp'];
if ($time > $last_update || cacti_version_compare(get_rrdtool_version(), '1.5', '>=')) {
$buflen += strlen(' ' . $time);
}
$tv_tmpl = $rrd_tmplpts;
} else {
$reset_template = false;
}
/* don't generate error messages if the RRD has already been updated */
if ($time < $last_update && cacti_version_compare(get_rrdtool_version(), '1.5', '<')) {
cacti_log("WARNING: Stale Poller Data Found! Item Time:'" . $time . "', RRD Time:'" . $last_update . "' Ignoring Value!", false, 'BOOST', POLLER_VERBOSITY_HIGH);
$value = 'DNP';
} else {
$value = trim($item['output']);
}
if ($time != $item['timestamp']) {
if ($vals_in_buffer > 0) {
/* place the latest update at the end of the output array */
$outarray[] = $tv_tmpl;
}
if ($buflen > $upd_string_len) {
/* new process output function */
boost_process_output($local_data_id, $outarray, $rrd_path, $rrd_tmplp, $rrdtool_pipe);
$buflen = 0;
$vals_in_buffer = 0;
$outarray = array();
}
$time = $item['timestamp'];
$tv_tmpl = $rrd_tmplpts;
}
if (empty($tv_tmpl['timestamp']) && $value != 'DNP') {
$tv_tmpl['timestamp'] = $item['timestamp'];
$buflen += strlen($item['timestamp']) + 1;
}
/* single one value output */
if (strpos($value, 'DNP') !== false) {
/* continue, bad time */
} elseif ((is_numeric($value)) || ($value == 'U' && $item['rrd_name'] !== '')) {
$tv_tmpl[$item['rrd_name']] = $value;
$buflen += strlen(':' . $value);
$vals_in_buffer++;
} elseif ((function_exists('is_hexadecimal')) && (is_hexadecimal($value))) {
$tval = hexdec($value);
$tv_tmpl[$item['rrd_name']] = $tval;
$buflen += strlen(':' . $tval);
$vals_in_buffer++;
} elseif (strpos($value, ':') !== false) {
/* break out multiple value output to an array */
$values = preg_split('/\s+/', $value);
if (!$reset_template) {
$rrd_tmpl = '';
} else {
if ($item['data_template_id'] > 0) {
$unused_data_source_names = array_rekey(
db_fetch_assoc_prepared('SELECT DISTINCT dtr.data_source_name, dtr.data_source_name
FROM data_template_rrd AS dtr
LEFT JOIN graph_templates_item AS gti
ON dtr.id = gti.task_item_id
WHERE dtr.local_data_id = ? AND gti.task_item_id IS NULL',
array($item['local_data_id'])),
'data_source_name', 'data_source_name'
);
} else {
$unused_data_source_names = array();
}
}
foreach($values as $value) {
$matches = explode(':', $value);
if (cacti_sizeof($matches) == 2) {
if (isset($rrd_field_names[$item['data_template_id'] . '_' . $matches[0]])) {
$field = $rrd_field_names[$item['data_template_id'] . '_' . $matches[0]]['data_source_name'];
if (cacti_sizeof($unused_data_source_names) && isset($unused_data_source_names[$field])) {
continue;
}
if ($reset_template) {
cacti_log("Parsed MULTI output field '" . $matches[0] . ':' . $field . "' [map " . $matches[0] . '->' . $field . ']', false, 'BOOST', ($debug ? POLLER_VERBOSITY_NONE:POLLER_VERBOSITY_HIGH));
if (trim(read_config_option('path_boost_log')) != '') {
print "DEBUG: Parsed MULTI output field in path 1 '" . $matches[0] . "' [map " . $field . '->' . $field . ']' . PHP_EOL;
}
$rrd_tmpl .= ($rrd_tmpl != '' ? ':':'') . $field;
}
if (is_numeric($matches[1]) || ($matches[1] == 'U')) {
$tv_tmpl[$field] = $matches[1];
$buflen += strlen(':' . $matches[1]);
} elseif ((function_exists('is_hexadecimal')) && (is_hexadecimal($matches[1]))) {
$tval = hexdec($matches[1]);
$tv_tmpl[$field] = $tval;
$buflen += strlen(':' . $tval);
} else {
$tv_tmpl[$field] = 'U';
$buflen += 2;
}
$vals_in_buffer++;
} else {
/**
* We have to check for Non-Templated Data Source first as they may not include
* a graph. So, for that case, we need the RRDfile to include all data sources
*/
if ($item['data_template_id'] > 0) {
$nt_rrd_field_names = array_rekey(
db_fetch_assoc_prepared('SELECT DISTINCT dtr.data_source_name, dif.data_name
FROM graph_templates_item AS gti
INNER JOIN data_template_rrd AS dtr
ON gti.task_item_id = dtr.id
INNER JOIN data_input_fields AS dif
ON dtr.data_input_field_id=dif.id
WHERE dtr.local_data_id = ?',
array($item['local_data_id'])),
'data_name', 'data_source_name'
);
} else {
$nt_rrd_field_names = array_rekey(
db_fetch_assoc_prepared('SELECT DISTINCT dtr.data_source_name, dif.data_name
FROM data_template_rrd AS dtr
INNER JOIN data_input_fields AS dif
ON dtr.data_input_field_id=dif.id
WHERE dtr.local_data_id = ?',
array($item['local_data_id'])),
'data_name', 'data_source_name'
);
}
if (cacti_sizeof($nt_rrd_field_names)) {
if (isset($nt_rrd_field_names[$matches[0]])) {
$field = $nt_rrd_field_names[$matches[0]];
if (cacti_sizeof($unused_data_source_names) && isset($unused_data_source_names[$field])) {
continue;
}
if ($reset_template) {
cacti_log("Parsed MULTI output field in path 2 '" . $matches[0] . ':' . $matches[1] . "' [map " . $matches[0] . '->' . $field . ']', false, 'BOOST', ($debug ? POLLER_VERBOSITY_NONE:POLLER_VERBOSITY_HIGH));
if (trim(read_config_option('path_boost_log')) != '') {
print "DEBUG: Parsed MULTI output field '" . $matches[0] . "' [map " . $matches[1] . '->' . $field . ']' . PHP_EOL;
}
$rrd_tmpl .= ($rrd_tmpl != '' ? ':':'') . $field;
}
if (is_numeric($matches[1]) || ($matches[1] == 'U')) {
$tv_tmpl[$field] = $matches[1];
$buflen += strlen(':' . $matches[1]);
} elseif ((function_exists('is_hexadecimal')) && (is_hexadecimal($matches[1]))) {
$tval = hexdec($matches[1]);
$tv_tmpl[$field] = $tval;
$buflen += strlen(':' . $tval);
} else {
$tv_tmpl[$field] = 'U';
$buflen += 2;
}
if (trim(read_config_option('path_boost_log')) != '') {
print "DEBUG: Parsed MULTI output field '" . $matches[0] . "' [map " . $matches[1] . '->' . $nt_rrd_field_names[$matches[1]] . ']' . PHP_EOL;
}
}
$vals_in_buffer++;
}
}
}
}
} else {
if ($reset_template) {
if ($item['data_template_id'] > 0) {
$unused_data_source_names = array_rekey(
db_fetch_assoc_prepared('SELECT DISTINCT dtr.data_source_name, dtr.data_source_name
FROM data_template_rrd AS dtr
LEFT JOIN graph_templates_item AS gti
ON dtr.id = gti.task_item_id
WHERE dtr.local_data_id = ? AND gti.task_item_id IS NULL',
array($item['local_data_id'])),
'data_source_name', 'data_source_name'
);
$nt_rrd_field_names = array_rekey(
db_fetch_assoc_prepared('SELECT DISTINCT dtr.data_source_name, dif.data_name
FROM graph_templates_item AS gti
INNER JOIN data_template_rrd AS dtr
ON gti.task_item_id = dtr.id
INNER JOIN data_input_fields AS dif
ON dtr.data_input_field_id=dif.id
WHERE dtr.local_data_id = ?',
array($item['local_data_id'])),
'data_name', 'data_source_name'
);
} else {
$unused_data_source_names = array_rekey(
db_fetch_assoc_prepared('SELECT DISTINCT dtr.data_source_name, dtr.data_source_name
FROM data_template_rrd AS dtr
WHERE dtr.local_data_id = ? AND gti.task_item_id IS NULL',
array($item['local_data_id'])),
'data_source_name', 'data_source_name'
);
$nt_rrd_field_names = array_rekey(
db_fetch_assoc_prepared('SELECT DISTINCT dtr.data_source_name, dif.data_name
FROM data_template_rrd AS dtr
INNER JOIN data_input_fields AS dif
ON dtr.data_input_field_id=dif.id
WHERE dtr.local_data_id = ?',
array($item['local_data_id'])),
'data_name', 'data_source_name'
);
}
}
$expected = '';
if (cacti_sizeof($nt_rrd_field_names)) {
foreach($nt_rrd_field_names as $field) {
if (cacti_sizeof($unused_data_source_names) && isset($unused_data_source_names[$field])) {
continue;
}
$expected .= ($expected != '' ? ' ':'') . "$field:value";
if ($reset_template) {
$rrd_tmpl .= ($rrd_tmpl != '' ? ':':'') . $field;
}
$tv_tmpl[$field] = 'U';
$buflen += 2;
}
}
cacti_log(sprintf('WARNING: Invalid output! MULTI DS[%d] Encountered [%s] Expected[%s]', $item['local_data_id'], $value, $expected), false, 'POLLER');
}
}
/* process the last rrdupdate if applicable */
if ($vals_in_buffer) {
/* place the latest update at the end of the output array */
$outarray[] = $tv_tmpl;
boost_process_output($local_data_id, $outarray, $rrd_path, $rrd_tmplp, $rrdtool_pipe);
}
/* release the last lock */
if (cacti_version_compare(get_rrdtool_version(), '1.5', '<')) {
db_execute("SELECT RELEASE_LOCK('boost.single_ds." . $item['local_data_id'] . "')");
}
$current_lock = false;
boost_timer('results_cycle', BOOST_TIMER_END);
}
/* remove the entries from the table */
boost_timer('delete', BOOST_TIMER_START);
db_execute_prepared('DELETE FROM poller_output_boost_local_data_ids
WHERE local_data_id <= ?
AND process_handler = ?',
array($last_id, $child));
boost_timer('delete', BOOST_TIMER_END);
/* restore original error handler */
restore_error_handler();
return cacti_sizeof($results);
}
function boost_process_output($local_data_id, $outarray, $rrd_path, $rrd_tmplp, $rrdtool_pipe) {
$outbuf = '';
if (cacti_sizeof($outarray)) {
foreach ($outarray as $tsdata) {
$outbuf .= ($outbuf != '' ? ' ':'') . implode(':', $tsdata);
}
}
$rrd_tmpl = implode(':', array_keys($rrd_tmplp));
if (trim(read_config_option('path_boost_log')) != '') {
print "DEBUG: Updating Local Data Id:'$local_data_id', Template:" . $rrd_tmpl . ', Output:' . $outbuf . PHP_EOL;
}
boost_timer('rrdupdate', BOOST_TIMER_START);
$return_value = boost_rrdtool_function_update($local_data_id, $rrd_path, $rrd_tmpl, $outbuf, $rrdtool_pipe);
boost_timer('rrdupdate', BOOST_TIMER_END);
/* check return status for delete operation */
if (trim($return_value) != 'OK' && $return_value != '') {
cacti_log("WARNING: RRD Update Warning '" . $return_value . "' for Local Data ID '$local_data_id'", false, 'BOOST');
}
}
function boost_log_statistics($rrd_updates) {
global $start, $boost_stats_log, $verbose;
/* take time and log performance data */
$end = microtime(true);
$cacti_stats = sprintf(
'Time:%01.2f ' .
'RRDUpdates:%s',
round($end - $start, 2),
$rrd_updates);
/* log to the database */
set_config_option('stats_boost', $cacti_stats);
/* log to the logfile */
cacti_log('BOOST STATS: ' . $cacti_stats , true, 'SYSTEM');
$output = array();
$order = array(
'RRDUpdates',
'TotalTime',
'get_records',
'results_cycle',
'rrd_filename_and_template',
'rrd_lastupdate',
'rrdupdate',
'delete'
);
$processes = read_config_option('boost_parallel');
if (empty($processes)) {
$processes = 1;
}
$stats = db_fetch_assoc('SELECT value
FROM settings
WHERE name LIKE "stats_detail_boost_%"');
if (cacti_sizeof($stats)) {
foreach ($stats as $stat) {
$stat = json_decode($stat['value']);
foreach ($stat as $key => $value) {
if (isset($output[$key])) {
$output[$key] += $value;
} else {
$output[$key] = $value;
}
}
}
$outstr = '';
foreach ($order as $key) {
if ($key == 'TotalTime') {
$outstr .= ($outstr != '' ? ', ':'') . "$key:" . round($end - $start, 2);
} elseif ($key == 'RRDUpdates') {
$outstr .= ($outstr != '' ? ', ':'') . "$key:" . round($output[$key], 0);
} else {
$outstr .= ($outstr != '' ? ', ':'') . "$key:" . round($output[$key] / $processes, 0);
}
}
/* log to the database */
set_config_option('stats_detail_boost', str_replace(',', '', $outstr));
/* log to the logfile */
if ($verbose) {
cacti_log('BOOST DETAIL STATS: ' . $outstr, true, 'SYSTEM');
}
}
/* prune old process statistics if the number has changed */
$processes = read_config_option('boost_parallel');
$stats = db_fetch_assoc('SELECT * FROM settings WHERE name LIKE "stats_boost_%"');
if (cacti_sizeof($stats)) {
foreach ($stats as $stat) {
$process = str_replace('stats_boost_', '', $stat['name']);
if ($process > $processes) {
db_execute_prepared('DELETE FROM settings WHERE name = ?', array('stats_boost_' . $process));
}
}
}
/* prune all detailed stats */
db_execute('DELETE FROM settings WHERE name LIKE "stats_detail_boost_%"');
}
function boost_log_child_statistics($rrd_updates, $child) {
global $start, $boost_stats_log, $verbose;
/* take time and log performance data */
$end = microtime(true);
$cacti_stats = sprintf(
'Time:%01.2f ' .
'ProcessNumber:%s ' .
'RRDUpdates:%s',
round($end - $start, 2),
$child,
$rrd_updates);
/* log to the database */
set_config_option('stats_boost_' . $child, $cacti_stats);
/* log to the logfile */
cacti_log('BOOST STATS: ' . $cacti_stats , true, 'SYSTEM');
if (isset($boost_stats_log)) {
$overhead = boost_timer_get_overhead();
$output = array();
$timer_cycles = 0;
foreach ($boost_stats_log as $area => $entry) {
if (isset($entry[BOOST_TIMER_TOTAL])) {
$output[$area] = round($entry[BOOST_TIMER_TOTAL] - (($overhead * $entry[BOOST_TIMER_CYCLES]) / BOOST_TIMER_OVERHEAD_MULTIPLIER), 2);
}
$timer_cycles += $entry[BOOST_TIMER_CYCLES];
}
if (cacti_sizeof($output)) {
$output['RRDUpdates'] = $rrd_updates;
$output['Process'] = $child;
$output['TotalTime'] = round($end - $start, 0);
$timer_overhead = round((($overhead * $timer_cycles) / BOOST_TIMER_OVERHEAD_MULTIPLIER), 0);
if ($timer_overhead > 0) {
$output['timer_overhead'] = $timer_overhead;
}
$output = json_encode($output);
/* log to the database */
set_config_option('stats_detail_boost_' . $child, $output);
/* log to the logfile */
if ($verbose) {
cacti_log('BOOST DETAIL STATS: ' . $output, true, 'SYSTEM');
}
}
}
}
function boost_purge_cached_png_files($forcerun) {
/* remove stale png's from the cache. I consider png's stale after 1 hour */
if ((read_config_option('boost_png_cache_enable') == 'on') || $forcerun) {
$cache_directory = read_config_option('boost_png_cache_directory');
$remove_time = time() - 3600;
$directory_contents = array();
if (is_dir($cache_directory)) {
if ($handle = opendir($cache_directory)) {
/* This is the correct way to loop over the directory. */
while (false !== ($file = readdir($handle))) {
$directory_contents[] = $file;
}
closedir($handle);
}
/* remove age old files */
if (cacti_sizeof($directory_contents)) {
/* goto the cache directory */
chdir($cache_directory);
/* check and fry as applicable */
foreach ($directory_contents as $file) {
if (is_writable($file)) {
$modify_time = filemtime($file);
if ($modify_time < $remove_time) {
/* only remove jpeg's and png's */
if ((substr_count(strtolower($file), '.png')) ||
(substr_count(strtolower($file), '.jpg'))) {
unlink($file);
}
}
}
}
}
}
}
}
/* do NOT run this script through a web browser */
/* display_version - displays version information */
function display_version() {
$version = get_cacti_cli_version();
print "Cacti Boost RRD Update Poller, Version $version " . COPYRIGHT_YEARS . "\n";
}
/* display_help - displays the usage of the function */
function display_help() {
display_version();
print "\nusage: poller_boost.php [--verbose] [--force] [--debug]\n\n";
print "Cacti's performance boosting poller. This poller will purge the boost cache periodically. You may\n";
print "force the processing of the boost cache by using the --force option.\n\n";
print "Optional:\n";
print " --verbose - Show details logs at the command line\n";
print " --force - Force the execution of a update process\n";
print " --debug - Display verbose output during execution\n\n";
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。