Commit 4c0f6517 authored by Karel Slaný's avatar Karel Slaný

Pulled changes from desktop application.

parent d1b75db1
......@@ -31,7 +31,8 @@ winphone|winrt|win32 {
} else {
QMAKE_CXXFLAGS += \
-g -O0 -std=c++11 \
-Wall -Wextra -pedantic
-Wall -Wextra -pedantic \
-Wdate-time -Wformat -Werror=format-security
SOURCES += \
src/crypto/crypto.c \
src/crypto/trusted_certs.c \
......@@ -106,6 +107,7 @@ SOURCES += \
src/datovka_shared/log/log.cpp \
src/datovka_shared/log/log_c.cpp \
src/datovka_shared/log/log_device.cpp \
src/datovka_shared/log/memory_log.cpp \
src/datovka_shared/records_management/conversion.cpp \
src/datovka_shared/records_management/io/records_management_connection.cpp \
src/datovka_shared/records_management/json/entry_error.cpp \
......@@ -212,6 +214,7 @@ HEADERS += \
src/datovka_shared/log/log_common.h \
src/datovka_shared/log/log_device.h \
src/datovka_shared/log/log.h \
src/datovka_shared/log/memory_log.h \
src/datovka_shared/records_management/conversion.h \
src/datovka_shared/records_management/io/records_management_connection.h \
src/datovka_shared/records_management/json/entry_error.h \
......
......@@ -25,9 +25,11 @@
#include <QCoreApplication>
#include <QDateTime>
#include <QHostInfo>
#include <QStringBuilder>
#include "src/datovka_shared/log/log_common.h"
#include "src/datovka_shared/log/log_device.h"
#include "src/datovka_shared/log/memory_log.h"
static
const QString logTimeFmt("MMM dd hh:mm:ss"); /*!< Format of time to be used in log output. */
......@@ -39,6 +41,7 @@ const QRegExp trailingNewlineRegExp("(\r\n|\r|\n)$"); /*!< Trailing newline regu
LogDevice::LogDevice(void)
: m_handler(Q_NULLPTR),
m_memLog(Q_NULLPTR),
m_usedSources(1),
m_openedFiles(0),
m_mutex(),
......@@ -355,6 +358,33 @@ QtMessageHandler LogDevice::installMessageHandler(QtMessageHandler handler)
return oldHandler;
}
MemoryLog *LogDevice::installMemoryLog(MemoryLog *memLog)
{
MemoryLog *oldMemLog;
m_mutex.lock();
oldMemLog = m_memLog;
m_memLog = memLog;
m_mutex.unlock();
return oldMemLog;
}
MemoryLog *LogDevice::memoryLog(void)
{
MemoryLog *memLog;
m_mutex.lock();
memLog = m_memLog;
m_mutex.unlock();
return memLog;
}
const char *LogDevice::urgencyPrefix(enum LogLevel level)
{
const char *prefix;
......@@ -374,6 +404,31 @@ const char *LogDevice::urgencyPrefix(enum LogLevel level)
return prefix;
}
const QString &LogDevice::urgencyPrefixStr(enum LogLevel level)
{
static const QString emergPref("emergency: ");
static const QString alertPref("alert: ");
static const QString critPref("critical: ");
static const QString errPref("error: ");
static const QString warnPref("warning: ");
static const QString noticPref("notice: ");
static const QString infoPref("info: ");
static const QString debugPref("debug: ");
static const QString nullStr;
switch (level) {
case LOG_EMERG: return emergPref; break;
case LOG_ALERT: return alertPref; break;
case LOG_CRIT: return critPref; break;
case LOG_ERR: return errPref; break;
case LOG_WARNING: return warnPref; break;
case LOG_NOTICE: return noticPref; break;
case LOG_INFO: return infoPref; break;
case LOG_DEBUG: return debugPref; break;
default: return nullStr; break;
}
}
enum LogLevel LogDevice::levelFromType(enum QtMsgType type)
{
switch (type) {
......@@ -431,29 +486,23 @@ enum QtMsgType LogDevice::typeFromLevel(enum LogLevel level)
}
}
QString LogDevice::buildPrefix(const char *urgPrefix) const
QString LogDevice::buildPrefix(const QString &urgPrefix) const
{
QString msgPrefix;
if (m_logVerbosity > 1) {
msgPrefix = QDateTime::currentDateTime().toString(logTimeFmt);
}
if (m_logVerbosity > 2) {
msgPrefix += QStringLiteral(" ") + m_hostName +
QStringLiteral(" ") + QCoreApplication::applicationName() +
QStringLiteral("[") +
QString::number(QCoreApplication::applicationPid()) +
QStringLiteral("]");
}
if (m_logVerbosity > 1) {
msgPrefix += QStringLiteral(": ");
}
if (NULL != urgPrefix) {
msgPrefix += urgPrefix;
return QDateTime::currentDateTime().toString(logTimeFmt) % /* 1 */
QStringLiteral(" ") % m_hostName % QStringLiteral(" ") %
QCoreApplication::applicationName() % QStringLiteral("[") %
QString::number(QCoreApplication::applicationPid()) %
QStringLiteral("]") %
QStringLiteral(": ") % /* 1 */
urgPrefix; /* 0 */
} else if (m_logVerbosity > 1) {
return QDateTime::currentDateTime().toString(logTimeFmt) % /* 1 */
QStringLiteral(": ") % /* 1 */
urgPrefix; /* 0 */
} else {
return urgPrefix; /* 0 */
}
return msgPrefix;
}
QString LogDevice::buildPostfix(const QMessageLogContext &logCtx)
......@@ -536,8 +585,8 @@ int LogDevice::logPrefixVlog(const QMessageLogContext &logCtx,
* allocated.
*/
const char *urgPrefix = urgencyPrefix(level);
if (Q_UNLIKELY(urgPrefix == NULL)) {
const QString &urgPrefix(urgencyPrefixStr(level));
if (Q_UNLIKELY(urgPrefix.isNull())) {
return -1;
}
......@@ -550,12 +599,11 @@ int LogDevice::logPrefixVlog(const QMessageLogContext &logCtx,
va_end(aq);
bool removed = removeTrailingNewline(msgFormatted);
msg = buildPrefix(urgPrefix) + msgFormatted;
if (m_logVerbosity > 0) {
msg += buildPostfix(logCtx);
msg = buildPrefix(urgPrefix) % msgFormatted % buildPostfix(logCtx);
}
if (removed) {
msg += QStringLiteral("\n");
msg = buildPrefix(urgPrefix) % msgFormatted % QStringLiteral("\n");
}
/* Message handler. */
......@@ -563,6 +611,11 @@ int LogDevice::logPrefixVlog(const QMessageLogContext &logCtx,
m_handler(typeFromLevel(level), logCtx, msgFormatted);
}
/* Memory log. */
if (m_memLog != Q_NULLPTR) {
m_memLog->log(msg);
}
logString(source, level, msg);
return 0;
......@@ -577,8 +630,8 @@ int LogDevice::logPrefixVlogMl(const QMessageLogContext &logCtx,
QStringList msgLines;
QString msg;
const char *urgPrefix = urgencyPrefix(level);
if (Q_UNLIKELY(urgPrefix == NULL)) {
const QString &urgPrefix(urgencyPrefixStr(level));
if (Q_UNLIKELY(urgPrefix.isNull())) {
return -1;
}
......@@ -601,8 +654,14 @@ int LogDevice::logPrefixVlogMl(const QMessageLogContext &logCtx,
}
foreach (const QString &msgLine, msgLines) {
logString(source, level,
msgPrefix + msgLine + QStringLiteral("\n"));
QString msg(msgPrefix % msgLine % QStringLiteral("\n"));
/* Memory log. */
if (m_memLog != Q_NULLPTR) {
m_memLog->log(msg);
}
logString(source, level, msg);
}
return 0;
......
......@@ -40,6 +40,8 @@
*/
#define MAX_SOURCES 64
class MemoryLog; /* Forward declaration. */
/*!
* @brief Logging device class.
*/
......@@ -240,8 +242,23 @@ public:
*/
QtMessageHandler installMessageHandler(QtMessageHandler handler);
/*!
* @brief Installs additional memory log. This device may be needed
* for viewing the log content form inside the application.
*
* @param[in] memLog Memory log device.
* @return Previously installed memory log device.
*/
MemoryLog *installMemoryLog(MemoryLog *memLog);
/*!
* @brief get pointer of installed memory log.
*/
MemoryLog *memoryLog(void);
private:
QtMessageHandler m_handler; /*!< Additional message handler. */
MemoryLog *m_memLog; /*!< Log message memory storage. */
FacDesc m_facDescVect[MAX_LOG_FILES]; /*!< Facility vector. */
int m_usedSources; /*!<
......@@ -264,6 +281,15 @@ private:
static
const char *urgencyPrefix(enum LogLevel level);
/*!
* @brief Converts log level to urgency prefix.
*
* @param[in] level Urgency level.
* @return Prefix string or null string on error.
*/
static
const QString &urgencyPrefixStr(enum LogLevel level);
/*!
* @brief Converts message type to urgency level.
*
......@@ -289,7 +315,7 @@ private:
* @param[in] urgPrefix Urgency prefix.
* @return Prefix string.
*/
QString buildPrefix(const char *urgPrefix) const;
QString buildPrefix(const QString &urgPrefix) const;
/*!
* @brief Build log line postfix string. Its content depends on
......
/*
* Copyright (C) 2014-2018 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#include <QDateTime>
#include "src/datovka_shared/log/memory_log.h"
MemoryLog::MemoryLog(QObject *parent)
: QObject(parent),
m_chars(0),
m_maxChars(0),
m_loggedMsgs(),
m_keys()
{
}
void MemoryLog::setMaxMemory(int bytes)
{
/* QStrings are UTF-16 encoded. */
m_maxChars = (bytes > 0) ? (bytes / 2) : 0;
/* If already filled and setting smaller. */
assureSpace(0);
}
int MemoryLog::maxMemory(void) const
{
return m_maxChars * 2;
}
bool MemoryLog::log(const QString &msg)
{
if (Q_UNLIKELY(msg.isEmpty())) {
return false;
}
if (Q_UNLIKELY(m_maxChars == 0)) {
/* Log is disabled. */
return false;
}
/*
* A single message may exceed the entire log capacity. In such cases
* the message is not accepted.
*/
if (Q_UNLIKELY(msg.size() > m_maxChars)) {
return false;
}
assureSpace(msg.size());
storeMsg(uniqueKey(), msg);
return true;
}
const QString &MemoryLog::message(quint64 key) const
{
static const QString nullStr;
const QHash<quint64, QString>::const_iterator iter(m_loggedMsgs.find(key));
if (Q_UNLIKELY(iter == m_loggedMsgs.end())) {
Q_ASSERT(0);
return nullStr;
}
return *iter;
}
QList<quint64> MemoryLog::keys(void) const
{
return m_keys.mid(0, -1);
}
quint64 MemoryLog::uniqueKey(void) const
{
static const quint64 msecBase = QDateTime::currentMSecsSinceEpoch();
static const quint64 upperHalf = Q_UINT64_C(1) << 32;
const quint64 msecOffset = QDateTime::currentMSecsSinceEpoch() - msecBase;
quint64 key = msecOffset;
unsigned iter = 0;
while (m_loggedMsgs.contains(key)) {
key = msecOffset + ((iter++) * upperHalf);
}
return key;
}
void MemoryLog::assureSpace(quint64 charNum)
{
while ((m_maxChars - m_chars) < (qint64)charNum) {
const quint64 key = m_keys.dequeue();
const QHash<quint64, QString>::const_iterator iter(m_loggedMsgs.find(key));
if (Q_UNLIKELY(iter == m_loggedMsgs.end())) {
Q_ASSERT(0);
continue;
}
int freedSpace = iter->size();
m_loggedMsgs.remove(key);
m_chars -= (quint64)freedSpace;
}
}
void MemoryLog::storeMsg(quint64 key, const QString &msg)
{
if (Q_UNLIKELY(m_loggedMsgs.contains(key))) {
Q_ASSERT(0);
return;
}
m_loggedMsgs.insert(key, msg);
m_keys.enqueue(key);
m_chars += msg.size();
emit logged(key);
}
/*
* Copyright (C) 2014-2018 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#pragma once
#include <QHash>
#include <QList>
#include <QObject>
#include <QQueue>
/*!
* @brief Hold log messages in memory.
*
* @note The operations are not thread safe. They aren't internally mutex-guarded.
*/
class MemoryLog : public QObject {
Q_OBJECT
public:
/*!
* @brief Constructor.
*
* @param[in] parent Parent object.
*/
explicit MemoryLog(QObject *parent = Q_NULLPTR);
/*!
* @brief Set maximal amount of memory to hold messages.
*
* @brief[in] bytes Amount of memory for strings.
*/
void setMaxMemory(int bytes);
/*!
* @brief Get memory limit.
*
* @return Maximal amount of memory which is reserved for log messages.
*/
int maxMemory(void) const;
/*!
* @brief Write a message to memory log.
*
* @param[in] msg Message.
* @return True when message has been stored.
*/
bool log(const QString &msg);
/*!
* @brief Get a message for given key.
*
* @param[in] key Identifying the message.
* @return Reference to held string, null string if the key does not exist.
*/
const QString &message(quint64 key) const;
/*!
* @brief Return list of held keys.
*
* @return Sequence of held keys.
*/
QList<quint64> keys(void) const;
signals:
/*!
* @brief This signed is emitted when a new message is stored.
*/
void logged(quint64 key);
private:
/*!
* @brief Generates a unique key.
*
* @return A key which does not exist in the storage.
*/
quint64 uniqueKey(void) const;
/*!
* @brief Make space for specified numbers of characters.
*
* @param[in] charNum Number of characters which are needed in the log.
*/
void assureSpace(quint64 charNum);
/*!
* @brief Append another string under given key.
*
* @note Emits the logged signal.
*
* @param[in] key Entry key.
* @param[in] msg Message to be stored.
*/
void storeMsg(quint64 key, const QString &msg);
qint64 m_chars; /*!< Number of logged string characters. */
qint64 m_maxChars; /*!< Maximal number of characters to be held. */
QHash<quint64, QString> m_loggedMsgs;
QQueue<quint64> m_keys;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment