1 /* 2 * Copyright (C) 2009, 2010, 2014, 2015 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 #include "linepositionarray.h" 31 #include "encodingspeculator.h" 32 #include "utils.h" 33 34 // This class is a thread-safe set of indexing data. 35 class IndexingData 36 { 37 public: 38 IndexingData() : dataMutex_(), linePosition_(), maxLength_(0), 39 indexedSize_(0), encoding_(EncodingSpeculator::Encoding::ASCII7) { } 40 41 // Get the total indexed size 42 qint64 getSize() const; 43 44 // Get the length of the longest line 45 int getMaxLength() const; 46 47 // Get the total number of lines 48 LineNumber getNbLines() const; 49 50 // Get the position (in byte from the beginning of the file) 51 // of the end of the passed line. 52 qint64 getPosForLine( LineNumber line ) const; 53 54 // Get the guessed encoding for the content. 55 EncodingSpeculator::Encoding getEncodingGuess() const; 56 57 // Atomically add to all the existing 58 // indexing data. 59 void addAll( qint64 size, int length, 60 const FastLinePositionArray& linePosition, 61 EncodingSpeculator::Encoding encoding ); 62 63 // Completely clear the indexing data. 64 void clear(); 65 66 private: 67 mutable QMutex dataMutex_; 68 69 LinePositionArray linePosition_; 70 int maxLength_; 71 qint64 indexedSize_; 72 73 EncodingSpeculator::Encoding encoding_; 74 }; 75 76 class IndexOperation : public QObject 77 { 78 Q_OBJECT 79 public: 80 IndexOperation( const QString& fileName, 81 IndexingData* indexingData, bool* interruptRequest, 82 EncodingSpeculator* encodingSpeculator ); 83 84 virtual ~IndexOperation() { } 85 86 // Start the indexing operation, returns true if it has been done 87 // and false if it has been cancelled (results not copied) 88 virtual bool start() = 0; 89 90 signals: 91 void indexingProgressed( int ); 92 93 protected: 94 static const int sizeChunk; 95 96 // Returns the total size indexed 97 // Modify the passed linePosition and maxLength 98 void doIndex( IndexingData* linePosition, EncodingSpeculator* encodingSpeculator, 99 qint64 initialPosition ); 100 101 QString fileName_; 102 bool* interruptRequest_; 103 IndexingData* indexing_data_; 104 105 EncodingSpeculator* encoding_speculator_; 106 }; 107 108 class FullIndexOperation : public IndexOperation 109 { 110 public: 111 FullIndexOperation( const QString& fileName, 112 IndexingData* indexingData, bool* interruptRequest, 113 EncodingSpeculator* speculator ) 114 : IndexOperation( fileName, indexingData, interruptRequest, speculator ) { } 115 virtual bool start(); 116 }; 117 118 class PartialIndexOperation : public IndexOperation 119 { 120 public: 121 PartialIndexOperation( const QString& fileName, 122 IndexingData* indexingData, bool* interruptRequest, 123 EncodingSpeculator* speculator ) 124 : IndexOperation( fileName, indexingData, interruptRequest, speculator ) { } 125 virtual bool start(); 126 }; 127 128 // Create and manage the thread doing loading/indexing for 129 // the creating LogData. One LogDataWorkerThread is used 130 // per LogData instance. 131 // Note everything except the run() function is in the LogData's 132 // thread. 133 class LogDataWorkerThread : public QThread 134 { 135 Q_OBJECT 136 137 public: 138 // Pass a pointer to the IndexingData (initially empty) 139 // This object will change it when indexing (IndexingData must be thread safe!) 140 LogDataWorkerThread( IndexingData* indexing_data ); 141 ~LogDataWorkerThread(); 142 143 // Attaches to a file on disk. Attaching to a non existant file 144 // will work, it will just appear as an empty file. 145 void attachFile( const QString& fileName ); 146 // Instructs the thread to start a new full indexing of the file, sending 147 // signals as it progresses. 148 void indexAll(); 149 // Instructs the thread to start a partial indexing (starting at 150 // the end of the file as indexed). 151 void indexAdditionalLines(); 152 // Interrupts the indexing if one is in progress 153 void interrupt(); 154 155 // Returns a copy of the current indexing data 156 void getIndexingData( qint64* indexedSize, 157 int* maxLength, LinePositionArray* linePosition ); 158 159 signals: 160 // Sent during the indexing process to signal progress 161 // percent being the percentage of completion. 162 void indexingProgressed( int percent ); 163 // Sent when indexing is finished, signals the client 164 // to copy the new data back. 165 void indexingFinished( LoadingStatus status ); 166 167 protected: 168 void run(); 169 170 private: 171 void doIndexAll(); 172 173 // Mutex to protect operationRequested_ and friends 174 QMutex mutex_; 175 QWaitCondition operationRequestedCond_; 176 QWaitCondition nothingToDoCond_; 177 QString fileName_; 178 179 // Set when the thread must die 180 bool terminate_; 181 bool interruptRequested_; 182 IndexOperation* operationRequested_; 183 184 // Pointer to the owner's indexing data (we modify it) 185 IndexingData* indexing_data_; 186 187 // To guess the encoding 188 EncodingSpeculator encodingSpeculator_; 189 }; 190 191 #endif 192