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