Files
EdgeNode/internal/utils/bfs/file_writer.go
GoEdgeLab c19be78e0d v1.4.1
2024-07-27 15:42:50 +08:00

113 lines
2.6 KiB
Go

// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cloud .
package bfs
import "errors"
// FileWriter file writer
// not thread-safe
type FileWriter struct {
bFile *BlocksFile
hasMeta bool
hash string
bodySize int64
originOffset int64
realHeaderSize int64
realBodySize int64
isPartial bool
}
func NewFileWriter(bFile *BlocksFile, hash string, bodySize int64, isPartial bool) (*FileWriter, error) {
if isPartial && bodySize <= 0 {
return nil, errors.New("invalid body size for partial content")
}
return &FileWriter{
bFile: bFile,
hash: hash,
bodySize: bodySize,
isPartial: isPartial,
}, nil
}
func (this *FileWriter) WriteMeta(status int, expiresAt int64, expectedFileSize int64) error {
this.hasMeta = true
return this.bFile.mFile.WriteMeta(this.hash, status, expiresAt, expectedFileSize)
}
func (this *FileWriter) WriteHeader(b []byte) (n int, err error) {
if !this.isPartial && !this.hasMeta {
err = errors.New("no meta found")
return
}
n, err = this.bFile.Write(this.hash, BlockTypeHeader, b, -1)
this.realHeaderSize += int64(n)
return
}
func (this *FileWriter) WriteBody(b []byte) (n int, err error) {
if !this.isPartial && !this.hasMeta {
err = errors.New("no meta found")
return
}
n, err = this.bFile.Write(this.hash, BlockTypeBody, b, this.originOffset)
this.originOffset += int64(n)
this.realBodySize += int64(n)
return
}
func (this *FileWriter) WriteBodyAt(b []byte, offset int64) (n int, err error) {
if !this.hasMeta {
err = errors.New("no meta found")
return
}
if !this.isPartial {
err = errors.New("can not write body at specified offset: it is not a partial file")
return
}
// still 'Write()' NOT 'WriteAt()'
this.originOffset = offset
n, err = this.bFile.Write(this.hash, BlockTypeBody, b, offset)
this.originOffset += int64(n)
return
}
func (this *FileWriter) Close() error {
defer func() {
this.bFile.removeWritingFile(this.hash)
}()
if !this.isPartial && !this.hasMeta {
return errors.New("no meta found")
}
if this.isPartial {
if this.originOffset > this.bodySize {
return errors.New("unexpected body size")
}
this.realBodySize = this.bodySize
} else {
if this.bodySize > 0 && this.bodySize != this.realBodySize {
return errors.New("unexpected body size")
}
}
err := this.bFile.mFile.WriteClose(this.hash, this.realHeaderSize, this.realBodySize)
if err != nil {
return err
}
return this.bFile.Sync()
}
func (this *FileWriter) Discard() error {
// TODO 需要测试
return this.bFile.mFile.RemoveFile(this.hash)
}