1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-02-12 07:47:12 +01:00
SqMod/vendor/POCO/Data/src/SQLChannel.cpp
Sandu Liviu Catalin 4a6bfc086c Major plugin refactor and cleanup.
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.
2021-01-30 08:51:39 +02:00

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