// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved namespace Microsoft.Samples.HyperV.Storage { using System; using System.Xml; using System.Globalization; using System.Management; using Microsoft.Samples.HyperV.Common; /// /// Contains information about a virtual hard disk file. /// /// /// This class could have also been reasonably designed as a struct. We decided against this /// approach, because client code had already been written assuming class semantics. /// public class VirtualHardDiskState { private Int64 m_FileSize; private bool m_InUse; private Int64? m_MinInternalSize; private Int32 m_PhysicalSectorSize; private Int32 m_Alignment; private Int32? m_FragmentationPercentage; /// /// Initializes a new class. /// /// The virtual disk size. /// The virtual disk in use flag. /// The minimum internal size of the virtual disk. /// The physical sector size of the underlying physical /// hard disk. /// The alignment within the virtual hard disk. public VirtualHardDiskState( Int64 fileSize, bool inUse, Int64? minInternalSize, Int32 physicalSectorSize, Int32 alignment, Int32? fragmentationPercentage) { m_FileSize = fileSize; m_InUse = inUse; m_MinInternalSize = minInternalSize; m_PhysicalSectorSize = physicalSectorSize; m_Alignment = alignment; m_FragmentationPercentage = fragmentationPercentage; } /// /// Gets the size of this disk. /// public long FileSize { get { return m_FileSize; } } /// /// Gets whether the virtual hard disk is in use. /// public bool InUse { get { return m_InUse;} } /// /// Gets the minimum internal size of this disk. /// public long? MinInternalSize { get { return m_MinInternalSize; } } /// /// Gets the disk's physical sector size. /// public long PhysicalSectorSize { get { return m_PhysicalSectorSize; } } /// /// Gets the disk's aligment. /// public long Alignment { get { return m_Alignment; } } /// /// Gets the disk's fragmentation percentage. /// public long? FragmentationPercentage { get { return m_FragmentationPercentage; } } /// /// Parses the hard disk State embedded instance returned from the server and /// creates a new VirtualHardDiskState with that information. /// /// The disk State embedded instance. /// A object with the data contained in the /// embedded instance. /// If either param is null. /// If there was a problem parsing the embedded instance /// public static VirtualHardDiskState Parse( string embeddedInstance) { if (embeddedInstance == null) { throw new ArgumentNullException("embeddedInstance"); } try { Int64 fileSize = 0; bool inUse = false; Int64? minInternalSize = 0; Int32 physicalSectorSize = 0; Int32 alignment = 0; Int32? fragmentationPercentage = 0; XmlDocument doc = new XmlDocument(); doc.LoadXml(embeddedInstance); XmlNodeList nodelist = doc.SelectNodes(@"/INSTANCE/@CLASSNAME"); if (nodelist.Count != 1) { throw new FormatException(); } if (nodelist[0].Value != "Msvm_VirtualHardDiskState") { throw new FormatException(); } // FileSize nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'FileSize']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } fileSize = Int64.Parse(nodelist[0].Value, CultureInfo.InvariantCulture); // InUse should be false nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'InUse']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } inUse = bool.Parse(nodelist[0].Value); // MinInternalSize nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'MinInternalSize']/VALUE/child::text()"); if (nodelist.Count == 0) { minInternalSize = null; } else if (nodelist.Count == 1) { minInternalSize = Int64.Parse(nodelist[0].Value, CultureInfo.InvariantCulture); } else { throw new FormatException(); } // PhysicalSectorSize nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'PhysicalSectorSize']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } physicalSectorSize = Int32.Parse(nodelist[0].Value, CultureInfo.InvariantCulture); // Alignment nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'Alignment']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } alignment = Int32.Parse(nodelist[0].Value, CultureInfo.InvariantCulture); // FragmentationPercentage nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'FragmentationPercentage']/VALUE/child::text()"); if (nodelist.Count == 0) { fragmentationPercentage = null; } else if (nodelist.Count == 1) { fragmentationPercentage = Int32.Parse(nodelist[0].Value, CultureInfo.InvariantCulture); } else { throw new FormatException(); } return new VirtualHardDiskState(fileSize, inUse, minInternalSize, physicalSectorSize, alignment, fragmentationPercentage); } catch (XmlException ex) { // There was an error parsing the embeddedInstance as XML. // Throw this as a FormatException- the format of the returned // embeddedInstance is not as expected. throw new FormatException(null, ex); } catch (OverflowException ex) { // Treat any overflows as a format exception so that we return a consistent error // from this method. throw new FormatException(null, ex); } } } }