// Reserves an oid so it can't be used later. public void Reserve(long oid) { // Add a empty block for the reserved data. GObjectBlock reservedBlock = new GObjectBlock(); reservedBlock.Blocks = new long[]{}; reservedBlock.OID = oid; reservedBlock.CountBytes = 0; m_objectBlocks.Add(oid, reservedBlock); m_lastOID = Math.Max(oid, m_lastOID); }
// (05.04.2007 10:19) // Saves oid internally in the file. public void SaveOIDs() { lock (m_dummy) { m_oidPos = 0; m_oidPosIndex = 0; if (SaveChanges != null) SaveChanges(this, new EventArgs()); // Free the blocks of the structure, but // do not allow use of root block. Delete(0); m_deletedPos.RemoveAt(0); // (02.07.2007 09:01) // Remove all deleted blocks at the end of file. long lastPos = LastDataBlockPos(); int c = this.m_deletedPos.Count; long deletedpos; for (int k = c - 1; k >= 0; k--) { deletedpos = (long)this.m_deletedPos.GetByIndex(k); if (deletedpos > lastPos) this.m_deletedPos.Remove(deletedpos); else break; } // (01.07.2007 13:43) // Set the length to be shortest as possible. this.m_stream.SetLength(lastPos + BLOCK_SIZE); // Make sure the file length ends at a block. long rest = m_stream.Length % BLOCK_SIZE; if (rest != 0) this.m_stream.SetLength(m_stream.Length + BLOCK_SIZE - m_stream.Length % BLOCK_SIZE); m_stream.Seek(0, System.IO.SeekOrigin.Begin); BinaryWriter w = new BinaryWriter(m_stream); // Repair the delete index if a block is in use // but marked as deleted. ICollection oids = m_objectBlocks.Values; foreach (GObjectBlock objectBlock in oids) { foreach (long pos in objectBlock.Blocks) { if (m_deletedPos.Contains(pos)) m_deletedPos.Remove(pos); } } ArrayList oidBlocks = new ArrayList(); oidBlocks.Add(0L); // Write number of object blocks. WriteOIDInt32(m_objectBlocks.Count, w, oidBlocks); int i = 0; foreach (GObjectBlock objectBlock in oids) { if (objectBlock.OID != 0) { /* // Stop if invalid object block. System.Diagnostics.Debug.Assert(objectBlock.OID != -1, "Invalid Object Block", "The OID of this Object Block is not set."); // Stop if the number of bytes is not correct. System.Diagnostics.Debug.Assert(objectBlock.CountBytes <= objectBlock.Blocks.Length * BLOCK_SIZE && objectBlock.CountBytes >= (objectBlock.Blocks.Length - 1) * BLOCK_SIZE, "Invalid object size", "The size of object in bytes is larger than\n the number of blocks multiplied the block size"); */ WriteOIDInt64(objectBlock.OID, w, oidBlocks); WriteOIDInt32(objectBlock.CountBytes, w, oidBlocks); // Write block positions. WriteOIDInt32(objectBlock.Blocks.Length, w, oidBlocks); int j = 0; foreach (long pos in objectBlock.Blocks) { /* // Stop if invalid block pos. System.Diagnostics.Debug.Assert(pos - m_stream.Length <= BLOCK_SIZE * 4194304, "Invalid Block Position", "The block position was invalid because it points to a position 1 GB after the end of file."); */ WriteOIDInt64(pos, w, oidBlocks); j++; } i++; } } // Write number of deleted object blocks. WriteOIDInt32(this.m_deletedPos.Count, w, oidBlocks); ICollection positions = m_deletedPos.Values; long[] positionsTable = new long[positions.Count]; positions.CopyTo(positionsTable, 0); foreach (long pos in positionsTable) { WriteOIDInt64(pos, w, oidBlocks); } GObjectBlock oidBlock = new GObjectBlock(); oidBlock.Blocks = new long[oidBlocks.Count]; oidBlocks.CopyTo(oidBlock.Blocks, 0); oidBlock.OID = 0L; oidBlock.CountBytes = oidBlock.Blocks.Length * BLOCK_SIZE; m_objectBlocks.Add(oidBlock.OID, oidBlock); } }
// (05.04.2007 10:19) // Reads oids internally in the file. public void ReadOIDs() { m_oidPos = 0; // Make sure the file length ends at a block. long rest = m_stream.Length % BLOCK_SIZE; if (rest != 0) this.m_stream.SetLength(m_stream.Length + BLOCK_SIZE - m_stream.Length % BLOCK_SIZE); this.m_stream.Seek(0, System.IO.SeekOrigin.Begin); this.m_objectBlocks.Clear(); this.m_deletedPos.Clear(); GObjectBlock oidBlock = new GObjectBlock(); if (m_stream.Length == 0) { oidBlock.OID = 0L; oidBlock.CountBytes = BLOCK_SIZE; oidBlock.Blocks = new long[]{0}; m_objectBlocks.Add(0L, oidBlock); return; } BinaryReader r = new BinaryReader(m_stream); ArrayList oidBlocks = new ArrayList(); oidBlocks.Add(0L); int countObjectBlocks = ReadOIDInt32(r, oidBlocks); long readPos = 0; for (int i = 0; i < countObjectBlocks; i++) { GObjectBlock objectBlock = new GObjectBlock(); objectBlock.OID = ReadOIDInt64(r, oidBlocks); if (objectBlock.OID != 0) { if (objectBlock.OID > m_lastOID) m_lastOID = objectBlock.OID; objectBlock.CountBytes = ReadOIDInt32(r, oidBlocks); // Read block positions. int blockCount = ReadOIDInt32(r, oidBlocks); // Stop if the number of bytes is not correct. System.Diagnostics.Debug.Assert(objectBlock.CountBytes <= blockCount * BLOCK_SIZE && objectBlock.CountBytes >= (blockCount - 1) * BLOCK_SIZE, "Invalid object size", "The size of object in bytes is larger than\n the number of blocks multiplied the block size"); objectBlock.Blocks = new long[blockCount]; for (int j = 0; j < blockCount; j++) { readPos = ReadOIDInt64(r, oidBlocks); // Repear delete index if the block is used. if (this.m_deletedPos.Contains(readPos)) this.m_deletedPos.Remove(readPos); objectBlock.Blocks[j] = readPos; } // Add object block. m_objectBlocks.Add(objectBlock.OID, objectBlock); } } // Read deleted block positions. int deletedBlocks = ReadOIDInt32(r, oidBlocks); for (int i = 0; i < deletedBlocks; i++) { long pos = ReadOIDInt64(r, oidBlocks); if (!m_deletedPos.Contains(pos)) m_deletedPos.Add(pos, pos); } oidBlock.Blocks = new long[oidBlocks.Count]; oidBlocks.CopyTo(oidBlock.Blocks, 0); oidBlock.OID = 0L; oidBlock.CountBytes = oidBlock.Blocks.Length * BLOCK_SIZE; m_objectBlocks.Add(oidBlock.OID, oidBlock); }
// Create an empty object block, // prepared for stream writing. public GObjectBlock GetEmptyBlock(long oid) { GObjectBlock objectBlock = new GObjectBlock(); objectBlock.OID = oid; objectBlock.CountBytes = 0; objectBlock.Blocks = new long[]{}; this.m_objectBlocks.Add(oid, objectBlock); return objectBlock; }
public OdbStream(GODB odb, long oid) { m_odb = odb; if (!m_odb.ReadOnly && !m_odb.Contains(oid)) m_objectBlock = m_odb.GetEmptyBlock(oid); else m_objectBlock = m_odb.GetObjectBlock(oid); }
private void ReserveOID(int bytesLength) { long oid = 0L; // Write block on new position. GObjectBlock objectBlock = new GObjectBlock(); objectBlock.OID = oid; objectBlock.CountBytes = bytesLength; // Delete old object block. Delete(oid); // Compute the number of blocks needed. int countBlocks = (int)Math.Ceiling(objectBlock.CountBytes / (double)BLOCK_SIZE); objectBlock.Blocks = this.FindNewOIDPos(countBlocks); // Add new object block. m_objectBlocks.Add(oid, objectBlock); if (oid > m_lastOID) m_lastOID = oid; }
/// <summary> /// Saves bytes. /// If the OID writed has larger value than /// the automatically created OID, the next /// generated OID will follow the writed OID. /// </summary> /// <param name="oid">The OID (object identifier).</param> /// <param name="bytes">The bytes to write.</param> public void Write(long oid, byte[] bytes) { lock (m_dummy) { // Write block on new position. GObjectBlock objectBlock = new GObjectBlock(); objectBlock.OID = oid; objectBlock.CountBytes = bytes.Length; // Delete old object block. Delete(oid); // Compute the number of blocks needed. int countBlocks = (int)Math.Ceiling(objectBlock.CountBytes / (double)BLOCK_SIZE); objectBlock.Blocks = this.FindNewPos(countBlocks); for (long i = 0; i < countBlocks; i++) { long pos = i * BLOCK_SIZE; m_stream.Seek(objectBlock.Blocks[i], System.IO.SeekOrigin.Begin); m_stream.Write(bytes, (int)pos, (int)(Math.Min(BLOCK_SIZE, bytes.Length - pos))); } // Add new object block. m_objectBlocks.Add(oid, objectBlock); if (oid > m_lastOID) m_lastOID = oid; } }