github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/daemon/logger/local/read.go (about) 1 package local 2 3 import ( 4 "context" 5 "encoding/binary" 6 "io" 7 8 "bytes" 9 10 "github.com/demonoid81/moby/api/types/plugins/logdriver" 11 "github.com/demonoid81/moby/daemon/logger" 12 "github.com/demonoid81/moby/daemon/logger/loggerutils" 13 "github.com/demonoid81/moby/errdefs" 14 "github.com/pkg/errors" 15 ) 16 17 func (d *driver) ReadLogs(config logger.ReadConfig) *logger.LogWatcher { 18 logWatcher := logger.NewLogWatcher() 19 20 go d.readLogs(logWatcher, config) 21 return logWatcher 22 } 23 24 func (d *driver) readLogs(watcher *logger.LogWatcher, config logger.ReadConfig) { 25 defer close(watcher.Msg) 26 27 d.mu.Lock() 28 d.readers[watcher] = struct{}{} 29 d.mu.Unlock() 30 31 d.logfile.ReadLogs(config, watcher) 32 33 d.mu.Lock() 34 delete(d.readers, watcher) 35 d.mu.Unlock() 36 } 37 38 func getTailReader(ctx context.Context, r loggerutils.SizeReaderAt, req int) (io.Reader, int, error) { 39 size := r.Size() 40 if req < 0 { 41 return nil, 0, errdefs.InvalidParameter(errors.Errorf("invalid number of lines to tail: %d", req)) 42 } 43 44 if size < (encodeBinaryLen*2)+1 { 45 return bytes.NewReader(nil), 0, nil 46 } 47 48 const encodeBinaryLen64 = int64(encodeBinaryLen) 49 var found int 50 51 buf := make([]byte, encodeBinaryLen) 52 53 offset := size 54 for { 55 select { 56 case <-ctx.Done(): 57 return nil, 0, ctx.Err() 58 default: 59 } 60 61 n, err := r.ReadAt(buf, offset-encodeBinaryLen64) 62 if err != nil && err != io.EOF { 63 return nil, 0, errors.Wrap(err, "error reading log message footer") 64 } 65 66 if n != encodeBinaryLen { 67 return nil, 0, errdefs.DataLoss(errors.New("unexpected number of bytes read from log message footer")) 68 } 69 70 msgLen := binary.BigEndian.Uint32(buf) 71 72 n, err = r.ReadAt(buf, offset-encodeBinaryLen64-encodeBinaryLen64-int64(msgLen)) 73 if err != nil && err != io.EOF { 74 return nil, 0, errors.Wrap(err, "error reading log message header") 75 } 76 77 if n != encodeBinaryLen { 78 return nil, 0, errdefs.DataLoss(errors.New("unexpected number of bytes read from log message header")) 79 } 80 81 if msgLen != binary.BigEndian.Uint32(buf) { 82 return nil, 0, errdefs.DataLoss(errors.Wrap(err, "log message header and footer indicate different message sizes")) 83 } 84 85 found++ 86 offset -= int64(msgLen) 87 offset -= encodeBinaryLen64 * 2 88 if found == req { 89 break 90 } 91 if offset <= 0 { 92 break 93 } 94 } 95 96 return io.NewSectionReader(r, offset, size), found, nil 97 } 98 99 type decoder struct { 100 rdr io.Reader 101 proto *logdriver.LogEntry 102 buf []byte 103 } 104 105 func (d *decoder) Decode() (*logger.Message, error) { 106 if d.proto == nil { 107 d.proto = &logdriver.LogEntry{} 108 } else { 109 resetProto(d.proto) 110 } 111 if d.buf == nil { 112 d.buf = make([]byte, initialBufSize) 113 } 114 var ( 115 read int 116 err error 117 ) 118 119 for i := 0; i < maxDecodeRetry; i++ { 120 var n int 121 n, err = io.ReadFull(d.rdr, d.buf[read:encodeBinaryLen]) 122 if err != nil { 123 if err != io.ErrUnexpectedEOF { 124 return nil, errors.Wrap(err, "error reading log message length") 125 } 126 read += n 127 continue 128 } 129 read += n 130 break 131 } 132 if err != nil { 133 return nil, errors.Wrapf(err, "could not read log message length: read: %d, expected: %d", read, encodeBinaryLen) 134 } 135 136 msgLen := int(binary.BigEndian.Uint32(d.buf[:read])) 137 138 if len(d.buf) < msgLen+encodeBinaryLen { 139 d.buf = make([]byte, msgLen+encodeBinaryLen) 140 } else { 141 if msgLen <= initialBufSize { 142 d.buf = d.buf[:initialBufSize] 143 } else { 144 d.buf = d.buf[:msgLen+encodeBinaryLen] 145 } 146 } 147 148 return decodeLogEntry(d.rdr, d.proto, d.buf, msgLen) 149 } 150 151 func (d *decoder) Reset(rdr io.Reader) { 152 d.rdr = rdr 153 if d.proto != nil { 154 resetProto(d.proto) 155 } 156 if d.buf != nil { 157 d.buf = d.buf[:initialBufSize] 158 } 159 } 160 161 func (d *decoder) Close() { 162 d.buf = d.buf[:0] 163 d.buf = nil 164 if d.proto != nil { 165 resetProto(d.proto) 166 } 167 d.rdr = nil 168 } 169 170 func decodeFunc(rdr io.Reader) loggerutils.Decoder { 171 return &decoder{rdr: rdr} 172 } 173 174 func decodeLogEntry(rdr io.Reader, proto *logdriver.LogEntry, buf []byte, msgLen int) (*logger.Message, error) { 175 var ( 176 read int 177 err error 178 ) 179 for i := 0; i < maxDecodeRetry; i++ { 180 var n int 181 n, err = io.ReadFull(rdr, buf[read:msgLen+encodeBinaryLen]) 182 if err != nil { 183 if err != io.ErrUnexpectedEOF { 184 return nil, errors.Wrap(err, "could not decode log entry") 185 } 186 read += n 187 continue 188 } 189 break 190 } 191 if err != nil { 192 return nil, errors.Wrapf(err, "could not decode entry: read %d, expected: %d", read, msgLen) 193 } 194 195 if err := proto.Unmarshal(buf[:msgLen]); err != nil { 196 return nil, errors.Wrap(err, "error unmarshalling log entry") 197 } 198 199 msg := protoToMessage(proto) 200 if msg.PLogMetaData == nil { 201 msg.Line = append(msg.Line, '\n') 202 } 203 return msg, nil 204 }