ledisdb/wal/gen.go

138 lines
2.0 KiB
Go

package wal
import (
"encoding/binary"
"fmt"
"os"
"path"
"sync"
)
type FileIDGenerator struct {
LogIDGenerator
m sync.Mutex
f *os.File
id uint64
}
func NewFileIDGenerator(base string) (*FileIDGenerator, error) {
if err := os.MkdirAll(base, 0755); err != nil {
return nil, err
}
g := new(FileIDGenerator)
name := path.Join(base, "log.id")
var err error
if g.f, err = os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0644); err != nil {
return nil, err
}
s, _ := g.f.Stat()
if s.Size() == 0 {
g.id = 0
} else if s.Size() == 8 {
if err = binary.Read(g.f, binary.BigEndian, &g.id); err != nil {
g.f.Close()
return nil, err
} else if g.id == InvalidLogID {
g.f.Close()
return nil, fmt.Errorf("read invalid log id in %s", name)
}
} else {
g.f.Close()
return nil, fmt.Errorf("log id file %s is invalid", name)
}
return g, nil
}
func (g *FileIDGenerator) Reset(id uint64) error {
g.m.Lock()
defer g.m.Unlock()
if g.f == nil {
return fmt.Errorf("generator closed")
}
if g.id < id {
g.id = id
}
return nil
}
func (g *FileIDGenerator) GenerateID() (uint64, error) {
g.m.Lock()
defer g.m.Unlock()
if g.f == nil {
return 0, fmt.Errorf("generator closed")
}
if _, err := g.f.Seek(0, os.SEEK_SET); err != nil {
return 0, nil
}
id := g.id + 1
if err := binary.Write(g.f, binary.BigEndian, id); err != nil {
return 0, nil
}
g.id = id
return id, nil
}
func (g *FileIDGenerator) Close() error {
g.m.Lock()
defer g.m.Unlock()
if g.f != nil {
err := g.f.Close()
g.f = nil
return err
}
return nil
}
type MemIDGenerator struct {
m sync.Mutex
LogIDGenerator
id uint64
}
func NewMemIDGenerator(baseID uint64) *MemIDGenerator {
g := &MemIDGenerator{id: baseID}
return g
}
func (g *MemIDGenerator) Reset(id uint64) error {
g.m.Lock()
defer g.m.Unlock()
if g.id < id {
g.id = id
}
return nil
}
func (g *MemIDGenerator) GenerateID() (uint64, error) {
g.m.Lock()
defer g.m.Unlock()
g.id++
id := g.id
return id, nil
}
func (g *MemIDGenerator) Close() error {
return nil
}