tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp
branchRCL_3
changeset 8 3f74d0d4af4c
parent 4 3b1da2848fc7
equal deleted inserted replaced
6:dee5afe5301f 8:3f74d0d4af4c
    61 
    61 
    62 #include "private/qfunctions_p.h"
    62 #include "private/qfunctions_p.h"
    63 
    63 
    64 QT_BEGIN_NAMESPACE
    64 QT_BEGIN_NAMESPACE
    65 
    65 
    66 namespace qt {
    66 namespace fulltextsearch {
    67     namespace fulltextsearch {
    67 namespace clucene {
    68         namespace clucene {
       
    69 
    68 
    70 // taken from qtexthtmlparser
    69 // taken from qtexthtmlparser
    71 static const struct QTextHtmlEntity
    70 static const struct QTextHtmlEntity
    72 {
    71 {
    73     const char *name;
    72     const char *name;
   584     this->m_reindex = reindex;
   583     this->m_reindex = reindex;
   585     this->m_collectionFile = collectionFile;
   584     this->m_collectionFile = collectionFile;
   586     this->m_indexFilesFolder = indexFilesFolder;
   585     this->m_indexFilesFolder = indexFilesFolder;
   587     mutex.unlock();
   586     mutex.unlock();
   588 
   587 
   589     start(QThread::NormalPriority);
   588     start(QThread::LowestPriority);
   590 }
   589 }
   591 
   590 
   592 void QHelpSearchIndexWriter::optimizeIndex()
   591 void QHelpSearchIndexWriter::optimizeIndex()
   593 {
   592 {
   594 #if !defined(QT_NO_EXCEPTIONS)
   593 #if !defined(QT_NO_EXCEPTIONS)
   611 #endif
   610 #endif
   612 }
   611 }
   613 
   612 
   614 void QHelpSearchIndexWriter::run()
   613 void QHelpSearchIndexWriter::run()
   615 {
   614 {
   616     QMutexLocker mutexLocker(&mutex);
       
   617 
       
   618     if (m_cancel)
       
   619         return;
       
   620 
       
   621     const bool reindex = this->m_reindex;
       
   622     const QString collectionFile(this->m_collectionFile);
       
   623 
       
   624     mutexLocker.unlock();
       
   625 
       
   626     QHelpEngineCore engine(collectionFile, 0);
       
   627     if (!engine.setupData())
       
   628         return;
       
   629 
       
   630     const QLatin1String key("CluceneIndexedNamespaces");
       
   631     if (reindex)
       
   632         engine.setCustomValue(key, QLatin1String(""));
       
   633 
       
   634     QMap<QString, QDateTime> indexMap;
       
   635     const QLatin1String oldKey("CluceneSearchNamespaces");
       
   636     if (!engine.customValue(oldKey, QString()).isNull()) {
       
   637         // old style qhc file < 4.4.2, need to convert...
       
   638         const QStringList indexedNamespaces = engine.customValue(oldKey).
       
   639             toString().split(QLatin1String("|"), QString::SkipEmptyParts);
       
   640         foreach (const QString &nameSpace, indexedNamespaces)
       
   641             indexMap.insert(nameSpace, QDateTime());
       
   642         engine.removeCustomValue(oldKey);
       
   643     } else {
       
   644         QDataStream dataStream(engine.customValue(key).toByteArray());
       
   645         dataStream >> indexMap;
       
   646     }
       
   647 
       
   648     QString indexPath = m_indexFilesFolder;
       
   649 
       
   650     QFileInfo fInfo(indexPath);
       
   651     if (fInfo.exists() && !fInfo.isWritable()) {
       
   652         qWarning("Full Text Search, could not create index (missing permissions for '%s').", qPrintable(indexPath));
       
   653         return;
       
   654     }
       
   655 
       
   656     emit indexingStarted();
       
   657 
       
   658     QCLuceneIndexWriter *writer = 0;
       
   659     QCLuceneStandardAnalyzer analyzer;
       
   660     const QStringList registeredDocs = engine.registeredDocumentations();
       
   661 
       
   662     QLocalSocket localSocket;
       
   663     localSocket.connectToServer(QString(QLatin1String("QtAssistant%1"))
       
   664         .arg(QLatin1String(QT_VERSION_STR)));
       
   665 
       
   666     QLocalServer localServer;
       
   667     bool otherInstancesRunning = true;
       
   668     if (!localSocket.waitForConnected()) {
       
   669         otherInstancesRunning = false;
       
   670         localServer.listen(QString(QLatin1String("QtAssistant%1"))
       
   671             .arg(QLatin1String(QT_VERSION_STR)));
       
   672     }
       
   673 
       
   674 #if !defined(QT_NO_EXCEPTIONS)
   615 #if !defined(QT_NO_EXCEPTIONS)
   675     try {
   616     try {
   676 #endif
   617 #endif
       
   618         QMutexLocker mutexLocker(&mutex);
       
   619 
       
   620         if (m_cancel)
       
   621             return;
       
   622 
       
   623         const bool reindex = this->m_reindex;
       
   624         const QString collectionFile(this->m_collectionFile);
       
   625 
       
   626         mutexLocker.unlock();
       
   627 
       
   628         QHelpEngineCore engine(collectionFile, 0);
       
   629         if (!engine.setupData())
       
   630             return;
       
   631 
       
   632         const QLatin1String key("CluceneIndexedNamespaces");
       
   633         if (reindex)
       
   634             engine.setCustomValue(key, QLatin1String(""));
       
   635 
       
   636         QMap<QString, QDateTime> indexMap;
       
   637         const QLatin1String oldKey("CluceneSearchNamespaces");
       
   638         if (!engine.customValue(oldKey, QString()).isNull()) {
       
   639             // old style qhc file < 4.4.2, need to convert...
       
   640             const QStringList indexedNamespaces
       
   641                 = engine.customValue(oldKey).toString()
       
   642                   .split(QLatin1String("|"), QString::SkipEmptyParts);
       
   643             foreach (const QString &nameSpace, indexedNamespaces)
       
   644                 indexMap.insert(nameSpace, QDateTime());
       
   645             engine.removeCustomValue(oldKey);
       
   646         } else {
       
   647             QDataStream dataStream(engine.customValue(key).toByteArray());
       
   648             dataStream >> indexMap;
       
   649         }
       
   650 
       
   651         QString indexPath = m_indexFilesFolder;
       
   652 
       
   653         QFileInfo fInfo(indexPath);
       
   654         if (fInfo.exists() && !fInfo.isWritable()) {
       
   655             qWarning("Full Text Search, could not create index (missing permissions for '%s').",
       
   656                      qPrintable(indexPath));
       
   657             return;
       
   658         }
       
   659 
       
   660         emit indexingStarted();
       
   661 
       
   662         QCLuceneIndexWriter *writer = 0;
       
   663         QCLuceneStandardAnalyzer analyzer;
       
   664         const QStringList registeredDocs = engine.registeredDocumentations();
       
   665 
       
   666         QLocalSocket localSocket;
       
   667         localSocket.connectToServer(QString(QLatin1String("QtAssistant%1"))
       
   668                                     .arg(QLatin1String(QT_VERSION_STR)));
       
   669 
       
   670         QLocalServer localServer;
       
   671         bool otherInstancesRunning = true;
       
   672         if (!localSocket.waitForConnected()) {
       
   673             otherInstancesRunning = false;
       
   674             localServer.listen(QString(QLatin1String("QtAssistant%1"))
       
   675                                .arg(QLatin1String(QT_VERSION_STR)));
       
   676         }
       
   677 
   677         // check if it's locked, and if the other instance is running
   678         // check if it's locked, and if the other instance is running
   678         if (!otherInstancesRunning && QCLuceneIndexReader::isLocked(indexPath))
   679         if (!otherInstancesRunning && QCLuceneIndexReader::isLocked(indexPath))
   679             QCLuceneIndexReader::unlock(indexPath);
   680             QCLuceneIndexReader::unlock(indexPath);
   680 
   681 
   681         if (QCLuceneIndexReader::isLocked(indexPath)) {
   682         if (QCLuceneIndexReader::isLocked(indexPath)) {
   703                 if (!indexMap.contains(namespaceName)) {
   704                 if (!indexMap.contains(namespaceName)) {
   704                     // make sure we remove some partly indexed stuff
   705                     // make sure we remove some partly indexed stuff
   705                     removeDocuments(indexPath, namespaceName);
   706                     removeDocuments(indexPath, namespaceName);
   706                 } else {
   707                 } else {
   707                     QString path = engine.documentationFileName(namespaceName);
   708                     QString path = engine.documentationFileName(namespaceName);
   708                     if (indexMap.value(namespaceName) < QFileInfo(path).lastModified()) {
   709                     if (indexMap.value(namespaceName)
       
   710                         < QFileInfo(path).lastModified()) {
   709                         // make sure we remove some outdated indexed stuff
   711                         // make sure we remove some outdated indexed stuff
   710                         indexMap.remove(namespaceName);
   712                         indexMap.remove(namespaceName);
   711                         removeDocuments(indexPath, namespaceName);
   713                         removeDocuments(indexPath, namespaceName);
   712                     }
   714                     }
   713 
   715 
   726             writer = new QCLuceneIndexWriter(indexPath, analyzer, false);
   728             writer = new QCLuceneIndexWriter(indexPath, analyzer, false);
   727         } else {
   729         } else {
   728             indexMap.clear();
   730             indexMap.clear();
   729             writer = new QCLuceneIndexWriter(indexPath, analyzer, true);
   731             writer = new QCLuceneIndexWriter(indexPath, analyzer, true);
   730         }
   732         }
   731 #if !defined(QT_NO_EXCEPTIONS)
   733 
   732     } catch (...) {
       
   733         qWarning("Full Text Search, could not create index writer in '%s'.",
       
   734             qPrintable(indexPath));
       
   735         return;
       
   736     }
       
   737 #endif
       
   738 
       
   739 #if !defined(QT_NO_EXCEPTIONS)
       
   740     try {
       
   741 #endif
       
   742         writer->setMergeFactor(100);
   734         writer->setMergeFactor(100);
   743         writer->setMinMergeDocs(1000);
   735         writer->setMinMergeDocs(1000);
   744         writer->setMaxFieldLength(QCLuceneIndexWriter::DEFAULT_MAX_FIELD_LENGTH);
   736         writer->setMaxFieldLength(QCLuceneIndexWriter::DEFAULT_MAX_FIELD_LENGTH);
       
   737 
       
   738         QStringList namespaces;
       
   739         foreach(const QString &namespaceName, registeredDocs) {
       
   740             mutexLocker.relock();
       
   741             if (m_cancel) {
       
   742                 closeIndexWriter(writer);
       
   743                 emit indexingFinished();
       
   744                 return;
       
   745             }
       
   746             mutexLocker.unlock();
       
   747 
       
   748             namespaces.append(namespaceName);
       
   749             if (indexMap.contains(namespaceName))
       
   750                 continue;
       
   751 
       
   752             const QList<QStringList> attributeSets =
       
   753                     engine.filterAttributeSets(namespaceName);
       
   754 
       
   755             if (attributeSets.isEmpty()) {
       
   756                 const QList<QUrl> docFiles = indexableFiles(&engine, namespaceName,
       
   757                                                             QStringList());
       
   758                 if (!addDocuments(docFiles, engine, QStringList(), namespaceName,
       
   759                                   writer, analyzer))
       
   760                     break;
       
   761             } else {
       
   762                 bool bail = false;
       
   763                 foreach (const QStringList &attributes, attributeSets) {
       
   764                     const QList<QUrl> docFiles = indexableFiles(&engine,
       
   765                                                                 namespaceName, attributes);
       
   766                     if (!addDocuments(docFiles, engine, attributes, namespaceName,
       
   767                                       writer, analyzer)) {
       
   768                         bail = true;
       
   769                         break;
       
   770                     }
       
   771                 }
       
   772                 if (bail)
       
   773                     break;
       
   774             }
       
   775 
       
   776             mutexLocker.relock();
       
   777             if (!m_cancel) {
       
   778                 QString path(engine.documentationFileName(namespaceName));
       
   779                 indexMap.insert(namespaceName, QFileInfo(path).lastModified());
       
   780                 writeIndexMap(engine, indexMap);
       
   781             }
       
   782             mutexLocker.unlock();
       
   783         }
       
   784 
       
   785         closeIndexWriter(writer);
       
   786 
       
   787         mutexLocker.relock();
       
   788         if (!m_cancel) {
       
   789             mutexLocker.unlock();
       
   790 
       
   791             QStringList indexedNamespaces = indexMap.keys();
       
   792             foreach(const QString &namespaceName, indexedNamespaces) {
       
   793                 mutexLocker.relock();
       
   794                 if (m_cancel)
       
   795                     break;
       
   796                 mutexLocker.unlock();
       
   797 
       
   798                 if (!namespaces.contains(namespaceName)) {
       
   799                     indexMap.remove(namespaceName);
       
   800                     writeIndexMap(engine, indexMap);
       
   801                     removeDocuments(indexPath, namespaceName);
       
   802                 }
       
   803             }
       
   804         }
       
   805 
   745 #if !defined(QT_NO_EXCEPTIONS)
   806 #if !defined(QT_NO_EXCEPTIONS)
   746     } catch (...) {
   807     } catch (...) {
   747         qWarning("Full Text Search, could not set writer properties.");
   808         qWarning("%s: Failed because of CLucene exception.", Q_FUNC_INFO);
   748         return;
       
   749     }
   809     }
   750 #endif
   810 #endif
   751 
   811 
   752     QStringList namespaces;
       
   753     foreach(const QString &namespaceName, registeredDocs) {
       
   754         mutexLocker.relock();
       
   755         if (m_cancel) {
       
   756             closeIndexWriter(writer);
       
   757             emit indexingFinished();
       
   758             return;
       
   759         }
       
   760         mutexLocker.unlock();
       
   761 
       
   762         namespaces.append(namespaceName);
       
   763         if (indexMap.contains(namespaceName))
       
   764             continue;
       
   765 
       
   766         const QList<QStringList> attributeSets =
       
   767             engine.filterAttributeSets(namespaceName);
       
   768 
       
   769         if (attributeSets.isEmpty()) {
       
   770             const QList<QUrl> docFiles = indexableFiles(&engine, namespaceName,
       
   771                 QStringList());
       
   772             if (!addDocuments(docFiles, engine, QStringList(), namespaceName,
       
   773                 writer, analyzer))
       
   774                 break;
       
   775         } else {
       
   776             bool bail = false;
       
   777             foreach (const QStringList &attributes, attributeSets) {
       
   778                 const QList<QUrl> docFiles = indexableFiles(&engine,
       
   779                     namespaceName, attributes);
       
   780                 if (!addDocuments(docFiles, engine, attributes, namespaceName,
       
   781                     writer, analyzer)) {
       
   782                     bail = true;
       
   783                     break;
       
   784                 }
       
   785             }
       
   786             if (bail)
       
   787                 break;
       
   788         }
       
   789 
       
   790         mutexLocker.relock();
       
   791         if (!m_cancel) {
       
   792             QString path(engine.documentationFileName(namespaceName));
       
   793             indexMap.insert(namespaceName, QFileInfo(path).lastModified());
       
   794             writeIndexMap(engine, indexMap);
       
   795         }
       
   796         mutexLocker.unlock();
       
   797     }
       
   798 
       
   799     closeIndexWriter(writer);
       
   800 
       
   801     mutexLocker.relock();
       
   802     if (!m_cancel) {
       
   803         mutexLocker.unlock();
       
   804 
       
   805         QStringList indexedNamespaces = indexMap.keys();
       
   806         foreach(const QString &namespaceName, indexedNamespaces) {
       
   807             mutexLocker.relock();
       
   808             if (m_cancel)
       
   809                 break;
       
   810             mutexLocker.unlock();
       
   811 
       
   812             if (!namespaces.contains(namespaceName)) {
       
   813                 indexMap.remove(namespaceName);
       
   814                 writeIndexMap(engine, indexMap);
       
   815                 removeDocuments(indexPath, namespaceName);
       
   816             }
       
   817         }
       
   818     }
       
   819     emit indexingFinished();
   812     emit indexingFinished();
   820 }
   813 }
   821 
   814 
   822 bool QHelpSearchIndexWriter::addDocuments(const QList<QUrl> docFiles,
   815 bool QHelpSearchIndexWriter::addDocuments(const QList<QUrl> docFiles,
   823     const QHelpEngineCore &engine, const QStringList &attributes,
   816     const QHelpEngineCore &engine, const QStringList &attributes,
   899         qWarning("Full Text Search, could not properly close index writer.");
   892         qWarning("Full Text Search, could not properly close index writer.");
   900     }
   893     }
   901 #endif
   894 #endif
   902 }
   895 }
   903 
   896 
   904         }   // namespace clucene
   897 }   // namespace clucene
   905     }   // namespace fulltextsearch
   898 }   // namespace fulltextsearch
   906 }   // namespace qt
       
   907 
   899 
   908 QT_END_NAMESPACE
   900 QT_END_NAMESPACE