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