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