public AllocationTableStruct GetIndexStruct(Int64 currentOffset, StreamStateBehaviour indexStreamStateBehaviour) { if (indexStreamStateBehaviour != StreamStateBehaviour.UseExistingStream) { throw new NotSupportedException("Only useexistingstream is currently supported "); } var result = new AllocationTableStruct { Pointers = new Int64[256] }; IndexStream.Seek(currentOffset, SeekOrigin.Begin); // // the stream is intentionaly left open // var binaryReader = new BinaryReader(IndexStream); for (int elementIndex = 0; elementIndex < 256; elementIndex++) { result.Pointers[elementIndex] = binaryReader.ReadInt64(); } return result; }
private Int64 GetOffsetInCurrentStream(Guid dataIdentifier, int currentIndexInGuid, Int64 currentOffset) { Int64 result; byte[] bytes = dataIdentifier.ToByteArray(); int indexerInGuid = bytes[currentIndexInGuid]; var currentIndexStruct = new AllocationTableStruct { Pointers = new Int64[256] }; IndexStream.Seek(currentOffset, SeekOrigin.Begin); var binaryReader = new BinaryReader(IndexStream); for (int elementIndex = 0; elementIndex < 256; elementIndex++) { currentIndexStruct.Pointers[elementIndex] = binaryReader.ReadInt64(); } if (currentIndexInGuid < 15) { long nextOffset = currentIndexStruct.Pointers[indexerInGuid]; if (nextOffset == 0) { // // file does not exist // result = 0; } else { // // recursively call BuildIndex for the next index in the guid // result = GetOffsetInCurrentStream(dataIdentifier, currentIndexInGuid + 1, nextOffset); } } else if (currentIndexInGuid == 15) { // // we reached the last index struct // if (currentIndexStruct.Pointers[indexerInGuid] == 0) { // // file does not exist // result = 0; } else { result = currentIndexStruct.Pointers[indexerInGuid]; } } else { throw new IndexOutOfRangeException(currentIndexInGuid.ToString()); } return result; }
private void BuildIndex(Guid dataIdentifier, int currentIndexInGuid, Int64 currentOffset, Int64 dataOffset, BuildIndexBehaviour buildIndexBehaviour, StreamStateBehaviour indexStreamStateBehaviour) { byte[] bytes = dataIdentifier.ToByteArray(); int indexerInGuid = bytes[currentIndexInGuid]; Int64 endOfFileOffset = IndexStream.Length; AllocationTableStruct currentIndexStruct = GetIndexStruct(currentOffset, indexStreamStateBehaviour); if (currentIndexInGuid < 15) { long nextOffset = currentIndexStruct.Pointers[indexerInGuid]; if (nextOffset == 0) { // // does not point to anywhere; this means we have to; // * append a new block at the end of the file, with 0-pointers for each guid indexer over there // * update the reference for the specific index in the guid to the end of the filestream // // update the struct currentIndexStruct.Pointers[indexerInGuid] = endOfFileOffset; // write the struct StoreStruct(currentOffset, currentIndexStruct); // create a new struct with offsets 0 for each index in guid var newIndexStruct = new AllocationTableStruct { Pointers = new Int64[256] }; StoreStruct(endOfFileOffset, newIndexStruct); nextOffset = endOfFileOffset; // // recursively call BuildIndex for the next index in the guid // BuildIndex(dataIdentifier, currentIndexInGuid + 1, nextOffset, dataOffset, buildIndexBehaviour, indexStreamStateBehaviour); } else { // // recursively call BuildIndex for the next index in the guid // BuildIndex(dataIdentifier, currentIndexInGuid + 1, nextOffset, dataOffset, buildIndexBehaviour, indexStreamStateBehaviour); } } else if (currentIndexInGuid == 15) { // // we reached the last index struct // switch (buildIndexBehaviour) { case BuildIndexBehaviour.OverrideWhenAlreadyExists: // // no matter if it already existed or not, we will override it // break; case BuildIndexBehaviour.ThrowExceptionWhenIndexAlreadyExists: if (currentIndexStruct.Pointers[indexerInGuid] == 0) { // // its still free, continue // break; } // // if we reach this point, it means the pointer was already allocated // throw new NotSupportedException(string.Format("Index {0} is already allocated", dataIdentifier)); default: throw new NotSupportedException(string.Format("{0} is an unsupported BuildIndexBehaviour", buildIndexBehaviour)); } currentIndexStruct.Pointers[indexerInGuid] = dataOffset; // store the index block StoreStruct(currentOffset, currentIndexStruct); } else { throw new IndexOutOfRangeException(currentIndexInGuid.ToString()); } }
private void StoreStruct(Int64 offsetInFileFromBegin, AllocationTableStruct indexStruct) { // // re-open the file to allow accessing the newly added bytes // // point to the end of the file IndexStream.Seek(offsetInFileFromBegin, SeekOrigin.Begin); // write the struct var binaryWriter = new BinaryWriter(IndexStream); foreach (Int64 c in indexStruct.Pointers) { binaryWriter.Write(c); } }
private static void CreateNewFileStorage_IndexFile(string indexFilename) { using (FileStream indexStream = File.Create(indexFilename)) { #region store the header var indexFileHeaderStruct = new IndexFileHeaderStruct { VersionMajor = VersionMajor, VersionMinor = VersionMinor }; string template = "[IndexFile of FileStorage. Check out www.constantum.com]"; template = template.PadRight(92, '-'); indexFileHeaderStruct.Text = template.ToCharArray(); #region store header // point to the beginning of the file indexStream.Seek(0, SeekOrigin.Begin); // write the struct // // the stream is intentionally left open // var binaryWriter = new BinaryWriter(indexStream); binaryWriter.Write(indexFileHeaderStruct.VersionMajor); binaryWriter.Write(indexFileHeaderStruct.VersionMinor); binaryWriter.Write(indexFileHeaderStruct.Text); #endregion #endregion #region store the initial index table const long offset = OffsetFirstIndexBlock; // create a new struct with offsets 0 for each index in guid var newIndexStruct = new AllocationTableStruct { Pointers = new Int64[256] }; // // re-open the file to allow accessing the newly added bytes // // point to the end of the file indexStream.Seek(offset, SeekOrigin.Begin); // write the struct foreach (Int64 c in newIndexStruct.Pointers) { binaryWriter.Write(c); } #endregion } }