func main0(fn string, oMax int, w func(s string, a ...interface{}), oStat bool, first, last string, dump bool, oBuckets bool) error { f, err := os.Open(fn) // O_RDONLY if err != nil { return err } defer f.Close() bits, err := ioutil.TempFile("", "kvaudit-") if err != nil { return err } defer func() { nm := bits.Name() bits.Close() os.Remove(nm) }() a, err := lldb.NewAllocator(lldb.NewInnerFiler(lldb.NewSimpleFileFiler(f), 16), &lldb.Options{}) if err != nil { return err } cnt := 0 var stats lldb.AllocStats err = a.Verify(lldb.NewSimpleFileFiler(bits), func(err error) bool { cnt++ w("%d: %v\n", cnt, err) return cnt < oMax }, &stats) if err != nil { return err } if oStat { w("Handles %10d // total valid handles in use\n", stats.Handles) w("Compression %10d // number of compressed blocks\n", stats.Compression) w("TotalAtoms %10d // total number of atoms == AllocAtoms + FreeAtoms\n", stats.TotalAtoms) w("AllocBytes %10d // bytes allocated (after decompression, if/where used)\n", stats.AllocBytes) w("AllocAtoms %10d // atoms allocated/used, including relocation atoms\n", stats.AllocAtoms) w("Relocations %10d // number of relocated used blocks\n", stats.Relocations) w("FreeAtoms %10d // atoms unused\n", stats.FreeAtoms) } if oBuckets { var alloc, free [14]int64 sizes := [14]int64{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 4112} for atoms, cnt := range stats.AllocMap { if atoms >= 4096 { alloc[13] += cnt continue } for i := range sizes { if sizes[i+1] > atoms { alloc[i] += cnt break } } } for atoms, cnt := range stats.FreeMap { if atoms > 4096 { free[13] += cnt continue } for i := range sizes { if sizes[i+1] > atoms { free[i] += cnt break } } } w("Alloc blocks\n") for i, v := range alloc { w("%4d: %10d\n", sizes[i], v) } w("Free blocks\n") for i, v := range free { w("%4d: %10d\n", sizes[i], v) } } if !(first != "" || last != "" || dump) { return nil } t, err := lldb.OpenBTree(a, nil, 1) if err != nil { return err } dw := bufio.NewWriter(os.Stdout) defer dw.Flush() var e *lldb.BTreeEnumerator switch { case first != "": e, _, err = t.Seek([]byte(first)) default: e, err = t.SeekFirst() } if err != nil { if err == io.EOF { err = nil } return err } blast := []byte(last) sep := []byte("->") for { k, v, err := e.Next() if err != nil { if err == io.EOF { err = nil } return err } dw.WriteString(fmt.Sprintf("+%d,%d:", len(k), len(v))) dw.Write(k) dw.Write(sep) dw.Write(v) dw.WriteByte('\n') if len(blast) != 0 && bytes.Compare(k, blast) >= 0 { break } } return nil }
func main0(fn string, oMax int, w func(s string, a ...interface{}), oStat bool, first, last string, dump bool) error { f, err := os.Open(fn) // O_RDONLY if err != nil { return err } defer f.Close() bits, err := ioutil.TempFile("", "kvaudit-") if err != nil { return err } defer bits.Close() a, err := lldb.NewAllocator(lldb.NewInnerFiler(lldb.NewSimpleFileFiler(f), 16), &lldb.Options{}) if err != nil { return err } cnt := 0 var stats lldb.AllocStats err = a.Verify(lldb.NewSimpleFileFiler(bits), func(err error) bool { cnt++ w("%d: %v\n", cnt, err) return cnt < oMax }, &stats) if oStat { w("%#v\n", &stats) } if err != nil { return err } if !(first != "" || last != "" || dump) { return nil } t, err := lldb.OpenBTree(a, nil, 1) if err != nil { return err } dw := bufio.NewWriter(os.Stdout) defer dw.Flush() var e *lldb.BTreeEnumerator switch { case first != "": e, _, err = t.Seek([]byte(first)) default: e, err = t.SeekFirst() } if err != nil { if err == io.EOF { err = nil } return err } blast := []byte(last) sep := []byte("->") for { k, v, err := e.Next() if err != nil { if err == io.EOF { err = nil } return err } dw.WriteString(fmt.Sprintf("+%d,%d:", len(k), len(v))) dw.Write(k) dw.Write(sep) dw.Write(v) dw.WriteByte('\n') if len(blast) != 0 && bytes.Compare(k, blast) >= 0 { break } } return nil }