/// <summary> /// Construct the log buffers for a given log file. /// </summary> /// <param name="logFileName"></param> public LogBuffers(string logFileName) { try { var fileInfo = new FileInfo(logFileName); var logLength = fileInfo.Length; // if log length exceeds MAX_INT we need multiple mapped buffers, (see FileChannel.map doc). if (logLength < int.MaxValue) { var mappedBuffer = IoUtil.MapExistingFile(logFileName, MapMode.ReadWrite); // TODO Java has sparse hint & Little Endian _mappedByteBuffers = new[] { mappedBuffer }; _logMetaDataBuffer = new UnsafeBuffer(mappedBuffer.Pointer, (int)(logLength - LogBufferDescriptor.LOG_META_DATA_LENGTH), LogBufferDescriptor.LOG_META_DATA_LENGTH); int termLength = LogBufferDescriptor.TermLength(_logMetaDataBuffer); int pageSize = LogBufferDescriptor.PageSize(_logMetaDataBuffer); LogBufferDescriptor.CheckTermLength(termLength); LogBufferDescriptor.CheckPageSize(pageSize); _termLength = termLength; for (var i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++) { _termBuffers[i] = new UnsafeBuffer(mappedBuffer.Pointer, i * termLength, termLength); } } else { _mappedByteBuffers = new MappedByteBuffer[LogBufferDescriptor.PARTITION_COUNT + 1]; int assumedTermLength = LogBufferDescriptor.TERM_MAX_LENGTH; long metaDataSectionOffset = assumedTermLength * (long)LogBufferDescriptor.PARTITION_COUNT; long metaDataMappingLength = logLength - metaDataSectionOffset; var memoryMappedFile = IoUtil.OpenMemoryMappedFile(logFileName); var metaDataMappedBuffer = new MappedByteBuffer(memoryMappedFile, metaDataSectionOffset, metaDataMappingLength); // Little Endian _mappedByteBuffers[LogBufferDescriptor.LOG_META_DATA_SECTION_INDEX] = metaDataMappedBuffer; _logMetaDataBuffer = new UnsafeBuffer( metaDataMappedBuffer.Pointer, (int)metaDataMappingLength - LogBufferDescriptor.LOG_META_DATA_LENGTH, LogBufferDescriptor.LOG_META_DATA_LENGTH); int metaDataTermLength = LogBufferDescriptor.TermLength(_logMetaDataBuffer); int pageSize = LogBufferDescriptor.PageSize(_logMetaDataBuffer); LogBufferDescriptor.CheckPageSize(pageSize); if (metaDataTermLength != assumedTermLength) { throw new InvalidOperationException( $"assumed term length {assumedTermLength} does not match metadta: termLength = {metaDataTermLength}"); } _termLength = assumedTermLength; for (var i = 0; i < LogBufferDescriptor.PARTITION_COUNT; i++) { long position = assumedTermLength * (long)i; _mappedByteBuffers[i] = new MappedByteBuffer(memoryMappedFile, position, assumedTermLength); // Little Endian _termBuffers[i] = new UnsafeBuffer(_mappedByteBuffers[i].Pointer, 0, assumedTermLength); } } } catch (InvalidOperationException ex) { Dispose(); throw ex; } }