diff --git a/README.md b/README.md index 877eca0..92ef0e0 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Replicated in-memory database and file store. ## TODO +* [ ] mdb: Tests for using `nil` snapshots ? * [ ] mdb: tests for sanitize and validate functions * [ ] Test: lib/wal iterator w/ corrupt file (random corruptions) * [ ] Test: lib/wal io.go diff --git a/mdb/pfile/freelist.go b/mdb/pfile/freelist.go index 3070e2d..27cae09 100644 --- a/mdb/pfile/freelist.go +++ b/mdb/pfile/freelist.go @@ -51,6 +51,10 @@ func (f *freeList) Push(pages ...uint64) { } } +func (f *freeList) SetNextPage(nextPage uint64) { + f.nextPage = nextPage +} + func (f *freeList) Pop(count int, out []uint64) []uint64 { out = out[:0] diff --git a/mdb/pfile/index.go b/mdb/pfile/index.go index 74d4caa..6d6898e 100644 --- a/mdb/pfile/index.go +++ b/mdb/pfile/index.go @@ -13,14 +13,19 @@ type Index struct { } func NewIndex(f *File) (*Index, error) { + maxPage, err := f.maxPage() + if err != nil { + return nil, err + } + idx := &Index{ - fList: newFreeList(0), + fList: newFreeList(maxPage), aList: *newAllocList(), seen: map[[2]uint64]struct{}{}, mask: []bool{}, } - err := f.iterate(func(pageID uint64, page dataPage) error { + err = f.iterate(func(pageID uint64, page dataPage) error { header := page.Header() switch header.PageType { case pageTypeHead: diff --git a/mdb/pfile/pagefile.go b/mdb/pfile/pagefile.go index c889e78..193f953 100644 --- a/mdb/pfile/pagefile.go +++ b/mdb/pfile/pagefile.go @@ -134,6 +134,21 @@ func (pf *File) writePage(page dataPage, id uint64) error { // Reading // ---------------------------------------------------------------------------- +func (pf *File) maxPage() (uint64, error) { + fi, err := pf.f.Stat() + if err != nil { + return 0, errs.IO.WithErr(err) + } + + fileSize := fi.Size() + if fileSize%pageSize != 0 { + return 0, errs.Corrupt.WithMsg("File size isn't a multiple of page size.") + } + + maxPage := uint64(fileSize / pageSize) + return maxPage, nil +} + func (pf *File) iterate(each func(pageID uint64, page dataPage) error) error { pf.lock.RLock() defer pf.lock.RUnlock()