亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

MySQL Debug Package 源碼分析

2024-11-08 09:21:30
17
0

MySQLDebug Package,涉及到源文件,主要是兩個文件my_dbug.hdbug.cc

幾個比較重要的結構:

Struct Settings
struct settings {
  uint flags;               /* Current settings flags               */
  uint maxdepth;            /* Current maximum trace depth          */
  uint delay;               /* Delay after each output line         */
  uint sub_level;           /* Sub this from code_state->level      */
  FILE *out_file;           /* Current output stream                */
  FILE *prof_file;          /* Current profiling stream             */
  char name[FN_REFLEN];     /* Name of output file                  */
  struct link *functions;   /* List of functions                    */
  struct link *p_functions; /* List of profiled functions           */
  struct link *keywords;    /* List of debug keywords               */
  struct link *processes;   /* List of process names                */
  struct settings *next;    /* Next settings in the list            */
};

用于記錄配置項,其中前面介紹的flags以及flags后面緊跟的配置設置值,會被記錄在該struct的實例中。

 Struct CODE_STATE
struct CODE_STATE {
  const char *process; /* Pointer to process name; usually argv[0] */
  const char *func;    /* Name of current user function            */
  int func_len;        /* How many bytes to print from func        */
  const char *file;    /* Name of current user file                */
  struct _db_stack_frame_ *framep; /* Pointer to current frame              */
  struct settings *stack; /* debugging settings                       */
  int lineno;             /* Current debugger output line number      */
  uint level;             /* Current function nesting level           */

  /*
   *      The following variables are used to hold the state information
   *      between the call to _db_pargs_() and _db_doprnt_(), during
   *      expansion of the DBUG_PRINT macro.  This is the only macro
   *      that currently uses these variables.
   *
   *      These variables are currently used only by _db_pargs_() and
   *      _db_doprnt_().
   */

  uint u_line;           /* User source code line number */
  int locked;            /* If locked with _db_lock_file_ */
  const char *u_keyword; /* Keyword for current macro */
  uint m_read_lock_count;
};

核心的數據結構,配置值,函數調用堆棧,調用信息的輸出展示,均需要該結構。

struct _db_stack_frame_
struct _db_stack_frame_ {
  const char *func;   /* function name of the previous stack frame       */
  int func_len;       /* how much to print from func */
  const char *file;   /* filename of the function of previous frame      */
  unsigned int level; /* this nesting level, highest bit enables tracing */
  struct _db_stack_frame_ *prev; /* pointer to the previous frame */
};

函數調用棧的主要結構,記錄了function名稱,func_len,該函數所在的源文件,函數調用堆棧中的層級。

核心函數

code_state 函數
static CODE_STATE *code_state(void) {
  CODE_STATE *cs, **cs_ptr;
//如果全局init_settings沒有初始化,對全局init_settings進行一次初始化
  if (!init_done) {
    init_done = true;
    native_mutex_init(&THR_LOCK_dbug, nullptr);
    native_mutex_init(&THR_LOCK_gcov, nullptr);
    native_rw_init(&THR_LOCK_init_settings);
    memset(&init_settings, 0, sizeof(init_settings));
    init_settings.out_file = stderr;
    init_settings.flags = OPEN_APPEND;
  }
//獲取調用函數code_state的線程是否初始化了自己的code_sate對象。如果cs_ptr為空,說明是在該線程初始化之前調用了code_state。
  if (!(cs_ptr = my_thread_var_dbug()))
return nullptr; /* Thread not initialised */


//這一步,為該線程初始化一個code_state對象。
  if (!(cs = *cs_ptr)) {
    cs = (CODE_STATE *)DbugMalloc(sizeof(*cs));
    memset(cs, 0, sizeof(*cs));
    cs->process = db_process ? db_process : "dbug";
    cs->func = "?func";
    cs->file = "?file";
    cs->stack = &init_settings;
    cs->m_read_lock_count = 0;
    *cs_ptr = cs;
  }
// 將該線程的code_state對象的地址返回出去,后續返回的都將是本線程的code_state對象。
  return cs;
}
_db_enter_ 函數
//將當前_stack_frame_的信息賦值給code_state對象
void _db_enter_(const char *_func_, int func_len, const char *_file_,
                uint _line_, struct _db_stack_frame_ *_stack_frame_) {
  int save_errno;
  CODE_STATE *cs;
  if (!((cs = code_state()))) {
    _stack_frame_->level =
        0; /* Set to avoid valgrind warnings if dbug is enabled later */
    _stack_frame_->prev = nullptr;
    return;
  }
  save_errno = errno;

  read_lock_stack(cs);
//將code_state中的當前信息,保存在_stack_frame_中,
  _stack_frame_->func = cs->func;
  _stack_frame_->func_len = cs->func_len;
  _stack_frame_->file = cs->file;
//更新code_state當前信息
  cs->func = _func_;
  cs->func_len = func_len;
  cs->file = _file_;
//對_stack_frame_進行壓棧處理
  _stack_frame_->prev = cs->framep;
  _stack_frame_->level = ++cs->level | framep_trace_flag(cs, cs->framep);
  cs->framep = _stack_frame_;
//判斷trace設置狀態
  switch (DoTrace(cs)) {
    case ENABLE_TRACE:
      cs->framep->level |= TRACE_ON;
      if (!TRACING) break;
      [[fallthrough]];
case DO_TRACE:
//如果trace中,則打印函數信息
      if (TRACING) {
        if (!cs->locked) native_mutex_lock(&THR_LOCK_dbug);
        DoPrefix(cs, _line_);
        Indent(cs, cs->level);
        (void)fprintf(cs->stack->out_file, ">%.*s\n", cs->func_len, cs->func);
	//刷新到trace輸出文件。
        DbugFlush(cs); /* This does a unlock */
      }
      break;
    case DISABLE_TRACE:
      cs->framep->level &= ~TRACE_ON;
      [[fallthrough]];
    case DONT_TRACE:
      break;
  }
  errno = save_errno;

  unlock_stack(cs);
}
_db_return_函數
調用該函數,把 case_date stack_frame 堆棧當前頭部的frame打印出出來,同時進行出棧出來,并銷毀該stack_frame
void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_) {
  int save_errno = errno;
  uint _slevel_ = _stack_frame_->level & ~TRACE_ON;
  CODE_STATE *cs;
//宏定義,將本線程的code_state對象指針傳給cs
  get_code_state_or_return;
//和_db_enter配對,在enter中壓棧的stack_frame肯定和同函數中調用return 出棧的stack_frame相同,否則報錯
  if (cs->framep != _stack_frame_) {
    char buf[512];
    snprintf(buf, sizeof(buf), ERR_MISSING_RETURN, cs->func);
    DbugExit(buf);
  }

  read_lock_stack(cs);

  if (DoTrace(cs) & DO_TRACE) {
    if (TRACING) {
      if (!cs->locked) native_mutex_lock(&THR_LOCK_dbug);
     //根據debug設置,打印前綴信息
      DoPrefix(cs, _line_);
	//根據level信息,打印空格,level深的,其前面空格就多,方便觀看函數調用層級
      Indent(cs, cs->level);
	//打印函數名,以及源文件行號
      if (_line_ == 0) {
        (void)fprintf(cs->stack->out_file, "<%.*s\n", cs->func_len, cs->func);
      } else {
        (void)fprintf(cs->stack->out_file, "<%.*s %u\n", cs->func_len, cs->func,
                      _line_);
      }
      DbugFlush(cs);
    }
  }
//將code_state 對象里的函數信息,level信息,file信息等修改為和傳入的_stack_frame_相同。
//同時將cs_freamep堆棧移到下一層
  /*
    Check to not set level < 0. This can happen if DBUG was disabled when
    function was entered and enabled in function.
  */
  cs->level = _slevel_ != 0 ? _slevel_ - 1 : 0;
  cs->func = _stack_frame_->func;
  cs->func_len = _stack_frame_->func_len;
  cs->file = _stack_frame_->file;
  if (cs->framep != nullptr) cs->framep = cs->framep->prev;
  errno = save_errno;

  unlock_stack(cs);
}

 

0條評論
0 / 1000
gqhao
1文章數
1粉絲數
gqhao
1 文章 | 1 粉絲
gqhao
1文章數
1粉絲數
gqhao
1 文章 | 1 粉絲
原創

MySQL Debug Package 源碼分析

2024-11-08 09:21:30
17
0

MySQLDebug Package,涉及到源文件,主要是兩個文件my_dbug.hdbug.cc

幾個比較重要的結構:

Struct Settings
struct settings {
  uint flags;               /* Current settings flags               */
  uint maxdepth;            /* Current maximum trace depth          */
  uint delay;               /* Delay after each output line         */
  uint sub_level;           /* Sub this from code_state->level      */
  FILE *out_file;           /* Current output stream                */
  FILE *prof_file;          /* Current profiling stream             */
  char name[FN_REFLEN];     /* Name of output file                  */
  struct link *functions;   /* List of functions                    */
  struct link *p_functions; /* List of profiled functions           */
  struct link *keywords;    /* List of debug keywords               */
  struct link *processes;   /* List of process names                */
  struct settings *next;    /* Next settings in the list            */
};

用于記錄配置項,其中前面介紹的flags以及flags后面緊跟的配置設置值,會被記錄在該struct的實例中。

 Struct CODE_STATE
struct CODE_STATE {
  const char *process; /* Pointer to process name; usually argv[0] */
  const char *func;    /* Name of current user function            */
  int func_len;        /* How many bytes to print from func        */
  const char *file;    /* Name of current user file                */
  struct _db_stack_frame_ *framep; /* Pointer to current frame              */
  struct settings *stack; /* debugging settings                       */
  int lineno;             /* Current debugger output line number      */
  uint level;             /* Current function nesting level           */

  /*
   *      The following variables are used to hold the state information
   *      between the call to _db_pargs_() and _db_doprnt_(), during
   *      expansion of the DBUG_PRINT macro.  This is the only macro
   *      that currently uses these variables.
   *
   *      These variables are currently used only by _db_pargs_() and
   *      _db_doprnt_().
   */

  uint u_line;           /* User source code line number */
  int locked;            /* If locked with _db_lock_file_ */
  const char *u_keyword; /* Keyword for current macro */
  uint m_read_lock_count;
};

核心的數據結構,配置值,函數調用堆棧,調用信息的輸出展示,均需要該結構。

struct _db_stack_frame_
struct _db_stack_frame_ {
  const char *func;   /* function name of the previous stack frame       */
  int func_len;       /* how much to print from func */
  const char *file;   /* filename of the function of previous frame      */
  unsigned int level; /* this nesting level, highest bit enables tracing */
  struct _db_stack_frame_ *prev; /* pointer to the previous frame */
};

函數調用棧的主要結構,記錄了function名稱,func_len,該函數所在的源文件,函數調用堆棧中的層級。

核心函數

code_state 函數
static CODE_STATE *code_state(void) {
  CODE_STATE *cs, **cs_ptr;
//如果全局init_settings沒有初始化,對全局init_settings進行一次初始化
  if (!init_done) {
    init_done = true;
    native_mutex_init(&THR_LOCK_dbug, nullptr);
    native_mutex_init(&THR_LOCK_gcov, nullptr);
    native_rw_init(&THR_LOCK_init_settings);
    memset(&init_settings, 0, sizeof(init_settings));
    init_settings.out_file = stderr;
    init_settings.flags = OPEN_APPEND;
  }
//獲取調用函數code_state的線程是否初始化了自己的code_sate對象。如果cs_ptr為空,說明是在該線程初始化之前調用了code_state。
  if (!(cs_ptr = my_thread_var_dbug()))
return nullptr; /* Thread not initialised */


//這一步,為該線程初始化一個code_state對象。
  if (!(cs = *cs_ptr)) {
    cs = (CODE_STATE *)DbugMalloc(sizeof(*cs));
    memset(cs, 0, sizeof(*cs));
    cs->process = db_process ? db_process : "dbug";
    cs->func = "?func";
    cs->file = "?file";
    cs->stack = &init_settings;
    cs->m_read_lock_count = 0;
    *cs_ptr = cs;
  }
// 將該線程的code_state對象的地址返回出去,后續返回的都將是本線程的code_state對象。
  return cs;
}
_db_enter_ 函數
//將當前_stack_frame_的信息賦值給code_state對象
void _db_enter_(const char *_func_, int func_len, const char *_file_,
                uint _line_, struct _db_stack_frame_ *_stack_frame_) {
  int save_errno;
  CODE_STATE *cs;
  if (!((cs = code_state()))) {
    _stack_frame_->level =
        0; /* Set to avoid valgrind warnings if dbug is enabled later */
    _stack_frame_->prev = nullptr;
    return;
  }
  save_errno = errno;

  read_lock_stack(cs);
//將code_state中的當前信息,保存在_stack_frame_中,
  _stack_frame_->func = cs->func;
  _stack_frame_->func_len = cs->func_len;
  _stack_frame_->file = cs->file;
//更新code_state當前信息
  cs->func = _func_;
  cs->func_len = func_len;
  cs->file = _file_;
//對_stack_frame_進行壓棧處理
  _stack_frame_->prev = cs->framep;
  _stack_frame_->level = ++cs->level | framep_trace_flag(cs, cs->framep);
  cs->framep = _stack_frame_;
//判斷trace設置狀態
  switch (DoTrace(cs)) {
    case ENABLE_TRACE:
      cs->framep->level |= TRACE_ON;
      if (!TRACING) break;
      [[fallthrough]];
case DO_TRACE:
//如果trace中,則打印函數信息
      if (TRACING) {
        if (!cs->locked) native_mutex_lock(&THR_LOCK_dbug);
        DoPrefix(cs, _line_);
        Indent(cs, cs->level);
        (void)fprintf(cs->stack->out_file, ">%.*s\n", cs->func_len, cs->func);
	//刷新到trace輸出文件。
        DbugFlush(cs); /* This does a unlock */
      }
      break;
    case DISABLE_TRACE:
      cs->framep->level &= ~TRACE_ON;
      [[fallthrough]];
    case DONT_TRACE:
      break;
  }
  errno = save_errno;

  unlock_stack(cs);
}
_db_return_函數
調用該函數,把 case_date stack_frame 堆棧當前頭部的frame打印出出來,同時進行出棧出來,并銷毀該stack_frame
void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_) {
  int save_errno = errno;
  uint _slevel_ = _stack_frame_->level & ~TRACE_ON;
  CODE_STATE *cs;
//宏定義,將本線程的code_state對象指針傳給cs
  get_code_state_or_return;
//和_db_enter配對,在enter中壓棧的stack_frame肯定和同函數中調用return 出棧的stack_frame相同,否則報錯
  if (cs->framep != _stack_frame_) {
    char buf[512];
    snprintf(buf, sizeof(buf), ERR_MISSING_RETURN, cs->func);
    DbugExit(buf);
  }

  read_lock_stack(cs);

  if (DoTrace(cs) & DO_TRACE) {
    if (TRACING) {
      if (!cs->locked) native_mutex_lock(&THR_LOCK_dbug);
     //根據debug設置,打印前綴信息
      DoPrefix(cs, _line_);
	//根據level信息,打印空格,level深的,其前面空格就多,方便觀看函數調用層級
      Indent(cs, cs->level);
	//打印函數名,以及源文件行號
      if (_line_ == 0) {
        (void)fprintf(cs->stack->out_file, "<%.*s\n", cs->func_len, cs->func);
      } else {
        (void)fprintf(cs->stack->out_file, "<%.*s %u\n", cs->func_len, cs->func,
                      _line_);
      }
      DbugFlush(cs);
    }
  }
//將code_state 對象里的函數信息,level信息,file信息等修改為和傳入的_stack_frame_相同。
//同時將cs_freamep堆棧移到下一層
  /*
    Check to not set level < 0. This can happen if DBUG was disabled when
    function was entered and enabled in function.
  */
  cs->level = _slevel_ != 0 ? _slevel_ - 1 : 0;
  cs->func = _stack_frame_->func;
  cs->func_len = _stack_frame_->func_len;
  cs->file = _stack_frame_->file;
  if (cs->framep != nullptr) cs->framep = cs->framep->prev;
  errno = save_errno;

  unlock_stack(cs);
}

 

文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0