1 /* 2 * Copyright (C) 2009, 2010, 2013, 2014 Nicolas Bonnefon and other contributors 3 * 4 * This file is part of glogg. 5 * 6 * glogg is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * glogg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with glogg. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef LOGDATA_H 21 #define LOGDATA_H 22 23 #include <memory> 24 25 #include <QObject> 26 #include <QString> 27 #include <QFile> 28 #include <QVector> 29 #include <QMutex> 30 #include <QDateTime> 31 32 #include "abstractlogdata.h" 33 #include "logdataworkerthread.h" 34 #include "filewatcher.h" 35 #include "loadingstatus.h" 36 37 class LogFilteredData; 38 39 // Represents a complete set of data to be displayed (ie. a log file content) 40 // This class is thread-safe. 41 class LogData : public AbstractLogData { 42 Q_OBJECT 43 44 public: 45 // Creates an empty LogData 46 LogData(); 47 // Destroy an object 48 ~LogData(); 49 50 enum MonitoredFileStatus { Unchanged, DataAdded, Truncated }; 51 52 // Attaches (or reattaches) the LogData to a file on disk 53 // It starts the asynchronous indexing and returns (almost) immediately 54 // Replace the ongoing loading if necessary. 55 // Attaching to a non existant file works and the file is reported 56 // to be empty. 57 void attachFile( const QString& fileName ); 58 // Interrupt the loading and restore the previous file. 59 // Does nothing if no loading in progress. 60 void interruptLoading(); 61 // Creates a new filtered data using the passed regexp 62 // ownership is passed to the caller 63 LogFilteredData* getNewFilteredData() const; 64 // Returns the size if the file in bytes 65 qint64 getFileSize() const; 66 // Returns the last modification date for the file. 67 // Null if the file is not on disk. 68 QDateTime getLastModifiedDate() const; 69 // Throw away all the file data and reload/reindex. 70 void reload(); 71 72 signals: 73 // Sent during the 'attach' process to signal progress 74 // percent being the percentage of completion. 75 void loadingProgressed( int percent ); 76 // Signal the client the file is fully loaded and available. 77 void loadingFinished( LoadingStatus status ); 78 // Sent when the file on disk has changed, will be followed 79 // by loadingProgressed if needed and then a loadingFinished. 80 void fileChanged( LogData::MonitoredFileStatus status ); 81 82 private slots: 83 // Consider reloading the file when it changes on disk updated 84 void fileChangedOnDisk(); 85 // Called when the worker thread signals the current operation ended 86 void indexingFinished( LoadingStatus status ); 87 88 private: 89 // This class models an indexing operation. 90 // It exists to permit LogData to delay the operation if another 91 // one is ongoing (operations are asynchronous) 92 class LogDataOperation { 93 public: 94 LogDataOperation( const QString& fileName ) : filename_( fileName ) {} 95 // Permit each child to have its destructor 96 virtual ~LogDataOperation() {}; 97 98 void start( LogDataWorkerThread& workerThread ) const 99 { doStart( workerThread ); } 100 const QString& getFilename() const { return filename_; } 101 virtual bool isFull() const { return true; } 102 103 protected: 104 virtual void doStart( LogDataWorkerThread& workerThread ) const = 0; 105 QString filename_; 106 }; 107 108 // Attaching a new file (change name + full index) 109 class AttachOperation : public LogDataOperation { 110 public: 111 AttachOperation( const QString& fileName ) 112 : LogDataOperation( fileName ) {} 113 ~AttachOperation() {}; 114 115 bool isFull() const { return true; } 116 117 protected: 118 void doStart( LogDataWorkerThread& workerThread ) const; 119 }; 120 121 // Reindexing the current file 122 class FullIndexOperation : public LogDataOperation { 123 public: 124 FullIndexOperation() : LogDataOperation( QString() ) {} 125 ~FullIndexOperation() {}; 126 127 bool isFull() const { return false; } 128 129 protected: 130 void doStart( LogDataWorkerThread& workerThread ) const; 131 }; 132 133 // Indexing part of the current file (from fileSize) 134 class PartialIndexOperation : public LogDataOperation { 135 public: 136 PartialIndexOperation( qint64 fileSize ) 137 : LogDataOperation( QString() ), filesize_( fileSize ) {} 138 ~PartialIndexOperation() {}; 139 140 bool isFull() const { return false; } 141 142 protected: 143 void doStart( LogDataWorkerThread& workerThread ) const; 144 145 private: 146 qint64 filesize_; 147 }; 148 149 FileWatcher fileWatcher_; 150 MonitoredFileStatus fileChangedOnDisk_; 151 152 // Implementation of virtual functions 153 virtual QString doGetLineString( qint64 line ) const; 154 virtual QString doGetExpandedLineString( qint64 line ) const; 155 virtual QStringList doGetLines( qint64 first, int number ) const; 156 virtual QStringList doGetExpandedLines( qint64 first, int number ) const; 157 virtual qint64 doGetNbLine() const; 158 virtual int doGetMaxLength() const; 159 virtual int doGetLineLength( qint64 line ) const; 160 161 void enqueueOperation( std::shared_ptr<const LogDataOperation> newOperation ); 162 void startOperation(); 163 164 QString indexingFileName_; 165 std::unique_ptr<QFile> file_; 166 LinePositionArray linePosition_; 167 qint64 fileSize_; 168 qint64 nbLines_; 169 int maxLength_; 170 QDateTime lastModifiedDate_; 171 std::shared_ptr<const LogDataOperation> currentOperation_; 172 std::shared_ptr<const LogDataOperation> nextOperation_; 173 174 // To protect the file: 175 mutable QMutex fileMutex_; 176 // To protect linePosition_, fileSize_ and maxLength_: 177 mutable QMutex dataMutex_; 178 // (are mutable to allow 'const' function to touch it, 179 // while remaining const) 180 // When acquiring both, data should be help before locking file. 181 182 LogDataWorkerThread workerThread_; 183 }; 184 185 #endif 186