/*
* Copyright (C) 2009, 2010 Nicolas Bonnefon and other contributors
*
* This file is part of glogg.
*
* glogg is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* glogg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with glogg. If not, see .
*/
#ifndef LOGFILTEREDDATAWORKERTHREAD_H
#define LOGFILTEREDDATAWORKERTHREAD_H
#include
#include
#include
#include
#include
#include
class LogData;
// Line number are unsigned 32 bits for now.
typedef uint32_t LineNumber;
// Class encapsulating a single matching line
// Contains the line number the line was found in and its content.
class MatchingLine {
public:
MatchingLine( LineNumber line ) { lineNumber_ = line; };
// Accessors
LineNumber lineNumber() const { return lineNumber_; }
bool operator <( const MatchingLine& other) const
{ return lineNumber_ < other.lineNumber_; }
private:
LineNumber lineNumber_;
};
// This is an array of matching lines.
// It shall be implemented for random lookup speed, so
// a fixed "in-place" array (vector) is probably fine.
typedef std::vector SearchResultArray;
// This class is a mutex protected set of search result data.
// It is thread safe.
class SearchData
{
public:
SearchData() : dataMutex_(), matches_(), maxLength_(0) { }
// Atomically get all the search data
void getAll( int* length, SearchResultArray* matches,
qint64* nbLinesProcessed ) const;
// Atomically set all the search data
// (overwriting the existing)
// (the matches are always moved)
void setAll( int length, SearchResultArray&& matches );
// Atomically add to all the existing search data.
void addAll( int length, const SearchResultArray& matches, LineNumber nbLinesProcessed );
// Get the number of matches
LineNumber getNbMatches() const;
// Delete the match for the passed line (if it exist)
void deleteMatch( LineNumber line );
// Atomically clear the data.
void clear();
private:
mutable QMutex dataMutex_;
SearchResultArray matches_;
int maxLength_;
LineNumber nbLinesProcessed_;
};
class SearchOperation : public QObject
{
Q_OBJECT
public:
SearchOperation(const LogData* sourceLogData,
const QRegularExpression ®Exp, bool* interruptRequest );
virtual ~SearchOperation() { }
// Start the search operation, returns true if it has been done
// and false if it has been cancelled (results not copied)
virtual void start( SearchData& result ) = 0;
signals:
void searchProgressed( int percent, int nbMatches, qint64 started );
protected:
static const int nbLinesInChunk;
// Implement the common part of the search, passing
// the shared results and the line to begin the search from.
void doSearch( SearchData& result, qint64 initialLine );
bool* interruptRequested_;
const QRegularExpression regexp_;
const LogData* sourceLogData_;
};
class FullSearchOperation : public SearchOperation
{
public:
FullSearchOperation( const LogData* sourceLogData, const QRegularExpression& regExp,
bool* interruptRequest )
: SearchOperation( sourceLogData, regExp, interruptRequest ) {}
virtual void start( SearchData& result );
};
class UpdateSearchOperation : public SearchOperation
{
public:
UpdateSearchOperation( const LogData* sourceLogData, const QRegularExpression& regExp,
bool* interruptRequest, qint64 position )
: SearchOperation( sourceLogData, regExp, interruptRequest ),
initialPosition_( position ) {}
virtual void start( SearchData& result );
private:
qint64 initialPosition_;
};
// Create and manage the thread doing loading/indexing for
// the creating LogData. One LogDataWorkerThread is used
// per LogData instance.
// Note everything except the run() function is in the LogData's
// thread.
class LogFilteredDataWorkerThread : public QThread
{
Q_OBJECT
public:
LogFilteredDataWorkerThread( const LogData* sourceLogData );
~LogFilteredDataWorkerThread();
// Start the search with the passed regexp
void search(const QRegularExpression ®Exp );
// Continue the previous search starting at the passed position
// in the source file (line number)
void updateSearch( const QRegularExpression& regExp, qint64 position );
// Interrupts the search if one is in progress
void interrupt();
// Returns a copy of the current indexing data
void getSearchResult( int* maxLength, SearchResultArray* searchMatches,
qint64* nbLinesProcessed );
signals:
// Sent during the indexing process to signal progress
// percent being the percentage of completion.
void searchProgressed( int percent, int nbMatches, qint64 initial_position );
// Sent when indexing is finished, signals the client
// to copy the new data back.
void searchFinished();
protected:
void run();
private:
const LogData* sourceLogData_;
// Mutex to protect operationRequested_ and friends
QMutex mutex_;
QWaitCondition operationRequestedCond_;
QWaitCondition nothingToDoCond_;
// Set when the thread must die
bool terminate_;
bool interruptRequested_;
SearchOperation* operationRequested_;
// Shared indexing data
SearchData searchData_;
};
#endif