xref: /glogg/src/data/logdata.h (revision 6e2e573c451ec24d720c967fab68538eaa3f3ab5)
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   signals:
78     // Sent during the 'attach' process to signal progress
79     // percent being the percentage of completion.
80     void loadingProgressed( int percent );
81     // Signal the client the file is fully loaded and available.
82     void loadingFinished( LoadingStatus status );
83     // Sent when the file on disk has changed, will be followed
84     // by loadingProgressed if needed and then a loadingFinished.
85     void fileChanged( LogData::MonitoredFileStatus status );
86 
87   private slots:
88     // Consider reloading the file when it changes on disk updated
89     void fileChangedOnDisk();
90     // Called when the worker thread signals the current operation ended
91     void indexingFinished( LoadingStatus status );
92 
93   private:
94     // This class models an indexing operation.
95     // It exists to permit LogData to delay the operation if another
96     // one is ongoing (operations are asynchronous)
97     class LogDataOperation {
98       public:
99         LogDataOperation( const QString& fileName ) : filename_( fileName ) {}
100         // Permit each child to have its destructor
101         virtual ~LogDataOperation() {};
102 
103         void start( LogDataWorkerThread& workerThread ) const
104         { doStart( workerThread ); }
105         const QString& getFilename() const { return filename_; }
106 
107       protected:
108         virtual void doStart( LogDataWorkerThread& workerThread ) const = 0;
109         QString filename_;
110     };
111 
112     // Attaching a new file (change name + full index)
113     class AttachOperation : public LogDataOperation {
114       public:
115         AttachOperation( const QString& fileName )
116             : LogDataOperation( fileName ) {}
117         ~AttachOperation() {};
118 
119       protected:
120         void doStart( LogDataWorkerThread& workerThread ) const;
121     };
122 
123     // Reindexing the current file
124     class FullIndexOperation : public LogDataOperation {
125       public:
126         FullIndexOperation() : LogDataOperation( QString() ) {}
127         ~FullIndexOperation() {};
128 
129       protected:
130         void doStart( LogDataWorkerThread& workerThread ) const;
131     };
132 
133     // Indexing part of the current file (from fileSize)
134     class PartialIndexOperation : public LogDataOperation {
135       public:
136         PartialIndexOperation( qint64 fileSize )
137             : LogDataOperation( QString() ), filesize_( fileSize ) {}
138         ~PartialIndexOperation() {};
139 
140       protected:
141         void doStart( LogDataWorkerThread& workerThread ) const;
142 
143       private:
144         qint64 filesize_;
145     };
146 
147     std::shared_ptr<FileWatcher> fileWatcher_;
148     MonitoredFileStatus fileChangedOnDisk_;
149 
150     // Implementation of virtual functions
151     QString doGetLineString( qint64 line ) const override;
152     QString doGetExpandedLineString( qint64 line ) const override;
153     QStringList doGetLines( qint64 first, int number ) const override;
154     QStringList doGetExpandedLines( qint64 first, int number ) const override;
155     qint64 doGetNbLine() const override;
156     int doGetMaxLength() const override;
157     int doGetLineLength( qint64 line ) const override;
158 
159     void enqueueOperation( std::shared_ptr<const LogDataOperation> newOperation );
160     void startOperation();
161 
162     QString indexingFileName_;
163     std::unique_ptr<QFile> attached_file_;
164 
165     // Indexing data, read by us, written by the worker thread
166     IndexingData indexing_data_;
167 
168     /*
169     LinePositionArray linePosition_;
170     qint64 fileSize_;
171     qint64 nbLines_;
172     int maxLength_;
173     */
174 
175     QDateTime lastModifiedDate_;
176     std::shared_ptr<const LogDataOperation> currentOperation_;
177     std::shared_ptr<const LogDataOperation> nextOperation_;
178 
179     // To protect the file:
180     mutable QMutex fileMutex_;
181     // (are mutable to allow 'const' function to touch it,
182     // while remaining const)
183     // When acquiring both, data should be help before locking file.
184 
185     LogDataWorkerThread workerThread_;
186 };
187 
188 Q_DECLARE_METATYPE( LogData::MonitoredFileStatus );
189 
190 #endif
191