OpenRead() method that returns a stream

Jan 23, 2011 at 12:39 PM

Instead of writing the file form FileDB in a stream or a file, it is sometimes usefull to have a readonly stream that directly operates on the DB without copying to memory.

 

Something like this (maybe needs improvment):

using System;
using System.IO;

namespace Numeria.IO
{
    public sealed class FileDBStream : Stream
    {
        private Engine _engine = null;
        private readonly long _streamLength = 0;

        private long _streamPosition = 0;
        private DataPage _currentPage = null;
        private int _positionInPage = 0;

        internal FileDBStream(Engine engine, Guid id)
        {
            _engine = engine;

            var indexNode = _engine.Search(id);
            if (indexNode != null)
            {
                _streamLength = indexNode.FileLength;
                _currentPage = PageFactory.GetDataPage(indexNode.DataPageID, engine.Reader, false);
            }
        }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }

        public override bool CanWrite
        {
            get { return false; }
        }

        public override void Flush()
        {
            throw new NotSupportedException();
        }

        public override long Length
        {
            get { return _streamLength; }
        }

        public override long Position
        {
            get
            {
                return _streamPosition;
            }
            set
            {
                throw new NotSupportedException();
            }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            int bytesLeft = count;

            while (_currentPage != null && bytesLeft > 0)
            {
                int bytesToCopy = Math.Min(bytesLeft, _currentPage.DataBlockLength - _positionInPage);
                Buffer.BlockCopy(_currentPage.DataBlock, _positionInPage, buffer, offset, bytesToCopy);

                _positionInPage += bytesToCopy;
                bytesLeft -= bytesToCopy;
                offset += bytesToCopy;
                _streamPosition += bytesToCopy;

                if (_positionInPage >= _currentPage.DataBlockLength)
                {
                    _positionInPage = 0;

                    if (_currentPage.NextPageID == uint.MaxValue)
                        _currentPage = null;
                    else
                        _currentPage = PageFactory.GetDataPage(_currentPage.NextPageID, _engine.Reader, false);
                }
            }

            return count - bytesLeft;
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }

        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }
    }
}

What do you think?

Coordinator
Jan 23, 2011 at 6:05 PM

Hi tibel,

It's a nice ideia, I never thought about that. It's can be another method in FileDB class. I will test and implement this one. About your issue to translate the source code comments, I will try do my best (my written in English it's a little dificult). FileDB it's my first open source project and I coded in my last christmas holiday :) Can you be a FileDB developer to contribuite?

 

Jan 26, 2011 at 11:36 AM

Hi David,
when I find some spare time, I can do some little changes...for sure ;-)

The feature I'm really missing, is this OpenRead() method that returns a stream to the stored file.
Thanks for this great project.