//
// See the file LICENSE for redistribution information.
//
// Copyright (c) 2002-2003
//	Sleepycat Software.  All rights reserved.
//

static const char revid[] = "$Id: Log.cpp,v 1.14 2003/05/09 00:01:49 mjc Exp $";

#include "dbxml_config.h"
#include "dbxml/XmlPortability.hpp"
#include "Log.hpp"

#include <db_cxx.h>

#include <iostream>
#include <cstring>

using namespace DbXml;

static int globalDebugLevels = DbXml::L_ERROR;
static int globalDebugCategories = DbXml::C_ALL;

void DbXml::implSetLogLevel(ImplLogLevel level, bool enabled)
{
	if (level == L_NONE) {
		globalDebugLevels = level;
	} else {
		if (enabled) {
			globalDebugLevels |= level;
		} else {
			globalDebugLevels &= ~level;
		}
	}
}

void DbXml::implSetLogCategory(ImplLogCategory category, bool enabled)
{
	if (category == C_NONE) {
		globalDebugCategories = category;
	} else {
		if (enabled) {
			globalDebugCategories |= category;
		} else {
			globalDebugCategories &= ~category;
		}
	}
}

static const char *categoryName(DbXml::ImplLogCategory category)
{
	switch (category) {
	case DbXml::C_NONE:
		return "None      ";
	case DbXml::C_INDEXER:
		return "Indexer   ";
	case DbXml::C_QUERY:
		return "Query     ";
	case DbXml::C_OPTIMIZER:
		return "Optimizer ";
	case DbXml::C_DICTIONARY:
		return "Dictionary";
	case DbXml::C_CONTAINER:
		return "Container ";
	case DbXml::C_ALL:
		return "All       ";
	}
	return "None";
}

bool DbXml::isLogEnabled(ImplLogCategory category, ImplLogLevel level)
{
	return (globalDebugLevels&level && globalDebugCategories&category);
}

void DbXml::log(DbEnv *environment, ImplLogCategory category, ImplLogLevel level, const char *container, const char *message)
{
	if (isLogEnabled(category, level)) {
		if (environment == 0) {
			std::cerr
			<< categoryName(category)
			<< " - "
			<< (container == 0 ? "none" : container)
			<< " - "
			<< message
			<< std::endl;
		} else {
			// db aborts if you try to log a message longer than an internal buffer,
			// so we must be very careful not to trip that abort. In db.4.1.24 the buffer
			// is 2048 bytes.
			//
			const char *p1 = categoryName(category);
			const char *p2 = (container == 0 ? "none" : container);
			size_t l = strlen(message);
			size_t r = 2048 - (strlen(p1) + 3) - (strlen(p2) + 3);
			if (l > r) {
				((char *)message)[r - 4] = '.';
				((char *)message)[r - 3] = '.';
				((char *)message)[r - 2] = '.';
				((char *)message)[r - 1] = '\0';
			}
			environment->errx("%s - %s - %s", categoryName(category), (container == 0 ? "none" : container), message);
		}
	}
}
