go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/logdog/common/storage/entry.go (about) 1 // Copyright 2016 The LUCI Authors. 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 storage 16 17 import ( 18 "go.chromium.org/luci/common/errors" 19 "go.chromium.org/luci/logdog/api/logpb" 20 "go.chromium.org/luci/logdog/common/types" 21 22 "github.com/golang/protobuf/proto" 23 ) 24 25 // Entry is a logpb.LogEntry wrapper that lazily evaluates / unmarshals the 26 // underlying LogEntry data as needed. 27 // 28 // Entry is not goroutine-safe. 29 type Entry struct { 30 D []byte 31 32 streamIndex types.MessageIndex 33 le *logpb.LogEntry 34 } 35 36 // MakeEntry creates a new Entry. 37 // 38 // All Entry must be backed by data. The index, "idx", is optional. If <0, it 39 // will be calculated by unmarshalling the data into a LogEntry and pulling the 40 // value from there. 41 func MakeEntry(d []byte, idx types.MessageIndex) *Entry { 42 return &Entry{ 43 D: d, 44 streamIndex: idx, 45 } 46 } 47 48 // GetStreamIndex returns the LogEntry's stream index. 49 // 50 // If this needs to be calculated by unmarshalling the LogEntry, this will be 51 // done. If this fails, an error will be returned. 52 // 53 // If GetLogEntry has succeeded, subsequent GetStreamIndex calls will always 54 // be fast and succeed. 55 func (e *Entry) GetStreamIndex() (types.MessageIndex, error) { 56 if e.streamIndex < 0 { 57 le, err := e.GetLogEntry() 58 if err != nil { 59 return -1, err 60 } 61 62 e.streamIndex = types.MessageIndex(le.StreamIndex) 63 } 64 65 return e.streamIndex, nil 66 } 67 68 // GetLogEntry returns the unmarshalled LogEntry data. 69 // 70 // The first time this is called, the LogEntry will be unmarshalled from its 71 // underlying data. 72 func (e *Entry) GetLogEntry() (*logpb.LogEntry, error) { 73 if e.le == nil { 74 if e.D == nil { 75 // This can happen with keys-only results. 76 return nil, errors.New("no log entry data") 77 } 78 79 var le logpb.LogEntry 80 if err := proto.Unmarshal(e.D, &le); err != nil { 81 return nil, errors.Annotate(err, "failed to unmarshal").Err() 82 } 83 e.le = &le 84 } 85 86 return e.le, nil 87 }