github.com/qiniu/go-sdk/v7@v7.27.0/storagev2/uploader/source/source.go (about)

     1  package source
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"path/filepath"
     9  	"sync"
    10  	"sync/atomic"
    11  
    12  	internal_io "github.com/qiniu/go-sdk/v7/internal/io"
    13  )
    14  
    15  type (
    16  	// 数据源
    17  	Source interface {
    18  		io.Closer
    19  
    20  		// 切片
    21  		Slice(uint64) (Part, error)
    22  
    23  		// 数据源 ID
    24  		SourceID() (string, error)
    25  
    26  		// 获取文件,如果数据源不是文件,则返回 nil
    27  		GetFile() *os.File
    28  	}
    29  
    30  	// 预知大小的数据源
    31  	SizedSource interface {
    32  		Source
    33  
    34  		// 获取数据源大小
    35  		TotalSize() (uint64, error)
    36  	}
    37  
    38  	// 可重置的数据源
    39  	ResetableSource interface {
    40  		Source
    41  
    42  		// 重置数据源
    43  		Reset() error
    44  	}
    45  
    46  	// 分片
    47  	Part interface {
    48  		io.ReadSeeker
    49  
    50  		// 分片偏移量
    51  		Offset() uint64
    52  
    53  		// 分片大小
    54  		Size() uint64
    55  
    56  		// 分片编号,从 1 开始
    57  		PartNumber() uint64
    58  	}
    59  
    60  	seekablePart struct {
    61  		*io.SectionReader
    62  		partNumber, offset uint64
    63  	}
    64  
    65  	unseekablePart struct {
    66  		*bytes.Reader
    67  		partNumber, offset, size uint64
    68  	}
    69  
    70  	readSeekCloseSource struct {
    71  		rscra      *readSeekCloseReaderAt
    72  		off        uint64
    73  		sourceID   string
    74  		partNumber uint64
    75  		m          sync.Mutex
    76  	}
    77  
    78  	readSeekCloseReaderAt struct {
    79  		r   internal_io.ReadSeekCloser
    80  		off int64
    81  		m   sync.Mutex
    82  	}
    83  
    84  	readCloseSource struct {
    85  		r                  io.ReadCloser
    86  		sourceID           string
    87  		offset, partNumber uint64
    88  	}
    89  
    90  	ReadAtSeekCloser interface {
    91  		io.ReaderAt
    92  		io.Seeker
    93  		io.Closer
    94  	}
    95  
    96  	readAtSeekCloseSource struct {
    97  		r          ReadAtSeekCloser
    98  		off        uint64
    99  		sourceID   string
   100  		partNumber uint64
   101  		m          sync.Mutex
   102  	}
   103  )
   104  
   105  // 将 io.ReadSeekCloser 封装为数据源
   106  func NewReadSeekCloserSource(r internal_io.ReadSeekCloser, sourceID string) Source {
   107  	return &readSeekCloseSource{rscra: newReadSeekCloseReaderAt(r), sourceID: sourceID}
   108  }
   109  
   110  func (rscs *readSeekCloseSource) Slice(n uint64) (Part, error) {
   111  	rscs.m.Lock()
   112  	defer rscs.m.Unlock()
   113  
   114  	offset := rscs.off
   115  	if totalSize, err := rscs.TotalSize(); err != nil {
   116  		return nil, err
   117  	} else if offset >= totalSize {
   118  		return nil, nil
   119  	} else if n > totalSize-offset {
   120  		n = totalSize - offset
   121  	}
   122  	rscs.off += n
   123  	rscs.partNumber += 1
   124  	return seekablePart{
   125  		io.NewSectionReader(rscs.rscra, int64(offset), int64(n)),
   126  		rscs.partNumber,
   127  		uint64(offset),
   128  	}, nil
   129  }
   130  
   131  func (rscs *readSeekCloseSource) TotalSize() (uint64, error) {
   132  	return rscs.rscra.TotalSize()
   133  }
   134  
   135  func (rscs *readSeekCloseSource) SourceID() (string, error) {
   136  	return rscs.sourceID, nil
   137  }
   138  
   139  func (rscs *readSeekCloseSource) Close() error {
   140  	return rscs.rscra.Close()
   141  }
   142  
   143  func (rscs *readSeekCloseSource) Reset() error {
   144  	rscs.m.Lock()
   145  	defer rscs.m.Unlock()
   146  
   147  	rscs.off = 0
   148  	rscs.partNumber = 0
   149  	return nil
   150  }
   151  
   152  func (rscs *readSeekCloseSource) GetFile() *os.File {
   153  	return rscs.rscra.GetFile()
   154  }
   155  
   156  func newReadSeekCloseReaderAt(r internal_io.ReadSeekCloser) *readSeekCloseReaderAt {
   157  	return &readSeekCloseReaderAt{r: r, off: -1}
   158  }
   159  
   160  func (rscra *readSeekCloseReaderAt) ReadAt(b []byte, off int64) (n int, err error) {
   161  	rscra.m.Lock()
   162  	defer rscra.m.Unlock()
   163  
   164  	if rscra.off != off {
   165  		if rscra.off, err = rscra.r.Seek(off, io.SeekStart); err != nil {
   166  			return
   167  		}
   168  	}
   169  	n, err = rscra.r.Read(b)
   170  	rscra.off += int64(n)
   171  	return
   172  }
   173  
   174  func (rscra *readSeekCloseReaderAt) TotalSize() (uint64, error) {
   175  	rscra.m.Lock()
   176  	defer rscra.m.Unlock()
   177  
   178  	var err error
   179  
   180  	if rscra.off < 0 {
   181  		if rscra.off, err = rscra.r.Seek(0, io.SeekCurrent); err != nil {
   182  			return 0, err
   183  		}
   184  	}
   185  	len, err := rscra.r.Seek(0, io.SeekEnd)
   186  	if err != nil {
   187  		return 0, err
   188  	}
   189  	_, err = rscra.r.Seek(rscra.off, io.SeekStart)
   190  	return uint64(len), err
   191  }
   192  
   193  func (rscra *readSeekCloseReaderAt) Close() error {
   194  	return rscra.r.Close()
   195  }
   196  
   197  func (rscra *readSeekCloseReaderAt) GetFile() *os.File {
   198  	if file, ok := rscra.r.(*os.File); ok {
   199  		return file
   200  	} else {
   201  		return nil
   202  	}
   203  }
   204  
   205  // 将 io.ReadAt + io.Seek + io.Closer 封装为数据源
   206  func NewReadAtSeekCloserSource(r ReadAtSeekCloser, sourceID string) Source {
   207  	return &readAtSeekCloseSource{r: r, sourceID: sourceID}
   208  }
   209  
   210  func (racs *readAtSeekCloseSource) Slice(n uint64) (Part, error) {
   211  	racs.m.Lock()
   212  	defer racs.m.Unlock()
   213  
   214  	offset := racs.off
   215  	if totalSize, err := racs.TotalSize(); err != nil {
   216  		return nil, err
   217  	} else if offset >= totalSize {
   218  		return nil, nil
   219  	} else if n > totalSize-offset {
   220  		n = totalSize - offset
   221  	}
   222  	racs.off += n
   223  	racs.partNumber += 1
   224  	return seekablePart{
   225  		io.NewSectionReader(racs.r, int64(offset), int64(n)),
   226  		racs.partNumber,
   227  		uint64(offset),
   228  	}, nil
   229  }
   230  
   231  func (racs *readAtSeekCloseSource) TotalSize() (uint64, error) {
   232  	curPos, err := racs.r.Seek(0, io.SeekCurrent)
   233  	if err != nil {
   234  		return 0, err
   235  	}
   236  	totalSize, err := racs.r.Seek(0, io.SeekEnd)
   237  	if err != nil {
   238  		return 0, err
   239  	}
   240  	if _, err = racs.r.Seek(curPos, io.SeekStart); err != nil {
   241  		return 0, err
   242  	}
   243  	return uint64(totalSize), nil
   244  }
   245  
   246  func (racs *readAtSeekCloseSource) SourceID() (string, error) {
   247  	return racs.sourceID, nil
   248  }
   249  
   250  func (racs *readAtSeekCloseSource) Close() error {
   251  	return racs.r.Close()
   252  }
   253  
   254  func (racs *readAtSeekCloseSource) Reset() error {
   255  	racs.m.Lock()
   256  	defer racs.m.Unlock()
   257  
   258  	racs.off = 0
   259  	racs.partNumber = 0
   260  	return nil
   261  }
   262  
   263  func (racs *readAtSeekCloseSource) GetFile() *os.File {
   264  	if file, ok := racs.r.(*os.File); ok {
   265  		return file
   266  	} else {
   267  		return nil
   268  	}
   269  }
   270  
   271  // 将 io.ReadCloser 封装为数据源
   272  func NewReadCloserSource(r io.ReadCloser, sourceID string) Source {
   273  	return &readCloseSource{r: r, sourceID: sourceID}
   274  }
   275  
   276  func (rcs *readCloseSource) Slice(n uint64) (Part, error) {
   277  	buf := make([]byte, n)
   278  	haveRead, err := io.ReadFull(rcs.r, buf)
   279  	if err != nil && err != io.ErrUnexpectedEOF && err != io.EOF {
   280  		return nil, err
   281  	} else if haveRead == 0 {
   282  		return nil, nil
   283  	}
   284  	return &unseekablePart{
   285  		bytes.NewReader(buf[:haveRead]),
   286  		atomic.AddUint64(&rcs.partNumber, 1),
   287  		atomic.AddUint64(&rcs.offset, uint64(haveRead)) - uint64(haveRead),
   288  		uint64(haveRead),
   289  	}, nil
   290  }
   291  
   292  func (rcs *readCloseSource) SourceID() (string, error) {
   293  	return rcs.sourceID, nil
   294  }
   295  
   296  func (rcs *readCloseSource) Close() error {
   297  	return rcs.r.Close()
   298  }
   299  
   300  func (racs *readCloseSource) GetFile() *os.File {
   301  	if file, ok := racs.r.(*os.File); ok {
   302  		return file
   303  	} else {
   304  		return nil
   305  	}
   306  }
   307  
   308  func (p seekablePart) PartNumber() uint64 {
   309  	return p.partNumber
   310  }
   311  
   312  func (p seekablePart) Offset() uint64 {
   313  	return p.offset
   314  }
   315  
   316  func (p seekablePart) Size() uint64 {
   317  	return uint64(p.SectionReader.Size())
   318  }
   319  
   320  func (p unseekablePart) PartNumber() uint64 {
   321  	return p.partNumber
   322  }
   323  
   324  func (p unseekablePart) Offset() uint64 {
   325  	return p.offset
   326  }
   327  
   328  func (p unseekablePart) Size() uint64 {
   329  	return p.size
   330  }
   331  
   332  // 将文件封装为数据源
   333  func NewFileSource(filePath string) (Source, error) {
   334  	file, err := os.Open(filePath)
   335  	if err != nil {
   336  		return nil, err
   337  	}
   338  	if !canSeekReally(file) {
   339  		return NewReadCloserSource(file, ""), nil
   340  	} else if absFilePath, err := filepath.Abs(filePath); err != nil {
   341  		return nil, err
   342  	} else if fileInfo, err := file.Stat(); err != nil {
   343  		return nil, err
   344  	} else {
   345  		sourceID := fmt.Sprintf("%d:%d:%s", fileInfo.Size(), fileInfo.ModTime().UnixNano(), absFilePath)
   346  		return NewReadAtSeekCloserSource(file, sourceID), nil
   347  	}
   348  }
   349  
   350  func canSeekReally(seeker io.Seeker) bool {
   351  	_, err := seeker.Seek(0, io.SeekCurrent)
   352  	return err == nil
   353  }