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