Example #1
0
        /// <summary>
        ///     Writes a file contained in an archive to the cache.
        /// </summary>
        /// <param name="type"> The type of file. </param>
        /// <param name="file"> The id of the archive. </param>
        /// <param name="member"> The file within the archive. </param>
        /// <param name="data"> The data to write. </param>
        /// <exception cref="IOException"> if an I/O error occurs. </exception>
        public void Write(int type, int file, int member, ByteBuffer data)
        {
            /* grab the reference table */
            var tableContainer = Container.Decode(store.Read(255, type));
            var table          = ReferenceTable.Decode(tableContainer.GetData());

            /* create a new entry if necessary */
            var entry          = table.GetEntry(file);
            var oldArchiveSize = -1;

            if (entry == null)
            {
                entry = new ReferenceTable.Entry();
                table.PutEntry(file, entry);
            }
            else
            {
                oldArchiveSize = entry.Capacity();
            }

            /* add a child entry if one does not exist */
            var child = entry.GetEntry(member);

            if (child == null)
            {
                child = new ReferenceTable.ChildEntry();
                entry.PutEntry(member, child);
            }

            /* extract the current archive into memory so we can modify it */
            Archive archive;
            int     containerType,
                    containerVersion;
            Container container;

            if (file < store.GetFileCount(type) && oldArchiveSize != -1)
            {
                container        = Read(type, file);
                containerType    = container.GetType();
                containerVersion = container.GetVersion();
                archive          = Archive.Decode(container.GetData(), oldArchiveSize);
            }
            else
            {
                containerType    = Container.COMPRESSION_GZIP;
                containerVersion = 1;
                archive          = new Archive(member + 1);
            }

            /* expand the archive if it is not large enough */
            if (member >= archive.Size())
            {
                var newArchive = new Archive(member + 1);
                for (var id = 0; id < archive.Size(); id++)
                {
                    newArchive.PutEntry(id, archive.GetEntry(id));
                }
                archive = newArchive;
            }

            /* put the member into the archive */
            archive.PutEntry(member, data);

            /* create 'dummy' entries */
            for (var id = 0; id < archive.Size(); id++)
            {
                if (archive.GetEntry(id) == null)
                {
                    entry.PutEntry(id, new ReferenceTable.ChildEntry());
                    archive.PutEntry(id, ByteBuffer.allocate(1));
                }
            }

            /* write the reference table out again */
            tableContainer = new Container(tableContainer.GetType(), table.Encode());
            store.Write(255, type, tableContainer.Encode());

            /* and write the archive back to memory */
            container = new Container(containerType, archive.Encode(), containerVersion);
            Write(type, file, container);
        }
Example #2
0
        /// <summary>
        ///     Writes a file to the cache and updates the <seealso cref="ReferenceTable" /> that
        ///     it is associated with.
        /// </summary>
        /// <param name="type"> The type of file. </param>
        /// <param name="file"> The file id. </param>
        /// <param name="container"> The <seealso cref="Container" /> to write. </param>
        /// <exception cref="IOException"> if an I/O error occurs. </exception>
        public void Write(int type, int file, Container container)
        {
            /* we don't want people reading/manipulating these manually */
            if (type == 255)
            {
                throw new IOException("Reference tables can only be modified with the low level FileStore API!");
            }

            /* increment the container's version */
            container.SetVersion(container.GetVersion() + 1);

            /* decode the reference table for this index */
            var tableContainer = Container.Decode(store.Read(255, type));
            var table          = ReferenceTable.Decode(tableContainer.GetData());

            /* grab the bytes we need for the checksum */
            var buffer = container.Encode();
            var bytes  = new byte[buffer.limit() - 2]; // last two bytes are the version and shouldn't be included

            buffer.mark();
            try
            {
                buffer.position(0);
                buffer.get(bytes, 0, bytes.Length);
            }
            finally
            {
                buffer.reset();
            }

            /* calculate the new CRC checksum */
            var crc = new CRC32();

            crc.update(bytes, 0, bytes.Length);

            /* update the version and checksum for this file */
            var entry = table.GetEntry(file);

            if (entry == null)
            {
                /* create a new entry for the file */
                entry = new ReferenceTable.Entry();
                table.PutEntry(file, entry);
            }
            entry.SetVersion(container.GetVersion());
            entry.SetCrc((int)crc.getValue());

            /* calculate and update the whirlpool digest if we need to */
            if ((table.GetFlags() & ReferenceTable.FLAG_WHIRLPOOL) != 0)
            {
                var whirlpool = Whirlpool.Crypt(bytes, 0, bytes.Length);
                entry.SetWhirlpool(whirlpool);
            }

            /* update the reference table version */
            table.SetVersion(table.GetVersion() + 1);

            /* save the reference table */
            tableContainer = new Container(tableContainer.GetType(), table.Encode());
            store.Write(255, type, tableContainer.Encode());

            /* save the file itself */
            store.Write(type, file, buffer);
        }