Skip to content

Commit

Permalink
Support Option Initialization Pattern (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
ghosx authored Jun 21, 2024
1 parent af7806b commit 509b76a
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 74 deletions.
11 changes: 5 additions & 6 deletions benchmark/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ var walFile *wal.WAL

func init() {
dir, _ := os.MkdirTemp("", "wal-benchmark-test")
opts := wal.Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: wal.GB,
}
var err error
walFile, err = wal.Open(opts)
walFile, err = wal.Open(
wal.WithDirPath(dir),
wal.WithSegmentFileExt(".SEG"),
wal.WithSegmentSize(wal.GB),
)
if err != nil {
panic(err)
}
Expand Down
2 changes: 1 addition & 1 deletion examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func main() {
walFile, _ := wal.Open(wal.DefaultOptions)
walFile, _ := wal.Open()
// write some data
chunkPosition, _ := walFile.Write([]byte("some data 1"))
// read by the position
Expand Down
37 changes: 37 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package wal

import "os"

type Option func(*Options)

// Options represents the configuration options for a Write-Ahead Log (WAL).
type Options struct {
// DirPath specifies the directory path where the WAL segment files will be stored.
Expand Down Expand Up @@ -45,3 +47,38 @@ var DefaultOptions = Options{
Sync: false,
BytesPerSync: 0,
}

// WithDirPath sets the directory path where the WAL segment files will be stored.
func WithDirPath(dir string) Option {
return func(o *Options) {
o.DirPath = dir
}
}

// WithSegmentSize sets the maximum size of each segment file in bytes.
func WithSegmentSize(size int64) Option {
return func(o *Options) {
o.SegmentSize = size
}
}

// WithSegmentFileExt sets the file extension of the segment files.
func WithSegmentFileExt(ext string) Option {
return func(o *Options) {
o.SegmentFileExt = ext
}
}

// WithSync sets the whether to synchronize writes through os buffer cache and down onto the actual disk.
func WithSync(sync bool) Option {
return func(o *Options) {
o.Sync = sync
}
}

// WithBytesPerSync sets the number of bytes to write before calling fsync.
func WithBytesPerSync(bytesPerSync uint32) Option {
return func(o *Options) {
o.BytesPerSync = bytesPerSync
}
}
9 changes: 7 additions & 2 deletions wal.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var (
type WAL struct {
activeSegment *segment // active segment file, used for new incoming writes.
olderSegments map[SegmentID]*segment // older segment files, only used for read.
options Options
options *Options
mu sync.RWMutex
bytesWrite uint32
renameIds []SegmentID
Expand All @@ -56,7 +56,12 @@ type Reader struct {
// Open opens a WAL with the given options.
// It will create the directory if not exists, and open all segment files in the directory.
// If there is no segment file in the directory, it will create a new one.
func Open(options Options) (*WAL, error) {
func Open(opts ...Option) (*WAL, error) {
options := &DefaultOptions
for _, opt := range opts {
opt(options)
}

if !strings.HasPrefix(options.SegmentFileExt, ".") {
return nil, fmt.Errorf("segment file extension must start with '.'")
}
Expand Down
128 changes: 63 additions & 65 deletions wal_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package wal

import (
"github.com/stretchr/testify/assert"
"io"
"os"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

func destroyWAL(wal *WAL) {
Expand All @@ -17,12 +18,11 @@ func destroyWAL(wal *WAL) {

func TestWAL_WriteALL(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-write-batch-1")
opts := Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: 32 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
defer destroyWAL(wal)

Expand All @@ -35,12 +35,11 @@ func TestWAL_WriteALL(t *testing.T) {

func TestWAL_Write(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-write1")
opts := Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: 32 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
defer destroyWAL(wal)

Expand Down Expand Up @@ -68,12 +67,11 @@ func TestWAL_Write(t *testing.T) {

func TestWAL_Write_large(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-write2")
opts := Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: 32 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
defer destroyWAL(wal)

Expand All @@ -82,12 +80,11 @@ func TestWAL_Write_large(t *testing.T) {

func TestWAL_Write_large2(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-write3")
opts := Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: 32 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
defer destroyWAL(wal)

Expand All @@ -96,12 +93,11 @@ func TestWAL_Write_large2(t *testing.T) {

func TestWAL_OpenNewActiveSegment(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-new-active-segment")
opts := Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: 32 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
defer destroyWAL(wal)

Expand All @@ -119,12 +115,11 @@ func TestWAL_OpenNewActiveSegment(t *testing.T) {

func TestWAL_IsEmpty(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-is-empty")
opts := Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: 32 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
defer destroyWAL(wal)

Expand All @@ -135,12 +130,11 @@ func TestWAL_IsEmpty(t *testing.T) {

func TestWAL_Reader(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-wal-reader")
opts := Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: 32 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
defer destroyWAL(wal)

Expand Down Expand Up @@ -174,7 +168,11 @@ func TestWAL_Reader(t *testing.T) {
err = wal.Close()
assert.Nil(t, err)

wal2, err := Open(opts)
wal2, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
defer func() {
_ = wal2.Close()
Expand Down Expand Up @@ -239,12 +237,11 @@ func testWriteAndIterate(t *testing.T, wal *WAL, size int, valueSize int) {

func TestWAL_Delete(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-delete")
opts := Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: 32 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
testWriteAndIterate(t, wal, 2000, 512)
assert.False(t, wal.IsEmpty())
Expand All @@ -253,19 +250,22 @@ func TestWAL_Delete(t *testing.T) {
err = wal.Delete()
assert.Nil(t, err)

wal, err = Open(opts)
wal, err = Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(32*1024*1024),
)
assert.Nil(t, err)
assert.True(t, wal.IsEmpty())
}

func TestWAL_ReaderWithStart(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-wal-reader-with-start")
opts := Options{
DirPath: dir,
SegmentFileExt: ".SEG",
SegmentSize: 8 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".SEG"),
WithSegmentSize(8*1024*1024),
)
assert.Nil(t, err)
defer destroyWAL(wal)

Expand Down Expand Up @@ -295,12 +295,11 @@ func TestWAL_ReaderWithStart(t *testing.T) {

func TestWAL_RenameFileExt(t *testing.T) {
dir, _ := os.MkdirTemp("", "wal-test-rename-ext")
opts := Options{
DirPath: dir,
SegmentFileExt: ".VLOG.1.temp",
SegmentSize: 8 * 1024 * 1024,
}
wal, err := Open(opts)
wal, err := Open(
WithDirPath(dir),
WithSegmentFileExt(".VLOG.1.temp"),
WithSegmentSize(8*1024*1024),
)
assert.Nil(t, err)
defer destroyWAL(wal)
testWriteAndIterate(t, wal, 20000, 512)
Expand All @@ -311,8 +310,7 @@ func TestWAL_RenameFileExt(t *testing.T) {
err = wal.RenameFileExt(".VLOG.1")
assert.Nil(t, err)

opts.SegmentFileExt = ".VLOG.1"
wal2, err := Open(opts)
wal2, err := Open(WithSegmentFileExt(".VLOG.1"))
assert.Nil(t, err)
defer func() {
_ = wal2.Close()
Expand Down

0 comments on commit 509b76a

Please sign in to comment.