1 /* 2 * Copyright (C) 2009, 2010 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 <QObject> 24 #include <QString> 25 #include <QFile> 26 #include <QVector> 27 #include <QMutex> 28 #include <QDateTime> 29 30 #include "abstractlogdata.h" 31 #include "logdataworkerthread.h" 32 #include "filewatcher.h" 33 34 class LogFilteredData; 35 36 // Represents a complete set of data to be displayed (ie. a log file content) 37 // This class is thread-safe. 38 class LogData : public AbstractLogData { 39 Q_OBJECT 40 41 public: 42 // Creates an empty LogData 43 LogData(); 44 // Destroy an object 45 ~LogData(); 46 47 enum MonitoredFileStatus { Unchanged, DataAdded, Truncated }; 48 49 // Attaches (or reattaches) the LogData to a file on disk 50 // It starts the asynchronous indexing and returns (almost) immediately 51 // Replace the ongoing loading if necessary. 52 // Attaching to a non existant file works and the file is reported 53 // to be empty. 54 void attachFile( const QString& fileName ); 55 // Interrupt the loading and restore the previous file. 56 // Does nothing if no loading in progress. 57 void interruptLoading(); 58 // Creates a new filtered data using the passed regexp 59 // ownership is passed to the caller 60 LogFilteredData* getNewFilteredData() const; 61 // Returns the size if the file in bytes 62 qint64 getFileSize() const; 63 // Returns the last modification date for the file. 64 // Null if the file is not on disk. 65 QDateTime getLastModifiedDate() const; 66 67 signals: 68 // Sent during the 'attach' process to signal progress 69 // percent being the percentage of completion. 70 void loadingProgressed( int percent ); 71 // Signal the client the file is fully loaded and available. 72 void loadingFinished( bool success ); 73 // Sent when the file on disk has changed, will be followed 74 // by loadingProgressed if needed and then a loadingFinished. 75 void fileChanged( LogData::MonitoredFileStatus status ); 76 77 private slots: 78 // Consider reloading the file when it changes on disk updated 79 void fileChangedOnDisk(); 80 // Called when the worker thread signals the current operation ended 81 void indexingFinished( bool success ); 82 83 private: 84 // This class models an indexing operation. 85 // It exists to permit LogData to delay the operation if another 86 // one is ongoing (operations are asynchronous) 87 class LogDataOperation { 88 public: 89 LogDataOperation( const QString& fileName ) : filename_( fileName ) {} 90 // Permit each child to have its destructor 91 virtual ~LogDataOperation() {}; 92 93 void start( LogDataWorkerThread& workerThread ) const 94 { doStart( workerThread ); } 95 const QString& getFilename() const { return filename_; } 96 virtual bool isFull() const { return true; } 97 98 protected: 99 virtual void doStart( LogDataWorkerThread& workerThread ) const = 0; 100 QString filename_; 101 }; 102 103 // Attaching a new file (change name + full index) 104 class AttachOperation : public LogDataOperation { 105 public: 106 AttachOperation( const QString& fileName ) 107 : LogDataOperation( fileName ) {} 108 ~AttachOperation() {}; 109 110 bool isFull() const { return true; } 111 112 protected: 113 void doStart( LogDataWorkerThread& workerThread ) const; 114 }; 115 116 // Reindexing the current file 117 class FullIndexOperation : public LogDataOperation { 118 public: 119 FullIndexOperation() : LogDataOperation( QString() ) {} 120 ~FullIndexOperation() {}; 121 122 bool isFull() const { return false; } 123 124 protected: 125 void doStart( LogDataWorkerThread& workerThread ) const; 126 }; 127 128 // Indexing part of the current file (from fileSize) 129 class PartialIndexOperation : public LogDataOperation { 130 public: 131 PartialIndexOperation( qint64 fileSize ) 132 : LogDataOperation( QString() ), filesize_( fileSize ) {} 133 ~PartialIndexOperation() {}; 134 135 bool isFull() const { return false; } 136 137 protected: 138 void doStart( LogDataWorkerThread& workerThread ) const; 139 140 private: 141 qint64 filesize_; 142 }; 143 144 FileWatcher fileWatcher_; 145 MonitoredFileStatus fileChangedOnDisk_; 146 147 // Implementation of virtual functions 148 virtual QString doGetLineString( qint64 line ) const; 149 virtual QString doGetExpandedLineString( qint64 line ) const; 150 virtual QStringList doGetLines( qint64 first, int number ) const; 151 virtual QStringList doGetExpandedLines( qint64 first, int number ) const; 152 virtual qint64 doGetNbLine() const; 153 virtual int doGetMaxLength() const; 154 virtual int doGetLineLength( qint64 line ) const; 155 156 void enqueueOperation( const LogDataOperation* newOperation ); 157 void startOperation(); 158 159 QString indexingFileName_; 160 QFile* file_; 161 LinePositionArray linePosition_; 162 qint64 fileSize_; 163 qint64 nbLines_; 164 int maxLength_; 165 QDateTime lastModifiedDate_; 166 const LogDataOperation* currentOperation_; 167 const LogDataOperation* nextOperation_; 168 169 // To protect the file: 170 mutable QMutex fileMutex_; 171 // To protect linePosition_, fileSize_ and maxLength_: 172 mutable QMutex dataMutex_; 173 // (are mutable to allow 'const' function to touch it, 174 // while remaining const) 175 // When acquiring both, data should be help before locking file. 176 177 LogDataWorkerThread workerThread_; 178 }; 179 180 #endif 181