Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Option Initialization Pattern #37

Merged
merged 1 commit into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading