From a22c7f9a472aa4c482f5ed8db9c572dd998fe078 Mon Sep 17 00:00:00 2001 From: Anton Filimonov Date: Tue, 4 May 2021 19:22:44 +0300 Subject: [PATCH] Add back option to select preferred regex engine I've seen some crashes in hyperscan internals. Added an option in settings to use only Qt engine as it is more stable. --- src/logdata/src/logfiltereddataworker.cpp | 27 ++++++------- src/ui/include/optionsdialog.h | 3 ++ src/ui/include/optionsdialog.ui | 47 +++++++++++++++-------- src/ui/src/optionsdialog.cpp | 44 +++++++++++++++++++++ src/utils/include/configuration.h | 18 +++++++++ src/utils/src/configuration.cpp | 4 +- 6 files changed, 114 insertions(+), 29 deletions(-) diff --git a/src/logdata/src/logfiltereddataworker.cpp b/src/logdata/src/logfiltereddataworker.cpp index cb0bb7f28..be4e69031 100644 --- a/src/logdata/src/logfiltereddataworker.cpp +++ b/src/logdata/src/logfiltereddataworker.cpp @@ -99,7 +99,7 @@ PartialSearchResults filterLines( const MatcherVariant& matcher, const std::vect const auto& line = lines[ offset.get() ]; const auto hasMatch - = absl::visit( [ &line ]( const auto& m ) { return m.hasMatch( line ); }, matcher ); + = absl::visit( [&line]( const auto& m ) { return m.hasMatch( line ); }, matcher ); if ( hasMatch ) { results.maxLength = qMax( results.maxLength, getUntabifiedLength( line ) ); @@ -146,7 +146,7 @@ void SearchData::addAll( LineLength length, const SearchResultArray& matches, Li if ( !matches.empty() ) { lastMatchedLineNumber_ = std::max( lastMatchedLineNumber_, matches.back().lineNumber() ); - const auto insertNewMatches = [ &matches ]( SearchResultArray& oldMatches ) { + const auto insertNewMatches = [&matches]( SearchResultArray& oldMatches ) { const auto insertIt = std::lower_bound( begin( oldMatches ), end( oldMatches ), matches.front() ); @@ -258,7 +258,7 @@ void LogFilteredDataWorker::search( const RegularExpressionPattern& regExp, Line operationFuture_.waitForFinished(); interruptRequested_.clear(); - operationFuture_ = QtConcurrent::run( [ this, regExp, startLine, endLine ] { + operationFuture_ = QtConcurrent::run( [this, regExp, startLine, endLine] { auto operationRequested = std::make_unique( sourceLogData_, interruptRequested_, regExp, startLine, endLine ); connectSignalsAndRun( operationRequested.get() ); @@ -276,7 +276,7 @@ void LogFilteredDataWorker::updateSearch( const RegularExpressionPattern& regExp operationFuture_.waitForFinished(); interruptRequested_.clear(); - operationFuture_ = QtConcurrent::run( [ this, regExp, startLine, endLine, position ] { + operationFuture_ = QtConcurrent::run( [this, regExp, startLine, endLine, position] { auto operationRequested = std::make_unique( sourceLogData_, interruptRequested_, regExp, startLine, endLine, position ); connectSignalsAndRun( operationRequested.get() ); @@ -322,7 +322,7 @@ void SearchOperation::doSearch( SearchData& searchData, LineNumber initialLine ) high_resolution_clock::time_point t1 = high_resolution_clock::now(); const auto& config = Configuration::get(); - const auto matchingThreadsCount = static_cast( [ &config ]() { + const auto matchingThreadsCount = static_cast( [&config]() { if ( !config.useParallelSearch() ) { return 1; } @@ -352,8 +352,8 @@ void SearchOperation::doSearch( SearchData& searchData, LineNumber initialLine ) auto chunkStart = initialLine; auto linesSource = tbb::flow::input_node( searchGraph, - [ this, endLine, nbLinesInChunk, &chunkStart, - &fileReadingDuration ]( tbb::flow_control& fc ) -> BlockDataType { + [this, endLine, nbLinesInChunk, &chunkStart, + &fileReadingDuration]( tbb::flow_control& fc ) -> BlockDataType { if ( interruptRequested_ ) { LOG_INFO << "Block reader interrupted"; fc.stop(); @@ -399,19 +399,20 @@ void SearchOperation::doSearch( SearchData& searchData, LineNumber initialLine ) auto lineBlocksQueue = tbb::flow::buffer_node( searchGraph ); - HsRegularExpression hsRegularExpression{ regexp_ }; - using RegexMatcherNode = tbb::flow::function_node; - using MatcherContext = std::tuple; + std::vector regexMatchers; + HsRegularExpression hsRegularExpression{ regexp_ }; + const auto useHyperscanEngine = config.regexpEngine() == RegexpEngine::Hyperscan; for ( auto index = 0u; index < matchingThreadsCount; ++index ) { regexMatchers.emplace_back( - hsRegularExpression.createMatcher(), + useHyperscanEngine ? hsRegularExpression.createMatcher() + : MatcherVariant{ DefaultRegularExpressionMatcher( regexp_ ) }, microseconds{ 0 }, RegexMatcherNode( - searchGraph, 1, [ this, ®exMatchers, index ]( const BlockDataType& blockData ) { + searchGraph, 1, [this, ®exMatchers, index]( const BlockDataType& blockData ) { const auto& matcher = std::get<0>( regexMatchers.at( index ) ); const auto matchStartTime = high_resolution_clock::now(); @@ -442,7 +443,7 @@ void SearchOperation::doSearch( SearchData& searchData, LineNumber initialLine ) auto matchProcessor = tbb::flow::function_node( - searchGraph, 1, [ & ]( const PartialResultType& matchResults ) { + searchGraph, 1, [&]( const PartialResultType& matchResults ) { if ( interruptRequested_ ) { LOG_INFO << "Match processor interrupted"; return tbb::flow::continue_msg{}; diff --git a/src/ui/include/optionsdialog.h b/src/ui/include/optionsdialog.h index 1fc31c71d..92409052a 100644 --- a/src/ui/include/optionsdialog.h +++ b/src/ui/include/optionsdialog.h @@ -80,6 +80,9 @@ class OptionsDialog : public QDialog, public Ui::OptionsDialog { int getRegexpTypeIndex( SearchRegexpType syntax ) const; SearchRegexpType getRegexpTypeFromIndex( int index ) const; + int getRegexpEngineIndex( RegexpEngine engine ) const; + RegexpEngine getRegexpEngineFromIndex( int index ) const; + void updateDialogFromConfig(); }; diff --git a/src/ui/include/optionsdialog.ui b/src/ui/include/optionsdialog.ui index c39503d3d..3f2385ac9 100644 --- a/src/ui/include/optionsdialog.ui +++ b/src/ui/include/optionsdialog.ui @@ -7,7 +7,7 @@ 0 0 617 - 711 + 619 @@ -468,13 +468,30 @@ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + Regular expressions engine: + + + + + + + Use parallel search + + + true + + + + Index file read buffer (Mib): - + @@ -484,14 +501,14 @@ - + Search read buffer (lines): - + @@ -507,17 +524,7 @@ - - - - Use parallel search - - - true - - - - + File will be kept closed as much as possible. Affects only files opened after check state changed @@ -527,6 +534,16 @@ + + + + + 0 + 0 + + + + diff --git a/src/ui/src/optionsdialog.cpp b/src/ui/src/optionsdialog.cpp index e1ef96ad7..e507bc934 100644 --- a/src/ui/src/optionsdialog.cpp +++ b/src/ui/src/optionsdialog.cpp @@ -97,6 +97,11 @@ void OptionsDialog::setupTabs() #ifdef Q_OS_MAC minimizeToTrayCheckBox->setVisible( false ); #endif + +#ifndef KLOGG_HAS_HS + regexpEngineLabel->setVisible( false ); + regexpEngineComboBox->setVisible( false ); +#endif } // Populates the 'family' ComboBox @@ -120,6 +125,11 @@ void OptionsDialog::setupRegexp() mainSearchBox->addItems( regexpTypes ); quickFindSearchBox->addItems( regexpTypes ); + + QStringList regexpEngines; + regexpEngines << tr( "Hyperscan" ) << tr( "Qt" ); + + regexpEngineComboBox->addItems( regexpEngines ); } void OptionsDialog::setupStyles() @@ -194,6 +204,38 @@ SearchRegexpType OptionsDialog::getRegexpTypeFromIndex( int index ) const return type; } +int OptionsDialog::getRegexpEngineIndex( RegexpEngine engine ) const +{ + int index; + + switch ( engine ) { + case RegexpEngine::QRegularExpression: + index = 1; + break; + default: + index = 0; + break; + } + + return index; +} + +RegexpEngine OptionsDialog::getRegexpEngineFromIndex( int index ) const +{ + RegexpEngine type; + + switch ( index ) { + case 1: + type = RegexpEngine::QRegularExpression; + break; + default: + type = RegexpEngine::Hyperscan; + break; + } + + return type; +} + // Updates the dialog box using values in global Config() void OptionsDialog::updateDialogFromConfig() { @@ -227,6 +269,7 @@ void OptionsDialog::updateDialogFromConfig() // Regexp types mainSearchBox->setCurrentIndex( getRegexpTypeIndex( config.mainRegexpType() ) ); quickFindSearchBox->setCurrentIndex( getRegexpTypeIndex( config.quickfindRegexpType() ) ); + regexpEngineComboBox->setCurrentIndex( getRegexpEngineIndex( config.regexpEngine() ) ); incrementalCheckBox->setChecked( config.isQuickfindIncremental() ); @@ -301,6 +344,7 @@ void OptionsDialog::updateConfigFromDialog() config.setMainRegexpType( getRegexpTypeFromIndex( mainSearchBox->currentIndex() ) ); config.setQuickfindRegexpType( getRegexpTypeFromIndex( quickFindSearchBox->currentIndex() ) ); config.setQuickfindIncremental( incrementalCheckBox->isChecked() ); + config.setRegexpEnging( getRegexpEngineFromIndex( regexpEngineComboBox->currentIndex() ) ); config.setNativeFileWatchEnabled( nativeFileWatchCheckBox->isChecked() ); config.setPollingEnabled( pollingCheckBox->isChecked() ); diff --git a/src/utils/include/configuration.h b/src/utils/include/configuration.h index 80b482c98..8634a1741 100644 --- a/src/utils/include/configuration.h +++ b/src/utils/include/configuration.h @@ -52,6 +52,11 @@ enum class SearchRegexpType { FixedString, }; +enum class RegexpEngine { + Hyperscan, + QRegularExpression +}; + // Configuration class containing everything in the "Settings" dialog class Configuration final : public Persistable { public: @@ -224,6 +229,16 @@ class Configuration final : public Persistable { useLineEndingCache_ = useLineEndingCache; } + RegexpEngine regexpEngine() const + { + return regexpEngine_; + } + + void setRegexpEnging( RegexpEngine engine ) + { + regexpEngine_ = engine; + } + // Accessors bool versionCheckingEnabled() const { @@ -437,6 +452,9 @@ class Configuration final : public Persistable { bool enableQtHighDpi_ = true; int scaleFactorRounding_ = 1; + + RegexpEngine regexpEngine_ = RegexpEngine::Hyperscan; + }; #endif diff --git a/src/utils/src/configuration.cpp b/src/utils/src/configuration.cpp index 6201e6488..854e948ca 100644 --- a/src/utils/src/configuration.cpp +++ b/src/utils/src/configuration.cpp @@ -101,7 +101,8 @@ void Configuration::retrieveFromStorage( QSettings& settings ) quickfindRegexpType_ = static_cast( settings.value( "regexpType.quickfind", static_cast( Default.quickfindRegexpType_ ) ) .toInt() ); - + regexpEngine_ = static_cast( + settings.value( "regexpType.engine", static_cast( Default.regexpEngine_ ) ).toInt() ); quickfindIncremental_ = settings.value( "quickfind.incremental", Default.quickfindIncremental_ ).toBool(); @@ -214,6 +215,7 @@ void Configuration::saveToStorage( QSettings& settings ) const settings.setValue( "mainFont.antialiasing", forceFontAntialiasing_ ); settings.setValue( "regexpType.main", static_cast( mainRegexpType_ ) ); settings.setValue( "regexpType.quickfind", static_cast( quickfindRegexpType_ ) ); + settings.setValue( "regexpType.engine", static_cast( regexpEngine_ ) ); settings.setValue( "quickfind.incremental", quickfindIncremental_ ); settings.setValue( "filewatch.useNative", nativeFileWatchEnabled_ ); settings.setValue( "filewatch.usePolling", pollingEnabled_ );