// NewReader returns a new table reader for the file. Closing the reader will // close the file. func NewReader(f db.File, o *db.Options) *Reader { r := &Reader{ file: f, comparer: o.GetComparer(), verifyChecksums: o.GetVerifyChecksums(), } if f == nil { r.err = errors.New("leveldb/table: nil file") return r } stat, err := f.Stat() if err != nil { r.err = fmt.Errorf("leveldb/table: invalid table (could not stat file): %v", err) return r } var footer [footerLen]byte if stat.Size() < int64(len(footer)) { r.err = errors.New("leveldb/table: invalid table (file size is too small)") return r } _, err = f.ReadAt(footer[:], stat.Size()-int64(len(footer))) if err != nil && err != io.EOF { r.err = fmt.Errorf("leveldb/table: invalid table (could not read footer): %v", err) return r } if string(footer[footerLen-len(magic):footerLen]) != magic { r.err = errors.New("leveldb/table: invalid table (bad magic number)") return r } // Ignore the metaindex. _, n := decodeBlockHandle(footer[:]) if n == 0 { r.err = errors.New("leveldb/table: invalid table (bad metaindex block handle)") return r } // Read the index into memory. indexBH, n := decodeBlockHandle(footer[n:]) if n == 0 { r.err = errors.New("leveldb/table: invalid table (bad index block handle)") return r } r.index, r.err = r.readBlock(indexBH) return r }