コード例 #1
0
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentException"></exception>
        internal DataStream(
            IDataStreamStructureBuilder streamStructureBuilder,
            int blockSize,
            IFileSystemLockReleaseManager lockingManager,
            Guid idOfLockBeingHeld)
        {
            try
            {
                if (streamStructureBuilder == null)
                {
                    throw new ArgumentNullException("streamStructureBuilder");
                }
                if (lockingManager == null)
                {
                    throw new ArgumentNullException("lockingManager");
                }
                MethodArgumentValidator.ThrowIfIsDefault(idOfLockBeingHeld, "idOfLockBeingHeld");
                MethodArgumentValidator.ThrowIfNegative(blockSize, "blockSize");

                _streamStructureBuilder = streamStructureBuilder;
                _blockSize           = blockSize;
                _lockingManager      = lockingManager;
                _idOfLockBeingHeld   = idOfLockBeingHeld;
                _diskBlockEnumerator = streamStructureBuilder.CreateEnumerator();
            }
            catch (Exception)
            {
                GC.SuppressFinalize(this);

                throw;
            }
        }
コード例 #2
0
        private void Shrink(int newLength)
        {
            _streamStructureBuilder.SetSize(newLength);

            _diskBlockEnumerator = _streamStructureBuilder.CreateEnumerator();

            this.MoveToEnd();
        }
コード例 #3
0
        /// <summary>
        /// Записывает в поток указанное число байт из массива. Если поток недостаточного размера, он увеличивается.
        /// Запись производится, начиная с текущей позиции в потоке.
        /// </summary>
        /// <param name="bytesToWrite">Массив байт, данные из которого следует записать в поток.</param>
        /// <param name="arrayOffset">Указывает начальную позицию в массиве (<paramref name="bytesToWrite"/>), с которой нужно брать байты для записи.</param>
        /// <param name="count">Количество байт, которые, начиная с <paramref name="arrayOffset"/>, следует записать в поток.</param>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="MaximumFileSizeReachedException"></exception>
        public override void Write(byte[] bytesToWrite, int arrayOffset, int count)
        {
            if (bytesToWrite == null)
            {
                throw new ArgumentNullException("bytesToWrite");
            }

            // Note: этому методу, подозреваю, сильно не хватило тестов.

            MethodArgumentValidator.ThrowIfNegative(arrayOffset, "arrayOffset");
            MethodArgumentValidator.ThrowIfNegative(count, "count");

            if ((arrayOffset + count) > bytesToWrite.Length)
            {
                throw new ArgumentException("Не удастся прочитать {0} байт, начиная с позиции {1} в массиве. В массиве содержится следующее число элементов: {2}".FormatWith(count, arrayOffset, bytesToWrite.Length));
            }

            if (count == 0)
            {
                return;
            }

            Monitor.Enter(_stateChangeCriticalSection);

            try
            {
                this.ThrowIfDisposed();

                int numberOfBytesAvailable = this.Length - this.Position; // есть еще зажатые в выделенном блоке, ими мы занимаемся ниже.

                int numberOfBytesNeeded = count - numberOfBytesAvailable;

                bool canAvoidNewBlocksAcquisition =
                    _diskBlockEnumerator.Current.NumberOfBytesCanBeWrittenAtCurrentPosition >= numberOfBytesNeeded;

                if ((numberOfBytesNeeded > 0) && !canAvoidNewBlocksAcquisition)
                {
                    int oldBlockIndex          = _diskBlockEnumerator.Position;
                    int oldInsideBlockPosition = _diskBlockEnumerator.Current.Position;

                    _streamStructureBuilder.SetSize(_streamStructureBuilder.CurrentSize + numberOfBytesNeeded);

                    _diskBlockEnumerator = _streamStructureBuilder.CreateEnumerator();
                    _diskBlockEnumerator.SetPosition(oldBlockIndex);

                    if (!_diskBlockEnumerator.Current.IsNull)
                    {
                        _diskBlockEnumerator.Current.Position = oldInsideBlockPosition;
                    }
                }

                WriteBytesKnowingStreamLengthIsRight(bytesToWrite, arrayOffset, count);
            }
            catch (MaximumFileSizeReachedException)
            {
                throw new MaximumFileSizeReachedException("Не удаcтся записать {0} байт в файл: максимальный размер файла в текущей версии системы - {1} байт, текущий размер файла - {2} байт.".FormatWith(count, _streamStructureBuilder.MaximumSize, this.Length));
            }
            catch (NoFreeBlocksException)
            {
                throw new InsufficientSpaceException("Операция записи отменена: недостаточно места на диске для записи в поток следующего числа байт -- {0}".FormatWith(count));
            }
            finally
            {
                Monitor.Exit(_stateChangeCriticalSection);
            }
        }