public void Extend(ulong additionalLengthInBytes) { ulong currentSize = this.Length; if (m_attributeRecord is NonResidentAttributeRecord) { NonResidentAttributeData attributeData = new NonResidentAttributeData(m_volume, m_fileRecord, (NonResidentAttributeRecord)m_attributeRecord); attributeData.Extend(additionalLengthInBytes); } else { byte[] data = ((ResidentAttributeRecord)m_attributeRecord).Data; ulong finalDataLength = (uint)data.Length + additionalLengthInBytes; ulong finalRecordLength = (uint)m_attributeRecord.RecordLength + additionalLengthInBytes; if (finalRecordLength >= (ulong)m_volume.AttributeRecordLengthToMakeNonResident && m_attributeRecord.AttributeType != AttributeType.AttributeList) // We will create an attribute list with the right attribute form in advance. { // Convert the attribute to non-resident long clustersToAllocate = (long)Math.Ceiling((double)finalDataLength / m_volume.BytesPerCluster); if (clustersToAllocate > m_volume.NumberOfFreeClusters) { throw new DiskFullException(); } NonResidentAttributeRecord attributeRecord = NonResidentAttributeRecord.Create(m_attributeRecord.AttributeType, m_attributeRecord.Name); NonResidentAttributeData attributeData = new NonResidentAttributeData(m_volume, null, attributeRecord); attributeData.Extend(finalDataLength); if (data.Length % m_volume.BytesPerCluster > 0) { int fillDataLength = m_volume.BytesPerCluster - (data.Length % m_volume.BytesPerCluster); if ((uint)data.Length + (uint)fillDataLength < finalDataLength) { // Only the last cluster can be partially used, if this is not the last cluster, zero-fill it data = ByteUtils.Concatenate(data, new byte[fillDataLength]); } } attributeData.WriteClusters(0, data); // Note that we overwrite the old attribute only after writing the non-resident data if (m_fileRecord != null) { m_fileRecord.RemoveAttributeRecord(m_attributeRecord.AttributeType, m_attributeRecord.Name); FileRecordHelper.InsertSorted(m_fileRecord.Attributes, attributeRecord); } m_attributeRecord = attributeRecord; } else { int currentLength = data.Length; byte[] temp = new byte[currentLength + (int)additionalLengthInBytes]; Array.Copy(data, temp, data.Length); ((ResidentAttributeRecord)m_attributeRecord).Data = temp; } if (m_fileRecord != null) { m_volume.UpdateFileRecord(m_fileRecord); } } }
/// <returns>Record Index</returns> private long AllocateIndexRecord() { long?indexRecord = m_bitmapData.AllocateRecord(); if (indexRecord == null) { long numberOfUsableBits = m_bitmapData.NumberOfUsableBits; m_indexAllocationData.Extend(m_rootRecord.BytesPerIndexRecord * ExtendGranularity); m_bitmapData.ExtendBitmap(ExtendGranularity); indexRecord = m_bitmapData.AllocateRecord(numberOfUsableBits); } return(indexRecord.Value); }
/// <returns>Record Index</returns> private long AllocateIndexRecord() { uint transactionID = m_volume.LogClient.AllocateTransactionID(); long?indexRecord = m_bitmapData.AllocateRecord(transactionID); if (indexRecord == null) { long numberOfUsableBits = m_bitmapData.NumberOfUsableBits; m_indexAllocationData.Extend(m_rootRecord.BytesPerIndexRecord * ExtendGranularity); m_bitmapData.ExtendBitmap(ExtendGranularity); indexRecord = m_bitmapData.AllocateRecord(numberOfUsableBits, transactionID); } m_volume.LogClient.WriteForgetTransactionRecord(transactionID); return(indexRecord.Value); }