yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/azure/progress/readerWithProgress.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package progress 16 17 import ( 18 "io" 19 "time" 20 ) 21 22 // ReaderWithProgress wraps an io.ReadCloser, it track and report the read progress. 23 // 24 type ReaderWithProgress struct { 25 ProgressChan <-chan *Record 26 innerReadCloser io.ReadCloser 27 progressStatus *Status 28 } 29 30 // NewReaderWithProgress creates a new instance of ReaderWithProgress. The parameter inner is the inner stream whose 31 // read progress needs to be tracked, sizeInBytes is the total size of the inner stream in bytes, 32 // progressIntervalInSeconds is the interval at which the read progress needs to be send to ProgressChan channel. 33 // After using the this reader, it must be closed by calling Close method to avoid goroutine leak. 34 // 35 func NewReaderWithProgress(inner io.ReadCloser, sizeInBytes int64, progressIntervalInSeconds time.Duration) *ReaderWithProgress { 36 r := &ReaderWithProgress{} 37 r.innerReadCloser = inner 38 r.progressStatus = NewStatus(0, 0, sizeInBytes, NewComputestateDefaultSize()) 39 r.ProgressChan = r.progressStatus.Run() 40 return r 41 } 42 43 // Read reads up to len(b) bytes from the inner stream. It returns the number of bytes read and an error, if any. 44 // EOF is signaled when no more data to read and n will set to 0. 45 // 46 func (r *ReaderWithProgress) Read(p []byte) (n int, err error) { 47 n, err = r.innerReadCloser.Read(p) 48 if err == nil { 49 r.progressStatus.ReportBytesProcessedCount(int64(n)) 50 } 51 return 52 } 53 54 // Close closes the inner stream and stop reporting read progress in the ProgressChan chan. 55 // 56 func (r *ReaderWithProgress) Close() error { 57 err := r.innerReadCloser.Close() 58 r.progressStatus.Close() 59 return err 60 }