/* Copyright (c) Citrix Systems Inc. * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ using System; using System.Collections; using System.Collections.Generic; using System.Xml; namespace XenAdmin { public enum RoundingBehaviour { Up, Down, Nearest } /// /// Miscellaneous utility functions /// public static class Util { public const long BINARY_KILO = 1024; public const long BINARY_MEGA = BINARY_KILO * BINARY_KILO; public const long BINARY_GIGA = BINARY_KILO * BINARY_KILO * BINARY_KILO; public const long DEC_KILO = 1000; public const long DEC_MEGA = DEC_KILO * DEC_KILO; public const long DEC_GIGA = DEC_KILO * DEC_KILO * DEC_KILO; /// /// The default iSCSI filer port. /// public const UInt16 DEFAULT_ISCSI_PORT = 3260; public static string MemorySizeString(double bytes) { return string.Format(Messages.VAL_MB, Math.Round(bytes / BINARY_MEGA)); } public static string MemorySizeStringWithoutUnits(double bytes) { return Math.Round(bytes / BINARY_MEGA).ToString(); } public static string DataRateString(double bytesPerSec) { string unit; string value = ByteSizeString(bytesPerSec, 1, true, out unit); return string.Format(Messages.VAL_FORMAT, value, unit); } public static string DataRateValue(double bytesPerSec, out string unit) { return ByteSizeString(bytesPerSec, 1, true, out unit); } public static string DiskSizeString(ulong bytes) { string unit; string value = ByteSizeString(bytes, 1, false, out unit); return string.Format(Messages.VAL_FORMAT, value, unit); } public static string SuperiorSizeString(double bytes, int dp) { if (bytes >= 10 * BINARY_GIGA) { return string.Format(Messages.VAL_GB, Math.Round(bytes / BINARY_GIGA, dp)); } else if (bytes >= 10 * BINARY_MEGA) { return string.Format(Messages.VAL_MB, Math.Round(bytes / BINARY_MEGA, dp)); } else if (bytes >= 10 * BINARY_KILO) { return string.Format(Messages.VAL_KB, Math.Round(bytes / BINARY_KILO, dp)); } else { return string.Format(Messages.VAL_B, bytes); } } public static string DiskSizeString(long bytes) { return DiskSizeString(bytes, 1); } public static string DiskSizeString(long bytes, int dp) { ulong abs = (ulong)Math.Abs(bytes); string unit; string value = ByteSizeString(abs, dp, false, out unit); return string.Format(Messages.VAL_FORMAT, value, unit); } public static string DiskSizeStringWithoutUnits(long bytes) { string unit; return ByteSizeString(bytes, 1, false, out unit); } public static string MemorySizeStringVariousUnits(double bytes) { string unit; string value = ByteSizeString(bytes, 0, false, out unit); return string.Format(Messages.VAL_FORMAT, value, unit); } public static string MemorySizeValueVariousUnits(double bytes, out string unit) { return ByteSizeString(bytes, 0, false, out unit); } private static string ByteSizeString(double bytes, int decPlaces, bool isRate, out string unit) { if (bytes >= BINARY_GIGA) { unit = isRate ? Messages.VAL_GIGRATE : Messages.VAL_GIGB; return Math.Round(bytes / BINARY_GIGA, decPlaces).ToString(); } if (bytes >= BINARY_MEGA) { unit = isRate ? Messages.VAL_MEGRATE : Messages.VAL_MEGB; return Math.Round(bytes / BINARY_MEGA, decPlaces).ToString(); } if (bytes >= BINARY_KILO) { unit = isRate ? Messages.VAL_KILRATE : Messages.VAL_KILB; return Math.Round(bytes / BINARY_KILO, decPlaces).ToString(); } unit = isRate ? Messages.VAL_RATE : Messages.VAL_BYTE; return bytes.ToString(); } /// /// nothing actually is measured in nanoseconds, we actually output microseconds /// public static string NanoSecondsString(double t) { string unit; string value = NanoSecondsValue(t, out unit); return string.Format(Messages.VAL_FORMAT_SECONDS, value, unit); } public static string NanoSecondsValue(double t, out string unit) { if (t >= DEC_GIGA) { unit = Messages.VAL_SEC; return (t / DEC_GIGA).ToString("0"); } if (t >= DEC_MEGA) { unit = Messages.VAL_MILSEC; return (t / DEC_MEGA).ToString("0"); } if (t >= DEC_KILO) { unit = Messages.VAL_MICSEC; return (t / DEC_KILO).ToString("0"); } unit = Messages.VAL_NANOSEC; return t.ToString("0"); } public static string MilliWattString(double t) { string unit; string value = MilliWattValue(t, out unit); return string.Format(Messages.VAL_FORMAT, value, unit); } public static string MilliWattValue(double t, out string unit) { if (t >= DEC_GIGA) { unit = Messages.VAL_MWATT; return (t / DEC_GIGA).ToString("0"); } if (t >= DEC_MEGA) { unit = Messages.VAL_KILOWATT; return (t / DEC_MEGA).ToString("0"); } if (t >= DEC_KILO) { unit = Messages.VAL_WATT; return (t / DEC_KILO).ToString("0"); } unit = Messages.VAL_MILWATT; return t.ToString("0"); } public static long ToMB(long bytes) { return ToMB(bytes, RoundingBehaviour.Nearest); } public static long ToMB(long bytes, RoundingBehaviour rounding) { switch (rounding) { case RoundingBehaviour.Down: return (long)Math.Floor(bytes / (double)BINARY_MEGA); case RoundingBehaviour.Up: return (long)Math.Ceiling(bytes / (double)BINARY_MEGA); default: // case RoundingBehaviour.Nearest: return (long)Math.Round(bytes / (double)BINARY_MEGA, MidpointRounding.AwayFromZero); } } public static double ToUnixTime(DateTime time) { TimeSpan diff = time - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); return diff.TotalSeconds; } public static DateTime FromUnixTime(double time) { DateTime bootTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); return bootTime.AddSeconds(time); } public static string TimeString(long t) { if (t >= 120) return string.Format(Messages.TIME_MINUTES, t / 60); if (t > 0) return string.Format(Messages.TIME_SECONDS, t); return Messages.TIME_NEGLIGIBLE; } public static string TimeRangeString(long t1, long t2) { return t1 > 60 && t2 > 60 ? string.Format(Messages.TIME_RANGE_MINUTES, t1 / 60, t2 / 60) : string.Format(Messages.TIME_RANGE_SECONDS, t1, t2); } internal static string LThanTime(long max) { return string.Format(Messages.LESS_THAN, TimeString(max)); } internal static string GThanSize(long min) { return string.Format(Messages.GREATER_THAN, DiskSizeString(min)); } internal static string GThanTime(long min) { return string.Format(Messages.GREATER_THAN, TimeString(min)); } internal static string LThanSize(long max) { return string.Format(Messages.LESS_THAN, DiskSizeString(max)); } public static string CountsPerSecondString(double p) { return string.Format(Messages.VAL_FORMAT, p, Messages.COUNTS_PER_SEC_UNIT); } public static string PercentageString(double fraction) { return string.Format("{0}%", (fraction * 100d).ToString("0.0")); } public static void ThrowIfParameterNull(object obj, string name) { if (name == null) { throw new ArgumentNullException("name"); } if (name.Length == 0) { ThrowBecauseZeroLength("name"); } if (obj == null) { throw new ArgumentNullException(name); } } public static void ThrowIfStringParameterNullOrEmpty(string value, string name) { ThrowIfParameterNull(value, name); if (value.Length == 0) { ThrowBecauseZeroLength(name); } } public static void ThrowIfEnumerableParameterNullOrEmpty(IEnumerable value, string name) { ThrowIfParameterNull(value, name); #pragma warning disable 0168 foreach (object _ in value) { return; } #pragma warning restore 0168 ThrowBecauseZeroLength(name); } private static void ThrowBecauseZeroLength(string name) { throw new ArgumentException(string.Format("{0} cannot have 0 length.", name), name); } /// /// Loads the specified non-generic IEnumerable into a generic List<T>. /// /// The type to convert each element to /// The input non-generic IEnumerable. /// Generic List<T> public static List PopulateList(IEnumerable input) { ThrowIfParameterNull(input, "input"); List output = new List(); foreach (T t in input) { output.Add(t); } return output; } /// /// Gets a List that represents the specified IEnumerable. If the input isn't a List then one gets created by passing the input into /// List's constructor. If the input is already a List then it is returned directly. /// /// /// The input. /// A list for the specified enumerable public static List GetList(IEnumerable input) { if (input == null) { return null; } var list = input as List; if (list != null) { return list; } return new List(input); } /// /// Matches 1-65535 inclusive. /// /// The string to be parsed /// True if the specified string contains only a valid port, otherwise false. public static bool IsValidPort(string s) { int port; if (!int.TryParse(s, out port)) return false; return 0 < port && port <= 65535; } public static string GetXmlNodeInnerText(XmlNode node, string xPath) { ThrowIfParameterNull(node, "node"); ThrowIfStringParameterNullOrEmpty(xPath, "xPath"); XmlNodeList nodes = node.SelectNodes(xPath); if (nodes == null || nodes.Count == 0) { throw new InvalidOperationException("Node not found: " + xPath); } return nodes[0].InnerText; } /// /// Get the first node with name 'value' and returns its innerText. Used for gettings results of CGSL async actions. /// /// The XML. /// The contents of the first node with name 'value'. public static string GetContentsOfValueNode(string xml) { ThrowIfStringParameterNullOrEmpty(xml, "xml"); XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); // If we've got this from an async task result, then it will be wrapped // in a element. foreach (XmlNode node in doc.GetElementsByTagName("value")) { return node.InnerText; } return null; } } }