예제 #1
0
 internal EntryInfo(IndexNode node)
 {
     _id = node.ID;
     _fileName = node.FileName + "." + node.FileExtension;
     _mimeType = MimeTypeConverter.Convert(node.FileExtension);
     _fileLength = node.FileLength;
 }
예제 #2
0
        public static void ReadFile(IndexNode node, EntryInfo entry, Stream stream, Engine engine)
        {
            var dataPage         = PageFactory.GetDataPage(node.DataPageID, engine.Reader, false);
            int metaDataStartPos = 0;
            int metaDataLength   = entry.FileMetadataLength;
            int dataStartPos     = metaDataStartPos + metaDataLength;

            int curReadPos = 0;

            if (dataPage != null && entry.FileMetadataLength > 0)
            {
                //first round
                //read file meta data
                while (curReadPos < metaDataLength)
                {
                    //1.marker
                    byte marker = ReadByte(dataPage.DataBlock, curReadPos, out curReadPos);
                    switch (marker)
                    {
                    case 1:    //date time
                        long binaryTime = ReadInt64(dataPage.DataBlock, curReadPos, out curReadPos);
                        entry.FileDateTime = DateTime.FromBinary(binaryTime);
                        break;

                    case 2:
                        //long filename
                        int    nameLen    = (int)ReadUInt16(dataPage.DataBlock, curReadPos, out curReadPos);
                        byte[] nameBuffer = new byte[nameLen];
                        Array.Copy(dataPage.DataBlock, curReadPos, nameBuffer, 0, nameLen);
                        entry.FileUrl = System.Text.Encoding.UTF8.GetString(nameBuffer);
                        curReadPos   += nameLen;
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                }
            }
            //-----------------------------------
            //data part
            int toReadLen = dataPage.DataBlockLength - curReadPos;

            while (dataPage != null)
            {
                stream.Write(dataPage.DataBlock, curReadPos, toReadLen);
                if (dataPage.NextPageID == uint.MaxValue)
                {
                    dataPage = null;
                }
                else
                {
                    dataPage = PageFactory.GetDataPage(dataPage.NextPageID, engine.Reader, false);
                    //reset
                    curReadPos = 0;
                    toReadLen  = dataPage.DataBlockLength;
                }
            }
        }
예제 #3
0
 internal EntryInfo(IndexNode node)
 {
     ID                 = node.ID;
     FileUrl            = node.FileUrl;
     FileLength         = node.FileLength;
     FileMetadataLength = node.FileMetaDataLength;
     //---------------------
     //no datetime or other metadata here
     //---------------------
 }
예제 #4
0
파일: EntryInfo.cs 프로젝트: prepare/FileDB
 internal EntryInfo(IndexNode node)
 {
     ID = node.ID;
     FileUrl = node.FileUrl;
     FileLength = node.FileLength;
     FileMetadataLength = node.FileMetaDataLength;
     //---------------------
     //no datetime or other metadata here             
     //---------------------
 }
예제 #5
0
        public IndexPage(uint pageID)
        {
            PageID = pageID;
            NextPageID = uint.MaxValue;
            NodeIndex = 0;
            Nodes = new IndexNode[IndexPage.NODES_PER_PAGE];
            IsDirty = false;

            for (int i = 0; i < IndexPage.NODES_PER_PAGE; i++)
            {
                var node = Nodes[i] = new IndexNode(this);
            }
        }
예제 #6
0
        public IndexPage(uint pageID)
        {
            PageID     = pageID;
            NextPageID = uint.MaxValue;
            NodeIndex  = 0;
            Nodes      = new IndexNode[IndexPage.NODES_PER_PAGE];
            IsDirty    = false;

            for (int i = 0; i < IndexPage.NODES_PER_PAGE; i++)
            {
                var node = Nodes[i] = new IndexNode(this);
            }
        }
예제 #7
0
        public IndexNode Search(Guid id)
        {
            // Take the root node from inital index page
            IndexNode rootIndexNode = IndexFactory.GetRootIndexNode(this);

            var indexNode = IndexFactory.BinarySearch(id, rootIndexNode, this);

            // Returns null with not found the record, return false
            if (indexNode == null || indexNode.IsDeleted)
            {
                return(null);
            }

            return(indexNode);
        }
예제 #8
0
        public static void InsertFile(IndexNode node, Stream stream, Engine engine)
        {
            DataPage dataPage   = null;
            var      buffer     = new byte[DataPage.DATA_PER_PAGE];
            uint     totalBytes = 0;

            int read        = 0;
            int dataPerPage = (int)DataPage.DATA_PER_PAGE;

            while ((read = stream.Read(buffer, 0, dataPerPage)) > 0)
            {
                totalBytes += (uint)read;

                if (dataPage == null) // First read
                {
                    dataPage = engine.GetPageData(node.DataPageID);
                }
                else
                {
                    dataPage = GetNewDataPage(dataPage, engine);
                }

                if (!dataPage.IsEmpty) // This is never to happend!!
                {
                    throw new FileDBException("Page {0} is not empty", dataPage.PageID);
                }

                Array.Copy(buffer, dataPage.DataBlock, read);
                dataPage.IsEmpty         = false;
                dataPage.DataBlockLength = (short)read;
            }

            // If the last page point to another one, i need to fix that
            if (dataPage.NextPageID != uint.MaxValue)
            {
                engine.Header.FreeDataPageID = dataPage.NextPageID;
                dataPage.NextPageID          = uint.MaxValue;
            }

            // Salve the last page on disk
            PageFactory.WriteToFile(dataPage, engine.Writer);

            // Save on node index that file length
            node.FileLength = totalBytes;
        }
예제 #9
0
        public static void ReadFile(IndexNode node, Stream stream, Engine engine)
        {
            var dataPage = PageFactory.GetDataPage(node.DataPageID, engine.Reader, false);

            while (dataPage != null)
            {
                stream.Write(dataPage.DataBlock, 0, dataPage.DataBlockLength);

                if (dataPage.NextPageID == uint.MaxValue)
                {
                    dataPage = null;
                }
                else
                {
                    dataPage = PageFactory.GetDataPage(dataPage.NextPageID, engine.Reader, false);
                }
            }
        }
예제 #10
0
        private static IndexNode BinaryInsertNode(IndexLink baseLink, IndexNode baseNode, EntryInfo entry, Engine engine)
        {
            // Must insert my new nodo
            var pageIndex = engine.GetFreeIndexPage();
            var newNode = pageIndex.Nodes[pageIndex.NodeIndex];

            baseLink.PageID = pageIndex.PageID;
            baseLink.Index = pageIndex.NodeIndex;

            newNode.UpdateFromEntry(entry);
            newNode.DataPageID = DataFactory.GetStartDataPageID(engine);

            if (pageIndex.PageID != baseNode.IndexPage.PageID)
                engine.CacheIndexPage.AddPage(baseNode.IndexPage, true);

            engine.CacheIndexPage.AddPage(pageIndex, true);

            return newNode;
        }
예제 #11
0
        // Implement file physic storage
        public void Write(EntryInfo entry, Stream stream)
        {
            // Take the first index page
            IndexNode rootIndexNode = IndexFactory.GetRootIndexNode(this);

            // Search and insert the index
            var indexNode = IndexFactory.BinaryInsert(entry, rootIndexNode, this);

            // In this moment, the index are ready and saved. I use to add the file
            DataFactory.InsertFile(indexNode, stream, this);

            // Update entry information with file length (I know file length only after read all)
            entry.FileLength = indexNode.FileLength;

            // Only after insert all stream file I confirm that index node is valid
            indexNode.IsDeleted = false;

            // Mask header as dirty for save on dispose
            Header.IsDirty = true;
        }
예제 #12
0
        private static IndexNode BinaryInsertNode(IndexLink baseLink, IndexNode baseNode, EntryInfo entry, Engine engine)
        {
            // Must insert my new nodo
            var pageIndex = engine.GetFreeIndexPage();
            var newNode   = pageIndex.Nodes[pageIndex.UsedNodeCount];

            baseLink.PageID = pageIndex.PageID;
            baseLink.Index  = pageIndex.UsedNodeCount;

            newNode.UpdateFromEntry(entry);
            newNode.DataPageID = DataFactory.GetStartDataPageID(engine);

            if (pageIndex.PageID != baseNode.IndexPage.PageID)
            {
                engine.CacheIndexPage.AddPage(baseNode.IndexPage, true);
            }

            engine.CacheIndexPage.AddPage(pageIndex, true);

            return(newNode);
        }
예제 #13
0
        public static void InsertFile(IndexNode node, Stream stream, Engine engine)
        {
            DataPage dataPage = null;
            var buffer = new byte[DataPage.DATA_PER_PAGE];
            uint totalBytes = 0;

            int read = 0;
            int dataPerPage = (int)DataPage.DATA_PER_PAGE;

            while ((read = stream.Read(buffer, 0, dataPerPage)) > 0)
            {
                totalBytes += (uint)read;

                if (dataPage == null) // First read
                    dataPage = engine.GetPageData(node.DataPageID);
                else
                    dataPage = GetNewDataPage(dataPage, engine);

                if (!dataPage.IsEmpty) // This is never to happend!!
                    throw new FileDBException("Page {0} is not empty", dataPage.PageID);

                Array.Copy(buffer, dataPage.DataBlock, read);
                dataPage.IsEmpty = false;
                dataPage.DataBlockLength = (short)read;
            }

            // If the last page point to another one, i need to fix that
            if (dataPage.NextPageID != uint.MaxValue)
            {
                engine.Header.FreeDataPageID = dataPage.NextPageID;
                dataPage.NextPageID = uint.MaxValue;
            }

            // Salve the last page on disk
            PageFactory.WriteToFile(dataPage, engine.Writer);

            // Save on node index that file length
            node.FileLength = totalBytes;
        }
예제 #14
0
        public static IndexNode BinaryInsert(EntryInfo target, IndexNode baseNode, Engine engine)
        {
            var dif = baseNode.ID.CompareTo(target.ID);

            if (dif == 1) // > Maior (Right)
            {
                if (baseNode.Right.IsEmpty)
                    return BinaryInsertNode(baseNode.Right, baseNode, target, engine);
                else
                    return BinaryInsert(target, GetChildIndexNode(baseNode.Right, engine), engine);
            }
            else if (dif == -1) // < Menor (Left)
            {
                if (baseNode.Left.IsEmpty)
                    return BinaryInsertNode(baseNode.Left, baseNode, target, engine);
                else
                    return BinaryInsert(target, GetChildIndexNode(baseNode.Left, engine), engine);
            }
            else
            {
                throw new FileDBException("Same GUID?!?");
            }
        }
예제 #15
0
        public static IndexNode BinarySearch(Guid target, IndexNode baseNode, Engine engine)
        {
            var dif = baseNode.ID.CompareTo(target);

            if (dif == 1) // > Maior (Right)
            {
                if (baseNode.Right.IsEmpty) // If there no ones on right, GUID not found
                    return null;
                else
                    return BinarySearch(target, GetChildIndexNode(baseNode.Right, engine), engine); // Recursive call on right node
            }
            else if (dif == -1) // < Menor (Left)
            {
                if (baseNode.Left.IsEmpty) // If there no ones on left, GUID not found
                    return null;
                else
                    return BinarySearch(target, GetChildIndexNode(baseNode.Left, engine), engine); // Recursive call on left node
            }
            else
            {
                // Found it
                return baseNode;
            }
        }
예제 #16
0
        public static void InsertFile(IndexNode node, EntryInfo enInfo, Stream stream, Engine engine)
        {
            var buffer = new byte[DataPage.DATA_PER_PAGE];

            int      dataFreeInPage = DataPage.DATA_PER_PAGE;
            int      writePos       = 0;
            int      read           = 0;
            DataPage dataPage       = engine.GetDataPage(node.DataPageID);

            if (!dataPage.IsEmpty) // This is never to happend!!
            {
                throw new FileDBException("Page {0} is not empty", dataPage.PageID);
            }
            //-----------------------
            //write metadata
            //1. datetime of file
            DateTime filedtm = enInfo.FileDateTime;

            //--------------------------
            writePos = WriteByte(dataPage.DataBlock, 0, 1);                          //marker - 1
            writePos = WriteInt64(dataPage.DataBlock, writePos, filedtm.ToBinary()); //data part
            //--------------------------
            //2. long filename (if has long filename)
            //-----------------------
            if (enInfo.HasLongFileName)
            {
                //write full filename here
                byte[] longFileNameBuff = System.Text.Encoding.UTF8.GetBytes(enInfo.FileUrl);
                int    buffLen          = longFileNameBuff.Length;
                if (buffLen > 512)
                {
                    //for this version ***
                    throw new Exception("file name must not longer than 512 bytes");
                }
                writePos = WriteByte(dataPage.DataBlock, writePos, 2);                  //marker 2 long filename
                //--------
                writePos = WriteUInt16(dataPage.DataBlock, writePos, (ushort)buffLen);  //2 bytes length of buffer
                writePos = WriteBuffer(dataPage.DataBlock, writePos, longFileNameBuff); //buffer
                //--------
            }

            dataPage.IsEmpty         = false;
            dataPage.DataBlockLength = (short)writePos;
            dataFreeInPage          -= writePos;


            node.FileMetaDataLength = (ushort)writePos;
            //-----------------------
            bool isFirstRound = true;
            uint fileLength   = 0;

            while ((read = stream.Read(buffer, 0, dataFreeInPage)) > 0)
            {
                //if we have some data to write
                fileLength += (uint)read;
                if (!isFirstRound)
                {
                    dataPage = GetNewDataPage(dataPage, engine);
                    if (!dataPage.IsEmpty) // This is never to happend!!
                    {
                        throw new FileDBException("Page {0} is not empty", dataPage.PageID);
                    }
                }
                writePos                 = WriteBuffer(dataPage.DataBlock, writePos, buffer, read);
                dataPage.IsEmpty         = false;
                dataPage.DataBlockLength = (short)writePos;
                //----------------------------------------------
                //reset  for next
                dataFreeInPage = DataPage.DATA_PER_PAGE;
                writePos       = 0;
                isFirstRound   = false;
                //----------------------------------------------
            }


            // If the last page point to another one, i need to fix that
            if (dataPage.NextPageID != uint.MaxValue)
            {
                engine.Header.FreeDataPageID = dataPage.NextPageID;
                dataPage.NextPageID          = uint.MaxValue;
            }

            // Save the last page on disk
            PageFactory.WriteToFile(dataPage, engine.Writer);

            // Save on node index that file length
            node.FileLength = fileLength;
        }
예제 #17
0
        public static void ReadFile(IndexNode node, Stream stream, Engine engine)
        {
            var dataPage = PageFactory.GetDataPage(node.DataPageID, engine.Reader, false);

            while (dataPage != null)
            {
                stream.Write(dataPage.DataBlock, 0, dataPage.DataBlockLength);

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