From 957d8f756240363ad43ac68a4c18b7f9e8e1c57b Mon Sep 17 00:00:00 2001 From: Seth Mos Date: Fri, 13 Mar 2009 02:43:57 +0100 Subject: Rewrite the rrd upgrade code to use the newly added xml2array function specifically for the rrd upgrade code. This is about 4 times faster then our builtin parser. Hoping this can solve part of the the 45 minute upgrade cycles on embedded builds --- etc/inc/config.inc | 16 +++++-- etc/inc/rrd.inc | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 5 deletions(-) diff --git a/etc/inc/config.inc b/etc/inc/config.inc index faf5af7..7c8597e 100644 --- a/etc/inc/config.inc +++ b/etc/inc/config.inc @@ -2086,7 +2086,9 @@ endif; mwexec("$rrdtool tune {$rrddbpath}{$database} -r roundtrip:delay 2>&1"); dump_rrd_to_xml("{$rrddbpath}/{$database}", "{$g['tmp_path']}/{$xmldump}"); - $rrdold = parse_xml_config_raw("{$g['tmp_path']}/{$xmldump}", "rrd"); + $rrdoldxml = file_get_contents("{$g['tmp_path']}/{$xmldump}"); + $rrdold = xml2array($rrdoldxml, 1, "tag"); + $rrdold = $rrdold['rrd']; $i = 0; foreach($rrdold['rra'] as $rra) { @@ -2140,9 +2142,14 @@ endif; /* create temporary xml from new RRD */ dump_rrd_to_xml("{$g['tmp_path']}/{$databasetmp}", "{$g['tmp_path']}/{$xmldumptmp}"); - $rrdold = parse_xml_config_raw("{$g['tmp_path']}/{$xmldump}", "rrd"); - $rrdnew = parse_xml_config_raw("{$g['tmp_path']}/{$xmldumptmp}", "rrd"); - + $rrdoldxml = file_get_contents("{$g['tmp_path']}/{$xmldump}"); + $rrdold = xml2array($rrdoldxml, 1, "tag"); + $rrdold = $rrdold['rrd']; + + $rrdnewxml = file_get_contents("{$g['tmp_path']}/{$xmldumptmp}"); + $rrdnew = xml2array($rrdnewxml, 1, "tag"); + $rrdnew = $rrdnew['rrd']; + /* remove any MAX RRA's. Not needed for traffic. */ $i = 0; foreach ($rrdold['rra'] as $rra) { @@ -2156,7 +2163,6 @@ endif; $rrdxml = dump_xml_config_raw($rrdxmlarray, "rrd"); file_put_contents("{$g['tmp_path']}/{$xmldumpnew}", $rrdxml); mwexec("$rrdtool restore -f {$g['tmp_path']}/{$xmldumpnew} {$rrddbpath}/{$database} 2>&1"); - // mwexec("$rrdtool resize {$rrddbpath}/{$database} 3 GROW 3000 2>&1"); } enable_rrd_graphing(); diff --git a/etc/inc/rrd.inc b/etc/inc/rrd.inc index 1d02970..1160f40 100644 --- a/etc/inc/rrd.inc +++ b/etc/inc/rrd.inc @@ -616,3 +616,139 @@ function kill_traffic_collector() { mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill"); } +/* This xml 2 array function is courtesy of the php.net comment section on xml_parse. + * it is roughly 4 times faster then our existing pfSense parser but due to the large + * size of the RRD xml dumps this is required. + * The reason we do not use it for pfSense is that it does not know about array fields + * which causes it to fail on array fields with single items. Possible Todo? + */ +function xml2array($contents, $get_attributes = 1, $priority = 'tag') +{ + if (!function_exists('xml_parser_create')) + { + return array (); + } + $parser = xml_parser_create(''); + xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); + xml_parse_into_struct($parser, trim($contents), $xml_values); + xml_parser_free($parser); + if (!$xml_values) + return; //Hmm... + $xml_array = array (); + $parents = array (); + $opened_tags = array (); + $arr = array (); + $current = & $xml_array; + $repeated_tag_index = array (); + foreach ($xml_values as $data) + { + unset ($attributes, $value); + extract($data); + $result = array (); + $attributes_data = array (); + if (isset ($value)) + { + if ($priority == 'tag') + $result = $value; + else + $result['value'] = $value; + } + if (isset ($attributes) and $get_attributes) + { + foreach ($attributes as $attr => $val) + { + if ($priority == 'tag') + $attributes_data[$attr] = $val; + else + $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr' + } + } + if ($type == "open") + { + $parent[$level -1] = & $current; + if (!is_array($current) or (!in_array($tag, array_keys($current)))) + { + $current[$tag] = $result; + if ($attributes_data) + $current[$tag . '_attr'] = $attributes_data; + $repeated_tag_index[$tag . '_' . $level] = 1; + $current = & $current[$tag]; + } + else + { + if (isset ($current[$tag][0])) + { + $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result; + $repeated_tag_index[$tag . '_' . $level]++; + } + else + { + $current[$tag] = array ( + $current[$tag], + $result + ); + $repeated_tag_index[$tag . '_' . $level] = 2; + if (isset ($current[$tag . '_attr'])) + { + $current[$tag]['0_attr'] = $current[$tag . '_attr']; + unset ($current[$tag . '_attr']); + } + } + $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1; + $current = & $current[$tag][$last_item_index]; + } + } + elseif ($type == "complete") + { + if (!isset ($current[$tag])) + { + $current[$tag] = $result; + $repeated_tag_index[$tag . '_' . $level] = 1; + if ($priority == 'tag' and $attributes_data) + $current[$tag . '_attr'] = $attributes_data; + } + else + { + if (isset ($current[$tag][0]) and is_array($current[$tag])) + { + $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result; + if ($priority == 'tag' and $get_attributes and $attributes_data) + { + $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data; + } + $repeated_tag_index[$tag . '_' . $level]++; + } + else + { + $current[$tag] = array ( + $current[$tag], + $result + ); + $repeated_tag_index[$tag . '_' . $level] = 1; + if ($priority == 'tag' and $get_attributes) + { + if (isset ($current[$tag . '_attr'])) + { + $current[$tag]['0_attr'] = $current[$tag . '_attr']; + unset ($current[$tag . '_attr']); + } + if ($attributes_data) + { + $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data; + } + } + $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken + } + } + } + elseif ($type == 'close') + { + $current = & $parent[$level -1]; + } + } + return ($xml_array); +} + +?> -- cgit v1.1