github.com/m3db/m3@v1.5.0/src/m3em/os/fs/file_reader_iter.go (about) 1 // Copyright (c) 2017 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package fs 22 23 import ( 24 "bufio" 25 "io" 26 "os" 27 28 "github.com/m3db/m3/src/m3em/checksum" 29 ) 30 31 const ( 32 defaultBufferSize = 1024 33 ) 34 35 type bufferedFileReaderIter struct { 36 currentBytes []byte 37 checksum checksum.Accumulator 38 bufferedReader *bufio.Reader 39 fileHandle *os.File 40 err error 41 done bool 42 init bool 43 } 44 45 // NewFileReaderIter creates a new buffered FileReaderIter 46 func NewFileReaderIter( 47 filepath string, 48 ) (FileReaderIter, error) { 49 return NewSizedFileReaderIter(filepath, defaultBufferSize) 50 } 51 52 // NewSizedFileReaderIter creates a new buffered FileReaderIter 53 func NewSizedFileReaderIter( 54 filepath string, 55 bufferSize int, 56 ) (FileReaderIter, error) { 57 fhandle, err := os.Open(filepath) 58 if err != nil { 59 return nil, err 60 } 61 var ( 62 bytes = make([]byte, bufferSize) 63 buffReader = bufio.NewReaderSize(fhandle, bufferSize) 64 iter = &bufferedFileReaderIter{ 65 currentBytes: bytes, 66 checksum: checksum.NewAccumulator(), 67 bufferedReader: buffReader, 68 fileHandle: fhandle, 69 } 70 ) 71 return iter, nil 72 } 73 74 func (r *bufferedFileReaderIter) Current() []byte { 75 if r.Err() != nil { 76 return nil 77 } 78 79 return r.currentBytes 80 } 81 82 func (r *bufferedFileReaderIter) Next() bool { 83 if !r.init { 84 r.init = true 85 } 86 87 if r.done || r.err != nil { 88 return false 89 } 90 91 n, err := r.bufferedReader.Read(r.currentBytes) 92 if err != nil && err != io.EOF { 93 r.err = err 94 r.Close() 95 return false 96 } 97 98 bytes := r.currentBytes[:n] 99 r.checksum.Update(bytes) 100 r.currentBytes = bytes 101 if err == io.EOF { 102 r.done = true 103 r.Close() 104 } 105 106 return true 107 } 108 109 func (r *bufferedFileReaderIter) Close() error { 110 handle := r.fileHandle 111 r.fileHandle = nil 112 r.currentBytes = nil 113 r.bufferedReader = nil 114 if handle != nil { 115 return handle.Close() 116 } 117 return nil 118 } 119 120 func (r *bufferedFileReaderIter) Checksum() uint32 { 121 return r.checksum.Current() 122 } 123 124 func (r *bufferedFileReaderIter) Err() error { 125 return r.err 126 }