#include "dpiImpl.h"
#define DPI_DEBUG_THREAD_FORMAT "%.5" PRIu64
#define DPI_DEBUG_DATE_FORMAT "%.4d-%.2d-%.2d"
#define DPI_DEBUG_TIME_FORMAT "%.2d:%.2d:%.2d.%.3d"
unsigned long dpiDebugLevel = 0;
static char dpiDebugPrefixFormat[64] = "ODPI [%i] %d %t: ";
static FILE *dpiDebugStream = NULL;
static void dpiDebug__getFormatWithPrefix(const char *format,
char *formatWithPrefix, size_t maxFormatWithPrefixSize)
{
char *sourcePtr, *targetPtr;
int gotTime, tempSize;
uint64_t threadId;
size_t size;
#ifdef _WIN32
SYSTEMTIME time;
#else
struct timeval timeOfDay;
struct tm time;
#endif
gotTime = 0;
sourcePtr = dpiDebugPrefixFormat;
targetPtr = formatWithPrefix;
size = maxFormatWithPrefixSize - strlen(format);
while (*sourcePtr && size > 20) {
if (*sourcePtr != '%') {
*targetPtr++ = *sourcePtr++;
maxFormatWithPrefixSize--;
continue;
}
sourcePtr++;
switch (*sourcePtr) {
case 'i':
#ifdef _WIN32
threadId = (uint64_t) GetCurrentThreadId();
#elif defined __linux
threadId = (uint64_t) syscall(SYS_gettid);
#elif defined __APPLE__
pthread_threadid_np(NULL, &threadId);
#else
threadId = (uint64_t) pthread_self();
#endif
tempSize = sprintf(targetPtr, DPI_DEBUG_THREAD_FORMAT,
threadId);
size -= tempSize;
targetPtr += tempSize;
sourcePtr++;
break;
case 'd':
case 't':
if (!gotTime) {
gotTime = 1;
#ifdef _WIN32
GetLocalTime(&time);
#else
gettimeofday(&timeOfDay, NULL);
localtime_r(&timeOfDay.tv_sec, &time);
#endif
}
#ifdef _WIN32
if (*sourcePtr == 'd')
tempSize = sprintf(targetPtr, DPI_DEBUG_DATE_FORMAT,
time.wYear, time.wMonth, time.wDay);
else tempSize = sprintf(targetPtr, DPI_DEBUG_TIME_FORMAT,
time.wHour, time.wMinute, time.wSecond,
time.wMilliseconds);
#else
if (*sourcePtr == 'd')
tempSize = sprintf(targetPtr, DPI_DEBUG_DATE_FORMAT,
time.tm_year + 1900, time.tm_mon + 1,
time.tm_mday);
else tempSize = sprintf(targetPtr, DPI_DEBUG_TIME_FORMAT,
time.tm_hour, time.tm_min, time.tm_sec,
(int) (timeOfDay.tv_usec / 1000));
#endif
size -= tempSize;
targetPtr += tempSize;
sourcePtr++;
break;
case '\0':
break;
default:
*targetPtr++ = '%';
*targetPtr++ = *sourcePtr++;
break;
}
}
strcpy(targetPtr, format);
}
void dpiDebug__initialize(void)
{
char *envValue;
envValue = getenv("DPI_DEBUG_LEVEL");
if (envValue)
dpiDebugLevel = (unsigned long) strtol(envValue, NULL, 10);
envValue = getenv("DPI_DEBUG_PREFIX");
if (envValue && strlen(envValue) < sizeof(dpiDebugPrefixFormat))
strcpy(dpiDebugPrefixFormat, envValue);
dpiDebugStream = stderr;
if (dpiDebugLevel) {
dpiDebug__print("ODPI-C %s\n", DPI_VERSION_STRING);
dpiDebug__print("debugging messages initialized at level %lu\n",
dpiDebugLevel);
}
}
void dpiDebug__print(const char *format, ...)
{
char formatWithPrefix[512];
va_list varArgs;
dpiDebug__getFormatWithPrefix(format, formatWithPrefix,
sizeof(formatWithPrefix));
va_start(varArgs, format);
(void) vfprintf(dpiDebugStream, formatWithPrefix, varArgs);
va_end(varArgs);
}