github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/logtail/service/response.go (about) 1 // Copyright 2021 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 service 16 17 import ( 18 "fmt" 19 "math" 20 "sync" 21 22 "github.com/matrixorigin/matrixone/pkg/common/morpc" 23 "github.com/matrixorigin/matrixone/pkg/pb/logtail" 24 ) 25 26 // LogtailResponse wraps logtail.LogtailResponse. 27 type LogtailResponse struct { 28 logtail.LogtailResponse 29 closeCB func() 30 } 31 32 var _ morpc.Message = (*LogtailResponse)(nil) 33 34 func (r *LogtailResponse) SetID(id uint64) { 35 r.ResponseId = id 36 } 37 38 func (r *LogtailResponse) GetID() uint64 { 39 return r.ResponseId 40 } 41 42 func (r *LogtailResponse) DebugString() string { 43 return "" 44 } 45 46 func (r *LogtailResponse) Size() int { 47 return r.ProtoSize() 48 } 49 50 // LogtailResponsePool acquires or releases LogtailResponse. 51 type LogtailResponsePool interface { 52 // Acquire fetches item from pool. 53 Acquire() *LogtailResponse 54 55 // Release puts item back to pool. 56 Release(*LogtailResponse) 57 } 58 59 type responsePool struct { 60 pool *sync.Pool 61 } 62 63 func NewLogtailResponsePool() LogtailResponsePool { 64 return &responsePool{ 65 pool: &sync.Pool{ 66 New: func() any { 67 return &LogtailResponse{} 68 }, 69 }, 70 } 71 } 72 73 func (p *responsePool) Acquire() *LogtailResponse { 74 return p.pool.Get().(*LogtailResponse) 75 } 76 77 func (p *responsePool) Release(resp *LogtailResponse) { 78 if resp.closeCB != nil { 79 resp.closeCB() 80 resp.closeCB = nil 81 } 82 resp.Reset() 83 p.pool.Put(resp) 84 } 85 86 // LogtailResponseSegment wrps logtail.MessageSegment. 87 type LogtailResponseSegment struct { 88 logtail.MessageSegment 89 } 90 91 var _ morpc.Message = (*LogtailResponseSegment)(nil) 92 93 func (s *LogtailResponseSegment) SetID(id uint64) { 94 s.StreamID = id 95 } 96 97 func (s *LogtailResponseSegment) GetID() uint64 { 98 return s.StreamID 99 } 100 101 func (s *LogtailResponseSegment) DebugString() string { 102 return fmt.Sprintf( 103 "LogtailResponseSegment: StreamID=%d, MessageSize=%d, Sequence=%d, MaxSequence=%d", 104 s.GetStreamID(), 105 s.GetMessageSize(), 106 s.GetSequence(), 107 s.GetMaxSequence(), 108 ) 109 } 110 111 func (s *LogtailResponseSegment) Size() int { 112 return s.ProtoSize() 113 } 114 115 // LogtailResponseSegmentPool acquires or releases LogtailResponseSegment. 116 type LogtailResponseSegmentPool interface { 117 // Acquire fetches item from pool. 118 Acquire() *LogtailResponseSegment 119 120 // Release puts item back to pool. 121 Release(*LogtailResponseSegment) 122 } 123 124 // LogtailServerSegmentPool describes segment pool for logtail server. 125 type LogtailServerSegmentPool interface { 126 LogtailResponseSegmentPool 127 128 // LeastEffectiveCapacity evaluates least effective payload size. 129 LeastEffectiveCapacity() int 130 } 131 132 type serverSegmentPool struct { 133 maxMessageSize int 134 pool *sync.Pool 135 } 136 137 func NewLogtailServerSegmentPool(maxMessageSize int) LogtailServerSegmentPool { 138 return &serverSegmentPool{ 139 maxMessageSize: maxMessageSize, 140 pool: &sync.Pool{ 141 New: func() any { 142 seg := &LogtailResponseSegment{} 143 seg.Payload = make([]byte, maxMessageSize) 144 return seg 145 }, 146 }, 147 } 148 } 149 150 func (p *serverSegmentPool) Acquire() *LogtailResponseSegment { 151 return p.pool.Get().(*LogtailResponseSegment) 152 } 153 154 func (p *serverSegmentPool) Release(seg *LogtailResponseSegment) { 155 buf := seg.Payload 156 seg.Reset() 157 seg.Payload = buf[:cap(buf)] 158 p.pool.Put(seg) 159 } 160 161 func (p *serverSegmentPool) LeastEffectiveCapacity() int { 162 segment := p.Acquire() 163 defer p.Release(segment) 164 165 segment.StreamID = math.MaxUint64 166 segment.Sequence = math.MaxInt32 167 segment.MaxSequence = math.MaxInt32 168 segment.MessageSize = math.MaxInt32 169 maxHeaderSize := segment.ProtoSize() - p.maxMessageSize 170 171 // Take out reserved size, then effective capacity left. 172 return p.maxMessageSize - maxHeaderSize 173 }