Beispiel #1
0
// 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_ );
}
Beispiel #2
0
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 ) );
}
Beispiel #3
0
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 ;
   }