<?php if (!defined('PmWiki')) highlight_file(__FILE__); if (!defined('PmWiki')) exit(); /** \file calculate_availability.php \brief Extra PmWiki markup for calculating system availability Copyright 2006 Christian Ridderstrom (christian.ridderstrom@gmail.com) 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. For documentation, see the recipe page at http://pmwiki.org/wiki/Cookbook/CalculateAvailability?action=edit Syntax synopsis: * Form 1: (:calc-avail <nn>% :) Example: (:calc-avail 99.99% :) * Form 2: (:calc-avail mtbf=<MTBF><unit> mttr=<MTTR><unit> :) Example: (:calc-avail mtbf=5.5y mttr=12h :) * Form 3: (:calc-avail :) Example: (:calc-avail :) The arguments are used as follows <nn> A number 0-100 of availability in percent, e.g. 99.9. % The percent sign after the number is mandatory. <MTBF> A number (e.g. 12.5) indicating mean time between failure. <unit> A mandatory character indicating the unit, where 'y' = Year (365 days per week) 'm' = Month (30 days per week) 'w' = Week (7 days/per week) 'd' = Day 'h' = Hour (24 hours per day) <MTTR> A number (e.g. .5) indicating mean time to repeair. <unit> A character indicating the unit, same as described above. */ $RecipeInfo['CalculateAvailability']['Version'] = '2006-12-02'; // Define the markup for (:calc-avail ... :) Markup('calculate_availability', 'directives', '/\\(:calc-avail\\s+(.*?)\\s*:\\)/ei', "CalculateAvailability(\$pagename, PSS('$1'))"); // The array $CalculateAvailabilityD stores all global data // used by this recipe. The memeber 'current' contains the // currently estimated availability. SDVA($CalculateAvailabilityD, array('current'=>1.0)); // // Function: Calculate availability given arguments from the // the directive (:calc-avail ... :). See the top of this // script and the recipe page for details about the syntax and use. // // Note that actual calculations when using MTBF/MTTR are // done in units as specified for the MTBF. This is to avoid // numerical problems although it could probably be achieved // using some other way. // function CalculateAvailability($pagename, $arguments) { global $CalculateAvailabilityD; $defaults = array('fmt'=>'default'); $args = array_change_key_case( array_merge($defaults, ParseArgs($arguments))); if(array_key_exists('mttr', $args)) { // Use MTTR and MTBF $mttr = CalculateAvailabilityGetNumber($args['mttr']); $mtbf = CalculateAvailabilityGetNumber($args['mtbf']); if(!$mttr['unit'] || !$mtbf['unit']) return "<strong>Both mttr and mtbf must have units!</strong>"; $u = $mtbf['unit']; $A = $mtbf[$u] / ($mtbf[$u] + $mttr[$u]); $CalculateAvailabilityD['current'] *= $A; $s = sprintf("(%-10s MTTR=%s)", sprintf('MTBF=%s,', $args['mtbf']), $args['mttr']); $s .= sprintf(' %.3f%% ', $A*100); } elseif(count($args['']) == 0) { $s = sprintf('%.2f%% ', $CalculateAvailabilityD['current'] * 100); $CalculateAvailabilityD['current'] = 1.0; } else { $x = implode('', $args['']); if(substr($x, -1) != '%') return "<strong>A separate availability argument must end in '%'</strong>"; $A = $x * 0.01; $CalculateAvailabilityD['current'] *= $A; $s = sprintf('%.3f%% ', $A*100); } return "<span style='white-space:pre; font-size:smaller; font-family:monospace;'>$s</span>"; } function CalculateAvailabilityGetNumber($x) { $toDays = array('h'=>1/24, 'd'=>1, 'w'=>7, 'm'=>30, 'y'=>365); if(preg_match('/([0-9.]+)([hHdDwWmMyY])/', $x, $matches)) { $d = $matches[1] * $toDays[strtolower($matches[2])]; $res = array('h'=>$d*24, 'd'=>$d, 'w'=>$d/7, 'm'=>$d/30, 'y'=>$d/365, 'unit'=>strtolower($matches[2])); } else { $res = array('h'=>$x, 'unit' => false); } return $res; } ?>