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