github.com/lirm/aeron-go@v0.0.0-20230415210743-920325491dc4/aeron/logbuffer/descriptor.go (about) 1 /* 2 Copyright 2016-2018 Stanislav Liberman 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package logbuffer 18 19 import ( 20 "fmt" 21 22 "github.com/lirm/aeron-go/aeron/atomic" 23 "github.com/lirm/aeron-go/aeron/flyweight" 24 "github.com/lirm/aeron-go/aeron/util" 25 ) 26 27 const ( 28 Clean int32 = 0 29 NeedsCleaning = 1 30 PartitionCount = 3 31 LogMetaDataSectionIndex = PartitionCount 32 33 TermMinLength int32 = 64 * 1024 34 termMaxLength int32 = 1024 * 1024 * 1024 35 pageMinSize int32 = 4 * 1024 36 pageMaxSize int32 = 1024 * 1024 * 1024 37 maxSingleMappingSize int64 = 0x7FFFFFFF 38 LogMetaDataLength = pageMinSize 39 ) 40 41 /* LogBufferMetaData is the flyweight for LogBuffer meta data 42 * <pre> 43 * 0 1 2 3 44 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 46 * | Tail Counter 0 | 47 * | | 48 * +---------------------------------------------------------------+ 49 * | Tail Counter 1 | 50 * | | 51 * +---------------------------------------------------------------+ 52 * | Tail Counter 2 | 53 * | | 54 * +---------------------------------------------------------------+ 55 * | Active Term Count | 56 * +---------------------------------------------------------------+ 57 * | Cache Line Padding ... 58 * ... | 59 * +---------------------------------------------------------------+ 60 * | End of Stream Position | 61 * | | 62 * +---------------------------------------------------------------+ 63 * | Is Connected | 64 * +---------------------------------------------------------------+ 65 * | Cache Line Padding ... 66 * ... | 67 * +---------------------------------------------------------------+ 68 * | Registration / Correlation ID | 69 * | | 70 * +---------------------------------------------------------------+ 71 * | Initial Term Id | 72 * +---------------------------------------------------------------+ 73 * | Default Frame Header Length | 74 * +---------------------------------------------------------------+ 75 * | MTU Length | 76 * +---------------------------------------------------------------+ 77 * | Term Length | 78 * +---------------------------------------------------------------+ 79 * | Page Size | 80 * +---------------------------------------------------------------+ 81 * | Cache Line Padding ... 82 * ... | 83 * +---------------------------------------------------------------+ 84 * | Default Frame Header ... 85 * ... | 86 * +---------------------------------------------------------------+ 87 * </pre> 88 */ 89 type LogBufferMetaData struct { 90 flyweight.FWBase 91 92 TailCounter []flyweight.Int64Field // 0, 8, 16 93 ActiveTermCountOff flyweight.Int32Field // 24 94 padding0 flyweight.Padding // 28 95 EndOfStreamPosOff flyweight.Int64Field // 128 96 IsConnected flyweight.Int32Field // 136 97 ActiveTransportCountOff flyweight.Int32Field // 140 98 padding1 flyweight.Padding // 144 99 CorrelationId flyweight.Int64Field // 256 100 InitTermID flyweight.Int32Field // 264 101 DefaultFrameHdrLen flyweight.Int32Field // 270 102 MTULen flyweight.Int32Field // 274 103 TermLen flyweight.Int32Field // 278 104 PageSize flyweight.Int32Field // 282 105 padding2 flyweight.Padding // 286 106 DefaultFrameHeader flyweight.RawDataField // 384 107 padding3 flyweight.Padding 108 } 109 110 func (m *LogBufferMetaData) Wrap(buf *atomic.Buffer, offset int) flyweight.Flyweight { 111 pos := offset 112 m.TailCounter = make([]flyweight.Int64Field, PartitionCount) 113 pos += m.TailCounter[0].Wrap(buf, pos) 114 pos += m.TailCounter[1].Wrap(buf, pos) 115 pos += m.TailCounter[2].Wrap(buf, pos) 116 pos += m.ActiveTermCountOff.Wrap(buf, pos) 117 pos += m.padding0.Wrap(buf, pos, util.CacheLineLength*2, util.CacheLineLength) 118 pos += m.EndOfStreamPosOff.Wrap(buf, pos) 119 pos += m.IsConnected.Wrap(buf, pos) 120 pos += m.ActiveTransportCountOff.Wrap(buf, pos) 121 pos += m.padding1.Wrap(buf, pos, util.CacheLineLength*2, util.CacheLineLength) 122 pos += m.CorrelationId.Wrap(buf, pos) 123 pos += m.InitTermID.Wrap(buf, pos) 124 pos += m.DefaultFrameHdrLen.Wrap(buf, pos) 125 pos += m.MTULen.Wrap(buf, pos) 126 pos += m.TermLen.Wrap(buf, pos) 127 pos += m.PageSize.Wrap(buf, pos) 128 pos += m.padding2.Wrap(buf, pos, util.CacheLineLength, util.CacheLineLength) 129 pos += m.DefaultFrameHeader.Wrap(buf, pos, DataFrameHeader.Length) 130 pos += m.padding3.Wrap(buf, pos, util.CacheLineLength*2, util.CacheLineLength) 131 132 m.SetSize(pos - offset) 133 return m 134 } 135 136 // ActiveTransportCount returns the count of active transports for the Image. 137 func (m *LogBufferMetaData) ActiveTransportCount() int32 { 138 return m.ActiveTransportCountOff.Get() 139 } 140 141 func checkTermLength(termLength int32) { 142 if termLength < TermMinLength { 143 panic(fmt.Sprintf("Term length less than min size of %d, length=%d", 144 TermMinLength, termLength)) 145 } 146 147 if termLength > termMaxLength { 148 panic(fmt.Sprintf("Term length greater than max size of %d, length=%d", 149 termMaxLength, termLength)) 150 } 151 152 if !util.IsPowerOfTwo(int64(termLength)) { 153 panic(fmt.Sprintf("Term length not a power of 2, length=%d", termLength)) 154 } 155 } 156 157 func computeTermLength(logLength int32) int32 { 158 return (logLength - LogMetaDataLength) / PartitionCount 159 } 160 161 func checkPageSize(pageSize int32) { 162 if pageSize < pageMinSize { 163 panic(fmt.Sprintf("Page size less than min size of %d, size=%d", pageMinSize, pageSize)) 164 } 165 166 if pageSize > pageMaxSize { 167 panic(fmt.Sprintf("Page Size greater than max size of %d, size=%d", pageMaxSize, pageSize)) 168 } 169 170 if !util.IsPowerOfTwo(int64(pageSize)) { 171 panic(fmt.Sprintf("Page size not a power of 2, size=%d", pageSize)) 172 } 173 } 174 175 func TermID(rawTail int64) int32 { 176 return int32(rawTail >> 32) 177 } 178 179 func indexByTermCount(termCount int32) int32 { 180 return termCount % PartitionCount 181 } 182 183 func RotateLog(logMetaDataBuffer *LogBufferMetaData, currentTermCount int32, currentTermId int32) { 184 nextTermId := currentTermId + 1 185 nextTermCount := currentTermCount + 1 186 nextIndex := indexByTermCount(nextTermCount) 187 expectedTermId := nextTermId - PartitionCount 188 newRawTail := int64(nextTermId) * (int64(1) << 32) 189 tail := logMetaDataBuffer.TailCounter[nextIndex] 190 191 for { 192 rawTail := tail.Get() 193 if expectedTermId != TermID(rawTail) { 194 break 195 } 196 if tail.CAS(rawTail, newRawTail) { 197 break 198 } 199 } 200 logMetaDataBuffer.ActiveTermCountOff.CAS(currentTermCount, nextTermCount) 201 }