github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/bfs/file_reader.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 ( 6 "errors" 7 "github.com/iwind/TeaGo/types" 8 "io" 9 "os" 10 ) 11 12 type FileReader struct { 13 bFile *BlocksFile 14 fp *os.File 15 16 fileHeader *FileHeader 17 pos int64 18 19 isClosed bool 20 } 21 22 func NewFileReader(bFile *BlocksFile, fp *os.File, fileHeader *FileHeader) *FileReader { 23 return &FileReader{ 24 bFile: bFile, 25 fp: fp, 26 fileHeader: fileHeader, 27 } 28 } 29 30 func (this *FileReader) FileHeader() *FileHeader { 31 return this.fileHeader 32 } 33 34 func (this *FileReader) Read(b []byte) (n int, err error) { 35 n, err = this.ReadAt(b, this.pos) 36 this.pos += int64(n) 37 38 return 39 } 40 41 func (this *FileReader) ReadAt(b []byte, offset int64) (n int, err error) { 42 if offset >= this.fileHeader.MaxOffset() { 43 err = io.EOF 44 return 45 } 46 47 blockInfo, ok := this.fileHeader.BlockAt(offset) 48 if !ok { 49 err = errors.New("could not find block at '" + types.String(offset) + "'") 50 return 51 } 52 53 var delta = offset - blockInfo.OriginOffsetFrom 54 var bFrom = blockInfo.BFileOffsetFrom + delta 55 var bTo = blockInfo.BFileOffsetTo 56 if bFrom > bTo { 57 err = errors.New("invalid block information") 58 return 59 } 60 61 var bufLen = len(b) 62 if int64(bufLen) > bTo-bFrom { 63 bufLen = int(bTo - bFrom) 64 } 65 66 AckReadThread() 67 n, err = this.fp.ReadAt(b[:bufLen], bFrom) 68 ReleaseReadThread() 69 70 return 71 } 72 73 func (this *FileReader) Reset(fileHeader *FileHeader) { 74 this.fileHeader = fileHeader 75 this.pos = 0 76 } 77 78 func (this *FileReader) Close() error { 79 if this.isClosed { 80 return nil 81 } 82 this.isClosed = true 83 return this.bFile.CloseFileReader(this) 84 } 85 86 func (this *FileReader) Free() error { 87 return this.fp.Close() 88 }