1 /* 2 * Copyright (C) 2009, 2010, 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 LOGDATAWORKERTHREAD_H 21 #define LOGDATAWORKERTHREAD_H 22 23 #include <QObject> 24 #include <QThread> 25 #include <QMutex> 26 #include <QWaitCondition> 27 #include <QVector> 28 29 #include "loadingstatus.h" 30 31 // This class is a list of end of lines position, 32 // in addition to a list of qint64 (positions within the files) 33 // it can keep track of whether the final LF was added (for non-LF terminated 34 // files) and remove it when more data are added. 35 class LinePositionArray 36 { 37 public: 38 // Default constructor 39 LinePositionArray() : array() 40 { fakeFinalLF_ = false; } 41 // Copy constructor 42 inline LinePositionArray( const LinePositionArray& orig ) 43 : array(orig.array) 44 { fakeFinalLF_ = orig.fakeFinalLF_; } 45 46 // Add a new line position at the given position 47 inline void append( qint64 pos ) 48 { array.append( pos ); } 49 // Size of the array 50 inline int size() 51 { return array.size(); } 52 // Extract an element 53 inline qint64 at( int i ) const 54 { return array.at( i ); } 55 inline qint64 operator[]( int i ) const 56 { return array.at( i ); } 57 // Set the presence of a fake final LF 58 // Must be used after 'append'-ing a fake LF at the end. 59 void setFakeFinalLF( bool finalLF=true ) 60 { fakeFinalLF_ = finalLF; } 61 62 // Add another list to this one, removing any fake LF on this list. 63 LinePositionArray& operator+= ( const LinePositionArray& other ) 64 { 65 // If our final LF is fake, we remove it 66 if ( fakeFinalLF_ ) 67 this->array.pop_back(); 68 69 // Append the arrays 70 this->array += other.array; 71 72 // In case the 'other' object has a fake LF 73 this->fakeFinalLF_ = other.fakeFinalLF_; 74 75 return *this; 76 } 77 78 private: 79 QVector<qint64> array; 80 bool fakeFinalLF_; 81 }; 82 83 // This class is a mutex protected set of indexing data. 84 // It is thread safe. 85 class IndexingData 86 { 87 public: 88 IndexingData() : dataMutex_(), linePosition_(), maxLength_(0), indexedSize_(0) { } 89 90 // Atomically get all the indexing data 91 void getAll( qint64* size, int* length, 92 LinePositionArray* linePosition ); 93 94 // Atomically set all the indexing data 95 // (overwriting the existing) 96 void setAll( qint64 size, int length, 97 const LinePositionArray& linePosition ); 98 99 // Atomically add to all the existing 100 // indexing data. 101 void addAll( qint64 size, int length, 102 const LinePositionArray& linePosition ); 103 104 private: 105 QMutex dataMutex_; 106 107 LinePositionArray linePosition_; 108 int maxLength_; 109 qint64 indexedSize_; 110 }; 111 112 class IndexOperation : public QObject 113 { 114 Q_OBJECT 115 public: 116 IndexOperation( QString& fileName, bool* interruptRequest ); 117 118 virtual ~IndexOperation() { } 119 120 // Start the indexing operation, returns true if it has been done 121 // and false if it has been cancelled (results not copied) 122 virtual bool start( IndexingData& result ) = 0; 123 124 signals: 125 void indexingProgressed( int ); 126 127 protected: 128 static const int sizeChunk; 129 130 // Returns the total size indexed 131 qint64 doIndex( LinePositionArray& linePosition, int* maxLength, 132 qint64 initialPosition ); 133 134 QString fileName_; 135 bool* interruptRequest_; 136 }; 137 138 class FullIndexOperation : public IndexOperation 139 { 140 public: 141 FullIndexOperation( QString& fileName, bool* interruptRequest ) 142 : IndexOperation( fileName, interruptRequest ) { } 143 virtual bool start( IndexingData& result ); 144 }; 145 146 class PartialIndexOperation : public IndexOperation 147 { 148 public: 149 PartialIndexOperation( QString& fileName, bool* interruptRequest, qint64 position ); 150 virtual bool start( IndexingData& result ); 151 152 private: 153 qint64 initialPosition_; 154 }; 155 156 // Create and manage the thread doing loading/indexing for 157 // the creating LogData. One LogDataWorkerThread is used 158 // per LogData instance. 159 // Note everything except the run() function is in the LogData's 160 // thread. 161 class LogDataWorkerThread : public QThread 162 { 163 Q_OBJECT 164 165 public: 166 LogDataWorkerThread(); 167 ~LogDataWorkerThread(); 168 169 // Attaches to a file on disk. Attaching to a non existant file 170 // will work, it will just appear as an empty file. 171 void attachFile( const QString& fileName ); 172 // Instructs the thread to start a new full indexing of the file, sending 173 // signals as it progresses. 174 void indexAll(); 175 // Instructs the thread to start a partial indexing (starting at 176 // the index passed). 177 void indexAdditionalLines( qint64 position ); 178 // Interrupts the indexing if one is in progress 179 void interrupt(); 180 181 // Returns a copy of the current indexing data 182 void getIndexingData( qint64* indexedSize, 183 int* maxLength, LinePositionArray* linePosition ); 184 185 signals: 186 // Sent during the indexing process to signal progress 187 // percent being the percentage of completion. 188 void indexingProgressed( int percent ); 189 // Sent when indexing is finished, signals the client 190 // to copy the new data back. 191 void indexingFinished( LoadingStatus status ); 192 193 protected: 194 void run(); 195 196 private: 197 void doIndexAll(); 198 199 // Mutex to protect operationRequested_ and friends 200 QMutex mutex_; 201 QWaitCondition operationRequestedCond_; 202 QWaitCondition nothingToDoCond_; 203 QString fileName_; 204 205 // Set when the thread must die 206 bool terminate_; 207 bool interruptRequested_; 208 IndexOperation* operationRequested_; 209 210 // Shared indexing data 211 IndexingData indexingData_; 212 }; 213 214 #endif 215