44#include " logwatcherhelper.h"
55
66#include < QDebug>
7- #include < QDir>
7+ #include < QDBusPendingCallWatcher>
8+ #include < QDBusPendingCall>
89
9- #define UPDATE_LOG_FILE " /tmp/lastore_update_detail.log"
10+ #include < unistd.h>
11+ #include < fcntl.h>
1012
11- LogWatcherHelper::LogWatcherHelper (QObject *parent)
13+ #include " ../dbus/updatedbusproxy.h"
14+
15+ LogWatcherHelper::LogWatcherHelper (UpdateDBusProxy *dbusProxy, QObject *parent)
1216 : QObject(parent)
13- , m_fileWatcher(nullptr )
14- , m_lastFileSize(0 )
1517 , m_data(QString())
18+ , m_dbusProxy(dbusProxy)
19+ , m_readFd(-1 )
20+ , m_writeFd(-1 )
21+ , m_socketNotifier(nullptr )
1622{
1723
1824}
@@ -24,126 +30,136 @@ LogWatcherHelper::~LogWatcherHelper()
2430
2531void LogWatcherHelper::startWatchFile ()
2632{
27- qInfo () << " Start watch update log file" ;
28- if (m_fileWatcher) {
29- qWarning () << " Log file watcher already exists" ;
33+ qDebug () << " Start watch update log via DBus interface" ;
34+
35+ if (!m_dbusProxy) {
36+ qWarning () << " DBus proxy is null, cannot start watching" ;
3037 return ;
3138 }
32-
33- m_fileWatcher = new QFileSystemWatcher (this );
34- connect (m_fileWatcher, &QFileSystemWatcher::fileChanged, this , &LogWatcherHelper::onFileChanged);
35- connect (m_fileWatcher, &QFileSystemWatcher::directoryChanged, this , &LogWatcherHelper::onDirectoryChanged);
36-
37- // 总是监控 /tmp 目录以检测文件创建/删除
38- const QString logDir = " /tmp" ;
39- if (QDir (logDir).exists ()) {
40- m_fileWatcher->addPath (logDir);
41- } else {
42- qWarning () << " tmp directory does not exist:" << logDir;
39+
40+ if (m_readFd != -1 ) {
41+ qWarning () << " Log watcher already started" ;
42+ return ;
4343 }
4444
45- // 如果日志文件已存在,也监控它
46- if (QFile::exists (UPDATE_LOG_FILE )) {
47- m_fileWatcher->addPath (UPDATE_LOG_FILE );
48-
49- // 立即读取现有文件内容
50- m_lastFileSize = 0 ;
51- m_data = QString ();
52- readFileIncrement ();
53- }
45+ // 设置管道并调用 DBus 接口
46+ setupLogPipe ();
5447}
5548
5649void LogWatcherHelper::stopWatchFile ()
5750{
58- qInfo () << " Stop watch update log file" ;
59- if (m_fileWatcher) {
60- m_fileWatcher->removePaths (m_fileWatcher->files ());
61- delete m_fileWatcher;
62- m_fileWatcher = nullptr ;
51+ qDebug () << " Stop watch update log" ;
52+
53+ // 停止文件描述符监听
54+ if (m_socketNotifier) {
55+ m_socketNotifier->setEnabled (false );
56+ delete m_socketNotifier;
57+ m_socketNotifier = nullptr ;
58+ }
59+
60+ // 关闭文件描述符
61+ if (m_readFd != -1 ) {
62+ close (m_readFd);
63+ m_readFd = -1 ;
64+ }
65+
66+ if (m_writeFd != -1 ) {
67+ close (m_writeFd);
68+ m_writeFd = -1 ;
6369 }
6470
65- // 重置文件大小记录
66- m_lastFileSize = 0 ;
71+ // 重置数据
6772 m_data = QString ();
6873}
6974
70- void LogWatcherHelper::onFileChanged ( const QString &path )
75+ void LogWatcherHelper::setupLogPipe ( )
7176{
72- if (path != UPDATE_LOG_FILE ) {
77+ // 创建管道
78+ int pipefd[2 ];
79+ if (pipe (pipefd) == -1 ) {
80+ qWarning () << " Failed to create pipe for log reading" ;
7381 return ;
7482 }
7583
76- readFileIncrement ();
77-
78- // 重新添加文件到监控列表(QFileSystemWatcher 在文件变化后可能会自动移除监控)
79- if (m_fileWatcher && !m_fileWatcher->files ().contains (path)) {
80- m_fileWatcher->addPath (path);
81- }
84+ m_readFd = pipefd[0 ];
85+ m_writeFd = pipefd[1 ];
86+
87+ // 设置读端为非阻塞
88+ int flags = fcntl (m_readFd, F_GETFL , 0 );
89+ fcntl (m_readFd, F_SETFL , flags | O_NONBLOCK );
90+
91+ // 设置 QSocketNotifier 来监听读端文件描述符
92+ m_socketNotifier = new QSocketNotifier (m_readFd, QSocketNotifier::Read, this );
93+ connect (m_socketNotifier, &QSocketNotifier::activated, this , &LogWatcherHelper::onDataAvailable);
94+
95+ // 第一步:先获取历史日志 (realtime=false)
96+ qDebug () << " First getting historical logs..." ;
97+ QDBusPendingCall historyCall = m_dbusProxy->GetUpdateDetails (m_writeFd, false );
98+ QDBusPendingCallWatcher* historyWatcher = new QDBusPendingCallWatcher (historyCall, this );
99+
100+ connect (historyWatcher, &QDBusPendingCallWatcher::finished, this , [this , historyWatcher](void ) {
101+ // 可能获取历史日志失败(比如没有历史日志),但是不影响实时日志的获取
102+ if (historyWatcher->isError ()) {
103+ qWarning () << " GetUpdateDetails for history failed:" << historyWatcher->error ().message ();
104+ historyWatcher->deleteLater ();
105+ }
106+
107+ qDebug () << " Historical logs completed, starting realtime monitoring..." ;
108+
109+ // 历史日志获取完成,直接启动实时日志监听
110+ startRealtimeLogAfterHistory ();
111+
112+ historyWatcher->deleteLater ();
113+ });
82114}
83115
84- void LogWatcherHelper::onDirectoryChanged ( const QString &path )
116+ void LogWatcherHelper::startRealtimeLogAfterHistory ( )
85117{
86- if (path != " /tmp" ) {
87- return ;
88- }
89-
90- const bool fileExists = QFile::exists (UPDATE_LOG_FILE );
91- const bool fileWatched = m_fileWatcher && m_fileWatcher->files ().contains (UPDATE_LOG_FILE );
92-
93- if (fileExists && !fileWatched) {
94- m_fileWatcher->addPath (UPDATE_LOG_FILE );
95- m_lastFileSize = 0 ;
96- m_data = QString ();
97- readFileIncrement ();
98- } else if (!fileExists && fileWatched) {
99- qInfo () << " Update log file was deleted:" << UPDATE_LOG_FILE ;
100- m_lastFileSize = 0 ;
101- emit fileReset ();
102- m_data = QString ();
118+ // 启用文件描述符监听
119+ if (m_socketNotifier) {
120+ m_socketNotifier->setEnabled (true );
103121 }
122+
123+ // 开始获取实时增量日志 (realtime=true)
124+ QDBusPendingCall realtimeCall = m_dbusProxy->GetUpdateDetails (m_writeFd, true );
125+ QDBusPendingCallWatcher* realtimeWatcher = new QDBusPendingCallWatcher (realtimeCall, this );
126+
127+ connect (realtimeWatcher, &QDBusPendingCallWatcher::finished, this , [this , realtimeWatcher](void ) {
128+
129+ if (realtimeWatcher->isError ()) {
130+ qWarning () << " GetUpdateDetails for realtime failed:" << realtimeWatcher->error ().message ();
131+ stopWatchFile ();
132+ } else {
133+ qDebug () << " Realtime log monitoring started successfully" ;
134+ }
135+
136+ realtimeWatcher->deleteLater ();
137+ });
104138}
105139
106- void LogWatcherHelper:: readFileIncrement ()
140+ void LogWatcherHelper::onDataAvailable ()
107141{
108- QFile logFile (UPDATE_LOG_FILE );
109-
110- if (!logFile.exists ()) {
111- qWarning () << " Log file does not exist:" << UPDATE_LOG_FILE ;
112- return ;
113- }
114-
115- const qint64 currentFileSize = logFile.size ();
116-
117- // 如果文件变小了,说明文件被重新创建或截断,重新开始读取
118- if (currentFileSize < m_lastFileSize) {
119- m_lastFileSize = 0 ;
120- m_data = QString ();
121- emit fileReset ();
122- }
142+ readAvailableData ();
143+ }
123144
124- // 如果文件大小没变,没有新内容
125- if (currentFileSize == m_lastFileSize) {
145+ void LogWatcherHelper::readAvailableData ()
146+ {
147+ if (m_readFd == -1 ) {
126148 return ;
127149 }
128150
129- if (!logFile.open (QIODevice::ReadOnly | QIODevice::Text)) {
130- qWarning () << " Failed to open log file for reading:" << logFile.errorString ();
131- return ;
151+ QByteArray buffer;
152+ char readBuffer[4096 ];
153+ ssize_t bytesRead;
154+
155+ while ((bytesRead = read (m_readFd, readBuffer, sizeof (readBuffer))) > 0 ) {
156+ buffer.append (readBuffer, bytesRead);
132157 }
158+
159+ if (!buffer.isEmpty ()) {
160+ QString newContent = QString::fromUtf8 (buffer);
133161
134- // 定位到上次读取的位置
135- if (!logFile.seek (m_lastFileSize)) {
136- qWarning () << " Failed to seek to position:" << m_lastFileSize;
137- logFile.close ();
138- return ;
162+ m_data.append (newContent);
163+ emit incrementalDataChanged (newContent);
139164 }
140-
141- const QByteArray newData = logFile.readAll ();
142- logFile.close ();
143-
144- m_lastFileSize = currentFileSize;
145-
146- const QString incrementalContent = QString::fromUtf8 (newData);
147- m_data.append (incrementalContent);
148- emit incrementalDataChanged (incrementalContent);
149165}
0 commit comments