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 LOGFILTEREDDATAWORKERTHREAD_H 21 #define LOGFILTEREDDATAWORKERTHREAD_H 22 23 #include <QObject> 24 #include <QThread> 25 #include <QMutex> 26 #include <QWaitCondition> 27 #include <QRegularExpression> 28 #include <QList> 29 30 class LogData; 31 32 // Line number are unsigned 32 bits for now. 33 typedef uint32_t LineNumber; 34 35 // Class encapsulating a single matching line 36 // Contains the line number the line was found in and its content. 37 class MatchingLine { 38 public: 39 MatchingLine( LineNumber line ) { lineNumber_ = line; }; 40 41 // Accessors 42 LineNumber lineNumber() const { return lineNumber_; } 43 44 bool operator <( const MatchingLine& other) const 45 { return lineNumber_ < other.lineNumber_; } 46 47 private: 48 LineNumber lineNumber_; 49 }; 50 51 // This is an array of matching lines. 52 // It shall be implemented for random lookup speed, so 53 // a fixed "in-place" array (vector) is probably fine. 54 typedef std::vector<MatchingLine> SearchResultArray; 55 56 // This class is a mutex protected set of search result data. 57 // It is thread safe. 58 class SearchData 59 { 60 public: 61 SearchData() : dataMutex_(), matches_(), maxLength_(0) { } 62 63 // Atomically get all the search data 64 void getAll( int* length, SearchResultArray* matches, 65 qint64* nbLinesProcessed ) const; 66 // Atomically set all the search data 67 // (overwriting the existing) 68 // (the matches are always moved) 69 void setAll( int length, SearchResultArray&& matches ); 70 // Atomically add to all the existing search data. 71 void addAll( int length, const SearchResultArray& matches, LineNumber nbLinesProcessed ); 72 // Get the number of matches 73 LineNumber getNbMatches() const; 74 // Delete the match for the passed line (if it exist) 75 void deleteMatch( LineNumber line ); 76 // Atomically clear the data. 77 void clear(); 78 79 private: 80 mutable QMutex dataMutex_; 81 82 SearchResultArray matches_; 83 int maxLength_; 84 LineNumber nbLinesProcessed_; 85 }; 86 87 class SearchOperation : public QObject 88 { 89 Q_OBJECT 90 public: 91 SearchOperation(const LogData* sourceLogData, 92 const QRegularExpression ®Exp, bool* interruptRequest ); 93 94 virtual ~SearchOperation() { } 95 96 // Start the search operation, returns true if it has been done 97 // and false if it has been cancelled (results not copied) 98 virtual void start( SearchData& result ) = 0; 99 100 signals: 101 void searchProgressed( int percent, int nbMatches, qint64 started ); 102 103 protected: 104 static const int nbLinesInChunk; 105 106 // Implement the common part of the search, passing 107 // the shared results and the line to begin the search from. 108 void doSearch( SearchData& result, qint64 initialLine ); 109 110 bool* interruptRequested_; 111 const QRegularExpression regexp_; 112 const LogData* sourceLogData_; 113 }; 114 115 class FullSearchOperation : public SearchOperation 116 { 117 public: 118 FullSearchOperation( const LogData* sourceLogData, const QRegularExpression& regExp, 119 bool* interruptRequest ) 120 : SearchOperation( sourceLogData, regExp, interruptRequest ) {} 121 virtual void start( SearchData& result ); 122 }; 123 124 class UpdateSearchOperation : public SearchOperation 125 { 126 public: 127 UpdateSearchOperation( const LogData* sourceLogData, const QRegularExpression& regExp, 128 bool* interruptRequest, qint64 position ) 129 : SearchOperation( sourceLogData, regExp, interruptRequest ), 130 initialPosition_( position ) {} 131 virtual void start( SearchData& result ); 132 133 private: 134 qint64 initialPosition_; 135 }; 136 137 // Create and manage the thread doing loading/indexing for 138 // the creating LogData. One LogDataWorkerThread is used 139 // per LogData instance. 140 // Note everything except the run() function is in the LogData's 141 // thread. 142 class LogFilteredDataWorkerThread : public QThread 143 { 144 Q_OBJECT 145 146 public: 147 LogFilteredDataWorkerThread( const LogData* sourceLogData ); 148 ~LogFilteredDataWorkerThread(); 149 150 // Start the search with the passed regexp 151 void search(const QRegularExpression ®Exp ); 152 // Continue the previous search starting at the passed position 153 // in the source file (line number) 154 void updateSearch( const QRegularExpression& regExp, qint64 position ); 155 // Interrupts the search if one is in progress 156 void interrupt(); 157 158 // Returns a copy of the current indexing data 159 void getSearchResult( int* maxLength, SearchResultArray* searchMatches, 160 qint64* nbLinesProcessed ); 161 162 signals: 163 // Sent during the indexing process to signal progress 164 // percent being the percentage of completion. 165 void searchProgressed( int percent, int nbMatches, qint64 initial_position ); 166 // Sent when indexing is finished, signals the client 167 // to copy the new data back. 168 void searchFinished(); 169 170 protected: 171 void run(); 172 173 private: 174 const LogData* sourceLogData_; 175 176 // Mutex to protect operationRequested_ and friends 177 QMutex mutex_; 178 QWaitCondition operationRequestedCond_; 179 QWaitCondition nothingToDoCond_; 180 181 // Set when the thread must die 182 bool terminate_; 183 bool interruptRequested_; 184 SearchOperation* operationRequested_; 185 186 // Shared indexing data 187 SearchData searchData_; 188 }; 189 190 #endif 191