Esempio n. 1
0
        /// <summary>
        ///     Write a block and return the offset after the block
        /// </summary>
        /// <param name="block"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        private long WriteBlock(PersistentBlock block, long offset)
        {
            StorageStream.Seek(offset, SeekOrigin.Begin);
            var writer = new BinaryWriter(StorageStream);

            block.Write(writer);
            writer.Flush();

            return(StorageStream.Position);
        }
Esempio n. 2
0
        /// <summary>
        ///     Remove dirty blocks thus compacting the storage
        /// </summary>
        public void CleanStorage()
        {
            if (File.Exists(TempFileName))
            {
                File.Delete(TempFileName);
            }

            var fullPath = Path.Combine(DataPath, StorageFileName);
            var tempPath = Path.Combine(DataPath, TempFileName);

            using (var tempStream = new FileStream(tempPath, FileMode.Create))
            {
                var writer = new BinaryWriter(tempStream);
                StorageStream.Dispose();

                StorageStream = new FileStream(fullPath, FileMode.OpenOrCreate);

                var reader = new BinaryReader(StorageStream);

                var  block  = new PersistentBlock();
                long offset = 0;


                // read all the blocks
                while (block.Read(reader))
                {
                    if (block.BlockStatus == BlockStatus.Active)
                    {
                        offset = (int)StorageStream.Position;
                        block.Write(writer);
                    }
                }

                StorageSize = offset;

                writer.Flush();
                StorageStream.Dispose();
            }

            File.Delete(fullPath);

            File.Move(tempPath, fullPath);


            StorageStream = new FileStream(fullPath, FileMode.OpenOrCreate);

            InactiveBlockCount = 0;
        }
Esempio n. 3
0
        /// <summary>
        ///     For recovery tests only
        /// </summary>
        /// <param name="primaryKey"></param>
        public void MakeCorruptedBlock(string primaryKey)
        {
            if (BlockInfoByPrimaryKey.TryGetValue(primaryKey, out var info))
            {
                var block = new PersistentBlock();
                StorageStream.Seek(info.Offset, SeekOrigin.Begin);
                var reader = new BinaryReader(StorageStream);
                block.Read(reader);

                block.Hash = block.Hash + 1; // the hash will not match so the block is corrupted
                StorageStream.Seek(info.Offset, SeekOrigin.Begin);

                var writer = new BinaryWriter(StorageStream);
                block.Write(writer);
            }
        }
Esempio n. 4
0
        public void DeleteBlock(string primaryKey, int transactionId)
        {
            if (BlockInfoByPrimaryKey.TryGetValue(primaryKey, out var blockInfo))
            {
                StorageStream.Seek(blockInfo.Offset, SeekOrigin.Begin);

                var reader = new BinaryReader(StorageStream);
                var block  = new PersistentBlock();
                block.Read(reader);
                if (block.BlockStatus != BlockStatus.Active)
                {
                    // if the same id ok. We are re executing a transaction that was not marked as Processed.
                    // It happens if the server crashes during the update of persistence blocks. The transaction is simply played
                    // again when the server is restarted
                    if (block.LastTransactionId != transactionId)
                    {
                        throw new NotSupportedException(
                                  $"Trying to delete an inactive block for primary key {primaryKey}");
                    }
                }

                block.BlockStatus       = BlockStatus.Deleted;
                block.LastTransactionId = transactionId;

                StorageStream.Seek(blockInfo.Offset, SeekOrigin.Begin);
                var writer = new BinaryWriter(StorageStream);
                block.Write(writer);
                writer.Flush();

                BlockInfoByPrimaryKey.Remove(primaryKey);

                InactiveBlockCount++;

                _backupStorage?.DeleteBlock(primaryKey, transactionId);
            }
            else
            {
                throw new NotSupportedException($"Active block not found for primary key {primaryKey}");
            }
        }