Exemple #1
0
        public static IEnumerable <byte[]> Blocks(MYDBinaryReader br)
        {
            while (br.Position < br.Length)
            {
                MYDBlock root_block = MYDBlock.Read(br);
                //root_block.DumpStats();

                long post_block_processing_return_offset = br.Position;

                // Only follow blocks that are a 'starting block'
                if (!root_block.is_block_first)
                {
                    continue;
                }

                // Concatenate all blocks
                byte[] record_data = new byte[root_block.rec_len];
                {
                    MYDBlock block         = root_block;
                    int      record_data_i = 0;
                    while (true)
                    {
                        Array.Copy(block.data, 0, record_data, record_data_i, block.data_len);
                        record_data_i += block.data_len;
                        if (block.is_block_last)
                        {
                            break;
                        }

                        if (0 == block.next_filepos)
                        {
                            throw new GenericException("Expecting a file offset if we have more blocks!");
                        }
                        br.Seek(block.next_filepos);

                        //Logging.Info("Appending additional data from block at {0}", block.next_filepos);
                        block = MYDBlock.Read(br);
                        //block.DumpStats("\t");
                    }

                    if (record_data_i != root_block.rec_len)
                    {
                        throw new GenericException("Block building length {0} is different to expected length of {1}!", record_data_i, root_block.rec_len);
                    }
                }

                br.Seek(post_block_processing_return_offset);

                yield return(record_data);
            }
        }
        internal static MYDBlock Read(MYDBinaryReader br)
        {
            MYDBlock block = new MYDBlock();

            // Debugging purposes
            block.start_position = br.Position;

            // Start of header
            block.header = br.ReadByte();

            block.rec_len      = 0;
            block.data_len     = 0;
            block.block_len    = 0;
            block.next_filepos = 0;

            // See http://dev.mysql.com/doc/internals/en/layout-record-storage-frame.html
            // Or bottom of this code
            switch (block.header)
            {
            case 0:
                block.block_len        = br.Read3();
                block.block_len       -= 4; // Deleted blocks include the header in their total length...sigh.
                block.is_block_deleted = true;
                break;

            case 1:
                block.rec_len        = block.data_len = block.block_len = br.Read2();
                block.is_block_first = block.is_block_last = true;
                break;

            case 2:
                block.rec_len        = block.data_len = block.block_len = br.Read3();
                block.is_block_first = block.is_block_last = true;
                break;

            case 13:
                block.rec_len        = br.Read4();
                block.data_len       = block.block_len = br.Read3();
                block.next_filepos   = br.Read8();
                block.is_block_first = true;
                break;

            case 3:
                block.rec_len        = block.data_len = br.Read2();
                block.block_len      = block.rec_len + br.Read1();
                block.is_block_first = block.is_block_last = true;
                break;

            case 4:
                block.rec_len        = block.data_len = br.Read3();
                block.block_len      = block.rec_len + br.Read1();
                block.is_block_first = block.is_block_last = true;
                break;

            case 5:
                block.rec_len        = br.Read2();
                block.data_len       = block.block_len = br.Read2();
                block.next_filepos   = br.Read8();
                block.is_block_first = true;
                break;

            case 6:
                block.rec_len        = br.Read3();
                block.data_len       = block.block_len = br.Read3();
                block.next_filepos   = br.Read8();
                block.is_block_first = true;
                break;

            case 7:
                block.data_len      = block.block_len = br.Read2();
                block.is_block_last = true;
                break;

            case 8:
                block.data_len      = block.block_len = br.Read3();
                block.is_block_last = true;
                break;

            case 9:
                block.data_len      = br.Read2();
                block.block_len     = block.data_len + br.Read1();
                block.is_block_last = true;
                break;

            case 10:
                block.data_len      = br.Read3();
                block.block_len     = block.rec_len + br.Read1();
                block.is_block_last = true;
                break;

            case 11:
                block.data_len     = block.block_len = br.Read2();
                block.next_filepos = br.Read8();
                break;

            case 12:
                block.data_len     = block.block_len = br.Read3();
                block.next_filepos = br.Read8();
                break;

            default:
                break;
            }


            block.data = br.ReadBytes(block.block_len);

            return(block);
        }