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