RDB file parsing

I’m stuck on stage 26. Would it be possible to get RDB file for proper parsing? I am following RDB File Format and it would be helpful to get file for local test.

FB                          # Indicates a resizedb field
$length-encoded-int         # Size of the corresponding hash table
$length-encoded-int         # Size of the corresponding expire hash table

As per this block, I am expecting 2 integers however as per my logs, second integer is of value 0.

Here are my logs:

remote: [your_program] REDIS version: 0003
remote: [your_program] read_key_value, key: "redis-ver", value: "7.2.0"
remote: [your_program] 0xFA block, key: "redis-ver", value: "7.2.0"
remote: [your_program] read_key_value, key: "redis-bits", value: "@"
remote: [your_program] 0xFA block, key: "redis-bits", value: "@"
remote: [your_program] 0XFE block - DB Number: 0
remote: [your_program] Found first integer of length: 1
remote: [your_program] Found second integer of length: 0
remote: [your_program] 0xFB block, value1: 0, value2: 0

And here’s a snippet of my code:


        println!("REDIS version: {}", String::from_utf8(signature[5..].to_vec()).unwrap());
        let mut db_num = [0; 1];
        loop {
            //read next byte to interpret what type it is?
            let mut opcode = [0; 1];
            reader.read_exact(&mut opcode)?;
            match opcode[0] {
                0xFA => {
                    if let Ok((key, value)) = Self::read_key_value(&mut reader) {
                        println!("0xFA block, key: {:?}, value: {:?}",
                            String::from_utf8_lossy(&key),
                            String::from_utf8_lossy(&value));
                    }
                },
                0xFB => {
                    // read length encoded int
                    if let Ok(len1) = Self::encoded_length(&mut reader) {
                        println!("Found first integer of length: {}", len1);
                        let mut value1 = vec![0; len1];
                        reader.read_exact(&mut value1)?;
                        let hash_table_sz = match len1 {
                            1 => value1[0] as usize,
                            2 => 110, //u16::from_ne_bytes(value1) as usize,
                            4 => 220, //u32::from_ne_bytes(value1) as usize,
                            _ => 0,
                        };
                        if let Ok(len2) = Self::encoded_length(&mut reader) {
                            println!("Found second integer of length: {}", len2);
                            let mut value2 = vec![0; len2];
                            reader.read_exact(&mut value2)?;
                            let expire_hash_tbl_sz = match len2 {
                                1 => value2[0] as usize,
                                2 => 110, //u16::from_ne_bytes(value2) as usize,
                                4 => 220, //u32::from_ne_bytes(value2) as usize,
                                _ => 0,
                            };
                            println!("0xFB block, value1: {:?}, value2: {:?}", hash_table_sz, expire_hash_tbl_sz);
                        }
                    }
                },
                0xFC => {
                    println!("FC Block - please decode me!");
                    let mut expiry_time_ms_db = [0; 8];
                    reader.read_exact(&mut expiry_time_ms_db)?;
                    let expiry_time_ms = u64::from_ne_bytes(expiry_time_ms_db);
                    if let Ok((key, value)) = Self::read_key_value_with_type(&mut reader) {
                        println!("0xFC block - key: {}, value: {}, expiry: {} ms to be added in DB",
                        String::from_utf8_lossy(&key), String::from_utf8_lossy(&value), expiry_time_ms);
                    }
                },
                0xFD => {
                    println!("FD Block - please decode me!");
                    let mut expiry_time_sec_db = [0; 4];
                    reader.read_exact(&mut expiry_time_sec_db)?;
                    let expiry_time_sec = u32::from_ne_bytes(expiry_time_sec_db) as usize;
                    if let Ok((key, value)) = Self::read_key_value_with_type(&mut reader) {
                        println!("0xFD block - key: {}, value: {} with expiry {} sec to be added in DB",
                        String::from_utf8_lossy(&key), String::from_utf8_lossy(&value), expiry_time_sec);
                    }
                },
                0xFE => {
                    reader.read_exact(&mut db_num)?;
                    println!("0XFE block - DB Number: {}", db_num[0]);
                },
                0xFF => {
                    println!("0xFE block - received EOF opcode!!!");
                    break;
                },
                _ => {
                    println!("Invalid Opcode found: {}", opcode[0]);
                    return Err(std::io::Error::new(std::io::ErrorKind::Other,
                        format!("Invalid RDB Opcode found: {}", opcode[0])));
                }
            }
        }

@rajneeshks does this hint help?

Our tests create RDB files on the fly since they need to contain random values. You can find the code used to create rdb files here:

yes - perfect!! thank you so much @rohitpaulk

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.