File: parsethreadkern.cpp

package info (click to toggle)
deepin-log-viewer 6.5.8%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 14,752 kB
  • sloc: cpp: 61,723; ansic: 1,732; xml: 81; sh: 59; makefile: 12
file content (227 lines) | stat: -rwxr-xr-x 7,792 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// SPDX-FileCopyrightText: 2019 - 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "parsethreadkern.h"
#include "qtcompat.h"

#include <QDebug>
#include <QDateTime>
#include <time.h>
using namespace std;

#ifdef QT_DEBUG
Q_LOGGING_CATEGORY(logParseWorkKern, "org.deepin.log.viewer.parse.work.kern")
#else
Q_LOGGING_CATEGORY(logParseWorkKern, "org.deepin.log.viewer.parse.work.kern", QtInfoMsg)
#endif

/**
 * @brief ParseThreadKern::ParseThreadKern 构造函数
 * @param parent 父对象
 */
ParseThreadKern::ParseThreadKern(QObject *parent)
    : ParseThreadBase(parent)
{
    
}

/**
 * @brief ParseThreadKern::~ParseThreadKern 析构函数,停止并销毁process指针
 */
ParseThreadKern::~ParseThreadKern()
{

}

/**
 * @brief ParseThreadKern::run 线程执行虚函数
 */
void ParseThreadKern::run()
{
    //此线程刚开始把可以继续变量置true,不然下面没法跑
    m_canRun = true;

    handleKern();
}

/**
 * @brief ParseThreadKern::handleKern 处理获取内核日志
 */
void ParseThreadKern::handleKern()
{
    QList<QString> dataList;
    qint64 gStartLine = m_filter.segementIndex * SEGEMENT_SIZE;
    m_FilePath = DLDBusHandler::instance(this)->getFileInfo(m_filter.filePath, false);
    for (int i = 0; i < m_FilePath.count(); i++) {
        if (!m_FilePath.at(i).contains("txt")) {
            QFile file(m_FilePath.at(i)); // add by Airy
            if (!file.exists()) {
                emit parseFinished(m_threadCount, m_type);
                return;
            }
        }
        if (!m_canRun) {
            return;
        }

        if (!Utils::runInCmd) {
            initProccess();
            if (!m_canRun) {
                return;
            }
            m_process->setProcessChannelMode(QProcess::MergedChannels);
            if (!m_canRun) {
                return;
            }
            //共享内存对应变量置true,允许进程内部逻辑运行
            ShareMemoryInfo shareInfo;
            shareInfo.isStart = true;
            SharedMemoryManager::instance()->setRunnableTag(shareInfo);
            //启动日志需要提权获取,运行的时候把对应共享内存的名称传进去,方便获取进程拿标记量判断是否继续运行
            m_process->start("pkexec", QStringList() << "logViewerAuth"
                             << m_FilePath.at(i) << SharedMemoryManager::instance()->getRunnableKey());
            m_process->waitForFinished(-1);
            //有错则传出空数据
            if (m_process->exitCode() != 0) {
                emit parseFinished(m_threadCount, m_type, CancelAuth);
                return;
            }
        }

        if (!m_canRun) {
            return;
        }

        //如果是压缩文件,对其解压缩
        QString filePath = m_FilePath.at(i);
        if(QString::compare(QFileInfo(filePath).suffix(), "gz", Qt::CaseInsensitive) == 0){
            QStringList filePathList = DLDBusHandler::instance(this)->getFileInfo(filePath);
            if(filePathList.size()){
                filePath = filePathList.at(0);
            }else {
                filePath = "";
            }
        }

        qint64 lineCount = DLDBusHandler::instance(this)->getLineCount(filePath);

        // 获取全局起始行在当前文件的相对起始行位置
        if (gStartLine >= lineCount) {
            gStartLine -= lineCount;
            continue;
        }

        qint64 startLine = gStartLine;

        QStringList strList = DLDBusHandler::instance(this)->readLogLinesInRange(filePath, startLine, SEGEMENT_SIZE);
        for (int j = strList.size() - 1; j >= 0; --j) {
            if (!m_canRun) {
                return;
            }
            QString str = strList.at(j);
            LOG_MSG_BASE msg;
            //删除颜色格式字符
            str.replace(REG_EXP("\\#033\\[\\d+(;\\d+){0,2}m"), "");

            // 以 "kernel:" 开始分割
            int kernelIndex = str.indexOf("kernel:");
            if (kernelIndex == -1) {
                continue; // 如果没有找到 "kernel:",则跳过该行
            }
            QString msgContent = str.mid(kernelIndex + 7); // 去掉 "kernel:" 及其前面的部分
            str = str.left(kernelIndex); // 取 "kernel:" 前面的部分

            QStringList list = str.split(" ", SKIP_EMPTY_PARTS);
            if (list.size() < 2)
                continue;
            //获取内核年份接口已添加,等待系统接口添加年份改变相关日志
            QStringList timeList;
            QString dateTimeStr = list[0];
            bool isNewFormat = dateTimeStr.contains("T");
            if (isNewFormat) {
                QDateTime dateTime = QDateTime::fromString(dateTimeStr, Qt::ISODate);
                if (!dateTime.isValid()) {
                    dateTime = QDateTime::fromString(dateTimeStr, "yyyy-MM-ddTHH:mm:ss.zzzzzz+hh:mm");
                }
                timeList << dateTime.toString("yyyy-MM-dd") << dateTime.toString("HH:mm:ss");
                iTime = dateTime.toMSecsSinceEpoch();

                msg.hostName = list[1];
            } else {
                if (list[0].contains("-")) {
                    timeList << list[0] << list[1];
                    iTime = formatDateTime(list[0], list[1]);
                    msg.hostName = list[2];
                } else {
                    timeList << list[0] << list[1] << list[2];
                    iTime = formatDateTime(list[0], list[1], list[2]);
                    msg.hostName = list[3];
                }
            }

            // 对时间筛选
            if (m_filter.timeFilterBegin > 0 && m_filter.timeFilterEnd > 0) {
                if (iTime < m_filter.timeFilterBegin || iTime > m_filter.timeFilterEnd)
                    continue;
            }

            msg.dateTime = timeList.join(" ");

            msg.daemonName = "kernel";
            msg.daemonId = "0";
            msg.msg = msgContent.trimmed();

            dataList.append(QJsonDocument(msg.toJson()).toJson(QJsonDocument::Compact));
            if (!m_canRun) {
                return;
            }
            //每获得500个数据就发出信号给控件加载
            if (dataList.count() % SINGLE_READ_CNT == 0) {
                emit logData(m_threadCount, dataList, m_type);
                dataList.clear();
            }
            if (!m_canRun) {
                return;
            }
        }
    }
    //最后可能有余下不足500的数据
    if (dataList.count() >= 0) {
        emit logData(m_threadCount, dataList, m_type);
    }
    emit parseFinished(m_threadCount, m_type);
}

/**
 * @brief ParseThreadKern::formatDateTime 内核日志没有年份 格式为Sep 29 15:53:34 所以需要特殊转换
 * @param m 月份字符串
 * @param d 日期字符串
 * @param t 时间字符串
 * @return 时间毫秒数
 */
qint64 ParseThreadKern::formatDateTime(QString m, QString d, QString t)
{
    QLocale local(QLocale::English, QLocale::UnitedStates);

    QDate curdt = QDate::currentDate();

    QString tStr = QString("%1 %2 %3 %4").arg(m).arg(d).arg(curdt.year()).arg(t);
    QDateTime dt = local.toDateTime(tStr, "MMM d yyyy hh:mm:ss");
    return dt.toMSecsSinceEpoch();
}

/**
 * @brief ParseThreadKern::formatDateTime 内核日志有年份 格式为2020-01-05 所以需要特殊转换
 * @param y 年月日
 * @param t 时间字符串
 * @return 时间毫秒数
 */
qint64 ParseThreadKern::formatDateTime(QString y, QString t)
{
    //when /var/kern.log have the year
    QLocale local(QLocale::English, QLocale::UnitedStates);
    QString tStr = QString("%1 %2").arg(y).arg(t);
    QDateTime dt = local.toDateTime(tStr, "yyyy-MM-dd hh:mm:ss");
    return dt.toMSecsSinceEpoch();
}