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 }