diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f1e7f2..ef95fdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ --- develop --- +* issue#254: Scope partition maintenance to the target table and serialize partition creation * issue: Making changes to support Cacti 1.3 * issue: Don't use MyISAM for non-analytical tables * issue: The install advisor for Syslog was broken in current Cacti releases diff --git a/functions.php b/functions.php index 9bd3223..423efcb 100644 --- a/functions.php +++ b/functions.php @@ -186,32 +186,56 @@ function syslog_partition_manage() { return $syslog_deleted; } +/** + * Validate tables that support partition maintenance. + */ +function syslog_partition_table_allowed($table) { + return in_array($table, array('syslog', 'syslog_removed'), true); +} + /** * This function will create a new partition for the specified table. */ function syslog_partition_create($table) { global $syslogdb_default; + if (!syslog_partition_table_allowed($table)) { + return; + } + + $lock_name = $syslogdb_default . '.syslog_partition_create.' . $table; + $locked = syslog_db_fetch_cell_prepared('SELECT GET_LOCK(?, 10)', array($lock_name)); + + if ((int)$locked !== 1) { + cacti_log("SYSLOG: Unable to acquire partition create lock for '$table'", false, 'SYSTEM'); + return; + } + /* determine the format of the table name */ $time = time(); $cformat = 'd' . date('Ymd', $time); $lnow = date('Y-m-d', $time+86400); - $exists = syslog_db_fetch_row("SELECT * - FROM `information_schema`.`partitions` - WHERE table_schema='" . $syslogdb_default . "' - AND partition_name='" . $cformat . "' - AND table_name='syslog' - ORDER BY partition_ordinal_position"); + try { + $exists = syslog_db_fetch_row_prepared("SELECT * + FROM `information_schema`.`partitions` + WHERE table_schema = ? + AND partition_name = ? + AND table_name = ? + ORDER BY partition_ordinal_position", + array($syslogdb_default, $cformat, $table)); - if (!cacti_sizeof($exists)) { - cacti_log("SYSLOG: Creating new partition '$cformat'", false, 'SYSTEM'); + if (!cacti_sizeof($exists)) { + cacti_log("SYSLOG: Creating new partition '$cformat'", false, 'SYSTEM'); - syslog_debug("Creating new partition '$cformat'"); + syslog_debug("Creating new partition '$cformat'"); - syslog_db_execute("ALTER TABLE `" . $syslogdb_default . "`.`$table` REORGANIZE PARTITION dMaxValue INTO ( - PARTITION $cformat VALUES LESS THAN (TO_DAYS('$lnow')), - PARTITION dMaxValue VALUES LESS THAN MAXVALUE)"); + syslog_db_execute("ALTER TABLE `" . $syslogdb_default . "`.`$table` REORGANIZE PARTITION dMaxValue INTO ( + PARTITION $cformat VALUES LESS THAN (TO_DAYS('$lnow')), + PARTITION dMaxValue VALUES LESS THAN MAXVALUE)"); + } + } finally { + syslog_db_fetch_cell_prepared('SELECT RELEASE_LOCK(?)', array($lock_name)); } } @@ -221,11 +245,16 @@ function syslog_partition_create($table) { function syslog_partition_remove($table) { global $syslogdb_default; + if (!syslog_partition_table_allowed($table)) { + return 0; + } + $syslog_deleted = 0; - $number_of_partitions = syslog_db_fetch_assoc("SELECT * + $number_of_partitions = syslog_db_fetch_assoc_prepared("SELECT * FROM `information_schema`.`partitions` - WHERE table_schema='" . $syslogdb_default . "' AND table_name='syslog' - ORDER BY partition_ordinal_position"); + WHERE table_schema = ? AND table_name = ? + ORDER BY partition_ordinal_position", + array($syslogdb_default, $table)); $days = read_config_option('syslog_retention'); @@ -257,16 +286,21 @@ function syslog_partition_remove($table) { function syslog_partition_check($table) { global $syslogdb_default; + if (!syslog_partition_table_allowed($table)) { + return false; + } + if (defined('SYSLOG_CONFIG')) { include(SYSLOG_CONFIG); } /* find date of last partition */ - $last_part = syslog_db_fetch_cell("SELECT PARTITION_NAME + $last_part = syslog_db_fetch_cell_prepared("SELECT PARTITION_NAME FROM `information_schema`.`partitions` - WHERE table_schema='" . $syslogdb_default . "' AND table_name='syslog' + WHERE table_schema = ? AND table_name = ? ORDER BY partition_ordinal_position DESC - LIMIT 1,1;"); + LIMIT 1,1", + array($syslogdb_default, $table)); $lformat = str_replace('d', '', $last_part); $cformat = date('Ymd'); @@ -2421,4 +2455,3 @@ function alert_replace_variables($alert, $results, $hostname = '') { return $command; } - diff --git a/tests/regression/issue254_partition_table_locking_test.php b/tests/regression/issue254_partition_table_locking_test.php new file mode 100644 index 0000000..6374fba --- /dev/null +++ b/tests/regression/issue254_partition_table_locking_test.php @@ -0,0 +1,32 @@ +