Ejemplo n.º 1
0
        /// <summary>
        ///     Reads a file.
        /// </summary>
        /// <param name="type"> The type of the file. </param>
        /// <param name="id"> The id of the file. </param>
        /// <returns> A <seealso cref="ByteBuffer" /> containing the contents of the file. </returns>
        /// <exception cref="IOException"> if an I/O error occurs. </exception>
        public ByteBuffer Read(int type, int id)
        {
            if ((type < 0 || type >= indexChannels.Length) && type != 255)
            {
                throw new FileNotFoundException();
            }

            var indexChannel = type == 255 ? metaChannel : indexChannels[type];

            long ptr = id * Index.SIZE;

            if (ptr < 0 || ptr >= indexChannel.size())
            {
                throw new FileNotFoundException();
            }

            var buf = ByteBuffer.allocate(Index.SIZE);

            FileChannelUtils.ReadFully(indexChannel, buf, ptr);

            var index = Index.Decode((ByteBuffer)buf.flip());

            var data = ByteBuffer.allocate(index.GetSize());

            buf = ByteBuffer.allocate(Sector.SIZE);

            int chunk     = 0,
                remaining = index.GetSize();

            ptr = index.GetSector() * Sector.SIZE;
            do
            {
                buf.clear();
                FileChannelUtils.ReadFully(dataChannel, buf, ptr);
                var sector = Sector.Decode((ByteBuffer)buf.flip());

                if (remaining > Sector.DATA_SIZE)
                {
                    data.put(sector.GetData(), 0, Sector.DATA_SIZE);
                    remaining -= Sector.DATA_SIZE;

                    if (sector.GetType() != type)
                    {
                        throw new IOException("File type mismatch.");
                    }

                    if (sector.GetId() != id)
                    {
                        throw new IOException("File id mismatch.");
                    }

                    if (sector.GetChunk() != chunk++)
                    {
                        throw new IOException("Chunk mismatch.");
                    }

                    ptr = sector.GetNextSector() * Sector.SIZE;
                }
                else
                {
                    data.put(sector.GetData(), 0, remaining);
                    remaining = 0;
                }
            }while (remaining > 0);

            return((ByteBuffer)data.flip());
        }
Ejemplo n.º 2
0
        /// <summary>
        ///     Writes a file.
        /// </summary>
        /// <param name="type"> The type of the file. </param>
        /// <param name="id"> The id of the file. </param>
        /// <param name="data"> A <seealso cref="ByteBuffer" /> containing the contents of the file. </param>
        /// <param name="overwrite">
        ///     A flag indicating if the existing file should be
        ///     overwritten.
        /// </param>
        /// <returns> A flag indicating if the file was written successfully. </returns>
        /// <exception cref="IOException"> if an I/O error occurs. </exception>
        private bool Write(int type, int id, ByteBuffer data, bool overwrite)
        {
            if ((type < 0 || type >= indexChannels.Length) && type != 255)
            {
                throw new FileNotFoundException();
            }

            var indexChannel = type == 255 ? metaChannel : indexChannels[type];

            var        nextSector = 0;
            long       ptr        = id * Index.SIZE;
            ByteBuffer buf;
            Index      index;

            if (overwrite)
            {
                if (ptr < 0)
                {
                    throw new IOException();
                }
                if (ptr >= indexChannel.size())
                {
                    return(false);
                }

                buf = ByteBuffer.allocate(Index.SIZE);
                FileChannelUtils.ReadFully(indexChannel, buf, ptr);

                index      = Index.Decode((ByteBuffer)buf.flip());
                nextSector = index.GetSector();
                if (nextSector <= 0 || nextSector > dataChannel.size() * Sector.SIZE)
                {
                    return(false);
                }
            }
            else
            {
                nextSector = (int)((dataChannel.size() + Sector.SIZE - 1) / Sector.SIZE);
                if (nextSector == 0)
                {
                    nextSector = 1;
                }
            }

            index = new Index(data.remaining(), nextSector);
            indexChannel.write(index.Encode(), ptr);

            buf = ByteBuffer.allocate(Sector.SIZE);

            int chunk     = 0,
                remaining = index.GetSize();

            do
            {
                var curSector = nextSector;
                ptr        = curSector * Sector.SIZE;
                nextSector = 0;

                Sector sector;
                if (overwrite)
                {
                    buf.clear();
                    FileChannelUtils.ReadFully(dataChannel, buf, ptr);

                    sector = Sector.Decode((ByteBuffer)buf.flip());

                    if (sector.GetType() != type)
                    {
                        return(false);
                    }

                    if (sector.GetId() != id)
                    {
                        return(false);
                    }

                    if (sector.GetChunk() != chunk)
                    {
                        return(false);
                    }

                    nextSector = sector.GetNextSector();
                    if (nextSector < 0 || nextSector > dataChannel.size() / Sector.SIZE)
                    {
                        return(false);
                    }
                }

                if (nextSector == 0)
                {
                    overwrite  = false;
                    nextSector = (int)((dataChannel.size() + Sector.SIZE - 1) / Sector.SIZE);
                    if (nextSector == 0)
                    {
                        nextSector++;
                    }
                    if (nextSector == curSector)
                    {
                        nextSector++;
                    }
                }

                var bytes = new byte[Sector.DATA_SIZE];
                if (remaining < Sector.DATA_SIZE)
                {
                    data.get(bytes, 0, remaining);
                    nextSector = 0; // mark as EOF
                    remaining  = 0;
                }
                else
                {
                    remaining -= Sector.DATA_SIZE;
                    data.get(bytes, 0, Sector.DATA_SIZE);
                }

                sector = new Sector(type, id, chunk++, nextSector, bytes);
                dataChannel.write(sector.Encode(), ptr);
            }while (remaining > 0);

            return(true);
        }