github.com/lirm/aeron-go@v0.0.0-20230415210743-920325491dc4/aeron/logbuffer/logbuffers.go (about)

     1  /*
     2  Copyright 2016 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  	"unsafe"
    21  
    22  	"github.com/lirm/aeron-go/aeron/atomic"
    23  	"github.com/lirm/aeron-go/aeron/logging"
    24  	"github.com/lirm/aeron-go/aeron/util/memmap"
    25  )
    26  
    27  var logger = logging.MustGetLogger("logbuffers")
    28  
    29  // LogBuffers is the struct providing access to the file or files representing the terms containing the ring buffer
    30  type LogBuffers struct {
    31  	mmapFiles []*memmap.File
    32  	buffers   [PartitionCount + 1]atomic.Buffer
    33  	meta      LogBufferMetaData
    34  	refCount  int
    35  }
    36  
    37  // Wrap is the factory method wrapping the LogBuffers structure around memory mapped file
    38  func Wrap(fileName string) *LogBuffers {
    39  	buffers := new(LogBuffers)
    40  
    41  	logLength := memmap.GetFileSize(fileName)
    42  	termLength := computeTermLength(int32(logLength))
    43  
    44  	checkTermLength(termLength)
    45  
    46  	if logLength < maxSingleMappingSize {
    47  		mmap, err := memmap.MapExisting(fileName, 0, 0)
    48  		if err != nil {
    49  			panic(err)
    50  		}
    51  
    52  		buffers.mmapFiles = []*memmap.File{mmap}
    53  		basePtr := uintptr(mmap.GetMemoryPtr())
    54  		for i := 0; i < PartitionCount; i++ {
    55  			ptr := unsafe.Pointer(basePtr + uintptr(int64(i)*int64(termLength)))
    56  			buffers.buffers[i].Wrap(ptr, int32(termLength))
    57  		}
    58  
    59  		ptr := unsafe.Pointer(basePtr + uintptr(logLength-int64(LogMetaDataLength)))
    60  		buffers.buffers[LogMetaDataSectionIndex].Wrap(ptr, LogMetaDataLength)
    61  
    62  		buffers.meta.Wrap(&buffers.buffers[LogMetaDataSectionIndex], 0)
    63  
    64  		//metaBytes := buffers.buffers[LogMetaDataSectionIndex].GetBytesArray(0, LogMetaDataLength)
    65  		//util.Print(metaBytes)
    66  
    67  		//fmt.Printf("meta: TermLen: %d \n", buffers.meta.TermLen.Get())
    68  		//fmt.Printf("meta: PageSize: %d \n", buffers.meta.PageSize.Get())
    69  		//fmt.Printf("meta: CorrelationId: %d \n", buffers.meta.CorrelationId.Get())
    70  		//fmt.Printf("meta: InitTermID: %d \n", buffers.meta.InitTermID.Get())
    71  		//fmt.Printf("meta: MTULen: %d \n", buffers.meta.MTULen.Get())
    72  		//fmt.Printf("meta: EndOfStreamPosOff: %d \n", buffers.meta.EndOfStreamPosOff.Get())
    73  	} else {
    74  		buffers.mmapFiles = make([]*memmap.File, PartitionCount+1)
    75  		metaDataSectionOffset := int64(termLength) * int64(LogMetaDataSectionIndex)
    76  		metaDataSectionLength := int(logLength - metaDataSectionOffset)
    77  
    78  		mmap, err := memmap.MapExisting(fileName, metaDataSectionOffset, metaDataSectionLength)
    79  		if err != nil {
    80  			panic("Failed to map the log buffer")
    81  		}
    82  		buffers.mmapFiles = append(buffers.mmapFiles, mmap)
    83  
    84  		for i := 0; i < PartitionCount; i++ {
    85  			// one map for each term
    86  			mmap, err := memmap.MapExisting(fileName, int64(i)*int64(termLength), int(termLength))
    87  			if err != nil {
    88  				panic("Failed to map the log buffer")
    89  			}
    90  			buffers.mmapFiles = append(buffers.mmapFiles, mmap)
    91  
    92  			basePtr := buffers.mmapFiles[i+1].GetMemoryPtr()
    93  
    94  			buffers.buffers[i].Wrap(basePtr, int32(termLength))
    95  		}
    96  		metaDataBasePtr := buffers.mmapFiles[0].GetMemoryPtr()
    97  		buffers.buffers[LogMetaDataSectionIndex].Wrap(metaDataBasePtr, LogMetaDataLength)
    98  		buffers.meta.Wrap(&buffers.buffers[PartitionCount], 0)
    99  	}
   100  
   101  	return buffers
   102  }
   103  
   104  // Meta return log buffer meta data flyweight
   105  func (logBuffers *LogBuffers) Meta() *LogBufferMetaData {
   106  	return &logBuffers.meta
   107  }
   108  
   109  // Buffer returns a buffer backing a specific term based on index. PartitionLength+1 is the size of the buffer array,
   110  // and the last buffer is the metadata buffer, which can be accessed through a convenience wrapped via Meta() method.
   111  func (logBuffers *LogBuffers) Buffer(index int) *atomic.Buffer {
   112  	return &logBuffers.buffers[index]
   113  }
   114  
   115  // Close will try to unmap all backing memory maps
   116  func (logBuffers *LogBuffers) Close() error {
   117  	logger.Debug("Closing logBuffers")
   118  	// TODO accumulate errors
   119  	var err error
   120  	for _, mmap := range logBuffers.mmapFiles {
   121  		err = mmap.Close()
   122  	}
   123  	logBuffers.mmapFiles = nil
   124  	return err
   125  }
   126  
   127  // IncRef increments the reference count. Returns the current reference count after increment.
   128  func (logBuffers *LogBuffers) IncRef() int {
   129  	logBuffers.refCount++
   130  	return logBuffers.refCount
   131  }
   132  
   133  // DecRef decrements the reference count. Returns the current reference counter after decrement.
   134  func (logBuffers *LogBuffers) DecRef() int {
   135  	logBuffers.refCount--
   136  	return logBuffers.refCount
   137  }