Public Member Functions | Private Member Functions | Private Attributes

bea_FRI Class Reference
[IVD Back-End Agent]

#include <bea_fri.h>

Collaboration diagram for bea_FRI:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 bea_FRI (i_BackEndAgent_i &a_bea, bea_Volume *const a_volume_p, const cmn_Path &a_workDir, bool a_recreateInto=false, string a_extension="")
bool PositionToStartOfFRI ()
 Detects FRI on data volume and positions to the beginning of FRI or end od data (if there's no FRI).
void CloseVolume ()
 Performs all "medium close" steps:

  • mark the volume closed in the RMDB
  • write the FRI on the data volume
  • write the FRI on the system volume
  • verification of data format of the FRI when writing.

void CloseVolumeInRMDB ()
bool ReadFRIStart (cmn_UUID_t &a_volID)
 Reads first block of FRI and extracts volume ID.
bool ReadFRI (const cmn_UUID_t &a_volID)
 Reads one FRI from current medium position.
void CreateFRI (bool a_volumeClosed)
void DeleteFRIOnVolume ()
 Deletes last FRI on current volume (data or system).
UInt32_t GetFRIStartPosition () const

Private Member Functions

bool WriteFRI ()
void CopyFromDiskToMedium ()
void DeleteFRIOnDisk ()
void DeleteFRIOnDisk (const cmn_UUID_t &a_volID)
void MoveFromWorkToFRI ()
void SaveFRIOnError ()
bool VerifyExistenceOfFileMark (UInt32_t a_position)
 Verifies existance of the file mark on the specified position.

Private Attributes

 log_CLASSID_m
i_BackEndAgent_im_bea
bea_Drive *const m_drive_p
bea_Volume *const m_volume_p
bea_Volumem_sysVolume_p
bea_Volumem_currentVolume_p
const cmn_Pathm_workDir
bool m_recreateInto
string m_extension
UInt32_t m_friStartPos
 Position of the FRI on medium after the file mark.

Detailed Description

Definition at line 46 of file bea_fri.h.


Constructor & Destructor Documentation

bea_FRI::bea_FRI ( i_BackEndAgent_i a_bea,
bea_Volume *const   a_volume_p,
const cmn_Path a_workDir,
bool  a_recreateInto = false,
string  a_extension = "" 
)

Definition at line 50 of file bea_fri.cpp.

References dbg_LOW, bea_Drive::GetMedium(), bea_Medium::GetSysVolNumber(), bea_Medium::GetVolume(), log_DBG_m, log_FUNC_m, m_drive_p, and m_sysVolume_p.

  : m_bea(a_bea),
    m_drive_p(m_bea.GetDrive()),
    m_volume_p(a_volume_p),
    m_sysVolume_p(NULL),
    m_currentVolume_p(NULL),
    m_workDir(a_workDir),
    m_recreateInto(a_recreateInto),
    m_extension(a_extension),
    m_friStartPos(0) {

    log_FUNC_m(bea_FRI);

    bea_Medium* med_p = m_drive_p->GetMedium();
    if (med_p->GetSysVolNumber() > 0) {
        m_sysVolume_p = med_p->GetVolume(med_p->GetSysVolNumber());
        log_DBG_m(dbg_LOW, "Detected system volume is " << med_p->GetSysVolNumber());
    }
    else {
        log_DBG_m(dbg_LOW, "Medium doesn't have system volume.");
    }
}

Here is the call graph for this function:


Member Function Documentation

void bea_FRI::CloseVolume (  ) 

Performs all "medium close" steps:

  • mark the volume closed in the RMDB
  • write the FRI on the data volume
  • write the FRI on the system volume
  • verification of data format of the FRI when writing.

This functionality is used during the migration and when closing the volume manually.

It is assumed that:

  • volume IDs were already read from the medium
  • volume is positioned to the end of data volume (PositionToStartOfFRI() can be used)

Error handling covers:

  • terminate close if the medium volume is empty
  • terminate close if RMDB can't be updated
  • undo (erasing incomplete FRI) if writing to medium fails
  • removing FRI with data format problems from disk and medium
  • deleting incomplete FRI detected on the system volume

FRI file is kept on the disk (the fri directory) if

  • writing of FRI to medium is not successful for data and system volume
  • the volume already contains the FRI and the medium is WORM (recreate FRI)
  • for FSC check or recovery purpose
Warning:
This function does not delete the FRI from the medium when recreating FRI.

Definition at line 111 of file bea_fri.cpp.

References bea_OPWRITE, bea_Medium::ChangeVolume(), CloseVolumeInRMDB(), dbg_LOW, DeleteFRIOnDisk(), DeleteFRIOnVolume(), cmn_Global::dirs, bea_Volume::Erase(), evt_ERROR, evt_WARNING, ivd_Directories::fri, g_cmn, i_BackEndAgent_i::GetBarcode(), bea_Medium::GetCurrentVolume(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), bea_Volume::GetPosition(), bea_Volume::GetStartOfDataPosition(), bea_Medium::GetSysVolNumber(), bea_Volume::GetVolumeID(), bea_Volume::GetVolumeNumber(), i_BackEndAgent_i::HandleError(), ie_PRECONDITION, ivd_Error, log_DBG_m, log_FUNC_A_m, log_WriteEvent(), m_bea, m_currentVolume_p, m_drive_p, m_friStartPos, m_sysVolume_p, m_volume_p, m_workDir, MoveFromWorkToFRI(), NULL, bea_Volume::SeekEOD(), bea_Volume::SeekFileMark(), cmn_UUID_t::ToString(), VerifyExistenceOfFileMark(), bea_Volume::WriteFileMarks(), and WriteFRI().

Referenced by CreateFRI(), and bea_MigrationThread::Migrate().

                          {
    log_FUNC_A_m(CloseVolume, "volID: " << m_volume_p->GetVolumeID() );

    // Prevent closing system volumes
    if (   m_sysVolume_p != NULL
        && m_volume_p->GetVolumeNumber() == m_sysVolume_p->GetVolumeNumber()) {

        log_MARKLINE_m;
        throw ivd_Error(ie_PRECONDITION, "System volume can't be closed.", true);
    }

    bea_Medium* med_p = m_drive_p->GetMedium();
    m_currentVolume_p = med_p->GetCurrentVolume();

    // Prevent closing empty medium volumes.
    UInt32_t pos = m_currentVolume_p->GetPosition();
    if (pos <= m_currentVolume_p->GetStartOfDataPosition()) {
        ostringstream sstr;
        sstr
            << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
            << "Empty volume can't be closed.";

        log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        throw ivd_Error(ie_PRECONDITION, sstr.str(), true);
    }

    // Throws exception if it fails --> close volume is terminated.
    CloseVolumeInRMDB();

    cmn_File fri(m_workDir + m_currentVolume_p->GetVolumeID().ToString());

    if (!fri.Exists()) {
        // No FRI on disk is not treated as an error situation.
        ostringstream sstr;
        sstr
                << "Vol " << m_volume_p->GetVolumeNumber() << ": "
                << "No FRI file on disk.";

        log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
                       m_bea.GetJobID(), m_bea.GetBarcode() );

        return;
    };

    m_friStartPos = 0;

    // -- Data volume
    // Assumption is that the volume is already position to proper location
    // and writing can start.
    int successCount(0);
    try {
        m_currentVolume_p->WriteFileMarks();
        m_friStartPos = m_currentVolume_p->GetPosition();
    }
    catch (const ivd_Exception& ie) {
        // File mark was not written.
        ostringstream sstr;
        sstr
            << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
            << "Error writing file mark: " << ie.GetFriendly();

        log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        m_friStartPos = 0;
    }
    catch (...) {
        // File mark was not written.
        ostringstream sstr;
        sstr
            << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
            << "Error writing file mark.";

        log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        m_friStartPos = 0;
    }

    if (m_friStartPos > m_currentVolume_p->GetStartOfDataPosition()) {
        if (WriteFRI()) {
            ++successCount;
        }
    }

    if (m_sysVolume_p != NULL) {
        // -- System volume

        if (!fri.Exists()) {
        // No FRI on disk is not treated as an error situation.
            ostringstream sstr;
            sstr
                    << "Vol " << m_volume_p->GetVolumeNumber() << ": "
                    << "No FRI file on disk.";

            log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
                           m_bea.GetJobID(), m_bea.GetBarcode() );

            return;
        };

        bool readyToWrite(true);

        // Change to end of system volume.
        med_p->ChangeVolume( med_p->GetSysVolNumber() );
        m_currentVolume_p = med_p->GetCurrentVolume();
        m_currentVolume_p->SeekEOD();

        m_friStartPos = 0;
        // Verify existance of FM at the end of the system volume
        if (VerifyExistenceOfFileMark(m_currentVolume_p->GetPosition()-1))  {
            log_DBG_m(dbg_LOW,
                "System volume contains FM on pos: " <<
                m_currentVolume_p->GetPosition() );
        }
        else {
            // No file mark at the end of sysvol
            //   --> delete last FRI on the volume: it is incomplete.
            try {
                ostringstream sstr;
                sstr
                    << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
                    << "Erasing incomplete FRI on the system volume.";

                log_WriteEvent(sstr.str(), "FRI",
                    m_bea.GetJobID(), m_bea.GetBarcode() );

                m_currentVolume_p->SeekFileMark(-1);
                m_currentVolume_p->SeekFileMark(1);
                m_currentVolume_p->Erase();
            }
            catch (const ivd_Exception& ie) {
                ostringstream sstr;
                sstr
                    << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
                    << "FRI won't be written to system volume beacause "
                    << "erase of incomplete FRI on system volume failed: "
                    << ie.GetFriendly();

                log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
                    m_bea.GetJobID(), m_bea.GetBarcode() );

                readyToWrite = false;
            }
        }

        // Store position of the FRI
        m_friStartPos = m_currentVolume_p->GetPosition();
        if (WriteFRI()) {
            ++successCount;
        }
        try {
            // Write file mark after the FRI on system volume
            m_currentVolume_p->WriteFileMarks();
        }
        catch (const ivd_Error& ie) {
            // FRI on volume is not valid, no matter which error has occurred.
            DeleteFRIOnVolume();
            m_bea.HandleError(ie, bea_OPWRITE);
        }
        catch (...) {
            DeleteFRIOnVolume();
        }
    }

    if (successCount > 0) {
        if (m_workDir == g_cmn.dirs.fri) {
            DeleteFRIOnDisk();
        }
    }
    else {
        if (!fri.Exists()) {
            log_DBG_m(dbg_LOW, "No FRI on disk.");
        }
        else {
            ostringstream sstr;
            sstr
                << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
                << "FRI can't be written to medium and is left on disk.";

            log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
                m_bea.GetJobID(), m_bea.GetBarcode() );

            if (m_workDir != g_cmn.dirs.fri) {
                log_DBG_m(dbg_LOW, "Moving FRI file to " << g_cmn.dirs.fri);
                MoveFromWorkToFRI();
            }
        } // else
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_FRI::CloseVolumeInRMDB (  ) 

Definition at line 780 of file bea_fri.cpp.

References dbg_LOW, evt_ERROR, i_BackEndAgent_i::GetBarcode(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), i_BackEndAgent_i::GetRM(), bea_Volume::GetVolumeID(), bea_Volume::GetVolumeNumber(), ipc_EXEC_m, log_DBG_m, log_FUNC_m, log_WriteEvent(), m_bea, m_volume_p, and cmn_UUID_t::ToString().

Referenced by bea_MigrationThread::CheckFRI(), CloseVolume(), and bea_MigrationThread::Migrate().

                                {
    log_FUNC_m(CloseVolumeInRMDB);

    log_DBG_m(dbg_LOW,
        "Mark media volume full in RMDB." << m_volume_p->GetVolumeID());

    try {
        ipc_EXEC_m(
            i_ResourceManager_var rm = m_bea.GetRM();
            rm->VolumeFull(
                CORBA::string_dup(m_volume_p->GetVolumeID().ToString().c_str()) );
        );
    }
    catch (const ivd_Exception& ie) {
        ostringstream sstr;
        sstr
            << "Vol " << m_volume_p->GetVolumeNumber() << ": "
            << "Setting volume full in RMDM failed. "
            << "Error: " << ie.GetFriendly() << " "
            << "Close volume manually.";

        log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        throw;
    }
    catch (...) {
        ostringstream sstr;
        sstr
            << "Vol " << m_volume_p->GetVolumeNumber() << ": "
            << "Setting volume full in RMDM failed. "
            << "Close volume manually.";

        log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        throw;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_FRI::CopyFromDiskToMedium (  )  [private]

Definition at line 860 of file bea_fri.cpp.

References bbt_DISK_FRI, bea_OPWRITE, blk_FRI_c, dbg_DETAIL, dbg_LOW, dbg_NORM, evt_ERROR, bea_Volume::Flush(), fom_OPEN_EXISTING, fom_READ, i_BackEndAgent_i::GetBarcode(), bea_Volume::GetBlockSize(), ivd_BaseException::GetError(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), cmn_Time::GetMilliTime(), cmn_Time::GetTime_t(), bea_Volume::GetVolumeID(), bea_Volume::GetVolumeNumber(), i_BackEndAgent_i::HandleError(), ie_DATA_CORRUPTION, log_DBG_m, log_FUNC_m, log_WriteEvent(), m_bea, m_currentVolume_p, m_volume_p, m_workDir, cmn_UUID_t::ToString(), and bea_Volume::Write().

Referenced by WriteFRI().

                                   {
    log_FUNC_m(CopyFromDiskToMedium);

    log_DBG_m(dbg_DETAIL,
        "workDir: " << m_workDir <<
        ", m_volume_p: 0x" << m_volume_p);

    cmn_File fri(m_workDir + m_volume_p->GetVolumeID().ToString());

    log_DBG_m(dbg_LOW,
        "Copy FRI file :" << fri.GetFullPathRef() <<
        " to :" << m_bea.GetBarcode() << "/" << m_currentVolume_p->GetVolumeNumber());

    UInt64_t friSize(0);
    try {
        fri.OpenF(fom_READ | fom_OPEN_EXISTING);
        ivd_FileInfo_t  friInfo;
        fri.StatF(friInfo);
        friSize = (friInfo.size / 1024);
    }
    catch (const ivd_SysError& se) {
        ostringstream sstr;
        sstr
            << "Vol " << m_volume_p->GetVolumeNumber() << ": "
            << "FRI file can't be accessed. Error: " << se.GetFriendly();

        log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        throw;
    }

    UInt32_t blockSize(m_volume_p->GetBlockSize());
    UInt32_t blocksWritten(0);
    vector<UInt8_t> buffer(blockSize);

    df_RecReader parser(new df_BlockProxy(blk_FRI_c, bbt_DISK_FRI, blockSize), m_volume_p->GetVolumeID());

    cmn_Time startTime;
    // Copy loop
    while (true) {

        UInt32_t bytesRead = fri.ReadF(&(buffer[0]), blockSize);

        if (bytesRead == 0) {
            log_DBG_m(dbg_LOW, "End of FRI file.");
            break;
        }

        if (bytesRead < blockSize) {
            ostringstream sstr;
            sstr
                << "Read request of " << blockSize
                << " bytes returned only " << bytesRead;

            throw ivd_DFError(
                ie_DATA_CORRUPTION, blocksWritten, sstr.str(), true);
        }

        // Verify data format to prevent having invalid FRI on the medium.
        // Throws ivd_DFError
        (void)parser.Unpack(&(buffer[0]), blocksWritten);

        try {
            m_currentVolume_p->Write(&(buffer[0]));
        }
        catch (const ivd_Error &ie) {
            if (ie.GetError() == ie_MEDIUM_EOM) {
                log_DBG_m(dbg_NORM, "Early EOM on Write - ignore for FRI.");
            }
            else {
                m_bea.HandleError(ie, bea_OPWRITE);
                throw;
            }
        }
        ++blocksWritten;
    } // while

    try {
        m_currentVolume_p->Flush();
    }
    catch (const ivd_Exception& ie) {
        if (ie.GetError() == ie_MEDIUM_EOM) {
            log_DBG_m(dbg_NORM, "Early EOM on Write FM - ignore for FRI.");
        }
        else {
            ostringstream sstr;
            sstr
                << "Vol " << m_volume_p->GetVolumeNumber() << ": "
                << "Error flushing FRI to medium: " << ie.GetFriendly();

            log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
                m_bea.GetJobID(), m_bea.GetBarcode() );

            throw;
        }
    }

    // May throw ivd_DFError.
    parser.ProcEndOfInput();

    // Write statistics
    cmn_Time endTime;
    cmn_Time diffTime = endTime - startTime;

    UInt64_t msecDiff =
        UInt64_t(diffTime.GetTime_t()) * 1000 +
        diffTime.GetMilliTime();

    if (msecDiff == 0) {
        msecDiff = 1;
    }
    UInt64_t speed = (friSize * 1000) / (msecDiff) ;

    ostringstream sstr;
    sstr
        << "Vol " << m_volume_p->GetVolumeNumber()
        << ": FRI written to data volume " << m_volume_p->GetVolumeID()
        << " : " << friSize << " KB ( " << speed << " KB/s).";

    log_WriteEvent(sstr.str(), "", m_bea.GetJobID(), m_bea.GetBarcode() );
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_FRI::CreateFRI ( bool  a_volumeClosed  ) 

Definition at line 640 of file bea_fri.cpp.

References bbt_DISK_FRI, bbt_TAPE_READ, blk_Data_c, blk_FRI_c, CloseVolume(), dbg_LOW, dbg_NORM, cmn_Global::dirs, bea_Volume::Erase(), evt_ERROR, evt_WARNING, ivd_Directories::fri, g_cmn, i_BackEndAgent_i::GetBarcode(), bea_Volume::GetBlockSize(), bea_Medium::GetCurrentVolume(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), df_BlockReader::GetMgr(), bea_Volume::GetPartitionID(), bea_Volume::GetPoolID(), bea_Volume::GetStartOfDataPosition(), bea_Volume::GetVolumeID(), bea_Volume::GetVolumeNumber(), bea_Medium::IsWORM(), log_DBG_m, log_FUNC_m, log_WriteEvent(), log_WRN_m, m_bea, m_currentVolume_p, m_drive_p, m_extension, m_recreateInto, m_volume_p, m_workDir, MoveFromWorkToFRI(), bea_Volume::MustDumpFRI(), SaveFRIOnError(), bea_Volume::SeekBlock(), bea_Volume::SeekFileMark(), and cmn_UUID_t::ToString().

Referenced by bea_FRIThread::CreateFRI().

                                           {
    log_FUNC_m(CreateFRI);

    bea_Medium* med = m_drive_p->GetMedium();
    m_currentVolume_p = med->GetCurrentVolume();

    m_currentVolume_p->SeekBlock(m_currentVolume_p->GetStartOfDataPosition());

    ostringstream sstr;
    sstr
        << "Vol " << m_volume_p->GetVolumeNumber()
        << ": Creating new FRI. " << m_volume_p->GetVolumeID();

    log_WriteEvent( sstr.str(), "", m_bea.GetJobID(), m_bea.GetBarcode() );

    bool fmDetected(false);

    try {
        // Prepare output
        df_Writer writer(blk_FRI_c, bbt_DISK_FRI, m_volume_p->GetBlockSize());

        bool createFRIonTmp = (m_workDir != g_cmn.dirs.fri) && !m_recreateInto;

        writer.NewFRIBuffer(m_volume_p->GetVolumeID().ToString(),
                            true,
                            createFRIonTmp,
                            m_recreateInto,
                            m_workDir,
                            m_extension);
        writer.Go();

        // Prepare input
        {
            //
            // ** IMPORTANT **
            // These objects must be in a separate
            // block, because ~df_FRIDistiller() must be called
            // before writer.EndOfData().
            //

            df_BlockReader *blockReader_p =
                new df_BlockReader(
                blk_Data_c, bbt_TAPE_READ, m_volume_p->GetBlockSize());

            df_FRIDistiller dist(
                blockReader_p,
                m_volume_p->GetVolumeID(),
                m_volume_p->GetPoolID(),
                m_volume_p->GetPartitionID(),
                writer);

            bea_VolumeReader *volReader =
                new bea_VolumeReader(
                    blockReader_p->GetMgr(),
                    m_volume_p,
                    fmDetected);

            volReader->Start();

            dist.Unpack();
        }

        writer.EndOfData();
    }
    catch (const ivd_Error &ie) {
        sstr.str("");
        sstr
            << "FAILED creating new FRI: " << m_volume_p->GetVolumeID()
            << ". Error: " << ie.GetFriendly();

        log_WriteEvent(evt_ERROR, sstr.str(), "", m_bea.GetJobID(), m_bea.GetBarcode() );
        // partial and hopefully temporary solution for
        // problem reported in bug 7399

        // DeleteFRIOnDisk();
        SaveFRIOnError();
        throw;
    };
    
    if (m_recreateInto) {
        return;
    }

    // Write the FRI back to the medium if it was created on demand.
    if(fmDetected) {
        if (!a_volumeClosed) {
            log_WRN_m(
                "Volume not closed in RMDB, but there is FRI on volume: " <<
                "FRI will be closed and FRI overwritten. " <<
                m_bea.GetBarcode() << "/" << m_volume_p->GetVolumeNumber());
        }

        if (!med->IsWORM()) {
            log_DBG_m(dbg_NORM, "Overwriting old FRI.");
            // Overwrite old FRI
            m_volume_p->SeekFileMark(-1);
            m_volume_p->Erase();
            CloseVolume();
        }
        else {
            ostringstream sstr;
            sstr
                << "Vol " << m_volume_p->GetVolumeNumber() << ": "
                << "WORM medium --> FRI left on disk. ";

            log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
                m_bea.GetJobID(), m_bea.GetBarcode() );

            if (m_workDir != g_cmn.dirs.fri) {
                log_DBG_m(dbg_LOW, "Moving FRI file to " << g_cmn.dirs.fri);
                MoveFromWorkToFRI();
            }
        }
    }
    else if (a_volumeClosed) {
        log_WRN_m(
            "Volume already closed in RMDB, but no FRI on volume. " <<
            "Writing FRI. " <<
            m_bea.GetBarcode() << "/" << m_volume_p->GetVolumeNumber() );

        CloseVolume();
    }
    else if (m_volume_p->MustDumpFRI()) {
        log_DBG_m(dbg_NORM, "Dumping FRI to the end of volume.");
        // Medium volume is full enough to dump the FRI.
        CloseVolume();
    }
    else {
        log_DBG_m(dbg_NORM,
            "Volume still has space for data. FRI created on the disk.");
        if (m_workDir != g_cmn.dirs.fri) {
            log_DBG_m(dbg_LOW, "Moving FRI file to " << g_cmn.dirs.fri);
            MoveFromWorkToFRI();
        }
    };

}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_FRI::DeleteFRIOnDisk (  )  [private]

Definition at line 1025 of file bea_fri.cpp.

References bea_Volume::GetVolumeID(), log_FUNC_m, and m_volume_p.

Referenced by CloseVolume(), DeleteFRIOnDisk(), ReadFRI(), and WriteFRI().

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_FRI::DeleteFRIOnDisk ( const cmn_UUID_t a_volID  )  [private]

Definition at line 985 of file bea_fri.cpp.

References dbg_LOW, DeleteFRIOnDisk(), evt_ERROR, i_BackEndAgent_i::GetBarcode(), ivd_BaseException::GetError(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), bea_Volume::GetVolumeNumber(), log_DBG_m, log_FUNC_m, log_WriteEvent(), m_bea, m_volume_p, m_workDir, and cmn_UUID_t::ToString().

                                                       {
    log_FUNC_m(DeleteFRIOnDisk(a_volID));

    ostringstream sstr;
    sstr
        << "Vol " << m_volume_p->GetVolumeNumber() << ": "
        << "Deleting FRI on disk.";

    log_WriteEvent(sstr.str(), "FRI",
        m_bea.GetJobID(), m_bea.GetBarcode() );

    cmn_File fri(m_workDir + a_volID.ToString());
    try {
        fri.DeleteF();
    }
    catch (const ivd_SysError& se) {

        // No FRI on disk is not treated as an error situation.
#if IVD_POSIX_OS
        if (se.GetError() == ENOENT) {
#elif TGT_OS_windows
        if (se.GetError() == ERROR_FILE_NOT_FOUND) {
#endif
            log_DBG_m(dbg_LOW,
                "No FRI file on disk to delete. UUID: " << a_volID);
        }
        else {
            ostringstream sstr;
            sstr
                << "Vol " << m_volume_p->GetVolumeNumber() << ": "
                << "FRI file can't be deleted. Error: " << se.GetFriendly();

            log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
                m_bea.GetJobID(), m_bea.GetBarcode() );
        }
    }
}

Here is the call graph for this function:

void bea_FRI::DeleteFRIOnVolume (  ) 

Deletes last FRI on current volume (data or system).

Definition at line 1105 of file bea_fri.cpp.

References bea_OPWRITE, dbg_LOW, bea_Volume::Erase(), evt_ERROR, evt_WARNING, i_BackEndAgent_i::GetBarcode(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), bea_Volume::GetVolumeNumber(), i_BackEndAgent_i::HandleError(), bea_Medium::IsWORM(), log_DBG_m, log_FUNC_m, log_WriteEvent(), m_bea, m_currentVolume_p, m_drive_p, m_friStartPos, m_volume_p, and VerifyExistenceOfFileMark().

Referenced by bea_FRIThread::CheckFRI(), CloseVolume(), ReadFRI(), and WriteFRI().

                                {
    log_FUNC_m(DeleteFRIOnVolume);

    if (m_drive_p->GetMedium()->IsWORM()) {
        log_DBG_m(dbg_LOW, "FRI on WORM medium can't be deleted.")
        return;
    }

    // Stored start FRI position should be at least header + FRI file mark
    if (m_friStartPos < m_currentVolume_p->GetStartOfDataPosition() + 1) {
        log_DBG_m(dbg_LOW,
            "FRI start position not stored: " << m_friStartPos << " "<<
            "Won't delete FRI on medium.");
        return;
    }

    ostringstream sstr;
    sstr
        << "Vol " << m_volume_p->GetVolumeNumber() << ": "
        << "Deleting FRI on medium volume.";

    log_WriteEvent(sstr.str(), "FRI",
        m_bea.GetJobID(), m_bea.GetBarcode() );

    log_DBG_m(dbg_LOW,
        "Seeking to stored position: " << m_friStartPos << " "<<
        "and verifying the existence of FRI file mark.");

    if (! VerifyExistenceOfFileMark(m_friStartPos - 1) ) {
        ostringstream sstr;
        sstr
            << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
            << "FRI on the volume won't be deleted. No FRI file mark present.";

        log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        m_friStartPos = 0;
        return;
    }
    m_friStartPos = 0;

    // File mark verification passed. Delete the FRI on the medium.
    log_DBG_m(dbg_LOW, "Deleting the FRI on the medium.");

    try {
        m_currentVolume_p->Erase();
    }
    catch (const ivd_Error& ie) {
        ostringstream sstr;
        sstr
            << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
            << "Error when deleting invalid FRI on the medium: " << ie.GetFriendly();

        log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        m_bea.HandleError(ie, bea_OPWRITE);
    }
    catch (...) {
        ostringstream sstr;
        sstr
            << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
            << "Unknown error when deleting invalid FRI on the medium.";

        log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        return;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

UInt32_t bea_FRI::GetFRIStartPosition (  )  const

Definition at line 351 of file bea_fri.cpp.

References m_friStartPos.

Referenced by bea_FRIThread::ProcessFromDataVol().

                                            {
    return m_friStartPos;
}

Here is the caller graph for this function:

void bea_FRI::MoveFromWorkToFRI (  )  [private]

Definition at line 1033 of file bea_fri.cpp.

References cmn_MoveFile(), dbg_LOW, cmn_File::DeleteFile(), cmn_Global::dirs, ivd_Directories::fri, g_cmn, bea_Volume::GetVolumeID(), log_DBG_m, log_FUNC_m, log_WRN_m, m_volume_p, m_workDir, and cmn_UUID_t::ToString().

Referenced by CloseVolume(), and CreateFRI().

                                {
    log_FUNC_m(MoveFromWorkToFRI);

    log_DBG_m(dbg_LOW, "Moving FRI file to " << g_cmn.dirs.fri);

    cmn_Path src(m_workDir + m_volume_p->GetVolumeID().ToString());
    cmn_Path dest(g_cmn.dirs.fri + m_volume_p->GetVolumeID().ToString());

    try {
        cmn_MoveFile(src, dest);
    }
    catch (const ivd_SysError) {
        // TODO: Should failure in error recovery be handled?
        log_WRN_m(
            "Moving a file from " << src << " to " << dest <<
            " failed. Deleting source and target");
        cmn_File::DeleteFile(src);
        cmn_File::DeleteFile(dest);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool bea_FRI::PositionToStartOfFRI (  ) 

Detects FRI on data volume and positions to the beginning of FRI or end od data (if there's no FRI).

The first FM is after the medium volume header, the second one is between data and FRI.

Return values:
true FRI detected
false No FRI on the volume

Definition at line 316 of file bea_fri.cpp.

References bea_OPREAD, bea_Medium::ChangeVolume(), dbg_LOW, dbg_NORM, bea_Medium::GetCurrentVolume(), bea_Medium::GetCurVolNumber(), ivd_BaseException::GetError(), bea_Drive::GetMedium(), bea_Volume::GetPosition(), bea_Volume::GetVolumeNumber(), i_BackEndAgent_i::HandleError(), ie_MEDIUM_EOM, log_DBG_m, log_FUNC_m, m_bea, m_currentVolume_p, m_drive_p, m_friStartPos, m_volume_p, bea_Volume::Rewind(), and bea_Volume::SeekFileMark().

Referenced by bea_MigrationThread::CheckFRI(), bea_FRIThread::CheckFRI(), and bea_FRIThread::ProcessFromDataVol().

                                   {
    log_FUNC_m(PositionToStartOfFRI);

    bea_Medium* med_p = m_drive_p->GetMedium();
    if (med_p->GetCurVolNumber() != m_volume_p->GetVolumeNumber() ) {
        med_p->ChangeVolume( m_volume_p->GetVolumeNumber() );
    }
    m_currentVolume_p = med_p->GetCurrentVolume();
    m_friStartPos = 0;

    try {
        log_DBG_m(dbg_NORM, "Detecting previously written FRI.")
        m_friStartPos = 0;
        m_volume_p->Rewind();
        m_volume_p->SeekFileMark(2);
        m_friStartPos = m_currentVolume_p->GetPosition();

        return true;
    }
    catch (const ivd_Error& ie) {
        if (ie.GetError() == ie_MEDIUM_EOM ||
            ie.GetError() == ie_MEDIUM_EOD) {
            log_DBG_m(dbg_LOW, "End of medium detected ==> No FRI on the tape.");
            return false;
        }
        else {
            log_DBG_m(dbg_LOW, "Error when positioning to the FRI.");
            m_bea.HandleError(ie, bea_OPREAD);
            throw;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool bea_FRI::ReadFRI ( const cmn_UUID_t a_volID  ) 

Reads one FRI from current medium position.

Return values:
true Reading stopped because of encountered file mark
false Reading stopped because of other reasons (end of volume...)

Definition at line 462 of file bea_fri.cpp.

References bea_OPREAD, dbg_DETAIL, dbg_LOW, dbg_NORM, DeleteFRIOnDisk(), DeleteFRIOnVolume(), df_DISKFRI_BLOCKS_c, evt_WARNING, df_MgrWriter::Flush(), i_BackEndAgent_i::GetBarcode(), df_DataBlock::GetBlockSize(), bea_Volume::GetBlockSize(), ivd_BaseException::GetError(), df_MgrWriter::GetFree(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), bea_Medium::GetMediumMem(), cmn_Time::GetMilliTime(), df_DataBlock::GetPosition(), cmn_Time::GetTime_t(), bea_Volume::GetVolumeNumber(), i_BackEndAgent_i::HandleError(), ie_MEDIUM_EOD, ie_MEDIUM_EOM, ie_MEDIUM_FILEMARK, ie_MEDIUM_HWERR, ie_MEDIUM_ILENGTH, ie_MEDIUM_MEDERR, i_BackEndAgent_i::IsAborted(), bea_Medium::IsMediumMemValid(), bea_Volume::IsSysVolume(), log_DBG_m, log_FUNC_A_m, log_WriteEvent(), m_bea, m_currentVolume_p, m_drive_p, m_extension, m_recreateInto, m_volume_p, m_workDir, df_DataBlock::Move(), NULL, bea_Volume::Read(), cmn_UUID_t::ToString(), and bea_MediumMemory::UpdateAccess().

Referenced by bea_FRIThread::ReadFRI(), and bea_FRIThread::ReadFromSysVol().

                                               {
    log_FUNC_A_m(ReadFRI, "volid: " << a_volID);

    ostringstream sstr;
    if (m_volume_p->IsSysVolume()) {
        sstr
            << "Vol " << m_volume_p->GetVolumeNumber()
            << ": Reading FRI from system volume for " << a_volID;
    }
    else {
        sstr
            << "Vol " << m_volume_p->GetVolumeNumber()
            << ": Reading FRI from data volume for " << a_volID;
    }
    log_WriteEvent( sstr.str(), "", m_bea.GetJobID(), m_bea.GetBarcode() );

    m_currentVolume_p = m_volume_p;

    UInt64_t friSize(0);
    cmn_Time startTime;

    df_BlockManager mgr(m_volume_p->GetBlockSize(), df_DISKFRI_BLOCKS_c);

    blk_DiskFRIWriter *fri_p =
        new blk_DiskFRIWriter(  mgr, 
                                a_volID.ToString(), 
                                !m_recreateInto, 
                                true,
                                m_recreateInto,
                                m_workDir,
                                m_extension);

    fri_p->Start();

    bool fileMark(false);
    bool fileValid(true);
    {
        df_MgrWriter writer(mgr);

        df_DataBlock *blk(NULL);
        bool         eod(false);

        while ( (blk = writer.GetFree()) != NULL && !eod ) {
            try {
                m_volume_p->Read(blk->GetPosition());
                // Simulate ie_MEDIUM_MEDERR error 
                //SimulateMediumError();                
                blk->Move(m_volume_p->GetBlockSize());
                friSize += blk->GetBlockSize();
                writer.Flush();
            }
            catch (const ivd_Error &ie) {
                switch (ie.GetError()) {
                    case ie_MEDIUM_FILEMARK:
                        log_DBG_m(dbg_LOW,
                            "File mark detected ==> stop reading data.");
                        eod = fileMark = true;
                        break;
                    case ie_MEDIUM_EOM:
                        log_DBG_m(dbg_LOW,
                            "Early end of medium detected ==> continue.");
                        break;
                    case ie_MEDIUM_EOD:
                        log_DBG_m(dbg_LOW,
                            "End of data detected ==> stop reading data.");
                        eod = true;
                        break;
                    case ie_MEDIUM_ILENGTH:
                        log_DBG_m(dbg_LOW, "Illegal block length. Invalid FRI.");
                        eod = true;
                        fileValid = false;
                        break;
                    case ie_MEDIUM_MEDERR:
                        log_DBG_m(dbg_LOW,
                            "MED error while reading FRI ==> re-throw.");
                        if (!m_currentVolume_p->IsSysVolume()) {
                            m_bea.HandleError(ie, bea_OPREAD);
                        }
                        throw;
                    case ie_MEDIUM_HWERR:
                        log_DBG_m(dbg_LOW,
                            "HW error while reading FRI ==> re-throw.");
                        m_bea.HandleError(ie, bea_OPREAD);
                        throw;
                    default:
                        log_DBG_m(dbg_LOW, "Other error when reading.");
                        eod = true;
                        fileValid = false;
                        break;
                }
            } // catch

            if (m_bea.IsAborted()) {
                log_DBG_m(dbg_DETAIL, "Operation aborted.");
                break;
            }

        }// while
    }

    try {
        if (m_drive_p->GetMedium()->IsMediumMemValid()) {
            bea_MediumMemory* mm = m_drive_p->GetMedium()->GetMediumMem();
            mm->UpdateAccess(m_volume_p->GetVolumeNumber());
        }
    }
    catch(const ivd_Exception &ie) {
        log_DBG_m(dbg_LOW, "Error updating MIC. Ignored: " << ie );
    }

    if (m_volume_p->IsSysVolume()) {
        if (friSize > 0) {
            if (m_bea.IsAborted()) {
                log_DBG_m(dbg_LOW, "Aborted operation. Delete FRI on disk.");
                DeleteFRIOnDisk(a_volID);
                return false;
            }
            else if (!fileMark) {
                ostringstream sstr;
                sstr
                    << "Vol " << m_volume_p->GetVolumeNumber() << ": "
                    << "Missing file mark after the FRI on system volume."
                    << "Erasing the incomplete FRI.";

                log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
                    m_bea.GetJobID(), m_bea.GetBarcode() );

                DeleteFRIOnVolume();
                DeleteFRIOnDisk(a_volID);
            }
            return fileMark;
        }
    }

    if (!fileValid) {
        log_DBG_m(dbg_LOW, "FRI file is not valid. Will be deleted on disk.");
        if (friSize > 0) {
            DeleteFRIOnDisk(a_volID);
            return false;
        }
    }

    cmn_Time endTime;
    cmn_Time diffTime = endTime - startTime;

    UInt64_t msecDiff =
            UInt64_t(diffTime.GetTime_t()) * 1000 +
            diffTime.GetMilliTime();

    if (msecDiff == 0) {
        msecDiff = 1;
    }

    UInt64_t speed = (friSize * 1000) / (msecDiff * 1024) ;

    // log FRI read statistics
    sstr.str("");
    if (m_volume_p->IsSysVolume()) {
        sstr
            << "Vol " << m_volume_p->GetVolumeNumber()
            << ": FRI read from system volume for " << a_volID
            << " : " << friSize / 1024 << " KB (" << speed << " KB/s).";
    }
    else {
        sstr
            << "Vol " << m_volume_p->GetVolumeNumber()
            << ": FRI read from data volume for " << a_volID
            << " : " << friSize / 1024 << " KB (" << speed << " KB/s).";
    }
    log_WriteEvent( sstr.str(), "", m_bea.GetJobID(), m_bea.GetBarcode() );

    log_DBG_m(dbg_NORM, "FRI dumped to disk.");

    return fileMark;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool bea_FRI::ReadFRIStart ( cmn_UUID_t a_volID  ) 

Reads first block of FRI and extracts volume ID.

Parameters:
a_volID OUT read volume ID
Return values:
true end of volume encountered

Definition at line 363 of file bea_fri.cpp.

References bea_OPREAD, blk_FRI_c, cmn_UUID_t::Clear(), dbg_LOW, evt_WARNING, i_BackEndAgent_i::GetBarcode(), bea_Medium::GetBarcode(), bea_Volume::GetBlockSize(), ivd_BaseException::GetError(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), bea_Volume::GetStartOfDataPosition(), bea_Volume::GetVolumeNumber(), i_BackEndAgent_i::HandleError(), log_DBG_m, log_FUNC_m, log_WriteEvent(), log_WRN_m, m_bea, m_drive_p, m_volume_p, ntoh(), NULL, df_RecFRIStart_t::partID, df_RecFRIStart_t::poolID, bea_Volume::Read(), rec_FRIStart_c, rec_NoRec_c, df_RecFRIStart_t::startPos, df_RecCmn_t::type, df_BlockProxy::VerifiedBlock(), df_RecReader::VerifiedRecCmn(), and df_RecFRIStart_t::volID.

Referenced by bea_FRIThread::CheckFRI(), and bea_FRIThread::ReadFromSysVol().

                                              {
    log_FUNC_m(ReadFRIStart);

    a_volID.Clear();

    // Read block and parse the contents to get the
    // media volume UUID.
    vector<UInt8_t> block(m_volume_p->GetBlockSize(), 0);
    try {
        m_volume_p->Read(&(block[0]));
    }
    catch (ivd_Error &ie) {
        if (ie.GetError() == ie_MEDIUM_EOD) {
            log_DBG_m(dbg_LOW, "End of data. Stop reading FRI.");
            return true;
        }
        else if (ie.GetError() == ie_MEDIUM_FILEMARK) {
            log_DBG_m(dbg_LOW, "File mark detected -> No FRI.");
            return false;
        }
        else if (ie.GetError() == ie_MEDIUM_EOM) {
            log_DBG_m(dbg_LOW, "Early End of medium. Ignore.");
        }
        else {
            m_bea.HandleError(ie, bea_OPREAD);
            throw;
        }
    };

    const df_BlockHeader_t* blkHdr_p(NULL);
    try {
        UInt32_t blockNum(0);
        blkHdr_p = df_BlockReader::VerifiedBlock(
            &(block[0]), m_volume_p->GetBlockSize(), blockNum, blk_FRI_c, 0);
    }
    catch (const ivd_DFError& de) {
        log_WRN_m(
            m_drive_p->GetMedium()->GetBarcode() <<
            ": Reading FRI from system volume." <<
            " Data format in FRI header record: " << de.GetFriendly() );
            return false;
    }

    UInt32_t recNum(0), prevRecType(rec_NoRec_c);
    const df_RecCmn_t* recCmn_p = df_RecReader::VerifiedRecCmn(
        &(block[sizeof(*blkHdr_p)]),
        recNum, blk_FRI_c, prevRecType, 0);

    if (recCmn_p->type != rec_FRIStart_c) {
        log_WRN_m(
            m_drive_p->GetMedium()->GetBarcode() <<
            ": Reading FRI from system volume." <<
            " Invalid record type found." <<
            " (Expected FRIs, found " <<
            reinterpret_cast<const char*>(&(recCmn_p->type)) << ")");

        return false;

        // TODO: Shall reaction be more rigorous in this case?
    };

    const df_RecFRIStart_t* fris_p =
        reinterpret_cast<const df_RecFRIStart_t*>(
            &(block[0]) + sizeof(*blkHdr_p) + sizeof(*recCmn_p) );

    UInt32_t friStartPos = ntoh(fris_p->startPos);
    log_DBG_m(dbg_LOW,
        "Got FRI for:" << endl <<
        "volID  : " << fris_p->volID << endl <<
        "poolID : " << fris_p->poolID << endl <<
        "partID : " << fris_p->partID << endl <<
        "startP : " << friStartPos);

    if (friStartPos > m_volume_p->GetStartOfDataPosition()) {
        ostringstream sstr;
        sstr
            << "Vol " << m_volume_p->GetVolumeNumber() << ": "
            << "FRI doesn't cover complete medium. "
            << "FRI start position: " << friStartPos;

        log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );
    }
    else {
        // FRI start is valid.
        a_volID = fris_p->volID;
    }

    return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_FRI::SaveFRIOnError (  )  [private]

Definition at line 1056 of file bea_fri.cpp.

References cmn_MoveFile(), dbg_LOW, cmn_File::DeleteFile(), cmn_Global::dirs, g_cmn, bea_Volume::GetVolumeID(), log_DBG_m, log_FUNC_m, log_WRN_m, m_volume_p, m_workDir, ivd_Directories::tmp, and cmn_UUID_t::ToString().

Referenced by CreateFRI().

                             {
    log_FUNC_m(SaveFRIOnError);

    cmn_Path src(m_workDir + m_volume_p->GetVolumeID().ToString());

    cmn_Path dest(g_cmn.dirs.tmp  + 
                  cmn_Path("fri") + 
                  m_volume_p->GetVolumeID().ToString()); 

    dest.append("-read-error");

    try {
        log_DBG_m(dbg_LOW, "Moving FRI file to " << dest);
        log_WRN_m(
            "Moving a file from " << src << " to " << dest <<
            " because creation of a new FRI failed.");

        cmn_MoveFile(src, dest);
    }
    catch (const ivd_SysError) {
        log_WRN_m(
            "Moving a file from " << src << " to " << dest <<
            " failed. Try again on the same directory.");

        dest = src;
        dest.append("-read-error");

        try {
            log_DBG_m(dbg_LOW, "Moving FRI file to " << dest);
            log_WRN_m("Moving a file from " << src << " to " << dest << ".");

            cmn_MoveFile(src, dest);
        }
        catch (const ivd_SysError) {
            log_WRN_m(
                "Moving a file from " << src << " to " << dest <<
                " failed. Deleting source and target");

            cmn_File::DeleteFile(src);
            cmn_File::DeleteFile(dest);
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool bea_FRI::VerifyExistenceOfFileMark ( UInt32_t  a_position  )  [private]

Verifies existance of the file mark on the specified position.

Definition at line 1182 of file bea_fri.cpp.

References bea_OPREAD, dbg_LOW, evt_ERROR, evt_WARNING, i_BackEndAgent_i::GetBarcode(), bea_Volume::GetBlockSize(), ivd_BaseException::GetError(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), bea_Volume::GetVolumeNumber(), i_BackEndAgent_i::HandleError(), log_DBG_m, log_FUNC_m, log_WriteEvent(), m_bea, m_currentVolume_p, bea_Volume::Read(), and bea_Volume::SeekBlock().

Referenced by CloseVolume(), and DeleteFRIOnVolume().

                                                           {
    log_FUNC_m(VerifyExistenceOfFileMark);

    try {
        m_currentVolume_p->SeekBlock(a_position);
        vector<UInt8_t> buffer(m_currentVolume_p->GetBlockSize());
        m_currentVolume_p->Read(&(buffer[0]));

        // If reading succeeds then there is no FRI on the medium
        // This is unexpected situation.
        ostringstream sstr;
        sstr
            << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
            << "Missing FRI file mark. Please contact support.";

        log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );
    }
    catch (const ivd_Error& ie) {
        if (ie.GetError() == ie_MEDIUM_FILEMARK) {
            log_DBG_m(dbg_LOW, "File mark existence verified.");
            return true;
        }
        else {
            ostringstream sstr;
            sstr
                << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
                << "Error when detecting the FRI file mark: " << ie.GetFriendly();

            log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
                m_bea.GetJobID(), m_bea.GetBarcode() );

            m_bea.HandleError(ie, bea_OPREAD);
        }
    }
    catch (...) {
        ostringstream sstr;
        sstr
            << "Vol " << m_currentVolume_p->GetVolumeNumber() << ": "
            << "Unknown error when reading the FRI file mark.";

        log_WriteEvent(evt_ERROR, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );
    }
    return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool bea_FRI::WriteFRI (  )  [private]

Definition at line 821 of file bea_fri.cpp.

References CopyFromDiskToMedium(), DeleteFRIOnDisk(), DeleteFRIOnVolume(), evt_WARNING, i_BackEndAgent_i::GetBarcode(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), bea_Volume::GetVolumeNumber(), log_FUNC_m, log_WriteEvent(), m_bea, m_volume_p, and i_BackEndAgent_i::UpdateVolumeUsed().

Referenced by CloseVolume().

                       {
    log_FUNC_m(WriteFRI);

    try {
        CopyFromDiskToMedium();
        m_bea.UpdateVolumeUsed();
        return true;
    }
    catch (const ivd_DFError& dfe) {
        // FRI on disk is not useful and must be recreated.
        ostringstream sstr;
        sstr
            << "Vol " << m_volume_p->GetVolumeNumber() << ": "
            << "Detected data format error in FRI on disk.  It will be deleted "
            << "from the disk and medium volume to prevent future recovery "
            << "errors. FRI will be rebuilt on next use. ("
            << dfe.GetFriendly() << ")";

        log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        DeleteFRIOnDisk();
        DeleteFRIOnVolume();
    }
    catch (const ivd_Error) {
        // FRI on volume is not valid, no matter which error has occurred.
        DeleteFRIOnVolume();
    }
    catch (const ivd_SysError) {
        DeleteFRIOnVolume();
    }
    catch (...) {
        DeleteFRIOnVolume();
    }
    return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 65 of file bea_fri.h.

bea_Drive* const bea_FRI::m_drive_p [private]
string bea_FRI::m_extension [private]

Definition at line 75 of file bea_fri.h.

Referenced by CreateFRI(), and ReadFRI().

Position of the FRI on medium after the file mark.

Definition at line 78 of file bea_fri.h.

Referenced by CloseVolume(), DeleteFRIOnVolume(), GetFRIStartPosition(), and PositionToStartOfFRI().

bool bea_FRI::m_recreateInto [private]

Definition at line 74 of file bea_fri.h.

Referenced by CreateFRI(), and ReadFRI().

Definition at line 70 of file bea_fri.h.

Referenced by bea_FRI(), and CloseVolume().

bea_Volume* const bea_FRI::m_volume_p [private]
const cmn_Path& bea_FRI::m_workDir [private]

The documentation for this class was generated from the following files: