xref: /glogg/src/data/logdata.h (revision 80bca0a387968c28827e5f6a97058c7bbfcfbd38)
1 /*
2  * Copyright (C) 2009, 2010, 2013, 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 LOGDATA_H
21 #define LOGDATA_H
22 
23 #include <memory>
24 
25 #include <QObject>
26 #include <QString>
27 #include <QFile>
28 #include <QVector>
29 #include <QMutex>
30 #include <QDateTime>
31 
32 #include "utils.h"
33 
34 #include "abstractlogdata.h"
35 #include "logdataworkerthread.h"
36 #include "filewatcher.h"
37 #include "loadingstatus.h"
38 
39 class LogFilteredData;
40 
41 // Thrown when trying to attach an already attached LogData
42 class CantReattachErr {};
43 
44 // Represents a complete set of data to be displayed (ie. a log file content)
45 // This class is thread-safe.
46 class LogData : public AbstractLogData {
47   Q_OBJECT
48 
49   public:
50     // Creates an empty LogData
51     LogData();
52     // Destroy an object
53     ~LogData();
54 
55     enum MonitoredFileStatus { Unchanged, DataAdded, Truncated };
56 
57     // Attaches the LogData to a file on disk
58     // It starts the asynchronous indexing and returns (almost) immediately
59     // Attaching to a non existant file works and the file is reported
60     // to be empty.
61     // Reattaching is forbidden and will throw.
62     void attachFile( const QString& fileName );
63     // Interrupt the loading and report a null file.
64     // Does nothing if no loading in progress.
65     void interruptLoading();
66     // Creates a new filtered data.
67     // ownership is passed to the caller
68     LogFilteredData* getNewFilteredData() const;
69     // Returns the size if the file in bytes
70     qint64 getFileSize() const;
71     // Returns the last modification date for the file.
72     // Null if the file is not on disk.
73     QDateTime getLastModifiedDate() const;
74     // Throw away all the file data and reload/reindex.
75     void reload();
76 
77     // Update the polling interval (in ms, 0 means disabled)
78     void setPollingInterval( uint32_t interval_ms );
79 
80   signals:
81     // Sent during the 'attach' process to signal progress
82     // percent being the percentage of completion.
83     void loadingProgressed( int percent );
84     // Signal the client the file is fully loaded and available.
85     void loadingFinished( LoadingStatus status );
86     // Sent when the file on disk has changed, will be followed
87     // by loadingProgressed if needed and then a loadingFinished.
88     void fileChanged( LogData::MonitoredFileStatus status );
89 
90   private slots:
91     // Consider reloading the file when it changes on disk updated
92     void fileChangedOnDisk();
93     // Called when the worker thread signals the current operation ended
94     void indexingFinished( LoadingStatus status );
95 
96   private:
97     // This class models an indexing operation.
98     // It exists to permit LogData to delay the operation if another
99     // one is ongoing (operations are asynchronous)
100     class LogDataOperation {
101       public:
102         LogDataOperation( const QString& fileName ) : filename_( fileName ) {}
103         // Permit each child to have its destructor
104         virtual ~LogDataOperation() {};
105 
106         void start( LogDataWorkerThread& workerThread ) const
107         { doStart( workerThread ); }
108         const QString& getFilename() const { return filename_; }
109 
110       protected:
111         virtual void doStart( LogDataWorkerThread& workerThread ) const = 0;
112         QString filename_;
113     };
114 
115     // Attaching a new file (change name + full index)
116     class AttachOperation : public LogDataOperation {
117       public:
118         AttachOperation( const QString& fileName )
119             : LogDataOperation( fileName ) {}
120         ~AttachOperation() {};
121 
122       protected:
123         void doStart( LogDataWorkerThread& workerThread ) const;
124     };
125 
126     // Reindexing the current file
127     class FullIndexOperation : public LogDataOperation {
128       public:
129         FullIndexOperation() : LogDataOperation( QString() ) {}
130         ~FullIndexOperation() {};
131 
132       protected:
133         void doStart( LogDataWorkerThread& workerThread ) const;
134     };
135 
136     // Indexing part of the current file (from fileSize)
137     class PartialIndexOperation : public LogDataOperation {
138       public:
139         PartialIndexOperation( qint64 fileSize )
140             : LogDataOperation( QString() ), filesize_( fileSize ) {}
141         ~PartialIndexOperation() {};
142 
143       protected:
144         void doStart( LogDataWorkerThread& workerThread ) const;
145 
146       private:
147         qint64 filesize_;
148     };
149 
150     std::shared_ptr<FileWatcher> fileWatcher_;
151     MonitoredFileStatus fileChangedOnDisk_;
152 
153     // Implementation of virtual functions
154     QString doGetLineString( qint64 line ) const override;
155     QString doGetExpandedLineString( qint64 line ) const override;
156     QStringList doGetLines( qint64 first, int number ) const override;
157     QStringList doGetExpandedLines( qint64 first, int number ) const override;
158     qint64 doGetNbLine() const override;
159     int doGetMaxLength() const override;
160     int doGetLineLength( qint64 line ) const override;
161 
162     void enqueueOperation( std::shared_ptr<const LogDataOperation> newOperation );
163     void startOperation();
164 
165     QString indexingFileName_;
166     std::unique_ptr<QFile> attached_file_;
167 
168     // Indexing data, read by us, written by the worker thread
169     IndexingData indexing_data_;
170 
171     /*
172     LinePositionArray linePosition_;
173     qint64 fileSize_;
174     qint64 nbLines_;
175     int maxLength_;
176     */
177 
178     QDateTime lastModifiedDate_;
179     std::shared_ptr<const LogDataOperation> currentOperation_;
180     std::shared_ptr<const LogDataOperation> nextOperation_;
181 
182     // To protect the file:
183     mutable QMutex fileMutex_;
184     // (are mutable to allow 'const' function to touch it,
185     // while remaining const)
186     // When acquiring both, data should be help before locking file.
187 
188     LogDataWorkerThread workerThread_;
189 };
190 
191 Q_DECLARE_METATYPE( LogData::MonitoredFileStatus );
192 
193 #endif
194