

package writer

import (
	"os"
	"path/filepath"
	"sync"
)

// AOFWriter is the implementation of Append Only File strategy for storage
type AOFWriter struct {
	filePath   string
	file       *os.File
	writeCount int64
}

var once sync.Once

// Write data in dump file
func (w *AOFWriter) Write(data []byte) error {
	// filesize is the last valid position
	pos, err := w.FileSize()
	if err != nil {
		return err
	}

	// if error in write, back to the old valid position
	if _, err := w.file.Write(data); err != nil {
		w.file.Truncate(pos)
	}

	w.Sync()
	return nil
}

// FileSize returns file size
func (w *AOFWriter) FileSize() (int64, error) {
	stat, err := w.file.Stat()
	if err != nil {
		return 0, err
	}
	return stat.Size(), nil
}

//Sync flush data into harddrive
func (w *AOFWriter) Sync() {
	w.file.Sync()
}

// NewAOFWriter returns new AOFWriter
func NewAOFWriter(path string) *AOFWriter {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		os.Mkdir(path, 0777)
	}

	fullpath := filepath.Join(path, "dump.di")
	aof := AOFWriter{
		filePath: fullpath,
		file:     openFile(fullpath),
	}
	return &aof
}
