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  }