Add initial skeleton of WAL Compactor
parent
0c0c6cd757
commit
41c59ea531
@ -0,0 +1,89 @@
|
||||
package wal
|
||||
|
||||
import "io"
|
||||
|
||||
// Frame points to a single WAL frame in a WAL file.
|
||||
type Frame struct {
|
||||
Pgno uint32
|
||||
Commit uint32
|
||||
Offset int64
|
||||
}
|
||||
|
||||
// Compactor is used to compact a WAL file.
|
||||
type Compactor struct {
|
||||
r io.ReadSeeker
|
||||
wr *Reader
|
||||
}
|
||||
|
||||
// NewCompactor returns a new Compactor.
|
||||
func NewCompactor(r io.ReadSeeker) *Compactor {
|
||||
return &Compactor{
|
||||
r: r,
|
||||
wr: NewReader(r),
|
||||
}
|
||||
}
|
||||
|
||||
// WriteTo compacts the WAL file to the given writer.
|
||||
func (c *Compactor) WriteTo(w io.Writer) (n int64, err error) {
|
||||
frames, err := c.getFrames()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(frames) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Copy the WAL header.
|
||||
if _, err := c.r.Seek(0, io.SeekStart); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if _, err := io.CopyN(w, c.r, WALHeaderSize); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Write each new WAL Frame header, and the associated page data.
|
||||
for _, f := range frames {
|
||||
_ = f
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (c *Compactor) getFrames() (map[uint32]*Frame, error) {
|
||||
if err := c.wr.ReadHeader(); err != io.EOF {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Read the offset of the last version of each page in the WAL.
|
||||
frames := make(map[uint32]*Frame)
|
||||
txFrames := make(map[uint32]*Frame)
|
||||
buf := make([]byte, c.wr.PageSize())
|
||||
for {
|
||||
pgno, commit, err := c.wr.ReadFrame(buf)
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame := &Frame{
|
||||
Pgno: pgno,
|
||||
Commit: commit,
|
||||
Offset: c.wr.Offset(),
|
||||
}
|
||||
|
||||
// Save latest frame information for each page.
|
||||
txFrames[pgno] = frame
|
||||
|
||||
// If this is not a committing frame, continue to next frame.
|
||||
if commit == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// At the end of each transaction, copy frame information to main map.
|
||||
for k, v := range txFrames {
|
||||
frames[k] = v
|
||||
}
|
||||
txFrames = make(map[uint32]*Frame)
|
||||
}
|
||||
|
||||
return frames, nil
|
||||
}
|
Loading…
Reference in New Issue