package main import ( "encoding/binary" "fmt" "io" "os" "text/tabwriter" "igit.com/xbase/raft/db" ) const ( FlagDeleted = 0x00 FlagValid = 0x01 HeaderSize = 9 ) func main() { if len(os.Args) < 2 { fmt.Println("Usage: go run main.go ") return } dataDir := os.Args[1] dataFile := dataDir + "/values.data" f, err := os.Open(dataFile) if err != nil { fmt.Printf("Error opening file: %v\n", err) return } defer f.Close() fmt.Printf("Scanning storage file: %s\n\n", dataFile) w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', tabwriter.Debug) fmt.Fprintln(w, "Offset\tFlag\tStatus\tCapacity\tLength\tContent") fmt.Fprintln(w, "------\t----\t------\t--------\t------\t-------") offset := int64(0) reader := f for { // Read Header header := make([]byte, HeaderSize) if _, err := reader.ReadAt(header, offset); err != nil { if err == io.EOF { break } // If we hit EOF during read, it might be partial read at end if n, _ := reader.ReadAt(header, offset); n == 0 { break } fmt.Printf("Error reading header at offset %d: %v\n", offset, err) break } flag := header[0] cap := binary.LittleEndian.Uint32(header[1:]) length := binary.LittleEndian.Uint32(header[5:]) status := "VALID" if flag == FlagDeleted { status = "DELETED" } // Read Data // Even if deleted, we read to show what was there (or just skip) // But strictly we should read `cap` bytes to advance offset correctly. data := make([]byte, cap) if _, err := reader.ReadAt(data, offset+HeaderSize); err != nil { fmt.Printf("Error reading data at offset %d: %v\n", offset+HeaderSize, err) break } // Only show actual data content up to length, but indicate full capacity content := "" if flag == FlagValid { if length <= cap { content = string(data[:length]) } else { content = fmt.Sprintf(" cap=%d>", length, cap) } } else { content = "" // Optionally we could try to show it if we wanted to debug if length <= cap { content = fmt.Sprintf("", string(data[:length])) } } fmt.Fprintf(w, "%d\t0x%02X\t%s\t%d\t%d\t%q\n", offset, flag, status, cap, length, content) offset += int64(HeaderSize + int(cap)) } w.Flush() fmt.Println() // Also try to open Engine to show logical view e, err := db.NewEngine(dataDir) if err == nil { fmt.Println("Logical Key-Value View (Active Keys):") fmt.Println("-------------------------------------") // We need to expose some way to iterate keys in Engine for debug // Since Engine doesn't expose iterator, we can't easily list all keys without modifying Engine. // For now, let's just inspect the raw file structure which was the main request. // But wait, user asked for "format output table data". // Ideally we modify Engine to support iteration or just rely on file scan. // The file scan above shows PHYSICAL layout. // Let's add a simple usage demo to generate some data if dir is empty. e.Close() } }