public override void WriteDatabaseRecordFragment(DatabaseRecordFragment fragment) { foreach (DynamicDisk disk in m_disks) { VolumeManagerDatabase.WriteDatabaseRecordFragment(disk, fragment, (int)this.DatabaseHeader.BlockSize); } }
public static VolumeManagerDatabase ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock) { VolumeManagerDatabaseHeader databaseHeader = VolumeManagerDatabaseHeader.ReadFromDisk(disk, privateHeader, tocBlock); if (databaseHeader == null) { return(null); } List <DatabaseRecord> databaseRecords = new List <DatabaseRecord>(); // The first VBLK entry is the subsequent entry to the VMDB, which located at (ConfigurationStartLBA + Item1Start) ulong firstSector = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart + 1; // we skip the VMDB int sectorCount = (int)Math.Ceiling((long)databaseHeader.NumberOfVBlks * databaseHeader.BlockSize / (decimal)disk.BytesPerSector); byte[] databaseBytes = disk.ReadSectors((long)firstSector, sectorCount); // read all VBLK blocks: // Note: fragments are not necessarily contiguous! Dictionary <uint, List <DatabaseRecordFragment> > fragments = new Dictionary <uint, List <DatabaseRecordFragment> >(); for (uint index = 0; index < databaseHeader.NumberOfVBlks - 4; index++) { byte[] fragmentBytes = new byte[databaseHeader.BlockSize]; #warning long array index not supported Array.Copy(databaseBytes, (int)(index * databaseHeader.BlockSize), fragmentBytes, 0, (int)databaseHeader.BlockSize); DatabaseRecordFragment fragment = DatabaseRecordFragment.GetDatabaseRecordFragment(fragmentBytes); if (fragment != null) // null fragment means VBLK is empty { if (fragments.ContainsKey(fragment.GroupNumber)) { fragments[fragment.GroupNumber].Add(fragment); } else { List <DatabaseRecordFragment> recordFragments = new List <DatabaseRecordFragment>(); recordFragments.Add(fragment); fragments.Add(fragment.GroupNumber, recordFragments); } } } // We have all the fragments and we can now assemble the records: // We assume that fragments with lower FragmentNumber appear in the database before fragments // of the same group with higher FragmentNumber. foreach (List <DatabaseRecordFragment> recorFragments in fragments.Values) { DatabaseRecord databaseRecord = DatabaseRecord.GetDatabaseRecord(recorFragments); databaseRecords.Add(databaseRecord); } // read all KLog blocks KernelUpdateLog kernelUpdateLog = KernelUpdateLog.ReadFromDisk(disk, privateHeader, tocBlock); DynamicDisk dynamicDisk = new DynamicDisk(disk, privateHeader, tocBlock); return(new VolumeManagerDatabase(dynamicDisk, databaseHeader, databaseRecords, kernelUpdateLog)); }
public static void WriteDatabaseRecordFragment(DynamicDisk disk, DatabaseRecordFragment fragment, int blockSize) { if (fragment.SequenceNumber < FirstSequenceNumber) { throw new ArgumentException("VBLK SequenceNumber must start from 4"); } PrivateHeader privateHeader = disk.PrivateHeader; TOCBlock tocBlock = disk.TOCBlock; ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart; int fragmentsPerSector = (int)(disk.Disk.BytesPerSector / blockSize); sectorIndex += (ulong)(fragment.SequenceNumber / fragmentsPerSector); byte[] sectorBytes = disk.Disk.ReadSector((long)sectorIndex); byte[] fragmentBytes = fragment.GetBytes(blockSize); // should we use the same database header? int indexInSector = (int)(fragment.SequenceNumber % fragmentsPerSector); Array.Copy(fragmentBytes, 0, sectorBytes, indexInSector * blockSize, blockSize); disk.Disk.WriteSectors((long)sectorIndex, sectorBytes); }
/// <summary> /// Return record fragments containing updated record data. /// SequenceNumber and GroupNumber have to be set before writing these fragments to the database. /// </summary> private static List <DatabaseRecordFragment> GetUpdatedFragments(int blockSize, byte[] data) { int fragmentDataLength = blockSize - DatabaseRecordFragment.HeaderLength; int fragmentCount = (int)Math.Ceiling((double)data.Length / fragmentDataLength); List <DatabaseRecordFragment> result = new List <DatabaseRecordFragment>(); int dataOffset = 0; for (int numberInGroup = 0; numberInGroup < fragmentCount; numberInGroup++) { DatabaseRecordFragment fragment = new DatabaseRecordFragment(); fragment.NumberInGroup = (ushort)numberInGroup; fragment.FragmentCount = (ushort)fragmentCount; fragment.Data = new byte[fragmentDataLength]; int currentDataLength = Math.Min((int)fragmentDataLength, data.Length - dataOffset); Array.Copy(data, dataOffset, fragment.Data, 0, currentDataLength); dataOffset += currentDataLength; result.Add(fragment); } return(result); }
/// <summary> /// Will read all VBLK blocks and assemble the database records /// </summary> /// <param name="numberOfFragments">number of fragments excluding the database header</param> private static List <DatabaseRecord> ReadDatabaseRecords(byte[] databaseBytes, int headerSize, int fragmentSize, int numberOfFragments) { // Note: fragments are not necessarily contiguous! Dictionary <uint, List <DatabaseRecordFragment> > fragments = new Dictionary <uint, List <DatabaseRecordFragment> >(); for (uint index = 0; index < numberOfFragments; index++) { byte[] fragmentBytes = new byte[fragmentSize]; int fragmentOffset = (int)(headerSize + index * fragmentSize); Array.Copy(databaseBytes, fragmentOffset, fragmentBytes, 0, fragmentSize); DatabaseRecordFragment fragment = DatabaseRecordFragment.GetDatabaseRecordFragment(fragmentBytes); if (fragment != null) // null fragment means VBLK is empty { if (fragments.ContainsKey(fragment.GroupNumber)) { fragments[fragment.GroupNumber].Add(fragment); } else { List <DatabaseRecordFragment> recordFragments = new List <DatabaseRecordFragment>(); recordFragments.Add(fragment); fragments.Add(fragment.GroupNumber, recordFragments); } } } // We have all the fragments and we can now assemble the records: // We assume that fragments with lower FragmentNumber appear in the database before fragments // of the same group with higher FragmentNumber. List <DatabaseRecord> databaseRecords = new List <DatabaseRecord>(); foreach (List <DatabaseRecordFragment> recordFragments in fragments.Values) { DatabaseRecord databaseRecord = DatabaseRecord.GetDatabaseRecord(recordFragments); databaseRecords.Add(databaseRecord); } return(databaseRecords); }
public override void WriteDatabaseRecordFragment(DatabaseRecordFragment fragment) { WriteDatabaseRecordFragment(m_disk, fragment, (int)m_databaseHeader.BlockSize); }
public abstract void WriteDatabaseRecordFragment(DatabaseRecordFragment fragment);
virtual protected void WriteDatabaseRecordFragment(DatabaseRecordFragment fragment) { WriteDatabaseRecordFragment(m_disk, fragment, (int)m_databaseHeader.BlockSize); }