github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/bfs/file_writer.go (about)

     1  // Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
     2  
     3  package bfs
     4  
     5  import "errors"
     6  
     7  // FileWriter file writer
     8  // not thread-safe
     9  type FileWriter struct {
    10  	bFile   *BlocksFile
    11  	hasMeta bool
    12  	hash    string
    13  
    14  	bodySize     int64
    15  	originOffset int64
    16  
    17  	realHeaderSize int64
    18  	realBodySize   int64
    19  	isPartial      bool
    20  }
    21  
    22  func NewFileWriter(bFile *BlocksFile, hash string, bodySize int64, isPartial bool) (*FileWriter, error) {
    23  	if isPartial && bodySize <= 0 {
    24  		return nil, errors.New("invalid body size for partial content")
    25  	}
    26  
    27  	return &FileWriter{
    28  		bFile:     bFile,
    29  		hash:      hash,
    30  		bodySize:  bodySize,
    31  		isPartial: isPartial,
    32  	}, nil
    33  }
    34  
    35  func (this *FileWriter) WriteMeta(status int, expiresAt int64, expectedFileSize int64) error {
    36  	this.hasMeta = true
    37  	return this.bFile.mFile.WriteMeta(this.hash, status, expiresAt, expectedFileSize)
    38  }
    39  
    40  func (this *FileWriter) WriteHeader(b []byte) (n int, err error) {
    41  	if !this.isPartial && !this.hasMeta {
    42  		err = errors.New("no meta found")
    43  		return
    44  	}
    45  
    46  	n, err = this.bFile.Write(this.hash, BlockTypeHeader, b, -1)
    47  	this.realHeaderSize += int64(n)
    48  	return
    49  }
    50  
    51  func (this *FileWriter) WriteBody(b []byte) (n int, err error) {
    52  	if !this.isPartial && !this.hasMeta {
    53  		err = errors.New("no meta found")
    54  		return
    55  	}
    56  
    57  	n, err = this.bFile.Write(this.hash, BlockTypeBody, b, this.originOffset)
    58  	this.originOffset += int64(n)
    59  	this.realBodySize += int64(n)
    60  	return
    61  }
    62  
    63  func (this *FileWriter) WriteBodyAt(b []byte, offset int64) (n int, err error) {
    64  	if !this.hasMeta {
    65  		err = errors.New("no meta found")
    66  		return
    67  	}
    68  
    69  	if !this.isPartial {
    70  		err = errors.New("can not write body at specified offset: it is not a partial file")
    71  		return
    72  	}
    73  
    74  	// still 'Write()' NOT 'WriteAt()'
    75  	this.originOffset = offset
    76  	n, err = this.bFile.Write(this.hash, BlockTypeBody, b, offset)
    77  	this.originOffset += int64(n)
    78  	return
    79  }
    80  
    81  func (this *FileWriter) Close() error {
    82  	defer func() {
    83  		this.bFile.removeWritingFile(this.hash)
    84  	}()
    85  
    86  	if !this.isPartial && !this.hasMeta {
    87  		return errors.New("no meta found")
    88  	}
    89  
    90  	if this.isPartial {
    91  		if this.originOffset > this.bodySize {
    92  			return errors.New("unexpected body size")
    93  		}
    94  		this.realBodySize = this.bodySize
    95  	} else {
    96  		if this.bodySize > 0 && this.bodySize != this.realBodySize {
    97  			return errors.New("unexpected body size")
    98  		}
    99  	}
   100  
   101  	err := this.bFile.mFile.WriteClose(this.hash, this.realHeaderSize, this.realBodySize)
   102  	if err != nil {
   103  		return err
   104  	}
   105  
   106  	return this.bFile.Sync()
   107  }
   108  
   109  func (this *FileWriter) Discard() error {
   110  	// TODO 需要测试
   111  	return this.bFile.mFile.RemoveFile(this.hash)
   112  }