github.com/matrixorigin/matrixone@v0.7.0/pkg/fileservice/io_entry.go (about)

     1  // Copyright 2022 Matrix Origin
     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 fileservice
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"io"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  )
    24  
    25  type ioEntriesReader struct {
    26  	ctx     context.Context
    27  	entries []IOEntry
    28  	offset  int64
    29  }
    30  
    31  var _ io.Reader = new(ioEntriesReader)
    32  
    33  func newIOEntriesReader(ctx context.Context, entries []IOEntry) *ioEntriesReader {
    34  	es := make([]IOEntry, len(entries))
    35  	copy(es, entries)
    36  	return &ioEntriesReader{
    37  		ctx:     ctx,
    38  		entries: es,
    39  	}
    40  }
    41  
    42  func (i *ioEntriesReader) Read(buf []byte) (n int, err error) {
    43  	for {
    44  
    45  		select {
    46  		case <-i.ctx.Done():
    47  			return n, i.ctx.Err()
    48  		default:
    49  		}
    50  
    51  		// no more data
    52  		if len(i.entries) == 0 {
    53  			err = io.EOF
    54  			return
    55  		}
    56  
    57  		entry := i.entries[0]
    58  
    59  		// gap
    60  		if i.offset < entry.Offset {
    61  			numBytes := entry.Offset - i.offset
    62  			if l := int64(len(buf)); l < numBytes {
    63  				numBytes = l
    64  			}
    65  			buf = buf[numBytes:] // skip
    66  			n += int(numBytes)
    67  			i.offset += numBytes
    68  		}
    69  
    70  		// buffer full
    71  		if len(buf) == 0 {
    72  			return
    73  		}
    74  
    75  		// copy data
    76  		var bytesRead int
    77  
    78  		if entry.ReaderForWrite != nil && entry.Size < 0 {
    79  			// read from size unknown reader
    80  			bytesRead, err = entry.ReaderForWrite.Read(buf)
    81  			i.entries[0].Offset += int64(bytesRead)
    82  			if err == io.EOF {
    83  				i.entries = i.entries[1:]
    84  			} else if err != nil {
    85  				return
    86  			}
    87  
    88  		} else if entry.ReaderForWrite != nil {
    89  			bytesToRead := entry.Size
    90  			if l := int64(len(buf)); bytesToRead > l {
    91  				bytesToRead = l
    92  			}
    93  			r := io.LimitReader(entry.ReaderForWrite, int64(bytesToRead))
    94  			bytesRead, err = io.ReadFull(r, buf[:bytesToRead])
    95  			if err != nil {
    96  				return
    97  			}
    98  			if int64(bytesRead) != bytesToRead {
    99  				err = moerr.NewSizeNotMatchNoCtx("")
   100  				return
   101  			}
   102  			i.entries[0].Offset += int64(bytesRead)
   103  			i.entries[0].Size -= int64(bytesRead)
   104  			if i.entries[0].Size == 0 {
   105  				i.entries = i.entries[1:]
   106  			}
   107  
   108  		} else {
   109  			bytesToRead := entry.Size
   110  			if l := int64(len(buf)); bytesToRead > l {
   111  				bytesToRead = l
   112  			}
   113  			if int64(len(entry.Data)) != entry.Size {
   114  				err = moerr.NewSizeNotMatchNoCtx("")
   115  				return
   116  			}
   117  			bytesRead = copy(buf, entry.Data[:bytesToRead])
   118  			if int64(bytesRead) != bytesToRead {
   119  				err = moerr.NewSizeNotMatchNoCtx("")
   120  				return
   121  			}
   122  			i.entries[0].Data = entry.Data[bytesRead:]
   123  			i.entries[0].Offset += int64(bytesRead)
   124  			i.entries[0].Size -= int64(bytesRead)
   125  			if i.entries[0].Size == 0 {
   126  				i.entries = i.entries[1:]
   127  			}
   128  		}
   129  
   130  		buf = buf[bytesRead:]
   131  		i.offset += int64(bytesRead)
   132  		n += int(bytesRead)
   133  
   134  	}
   135  }
   136  
   137  func (e *IOEntry) setObjectFromData() error {
   138  	if e.ToObject == nil {
   139  		return nil
   140  	}
   141  	if len(e.Data) == 0 {
   142  		return nil
   143  	}
   144  	obj, size, err := e.ToObject(bytes.NewReader(e.Data), e.Data)
   145  	if err != nil {
   146  		return err
   147  	}
   148  	e.Object = obj
   149  	e.ObjectSize = size
   150  	return nil
   151  }