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