/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved. * * You can redistribute this program and/or modify it under the terms of * the GNU Lesser Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. */ using System; using System.Collections.Generic; using System.Text; using Utilities; namespace DiskAccessLibrary.LogicalDiskManager { public enum ComponentFlags : uint { Recover = 0x02, IOFail = 0x04, Pending = 0x08, } // a.k.a. Plex public class ComponentRecord : DatabaseRecord { public string StateString = "ACTIVE"; public ExtentLayoutName ExtentLayout; public ComponentFlags ComponentFlags; public uint NumberOfExtents; // number of extents public ulong CommitTransactionID; // 8 zeros public ulong VolumeId; public ulong LogSD; // DMDiag reports this as 'logging: logsd=x' public ulong StripeSizeLBA; // PaddedVarULong public uint NumberOfColumns; // DMDiag will read this value as (signed) Int32 public ComponentRecord() { this.RecordRevision = 3; this.RecordType = RecordType.Component; } public ComponentRecord(List<DatabaseRecordFragment> fragments) : base(fragments) { // Data begins at 0x10 (VBLK header is at 0x00) int offset = 0x00; // relative to Data ReadCommonFields(this.Data, ref offset); if (RecordRevision != 3) { throw new NotImplementedException("Unsupported record revision"); } StateString = ReadVarString(this.Data, ref offset); ExtentLayout = (ExtentLayoutName)ByteReader.ReadByte(this.Data, ref offset); ComponentFlags = (ComponentFlags)BigEndianReader.ReadUInt32(this.Data, ref offset); NumberOfExtents = ReadVarUInt(this.Data, ref offset); CommitTransactionID = BigEndianReader.ReadUInt64(this.Data, ref offset); offset += 8; VolumeId = ReadVarULong(this.Data, ref offset); LogSD = ReadVarULong(this.Data, ref offset); if (HasStripedExtentsFlag) { StripeSizeLBA = ReadVarULong(this.Data, ref offset); NumberOfColumns = ReadVarUInt(this.Data, ref offset); } } public override byte[] GetDataBytes() { int dataLength = 29; // fixed length components dataLength += VarULongSize(ComponentId); dataLength += Name.Length + 1; dataLength += StateString.Length + 1; dataLength += VarUIntSize(NumberOfExtents); dataLength += VarULongSize(VolumeId); dataLength += VarULongSize(LogSD); if (HasStripedExtentsFlag) { dataLength += PaddedVarULongSize(StripeSizeLBA); dataLength += VarUIntSize(NumberOfColumns); } byte[] data = new byte[dataLength]; int offset = 0x00; WriteCommonFields(data, ref offset); WriteVarString(data, ref offset, StateString); ByteWriter.WriteByte(data, ref offset, (byte)ExtentLayout); BigEndianWriter.WriteUInt32(data, ref offset, (uint)ComponentFlags); WriteVarUInt(data, ref offset, NumberOfExtents); BigEndianWriter.WriteUInt64(data, ref offset, CommitTransactionID); offset += 8; WriteVarULong(data, ref offset, VolumeId); WriteVarULong(data, ref offset, LogSD); if (HasStripedExtentsFlag) { WritePaddedVarULong(data, ref offset, StripeSizeLBA); WriteVarUInt(data, ref offset, NumberOfColumns); } return data; } public ulong ComponentId { get { return this.Id; } } public bool HasStripedExtentsFlag { get { return ((Flags & 0x10) != 0); } set { if (value) { this.Flags = 0x10; } else { this.Flags = 0; } } } } }