Skip to content

Commit

Permalink
feat: add pagefile api (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevmo314 authored Jan 20, 2024
1 parent a4f4e83 commit d5e2537
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
31 changes: 31 additions & 0 deletions pkg/btree/pagefile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package btree

import "io"

type PageFile struct {
io.ReadWriteSeeker
PageSize int
}

func (pf *PageFile) Seek(offset int64, whence int) (int64, error) {
if offset == 0 && whence == io.SeekEnd {
// Seek to the end of the file
offset, err := pf.ReadWriteSeeker.Seek(0, io.SeekEnd)
if err != nil {
return 0, err
}
// If the offset is not a multiple of the page size, we need to pad the file
// with zeros to the next page boundary.
if pf.PageSize > 0 && offset%int64(pf.PageSize) != 0 {
// Calculate the number of bytes to pad
pad := int64(pf.PageSize) - (offset % int64(pf.PageSize))
// Write the padding
if _, err := pf.Write(make([]byte, pad)); err != nil {
return 0, err
}
return offset + pad, nil
}
return offset, nil
}
return pf.ReadWriteSeeker.Seek(offset, whence)
}
62 changes: 62 additions & 0 deletions pkg/btree/pagefile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package btree

import (
"io"
"testing"
)

func TestPageFile(t *testing.T) {
t.Run("no page size behaves like regular ReadWriteSeeker", func(t *testing.T) {
buf := newSeekableBuffer()
pf := &PageFile{
ReadWriteSeeker: buf,
}
if _, err := pf.Seek(0, io.SeekStart); err != nil {
t.Fatal(err)
}
if _, err := pf.Write([]byte("hello")); err != nil {
t.Fatal(err)
}
if _, err := pf.Seek(0, io.SeekStart); err != nil {
t.Fatal(err)
}
b := make([]byte, 5)
if _, err := pf.Read(b); err != nil {
t.Fatal(err)
}
if string(b) != "hello" {
t.Fatalf("expected %q, got %q", "hello", string(b))
}
})

t.Run("page size allocates pages on seek end", func(t *testing.T) {
buf := newSeekableBuffer()
pf := &PageFile{
ReadWriteSeeker: buf,
PageSize: 16,
}
if _, err := pf.Seek(0, io.SeekEnd); err != nil {
t.Fatal(err)
}
if _, err := pf.Write([]byte("hello")); err != nil {
t.Fatal(err)
}
if _, err := pf.Seek(0, io.SeekStart); err != nil {
t.Fatal(err)
}
b := make([]byte, 5)
if _, err := pf.Read(b); err != nil {
t.Fatal(err)
}
if string(b) != "hello" {
t.Fatalf("expected %q, got %q", "hello", string(b))
}
n, err := pf.Seek(0, io.SeekEnd)
if err != nil {
t.Fatal(err)
}
if n != 16 {
t.Fatalf("expected %d, got %d", 16, n)
}
})
}

0 comments on commit d5e2537

Please sign in to comment.