xref: /glogg/src/data/logdataworkerthread.h (revision fcf40f1761134a69881dfa6f1d28d01064374a37)
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