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, IndexingData* indexingData, 122 bool* interruptRequest, EncodingSpeculator* speculator, qint64 position ); 123 virtual bool start(); 124 125 private: 126 qint64 initialPosition_; 127 }; 128 129 // Create and manage the thread doing loading/indexing for 130 // the creating LogData. One LogDataWorkerThread is used 131 // per LogData instance. 132 // Note everything except the run() function is in the LogData's 133 // thread. 134 class LogDataWorkerThread : public QThread 135 { 136 Q_OBJECT 137 138 public: 139 // Pass a pointer to the IndexingData (initially empty) 140 // This object will change it when indexing (IndexingData must be thread safe!) 141 LogDataWorkerThread( IndexingData* indexing_data ); 142 ~LogDataWorkerThread(); 143 144 // Attaches to a file on disk. Attaching to a non existant file 145 // will work, it will just appear as an empty file. 146 void attachFile( const QString& fileName ); 147 // Instructs the thread to start a new full indexing of the file, sending 148 // signals as it progresses. 149 void indexAll(); 150 // Instructs the thread to start a partial indexing (starting at 151 // the index passed). 152 void indexAdditionalLines( qint64 position ); 153 // Interrupts the indexing if one is in progress 154 void interrupt(); 155 156 // Returns a copy of the current indexing data 157 void getIndexingData( qint64* indexedSize, 158 int* maxLength, LinePositionArray* linePosition ); 159 160 signals: 161 // Sent during the indexing process to signal progress 162 // percent being the percentage of completion. 163 void indexingProgressed( int percent ); 164 // Sent when indexing is finished, signals the client 165 // to copy the new data back. 166 void indexingFinished( LoadingStatus status ); 167 168 protected: 169 void run(); 170 171 private: 172 void doIndexAll(); 173 174 // Mutex to protect operationRequested_ and friends 175 QMutex mutex_; 176 QWaitCondition operationRequestedCond_; 177 QWaitCondition nothingToDoCond_; 178 QString fileName_; 179 180 // Set when the thread must die 181 bool terminate_; 182 bool interruptRequested_; 183 IndexOperation* operationRequested_; 184 185 // Pointer to the owner's indexing data (we modify it) 186 IndexingData* indexing_data_; 187 188 // To guess the encoding 189 EncodingSpeculator encodingSpeculator_; 190 }; 191 192 #endif 193