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