content: /*
   * Copyright (C) 2016-2021 ActionTech.
   * based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT.
   * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
   */
  
  package com.actiontech.dble.buffer;
  
  import com.actiontech.dble.config.model.SystemConfig;
  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  
  import java.util.Map;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.function.BiConsumer;
  
  /**
   * @author dcy
   * Create Date: 2022-10-14
   */
  public class MemoryBufferMonitor {
      private static final Logger LOGGER = LogManager.getLogger(MemoryBufferMonitor.class);
      static final MemoryBufferMonitor INSTANCE = new MemoryBufferMonitor();
      final Map<Long/*address*/, BufferPoolRecord> monitorMap = new ConcurrentHashMap<>();
  
      private volatile boolean enable = false;
      static final int TRACE_LINE_NUM = 8;
  
      public MemoryBufferMonitor() {
          this.enable = SystemConfig.getInstance().getEnableMemoryBufferMonitor() == 1;
      }
  
      public void setEnable(boolean enable) {
          if (!enable) {
              clean();
          }
          this.enable = enable;
      }
  
      private void clean() {
          monitorMap.clear();
      }
  
      public boolean isEnable() {
          return enable;
      }
  
      public static MemoryBufferMonitor getInstance() {
          return INSTANCE;
      }
  
      public void recordForEach(BiConsumer<? super Long, ? super BufferPoolRecord> action) {
          monitorMap.forEach(action);
      }
  
      public void remove(Long allocateAddress) {
          if (!enable) {
              return;
          }
          final BufferPoolRecord record = monitorMap.remove(allocateAddress);
          if (record != null) {
              if (LOGGER.isDebugEnabled())
                  LOGGER.debug("removed  buffer record ,address: {}, content:{}", allocateAddress, record);
          }
      }
  
      public void addRecord(BufferPoolRecord.Builder bufferRecordBuilder, long allocateAddress, int allocateSize) {
          if (!enable) {
              return;
          }
          try {
              if (bufferRecordBuilder == null) {
                  bufferRecordBuilder = BufferPoolRecord.builder();
              }
              if (SystemConfig.getInstance().getEnableMemoryBufferMonitorRecordPool() == 0 && bufferRecordBuilder.getType() == BufferType.POOL) {
                  return;
              }
  
              try {
                  throw new Exception("for debug");
              } catch (Exception e) {
                  String[] stackTrace;
                  final StackTraceElement[] fromStackTrace = e.getStackTrace();
  
                  int len = Math.min(fromStackTrace.length, TRACE_LINE_NUM);
                  stackTrace = new String[len];
                  for (int i = 0; i < len; i++) {
                      stackTrace[i] = fromStackTrace[i].toString();
                  }
                  bufferRecordBuilder.withStacktrace(stackTrace);
  
              }
              final BufferPoolRecord record = bufferRecordBuilder.withAllocatedTime(System.currentTimeMillis()).withAllocateSize(allocateSize).build();
              if (LOGGER.isDebugEnabled())
                  LOGGER.debug("new  buffer record ,address: {}, content:{}", allocateAddress, record);
              monitorMap.put(allocateAddress, record);
  
          } catch (Exception e) {
              LOGGER.warn("record buffer monitor error", e);
          } finally {
              if (!enable) {
                  clean();
              }
          }
      }
  
  
  }
  