mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-02-12 07:47:12 +01:00
Switched to POCO library for unified platform/library interface. Deprecated the external module API. It was creating more problems than solving. Removed most built-in libraries in favor of system libraries for easier maintenance. Cleaned and secured code with help from static analyzers.
297 lines
5.3 KiB
C++
297 lines
5.3 KiB
C++
//
|
|
// SQLChannel.cpp
|
|
//
|
|
// Library: Data
|
|
// Package: Logging
|
|
// Module: SQLChannel
|
|
//
|
|
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
|
// and Contributors.
|
|
//
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
//
|
|
|
|
|
|
#include "Poco/Data/SQLChannel.h"
|
|
#include "Poco/Data/SessionFactory.h"
|
|
#include "Poco/DateTime.h"
|
|
#include "Poco/LoggingFactory.h"
|
|
#include "Poco/Instantiator.h"
|
|
#include "Poco/NumberParser.h"
|
|
#include "Poco/NumberFormatter.h"
|
|
#include "Poco/Format.h"
|
|
|
|
|
|
namespace Poco {
|
|
namespace Data {
|
|
|
|
|
|
using namespace Keywords;
|
|
|
|
|
|
const std::string SQLChannel::PROP_CONNECTOR("connector");
|
|
const std::string SQLChannel::PROP_CONNECT("connect");
|
|
const std::string SQLChannel::PROP_NAME("name");
|
|
const std::string SQLChannel::PROP_TABLE("table");
|
|
const std::string SQLChannel::PROP_ARCHIVE_TABLE("archive");
|
|
const std::string SQLChannel::PROP_MAX_AGE("keep");
|
|
const std::string SQLChannel::PROP_ASYNC("async");
|
|
const std::string SQLChannel::PROP_TIMEOUT("timeout");
|
|
const std::string SQLChannel::PROP_THROW("throw");
|
|
|
|
|
|
SQLChannel::SQLChannel():
|
|
_name("-"),
|
|
_table("T_POCO_LOG"),
|
|
_timeout(1000),
|
|
_throw(true),
|
|
_async(true),
|
|
_pid(),
|
|
_tid(),
|
|
_priority()
|
|
{
|
|
}
|
|
|
|
|
|
SQLChannel::SQLChannel(const std::string& connector,
|
|
const std::string& connect,
|
|
const std::string& name):
|
|
_connector(connector),
|
|
_connect(connect),
|
|
_name(name),
|
|
_table("T_POCO_LOG"),
|
|
_timeout(1000),
|
|
_throw(true),
|
|
_async(true),
|
|
_pid(),
|
|
_tid(),
|
|
_priority()
|
|
{
|
|
open();
|
|
}
|
|
|
|
|
|
SQLChannel::~SQLChannel()
|
|
{
|
|
try
|
|
{
|
|
close();
|
|
}
|
|
catch (...)
|
|
{
|
|
poco_unexpected();
|
|
}
|
|
}
|
|
|
|
|
|
void SQLChannel::open()
|
|
{
|
|
if (_connector.empty() || _connect.empty())
|
|
throw IllegalStateException("Connector and connect string must be non-empty.");
|
|
|
|
_pSession = new Session(_connector, _connect);
|
|
initLogStatement();
|
|
}
|
|
|
|
|
|
void SQLChannel::close()
|
|
{
|
|
wait();
|
|
}
|
|
|
|
|
|
void SQLChannel::log(const Message& msg)
|
|
{
|
|
if (_async) logAsync(msg);
|
|
else logSync(msg);
|
|
}
|
|
|
|
|
|
void SQLChannel::logAsync(const Message& msg)
|
|
{
|
|
poco_check_ptr (_pLogStatement);
|
|
if (0 == wait() && !_pLogStatement->done() && !_pLogStatement->initialized())
|
|
{
|
|
if (_throw)
|
|
throw TimeoutException("Timed out waiting for previous statement completion");
|
|
else return;
|
|
}
|
|
|
|
if (!_pSession || !_pSession->isConnected()) open();
|
|
logSync(msg);
|
|
}
|
|
|
|
|
|
void SQLChannel::logSync(const Message& msg)
|
|
{
|
|
if (_pArchiveStrategy) _pArchiveStrategy->archive();
|
|
|
|
_source = msg.getSource();
|
|
_pid = msg.getPid();
|
|
_thread = msg.getThread();
|
|
_tid = msg.getTid();
|
|
_priority = msg.getPriority();
|
|
_text = msg.getText();
|
|
_dateTime = msg.getTime();
|
|
if (_source.empty()) _source = _name;
|
|
|
|
try
|
|
{
|
|
_pLogStatement->execute();
|
|
}
|
|
catch (Exception&)
|
|
{
|
|
if (_throw) throw;
|
|
}
|
|
}
|
|
|
|
|
|
void SQLChannel::setProperty(const std::string& name, const std::string& value)
|
|
{
|
|
if (name == PROP_NAME)
|
|
{
|
|
_name = value;
|
|
if (_name.empty()) _name = "-";
|
|
}
|
|
else if (name == PROP_CONNECTOR)
|
|
{
|
|
_connector = value;
|
|
close(); open();
|
|
}
|
|
else if (name == PROP_CONNECT)
|
|
{
|
|
_connect = value;
|
|
close(); open();
|
|
}
|
|
else if (name == PROP_TABLE)
|
|
{
|
|
_table = value;
|
|
initLogStatement();
|
|
}
|
|
else if (name == PROP_ARCHIVE_TABLE)
|
|
{
|
|
if (value.empty())
|
|
{
|
|
_pArchiveStrategy = 0;
|
|
}
|
|
else if (_pArchiveStrategy)
|
|
{
|
|
_pArchiveStrategy->setDestination(value);
|
|
}
|
|
else
|
|
{
|
|
_pArchiveStrategy = new ArchiveByAgeStrategy(_connector, _connect, _table, value);
|
|
}
|
|
}
|
|
else if (name == PROP_MAX_AGE)
|
|
{
|
|
if (value.empty() || "forever" == value)
|
|
{
|
|
_pArchiveStrategy = 0;
|
|
}
|
|
else if (_pArchiveStrategy)
|
|
{
|
|
_pArchiveStrategy->setThreshold(value);
|
|
}
|
|
else
|
|
{
|
|
ArchiveByAgeStrategy* p = new ArchiveByAgeStrategy(_connector, _connect, _table);
|
|
p->setThreshold(value);
|
|
_pArchiveStrategy = p;
|
|
}
|
|
}
|
|
else if (name == PROP_ASYNC)
|
|
{
|
|
_async = isTrue(value);
|
|
initLogStatement();
|
|
}
|
|
else if (name == PROP_TIMEOUT)
|
|
{
|
|
if (value.empty() || '0' == value[0])
|
|
_timeout = Statement::WAIT_FOREVER;
|
|
else
|
|
_timeout = NumberParser::parse(value);
|
|
}
|
|
else if (name == PROP_THROW)
|
|
{
|
|
_throw = isTrue(value);
|
|
}
|
|
else
|
|
{
|
|
Channel::setProperty(name, value);
|
|
}
|
|
}
|
|
|
|
|
|
std::string SQLChannel::getProperty(const std::string& name) const
|
|
{
|
|
if (name == PROP_NAME)
|
|
{
|
|
if (_name != "-") return _name;
|
|
else return "";
|
|
}
|
|
else if (name == PROP_CONNECTOR)
|
|
{
|
|
return _connector;
|
|
}
|
|
else if (name == PROP_CONNECT)
|
|
{
|
|
return _connect;
|
|
}
|
|
else if (name == PROP_TABLE)
|
|
{
|
|
return _table;
|
|
}
|
|
else if (name == PROP_ARCHIVE_TABLE)
|
|
{
|
|
return _pArchiveStrategy ? _pArchiveStrategy->getDestination() : "";
|
|
}
|
|
else if (name == PROP_MAX_AGE)
|
|
{
|
|
return _pArchiveStrategy ? _pArchiveStrategy->getThreshold() : "forever";
|
|
}
|
|
else if (name == PROP_TIMEOUT)
|
|
{
|
|
return NumberFormatter::format(_timeout);
|
|
}
|
|
else if (name == PROP_THROW)
|
|
{
|
|
if (_throw) return "true";
|
|
else return "false";
|
|
}
|
|
else
|
|
{
|
|
return Channel::getProperty(name);
|
|
}
|
|
}
|
|
|
|
|
|
void SQLChannel::initLogStatement()
|
|
{
|
|
_pLogStatement = new Statement(*_pSession);
|
|
|
|
std::string sql;
|
|
Poco::format(sql, "INSERT INTO %s VALUES (?,?,?,?,?,?,?,?)", _table);
|
|
*_pLogStatement << sql,
|
|
use(_source),
|
|
use(_name),
|
|
use(_pid),
|
|
use(_thread),
|
|
use(_tid),
|
|
use(_priority),
|
|
use(_text),
|
|
use(_dateTime);
|
|
|
|
if (_async) _pLogStatement->setAsync();
|
|
}
|
|
|
|
|
|
void SQLChannel::registerChannel()
|
|
{
|
|
Poco::LoggingFactory::defaultFactory().registerChannelClass("SQLChannel",
|
|
new Poco::Instantiator<SQLChannel, Poco::Channel>);
|
|
}
|
|
|
|
|
|
} } // namespace Poco::Data
|