// Close and reopen the file. // Used if we suspect the file has been moved (we follow the old // inode but really want the one now associated with the name) void LogData::reOpenFile() const { auto reopened = std::make_unique<QFile>( indexingFileName_ ); openFileByHandle( reopened.get() ); QMutexLocker locker( &fileMutex_ ); attached_file_ = std::move( reopened ); attached_file_id_ = getFileId( indexingFileName_ ); }
void LogData::attachFile( const QString& fileName ) { LOG(logDEBUG) << "LogData::attachFile " << fileName.toStdString(); if ( attached_file_ ) { // We cannot reattach throw CantReattachErr(); } indexingFileName_ = fileName; attached_file_.reset( new QFile( fileName ) ); openFileByHandle( attached_file_.get() ); attached_file_id_ = getFileId( indexingFileName_ ); std::shared_ptr<const LogDataOperation> operation( new AttachOperation( fileName ) ); enqueueOperation( std::move( operation ) ); }
void LogData::fileChangedOnDisk( const QString& filename ) { LOG(logINFO) << "signalFileChanged " << filename.toStdString(); QFileInfo info( indexingFileName_ ); const auto currentFileId = getFileId( indexingFileName_ ); const auto file_size = indexing_data_.getSize(); LOG(logDEBUG) << "current indexed fileSize=" << file_size; LOG(logDEBUG) << "info file_->size()=" << info.size(); LOG(logDEBUG) << "attached_file_->size()=" << attached_file_->size(); LOG(logDEBUG) << "attached_file_id_ index " << attached_file_id_.fileIndex; LOG(logDEBUG) << "currentFileId index " << currentFileId.fileIndex; // In absence of any clearer information, we use the following size comparison // to determine whether we are following the same file or not (i.e. the file // has been moved and the inode we are following is now under a new name, if for // instance log has been rotated). We want to follow the name so we have to reopen // the file to ensure we are reading the right one. // This is a crude heuristic but necessary for notification services that do not // give details (e.g. kqueues) const bool isFileIdChanged = attached_file_id_ != currentFileId; if ( isFileIdChanged || ( info.size() != attached_file_->size() ) || ( attached_file_->openMode() == QIODevice::NotOpen ) ) { LOG(logINFO) << "Inconsistent size, or file index, the file might have changed, re-opening"; reOpenFile(); // We don't force a (slow) full reindex as this routinely happens if // the file is appended quickly. // This means we can occasionally have false negatives (should be dealt with at // a lower level): e.g. if a new file is created with the same name as the old one // and with a size greater than the old one (should be rare in practice). } std::function<std::shared_ptr<LogDataOperation>()> newOperation; const auto real_file_size = attached_file_->size(); if ( isFileIdChanged || real_file_size < file_size ) { fileChangedOnDisk_ = Truncated; LOG(logINFO) << "File truncated"; newOperation = std::make_shared<FullIndexOperation>; } else if ( real_file_size == file_size ) { LOG(logINFO) << "No change in file"; if ( keepFileClosed_ ) { QMutexLocker locker( &fileMutex_ ); attached_file_->close(); } } else if ( fileChangedOnDisk_ != DataAdded ) { fileChangedOnDisk_ = DataAdded; LOG(logINFO) << "New data on disk"; newOperation = std::make_shared<PartialIndexOperation>; } if ( newOperation ) { enqueueOperation( newOperation() ); lastModifiedDate_ = info.lastModified(); emit fileChanged( fileChangedOnDisk_ ); } }
INT32 dpsArchiveFileMgr::scanArchiveFiles( UINT32& minFileId, UINT32& maxFileId, BOOLEAN allowMoved ) { INT32 rc = SDB_OK ; minFileId = DPS_INVALID_LOG_FILE_ID ; maxFileId = DPS_INVALID_LOG_FILE_ID ; try { fs::path dir ( _archivePath ) ; fs::directory_iterator endIter ; for ( fs::directory_iterator dirIter( dir ) ; dirIter != endIter ; ++dirIter ) { const string fileName = dirIter->path().filename().string() ; if ( !isArchiveFileName( fileName ) ) { continue ; } if ( isFullFileName( fileName ) || isPartialFileName( fileName ) || ( allowMoved && isMovedFileName( fileName ) ) ) { UINT32 fileId = 0 ; rc = getFileId( fileName, fileId ) ; if ( SDB_OK != rc ) { SDB_ASSERT( FALSE, "invalid fileName" ) ; PD_LOG( PDWARNING, "Failed to get file id of file[%s]", fileName.c_str() ) ; continue ; // ignore this file } if ( minFileId > fileId || DPS_INVALID_LOG_FILE_ID == minFileId ) { minFileId = fileId ; } if ( maxFileId < fileId || DPS_INVALID_LOG_FILE_ID == maxFileId ) { maxFileId = fileId ; } } } } catch( fs::filesystem_error& e ) { if ( e.code() == boost::system::errc::permission_denied || e.code() == boost::system::errc::operation_not_permitted ) { rc = SDB_PERM ; } else { rc = SDB_IO ; } goto error ; } catch( std::exception& e ) { PD_LOG( PDERROR, "unexpected exception: %s", e.what() ) ; rc = SDB_SYS ; goto error ; } done: return rc ; error: goto done ; }