Projekt

Obecné

Profil

Stáhnout (5.39 KB) Statistiky
| Větev: | Tag: | Revize:
1 c137512e Oto Šťáva
// Copyright (c) 2013, Razvan Petru
2
// All rights reserved.
3
4
// Redistribution and use in source and binary forms, with or without modification,
5
// are permitted provided that the following conditions are met:
6
7
// * Redistributions of source code must retain the above copyright notice, this
8
//   list of conditions and the following disclaimer.
9
// * Redistributions in binary form must reproduce the above copyright notice, this
10
//   list of conditions and the following disclaimer in the documentation and/or other
11
//   materials provided with the distribution.
12
// * The name of the contributors may not be used to endorse or promote products
13
//   derived from this software without specific prior written permission.
14
15
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
19
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
24
// OF THE POSSIBILITY OF SUCH DAMAGE.
25
26
#include "QsLogDestFile.h"
27
#include <QTextCodec>
28
#include <QDateTime>
29
#include <QtGlobal>
30
#include <iostream>
31
32
const int QsLogging::SizeRotationStrategy::MaxBackupCount = 10;
33
34
QsLogging::RotationStrategy::~RotationStrategy()
35
{
36
}
37
38
QsLogging::SizeRotationStrategy::SizeRotationStrategy()
39
    : mCurrentSizeInBytes(0)
40
    , mMaxSizeInBytes(0)
41
    , mBackupsCount(0)
42
{
43
}
44
45
void QsLogging::SizeRotationStrategy::setInitialInfo(const QFile &file)
46
{
47
    mFileName = file.fileName();
48
    mCurrentSizeInBytes = file.size();
49
}
50
51
void QsLogging::SizeRotationStrategy::includeMessageInCalculation(const QString &message)
52
{
53
    mCurrentSizeInBytes += message.toUtf8().size();
54
}
55
56
bool QsLogging::SizeRotationStrategy::shouldRotate()
57
{
58
    return mCurrentSizeInBytes > mMaxSizeInBytes;
59
}
60
61
// Algorithm assumes backups will be named filename.X, where 1 <= X <= mBackupsCount.
62
// All X's will be shifted up.
63
void QsLogging::SizeRotationStrategy::rotate()
64
{
65
    if (!mBackupsCount) {
66
        if (!QFile::remove(mFileName))
67
            std::cerr << "QsLog: backup delete failed " << qPrintable(mFileName);
68
        return;
69
    }
70
71
     // 1. find the last existing backup than can be shifted up
72
     const QString logNamePattern = mFileName + QString::fromUtf8(".%1");
73
     int lastExistingBackupIndex = 0;
74
     for (int i = 1;i <= mBackupsCount;++i) {
75
         const QString backupFileName = logNamePattern.arg(i);
76
         if (QFile::exists(backupFileName))
77
             lastExistingBackupIndex = qMin(i, mBackupsCount - 1);
78
         else
79
             break;
80
     }
81
82
     // 2. shift up
83
     for (int i = lastExistingBackupIndex;i >= 1;--i) {
84
         const QString oldName = logNamePattern.arg(i);
85
         const QString newName = logNamePattern.arg(i + 1);
86
         QFile::remove(newName);
87
         const bool renamed = QFile::rename(oldName, newName);
88
         if (!renamed) {
89
             std::cerr << "QsLog: could not rename backup " << qPrintable(oldName)
90
                       << " to " << qPrintable(newName);
91
         }
92
     }
93
94
     // 3. rename current log file
95
     const QString newName = logNamePattern.arg(1);
96
     if (QFile::exists(newName))
97
         QFile::remove(newName);
98
     if (!QFile::rename(mFileName, newName)) {
99
         std::cerr << "QsLog: could not rename log " << qPrintable(mFileName)
100
                   << " to " << qPrintable(newName);
101
     }
102
}
103
104
QIODevice::OpenMode QsLogging::SizeRotationStrategy::recommendedOpenModeFlag()
105
{
106
    return QIODevice::Append;
107
}
108
109
void QsLogging::SizeRotationStrategy::setMaximumSizeInBytes(qint64 size)
110
{
111
    Q_ASSERT(size >= 0);
112
    mMaxSizeInBytes = size;
113
}
114
115
void QsLogging::SizeRotationStrategy::setBackupCount(int backups)
116
{
117
    Q_ASSERT(backups >= 0);
118
    mBackupsCount = qMin(backups, SizeRotationStrategy::MaxBackupCount);
119
}
120
121
122
QsLogging::FileDestination::FileDestination(const QString& filePath, RotationStrategyPtr rotationStrategy)
123
    : mRotationStrategy(rotationStrategy)
124
{
125
    mFile.setFileName(filePath);
126
    if (!mFile.open(QFile::WriteOnly | QFile::Text | mRotationStrategy->recommendedOpenModeFlag()))
127
        std::cerr << "QsLog: could not open log file " << qPrintable(filePath);
128
    mOutputStream.setDevice(&mFile);
129
    mOutputStream.setCodec(QTextCodec::codecForName("UTF-8"));
130
131
    mRotationStrategy->setInitialInfo(mFile);
132
}
133
134
void QsLogging::FileDestination::write(const QString& message, Level)
135
{
136
    mRotationStrategy->includeMessageInCalculation(message);
137
    if (mRotationStrategy->shouldRotate()) {
138
        mOutputStream.setDevice(NULL);
139
        mFile.close();
140
        mRotationStrategy->rotate();
141
        if (!mFile.open(QFile::WriteOnly | QFile::Text | mRotationStrategy->recommendedOpenModeFlag()))
142
            std::cerr << "QsLog: could not reopen log file " << qPrintable(mFile.fileName());
143
        mRotationStrategy->setInitialInfo(mFile);
144
        mOutputStream.setDevice(&mFile);
145
    }
146
147
    mOutputStream << message << endl;
148
    mOutputStream.flush();
149
}
150
151
bool QsLogging::FileDestination::isValid()
152
{
153
    return mFile.isOpen();
154
}