/****************************************************************************
**  SIONLIB     http://www.fz-juelich.de/jsc/sionlib                       **
*****************************************************************************
**  Copyright (c) 2008-2019                                                **
**  Forschungszentrum Juelich, Juelich Supercomputing Centre               **
**                                                                         **
**  See the file COPYRIGHT in the package base directory for details       **
****************************************************************************/

/*!
 * \file
 * \brief Debugging output
 *
 * Print debugging info according to the following environment variables:
 * <ul>
 *   <li>   SION_DEBUG        = filename - print to "filename" or stdout if filename is empty
 *   <li>   SION_MASK         = Binary mask used to select which messages should be logged
 *   <li>   SION_DEBUG_RANK   = Specifies for which rank to print the messages
 *   <li>   SION_DEBUG_RANK1  = The same as SION_DEBUG_RANK
 *   <li>   SION_DEBUG_RANK2  = Specifies a second rank to log
 * </ul>
 *
 * The value for the mask can be calculated by adding the following values:
 * <ul>
 *   <li>   1 -> sion user function entries and exits
 *   <li>   2 -> sion internal function entries and exits
 *   <li>   8 -> high frequently called sion user function entries and exits
 *   <li>  16 -> high frequently called sion internal function entries and exits
 *   <li>  32 -> internal steps of sion internal function
 *   <li>  64 -> internal steps of sion user function
 *   <li> 128 -> timings (top level)
 *   <li> 256 -> timings (low level)
 *   <li> 512 -> print filedesc structure contents
 *   <li>2048 -> higher frequently called sion internal function (internal steps)
 * </ul>
 */

#ifndef SION_SION_DEBUG_H
#define SION_SION_DEBUG_H

#include <stdio.h>

#include "sion_printts.h"

#define _SION_DEFAULT_RANK -1
#ifdef DPRINTF
#undef ONLY_DEBUG
#undef DPRINTF
#undef DPRINTFP
#undef DPRINTTS
#undef DPRINTFTS2
#endif
#ifdef SION_DEBUG
#define ONLY_DEBUG(A) A
#define DPRINTF(A) sion_dprintf A
#define DPRINTFP(A) sion_dprintfp A
#define DPRINTFTS(rank, desc) \
  sion_dprintfp(128, "TIMING", rank, "                                                       step=%-40s timestamp=%18.8f\n", \
    desc, _sion_get_time())
#define DPRINTFTS2(rank, desc) \
  sion_dprintfp(256, "TIMING", rank, "                                                       step=%-40s timestamp=%18.8f\n", \
    desc, _sion_get_time())
#else
#define ONLY_DEBUG(A)
#define DPRINTF(A)
#define DPRINTFP(A)
#define DPRINTFTS(A, B)
#define DPRINTFTS2(A, B)
#endif

#ifdef __cplusplus
extern "C" {
#endif

/*!
 * \brief initialize the debug environment
 *
 * evaluate the debug environment variables
 * set _sion_debug_isdebug and out
 */
int _sion_debug_init(void);

/*!
 * \brief Print debugging info formating the message like printf
 *
 */
int sion_dprintf(int mask, const char *format, ...);

/*!
 * \brief Print debugging info formating the message like printf and including the name of the calling function
 *
 */
int sion_dprintfp(int mask, const char *callfunction, int rank, const char *format, ...);
int sion_isdebug(void);

/*!
 * \brief sets debug mode.
 *
 * \param mask debug mask
 * \param filename if not NULL, output file for debug output (default is stderr)
 */
void sion_debug_on(int mask, const char *filename);
void sion_debug_off(void);

/*!
 * return the file pointer of the debug file
 */
FILE *sion_get_dfile(void);

/*!
 * close the debug-file
 */
void sion_dclose(void);

void _sion_debug_set_lock_cb(void (*set_lock)(void), void (*unset_lock)(void));

int _sion_debug_set_query_thread_num_function(int (*get_thread_num)(void));

#ifdef __cplusplus
}
#endif

#endif
