Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes

bea_MigrationThread Class Reference
[IVD Back-End Agent]

#include <bea_migration.h>

Inheritance diagram for bea_MigrationThread:
Inheritance graph
[legend]
Collaboration diagram for bea_MigrationThread:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 bea_MigrationThread (i_BackEndAgent_i &a_bea, bea_Drive *const a_drive_p)

Protected Member Functions

virtual ~bea_MigrationThread ()

Private Member Functions

virtual void Run (void *arg)
void Migrate ()
bool WriteBlock (df_FRI &a_fri, UInt8_t *a_blkBuf)
void SendToFSC (const vector< df_SplitInfo > &a_splits)
UInt8_tFRIVolumeStart (df_FRI &a_fri)
void FRIVolumeEnd (df_FRI &a_fri, UInt32_t a_status)
void ExchangeResources ()
void PrepareVolume ()
void CheckFRI ()

Private Attributes

 log_CLASSID_m
i_BackEndAgent_im_bea
bea_Drivem_drive_p
i_FSC_var m_fsc
bea_Volumem_vol_p
UInt32_t m_mediumPos
UInt64_t m_dataAmount
i_CompletionStatus_e m_status
vector< UInt64_tm_minColIds

Detailed Description

Definition at line 47 of file bea_migration.h.


Constructor & Destructor Documentation

bea_MigrationThread::bea_MigrationThread ( i_BackEndAgent_i a_bea,
bea_Drive *const   a_drive_p 
)

Definition at line 50 of file bea_migration.cpp.

References i_BackEndAgent_i::GetJob(), cmn_ThreadCounter::Inc(), ipc_EXEC_m, log_FUNC_m, m_bea, m_fsc, and i_BackEndAgent_i::m_threadCounter.

  : m_bea(a_bea),
    m_drive_p(a_drive_p),
    m_vol_p(NULL),
    m_mediumPos(0),
    m_dataAmount(0),
    m_status(i_UNKNOWN) {

    log_FUNC_m(bea_MigrationThread);

    ipc_EXEC_m(
        m_fsc = i_FSC::_duplicate(m_bea.GetJob()->GetFSC());
    );

    m_bea.m_threadCounter.Inc();
}

Here is the call graph for this function:

bea_MigrationThread::~bea_MigrationThread (  )  [protected, virtual]

Definition at line 72 of file bea_migration.cpp.

References bea_Drive::Close(), dbg_LOW, cmn_ThreadCounter::Dec(), i_BackEndAgent_i::GetBEANumber(), i_BackEndAgent_i::GetJob(), ipc_EXEC_m, i_BackEndAgent_i::IsAborted(), log_DBG_m, log_FUNC_m, m_bea, m_drive_p, m_status, i_BackEndAgent_i::m_threadCounter, and NULL.

                                          {

    log_FUNC_m(~bea_MigrationThread);

    // Close the device before contacting job
    if (m_drive_p != NULL) {
        m_drive_p->Close();
    }

    // Complete job
    try {
        if (m_bea.IsAborted()) {
            log_DBG_m(dbg_LOW, "Migration aborted. Won't contact job.");
        }
        else {
            ipc_EXEC_m(
                if( !CORBA::is_nil(m_bea.GetJob()) ) {
                    log_DBG_m(dbg_LOW, "Completion status: " << m_status);
                    i_Job_var job = m_bea.GetJob();
                    job->MediumOperationComplete(m_bea.GetBEANumber(), m_status);
                };
            );
        }
    }
    catch(...) {
        // Ignore all exceptions at this point.
    }

    m_bea.m_threadCounter.Dec();
}

Here is the call graph for this function:


Member Function Documentation

void bea_MigrationThread::CheckFRI (  )  [private]

Definition at line 665 of file bea_migration.cpp.

References bea_FRI::CloseVolumeInRMDB(), dbg_DETAIL, dbg_LOW, dbg_NORM, cmn_Global::dirs, evt_WARNING, ExchangeResources(), ivd_Directories::fri, g_cmn, bea_Medium::GetBarcode(), ivd_BaseException::GetFriendly(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), bea_Volume::GetStartOfDataPosition(), bea_Volume::GetVolumeID(), bea_Volume::GetVolumeNumber(), log_DBG_m, log_FUNC_m, log_WriteEvent(), m_bea, m_drive_p, m_mediumPos, m_vol_p, bea_FRI::PositionToStartOfFRI(), PrepareVolume(), and cmn_UUID_t::ToString().

Referenced by Migrate().

                                  {
    log_FUNC_m(CheckFRI);

    bool volumeFound(false);
    while (!volumeFound){

        // Check the position on the volume and the size of the FRI file.

        UInt32_t eodPos(m_mediumPos);
        UInt64_t friSize(0);
        try {
            cmn_File friFile(g_cmn.dirs.fri + m_vol_p->GetVolumeID().ToString());
            ivd_FileInfo_t info;
            friFile.StatF(info);
            friSize = info.size;
            log_DBG_m(dbg_LOW, "FRI found on disk: " << friFile.GetFullPathRef());
        }
        catch (const ivd_Exception& ie) {
            log_DBG_m(dbg_DETAIL, "Can't get FRI size. " << ie.GetFriendly());
        }

        ostringstream sstr;
        if (eodPos > m_vol_p->GetStartOfDataPosition()) {
            // Some data was already migrated.
            log_DBG_m(dbg_DETAIL, "Some data was already migrated.");

            if (friSize == 0) {
                // bug 8338
                log_DBG_m(dbg_NORM, "friSize == 0");

                //check if FRI is on medium
                //this can happen after restore from backup

                bea_FRI fri(m_bea, m_vol_p, g_cmn.dirs.fri);
                bool friOnMedium(false);
                friOnMedium = fri.PositionToStartOfFRI();

                if (friOnMedium){
                    sstr
                        << "Vol " << m_vol_p->GetVolumeNumber()
                        << ": Volume contains data and FRI. "
                        << "Will close volume and request new for migration.";

                    log_WriteEvent(
                        evt_WARNING, sstr.str(), "",
                        m_bea.GetJobID(), m_drive_p->GetMedium()->GetBarcode());

                    //close volume
                    fri.CloseVolumeInRMDB();

                    //
                    ExchangeResources();
                    PrepareVolume();
                } else {
                    //looks like there is only data, but no FRI
                    sstr
                        << "Vol " << m_vol_p->GetVolumeNumber()
                        << ": Volume contains data, but there is no FRI on the disk. "
                        << "Recreate FRI for this medium volume.";

                    log_WriteEvent(
                        evt_WARNING, sstr.str(), "",
                        m_bea.GetJobID(), m_drive_p->GetMedium()->GetBarcode());
                    volumeFound = true;
                }
            } else {
                volumeFound = true;
                log_DBG_m(dbg_NORM, "friSize:" << friSize);
            }
        } else if (friSize > 0) {
            // Volume is empty.
            sstr
                << "Vol " << m_vol_p->GetVolumeNumber()
                << ": Volume is empty, but there is FRI on the disk. "
                << "Recreate FRI for this medium volume.";

            log_WriteEvent(
                evt_WARNING, sstr.str(), "",
                m_bea.GetJobID(), m_drive_p->GetMedium()->GetBarcode());
            volumeFound = true;
        } else {
            //no data migrated and no FRI
            log_DBG_m(dbg_LOW, "No data migrated and no FRI.");
            volumeFound = true;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_MigrationThread::ExchangeResources (  )  [private]

Definition at line 512 of file bea_migration.cpp.

References dbg_NORM, i_BackEndAgent_i::GetDrive(), i_BackEndAgent_i::IsAborted(), log_DBG_m, log_FUNC_m, m_bea, m_drive_p, i_BackEndAgent_i::RequestNewResources(), and i_BackEndAgent_i::WaitForResources().

Referenced by CheckFRI(), and Migrate().

                                            {
    log_FUNC_m(ExchangeResources);

    m_bea.RequestNewResources();
    m_bea.WaitForResources();

    if (m_bea.IsAborted()) {
        log_DBG_m(dbg_NORM, "Aborted while requesting for resources.");
        return;
    }

    // m_drive was reopened. Re-read the drive & medium.
    m_drive_p = m_bea.GetDrive();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_MigrationThread::FRIVolumeEnd ( df_FRI a_fri,
UInt32_t  a_status 
) [private]

Definition at line 491 of file bea_migration.cpp.

References dbg_LOW, dbg_NORM, bea_Volume::GetEstimRemainingSize(), bea_Volume::GetPosition(), bea_Volume::GetVolumeID(), log_DBG_m, log_FUNC_m, m_vol_p, and df_FRI::MediumVolumeEnd().

Referenced by Migrate().

                                                                       {
    log_FUNC_m(FRIVolumeEnd);

    UInt32_t endPos = m_vol_p->GetPosition();

    log_DBG_m(dbg_LOW,
        "Finishing FRI for this medium volume." <<
        "End Pos: " << endPos << "  Remaining Capacity: " <<
        m_vol_p->GetEstimRemainingSize() << " MB");

    log_DBG_m(dbg_NORM,
        "End FRI for volume: " << m_vol_p->GetVolumeID() <<
        ", endPos=" << endPos);

    a_fri.MediumVolumeEnd(a_status);
}

Here is the call graph for this function:

Here is the caller graph for this function:

UInt8_t * bea_MigrationThread::FRIVolumeStart ( df_FRI a_fri  )  [private]

Definition at line 459 of file bea_migration.cpp.

References dbg_LOW, dbg_NORM, i_BackEndAgent_i::GetBEANumber(), bea_Volume::GetEstimRemainingSize(), i_BackEndAgent_i::GetMediumKey(), i_BackEndAgent_i::GetMigrationID(), bea_Volume::GetPosition(), bea_Volume::GetVolumeID(), bea_Volume::GetVolumeNumber(), ie_FATAL_ERROR, cmn_UUID_t::IsNull(), log_DBG_m, log_FUNC_m, m_bea, m_fsc, m_vol_p, and df_FRI::MediumVolumeStart().

Referenced by Migrate().

                                                          {
    log_FUNC_m(FRIVolumeStart);

    if (m_vol_p->GetVolumeID().IsNull()) {
        log_MARKLINE_m;
        throw ivd_InternalError(ie_FATAL_ERROR, "IDs not set for the migration.");
    }

    UInt32_t    startPos = m_vol_p->GetPosition();

    log_DBG_m(dbg_LOW,
        "Start Pos: " << startPos <<
        "  Remaining Capacity: " <<
        m_vol_p->GetEstimRemainingSize() << " MB");

    log_DBG_m(dbg_NORM,
        "Start FRI for volume: " << m_vol_p->GetVolumeID() <<
        ", startPos=" << startPos);

    return a_fri.MediumVolumeStart(
        m_vol_p->GetVolumeID(),
        startPos,
        m_bea.GetMigrationID(),
        m_bea.GetBEANumber(),
        m_bea.GetMediumKey(),
        m_vol_p->GetVolumeNumber(),
        m_fsc );

}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_MigrationThread::Migrate (  )  [private]

Definition at line 172 of file bea_migration.cpp.

References bea_OPWRITE, CheckFRI(), bea_FRI::CloseVolume(), bea_FRI::CloseVolumeInRMDB(), cmn_Num2Str(), dbg_DETAIL, dbg_LOW, dbg_NORM, df_DISKBUF_BLOCKS_c, df_FRIS_ABORTED, df_FRIS_COMPLETE, cmn_Global::dirs, evt_WARNING, ExchangeResources(), bea_Volume::Flush(), ivd_Directories::fri, FRIVolumeEnd(), FRIVolumeStart(), g_cmn, bea_Medium::GetBarcode(), i_BackEndAgent_i::GetBarcode(), bea_Volume::GetBlockSize(), i_BackEndAgent_i::GetBufferID(), df_DataBlock::GetData(), i_BackEndAgent_i::GetDiskBufferFS(), ivd_BaseException::GetError(), df_MgrReader::GetFull(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), bea_Volume::GetPartitionID(), bea_Volume::GetPoolID(), bea_Volume::GetPosition(), bea_Volume::GetVolumeNumber(), ie_DATA_CORRUPTION, ie_MEDIUM_EOM, ie_MEDIUM_OVERFLOW, i_BackEndAgent_i::IsAborted(), df_DataBlock::IsEmpty(), ivd_Error, log_DBG_m, log_FUNC_m, log_WriteEvent(), i_BackEndAgent_i::LogStats(), m_bea, m_dataAmount, m_drive_p, m_mediumPos, m_status, m_vol_p, bea_Volume::MustDumpFRI(), NULL, PrepareVolume(), df_MgrReader::Release(), cmn_Thread::Start(), i_BackEndAgent_i::WaitForResources(), and WriteBlock().

Referenced by Run().

                                  {
    log_FUNC_m(Migrate);

    log_DBG_m(dbg_LOW, "Starting migration. Job ID: " << m_bea.GetJobID());

    m_bea.WaitForResources();

    if (m_bea.IsAborted()) {
        log_DBG_m(dbg_LOW, "Job aborted (1). Exit.");
        return;
    };

    PrepareVolume();
    CheckFRI();
    cmn_Time startTime;

    bool        newVolume(true);       // has to do FRIVolumeStart
    UInt32_t    numBlkToCapChk(0);     // imediately perform capacity check

    df_BlockManager mgr(m_vol_p->GetBlockSize(), df_DISKBUF_BLOCKS_c);

    //
    // TODO: Replace df_FRI with df_FRIDistiller.
    //
    df_FRI fri(
        m_vol_p->GetPartitionID(),
        m_vol_p->GetPoolID(),
        m_vol_p->GetBlockSize() );

    {
        df_MgrReader reader(mgr);

        // Only disk buffer is used currently
        // Improve if new will be introduced.
        blk_DiskBufferReader *db_p =
            new blk_DiskBufferReader(mgr, m_bea.GetDiskBufferFS(), cmn_Num2Str(m_bea.GetBufferID()) );

        db_p->Start();

        df_DataBlock *blk = NULL;
        while ( (blk = reader.GetFull()) != NULL && !m_bea.IsAborted()) {
            if (!blk->IsEmpty()) {

                while (numBlkToCapChk == 0) {

                    if (m_vol_p->MustDumpFRI(&numBlkToCapChk)) {
                        cmn_Time endTime;
                        cmn_Time diffTime = endTime - startTime;
                        m_bea.LogStats(diffTime, m_dataAmount, bea_OPWRITE);

                        if (!newVolume) {
                            // we have written some block to volume - end FRI
                            FRIVolumeEnd(fri, df_FRIS_COMPLETE);
                        }

                        bea_FRI bfri(m_bea, m_vol_p, g_cmn.dirs.fri);
                        bfri.CloseVolume();

                        ExchangeResources();
                        PrepareVolume();

                        m_dataAmount = 0;
                        newVolume = true;
                        numBlkToCapChk = 0;
                        startTime.Refresh();
                        if (m_bea.IsAborted()) {
                            log_DBG_m(dbg_LOW,
                                "Job aborted (3). Stop writing to tape.");
                            break;
                        }
                    }
                }

                if (newVolume) {
                    auto_ptr<UInt8_t> contBlk_ap;
                    contBlk_ap.reset(FRIVolumeStart(fri));

                    if (contBlk_ap.get() != NULL) {
                        log_DBG_m(dbg_DETAIL, "Parse & write cont block...");
                        if (WriteBlock(fri, contBlk_ap.get())) {
                            // TODO: EOM - what to do??
                        }
                        numBlkToCapChk--;
                    }
                    newVolume = false;
                }

                bool reachedEOM(false);
                try {
                    // write actual block to tape
                    reachedEOM = WriteBlock(fri, blk->GetData());
                }
                catch (const ivd_Error &ie) {
                    switch (ie.GetError()) {
                        case ie_MEDIUM_EOM:
                            reachedEOM = true;
                        break;
                        case ie_MEDIUM_OVERFLOW:
                        {
                            bea_FRI fri(m_bea, m_vol_p, g_cmn.dirs.fri);
                            fri.CloseVolumeInRMDB();
                            ostringstream sstr;
                            sstr
                                << "Vol " << m_vol_p->GetVolumeNumber() << ": "
                                << "Overflow detected. Volume closed in RMDB.";

                            log_WriteEvent(evt_WARNING, sstr.str(), "FRI",
                                m_bea.GetJobID(), m_bea.GetBarcode() );
                        }
                        // fall through
                        default:
                            throw;
                    }
                }

                if (reachedEOM) {
                    cmn_Time endTime;
                    cmn_Time diffTime = endTime - startTime;
                    m_bea.LogStats(diffTime, m_dataAmount, bea_OPWRITE);

                    if (!newVolume) {
                        // we have written some block to volume - end FRI
                        FRIVolumeEnd(fri, df_FRIS_COMPLETE);
                    }

                    bea_FRI fri(m_bea, m_vol_p, g_cmn.dirs.fri);
                    fri.CloseVolume();

                    ExchangeResources();
                    PrepareVolume();
                    m_dataAmount = 0;
                    newVolume = true;
                    numBlkToCapChk = 0;
                    startTime.Refresh();
                }
                else {
                    numBlkToCapChk--;
                };

                if (m_bea.IsAborted()) {
                    log_DBG_m(dbg_LOW, "Job aborted. Stop writing to tape.");
                }
            }
            reader.Release();
        }
    }

    log_DBG_m(dbg_NORM, "End of data.");

    if (!newVolume) {
        if (m_bea.IsAborted()) {
            FRIVolumeEnd(fri, df_FRIS_ABORTED);
        }
        else {
            FRIVolumeEnd(fri, df_FRIS_COMPLETE);
        }
    }

    m_vol_p->Flush();

    // verify medium position
    UInt32_t actualMediumPos(m_vol_p->GetPosition());
    if (m_mediumPos != actualMediumPos) {
        log_MARKLINE_m;
        ostringstream sstr;
        sstr
            << "Counted medium position (" << m_mediumPos << ")"
            << " is different from actual (" << actualMediumPos << "). "
            << "Job: " << m_bea.GetJobID() << " "
            << "Medium/volume: "
            << m_drive_p->GetMedium()->GetBarcode() << "/"
            << m_vol_p->GetVolumeNumber();

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

    m_status = i_SUCCEDED;

    cmn_Time endTime;
    cmn_Time diffTime = endTime - startTime;
    m_bea.LogStats(diffTime, m_dataAmount, bea_OPWRITE);

    log_DBG_m(dbg_LOW, "Migration complete. Job ID: " << m_bea.GetJobID());
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_MigrationThread::PrepareVolume (  )  [private]

Definition at line 529 of file bea_migration.cpp.

References cfg_MEGABYTE, bea_Medium::ChangeVolume(), dbg_DETAIL, dbg_LOW, evt_WARNING, bea_Medium::GetBarcode(), i_BackEndAgent_i::GetBarcode(), bea_Volume::GetBlockSize(), bea_Medium::GetCurrentVolume(), bea_Medium::GetCurVolNumber(), ivd_BaseException::GetError(), i_BackEndAgent_i::GetJobType(), bea_Drive::GetMedium(), i_BackEndAgent_i::GetMedVolBlockSize(), i_BackEndAgent_i::GetMedVolID(), i_BackEndAgent_i::GetMedVolNumber(), i_BackEndAgent_i::GetPartitionID(), i_BackEndAgent_i::GetPoolID(), bea_Volume::GetPosition(), i_BackEndAgent_i::GetRM(), bea_Medium::GetVolume(), bea_Volume::GetVolumeID(), bea_Volume::GetVolumeNumber(), ie_FATAL_ERROR, ie_MEDIUM_MEDERR, bea_Medium::IsMediumMemValid(), ivd_Error, log_DBG_m, log_FUNC_m, log_WriteEvent(), m_bea, m_drive_p, m_mediumPos, m_vol_p, i_BackEndAgent_i::MustVerifyHeader(), NULL, bea_Volume::OverrideIDs(), i_BackEndAgent_i::ReadIDs(), bea_Volume::SeekEOD(), bea_Volume::SetBlockSize(), cmn_UUID_t::ToString(), i_BackEndAgent_i::VerifyIDs(), and bea_Drive::WasMediumChanged().

Referenced by CheckFRI(), and Migrate().

                                        {
    log_FUNC_m(PrepareVolume);

    bea_Medium* med = m_drive_p->GetMedium();

    if (med == NULL) {
        log_MARKLINE_m;
        throw ivd_InternalError(
            ie_FATAL_ERROR, "Medium not available after exchanging resources");
    }

    if (m_bea.GetJobType() != jt_MIGRATION) {
        // IDs for migration jobs already checked.
        // Check for other jobs (reorg) as well.

        if (med->IsMediumMemValid()) {
            //First try to verify IDs from MAM/MIC
            //If it fails, check what is specified in trace.cfg
            //for checking IDs in medium header
            log_DBG_m(dbg_DETAIL, "Medium memory is detected and it and it contains valid cookies.");
            m_bea.ReadIDs(m_bea.GetMedVolNumber(), false);

            try {
                m_bea.VerifyIDs(
                    m_bea.GetBarcode(),
                    m_bea.GetMedVolNumber(),
                    m_bea.GetMedVolBlockSize(),
                    cmn_UUID_t(m_bea.GetMedVolID()),
                    cmn_UUID_t(m_bea.GetPoolID()) );
                }
            catch (const ivd_Error) {
                log_DBG_m(dbg_LOW,
                    "Error verifying IDs in medium memory. Check if it is needed to read from header.");
                if (m_drive_p->WasMediumChanged() || m_bea.MustVerifyHeader()){
                    try{
                        m_bea.ReadIDs(m_bea.GetMedVolNumber(), true);
                        m_bea.VerifyIDs(
                            m_bea.GetBarcode(),
                            m_bea.GetMedVolNumber(),
                            m_bea.GetMedVolBlockSize(),
                            cmn_UUID_t(m_bea.GetMedVolID()),
                            cmn_UUID_t(m_bea.GetPoolID()) );
                    }
                    catch (const ivd_Error& e) {
                        if (e.GetError() == ie_BEA_INVVOLID){
                            //If header is not correct, medium error is returned,
                            //Handle error will set medium to unreliable
                            throw ivd_Error(ie_MEDIUM_MEDERR, "Marking medium as unreliable. Header is not correct!", true);
                        }
                        else throw;
                    }
                }
                else{
                    log_DBG_m(dbg_LOW, "Header won't be read and verified.");
                    string mediumBarcode = m_bea.GetBarcode();
                    ostringstream eventText;
                    eventText << "Reading from MAM/MIC has failed and header for media " << mediumBarcode;
                    eventText << " is not verified" << endl;
                    eventText << "Check in trace.cfg if HSM_BEA_VERIFY_HEADER is set to yes";
                    log_WriteEvent(evt_WARNING, eventText.str());
                }
            }
        }
        else {
            log_DBG_m(dbg_DETAIL, "Medium memory is not detected or does not contain valid cookies.");
            if (m_bea.MustVerifyHeader() || m_drive_p->WasMediumChanged()) {
                // Check medium IDs for migration.
                // Writing part of reorg checks before writing
                log_DBG_m(dbg_DETAIL, "Header will be read and verified.");
                try{
                    m_bea.ReadIDs(m_bea.GetMedVolNumber(), true);
                    m_bea.VerifyIDs(
                        m_bea.GetBarcode(),
                        m_bea.GetMedVolNumber(),
                        m_bea.GetMedVolBlockSize(),
                        cmn_UUID_t(m_bea.GetMedVolID()),
                        cmn_UUID_t(m_bea.GetPoolID()) );
                }
                catch (const ivd_Error& e) {
                    if (e.GetError() == ie_BEA_INVVOLID){
                        //If header is not correct, medium error is returned,
                        //Handle error will set medium to unreliable
                        throw ivd_Error(ie_MEDIUM_MEDERR, "Marking medium as unreliable. Header is not correct!", true);
                    }
                    else throw;
                }
            }
            else {
                log_DBG_m(dbg_LOW, "Header won't be read and verified.");
                string mediumBarcode = m_bea.GetBarcode();
                ostringstream eventText;
                eventText << "Reading from MAM/MIC has failed and header for media " << mediumBarcode;
                eventText << " is not verified" << endl;
                eventText << "Check in trace.cfg if HSM_BEA_VERIFY_HEADER is set to yes";
                log_WriteEvent(evt_WARNING, eventText.str());
            }
        }
    }

    if (!med->IsMediumMemValid() && !m_bea.MustVerifyHeader()) {
        // IDs were not read from medium header.
        // IDs received from the job are set.
        bea_Volume* vol_p = med->GetVolume(m_bea.GetMedVolNumber());
        vol_p->SetBlockSize(m_bea.GetMedVolBlockSize());

        cmn_UUID_t poolID(m_bea.GetPoolID());
        vol_p->OverrideIDs(m_bea.GetMedVolID(), poolID, m_bea.GetPartitionID());
    }

    if (m_bea.GetMedVolNumber() != med->GetCurVolNumber()) {
        med->ChangeVolume(m_bea.GetMedVolNumber());
    }

    m_vol_p = med->GetCurrentVolume();
    m_vol_p->SeekEOD();

    m_mediumPos = m_vol_p->GetPosition();

    i_ResourceManager_var rm = m_bea.GetRM();
    i_MediumVol_t_var rmvol = rm->SelectMediumVol(
        CORBA::string_dup(med->GetBarcode().c_str()),
        m_vol_p->GetVolumeNumber());

    if (rmvol->volUsed == 0) {
        UInt32_t percent(1);
        UInt64_t totalData = (UInt64_t(m_mediumPos) * m_vol_p->GetBlockSize()) / cfg_MEGABYTE;

        rm->VolumeUsage(
            CORBA::string_dup(m_vol_p->GetVolumeID().ToString().c_str()),
            percent,
            static_cast<i_VolSize_t>(totalData) );

        log_DBG_m(dbg_LOW, "Volume used is set to " << percent << "%");
    } // if (rmvol->volUsed == 0)
} //preparevolume

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_MigrationThread::Run ( void *  arg  )  [private, virtual]

Reimplemented from cmn_Thread.

Definition at line 105 of file bea_migration.cpp.

References bea_OPWRITE, dbg_LOW, dbg_NORM, evt_ERROR, i_BackEndAgent_i::GetBarcode(), i_BackEndAgent_i::GetJobID(), i_BackEndAgent_i::HandleError(), i_HW_ERROR, i_MEDIUM_ERROR, i_SUCCEDED, i_UNKNOWN, i_BackEndAgent_i::IsAborted(), log_DBG_m, log_ERR_m, log_FUNC_m, log_WriteEvent(), m_bea, m_status, Migrate(), i_BackEndAgent_i::ReleaseResources(), and i_BackEndAgent_i::UpdateVolumeUsed().

                                       {
    log_FUNC_m(Run);

    try {
        Migrate();
        m_status = i_SUCCEDED;
    }
    catch(const ivd_DFError &dfe) {
        log_WriteEvent(evt_ERROR, "Migration failed. Data format error.", "",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        log_ERR_m("Data format error on migration: " << dfe);

        m_status = i_DATA_ERROR;
    }
    catch(const ivd_Error& ie) {
        i_CompletionStatus_e status = m_bea.HandleError(ie, bea_OPWRITE);

        if (m_status == i_UNKNOWN || m_status == i_SUCCEDED) {
            m_status = status;
        }
    }
    catch(const std::exception& ie) {
        if (m_bea.IsAborted()) {
            log_DBG_m(dbg_LOW,
                "Migration aborted. Received exception: " << ie.what() );
        }
        else {
            ostringstream sstr;
            sstr << "Migration failed: " << ie.what();

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

        if (m_status == i_SUCCEDED) {
            m_status = i_UNKNOWN;
        }
    }
    catch(...) {
        log_WriteEvent(evt_ERROR, "Migration failed. Unknown error.", "",
            m_bea.GetJobID(), m_bea.GetBarcode() );

        if (m_status == i_SUCCEDED) {
            m_status = i_UNKNOWN;
        }
    }

    if (m_status != i_MEDIUM_ERROR && m_status != i_HW_ERROR) {
        // Update volume usage in RMDB
        m_bea.UpdateVolumeUsed();
    }
    else {
        log_DBG_m(dbg_NORM,
            "Won't update VolumeUsed in RM because of medium or hardware error.");
    }

    try {
        m_bea.ReleaseResources();
    }
    catch (...) {
        // Ignore everything
    }
}

Here is the call graph for this function:

void bea_MigrationThread::SendToFSC ( const vector< df_SplitInfo > &  a_splits  )  [private]
bool bea_MigrationThread::WriteBlock ( df_FRI a_fri,
UInt8_t a_blkBuf 
) [private]

Definition at line 359 of file bea_migration.cpp.

References df_FRI::BlockScan(), df_FRI::BlockWritten(), dbg_DETAIL, dbg_LOW, bea_Medium::GetBarcode(), bea_Volume::GetBlockSize(), ivd_BaseException::GetError(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), bea_Volume::GetMedium(), bea_Volume::GetPosition(), bea_Volume::GetVolumeNumber(), ie_DATA_CORRUPTION, ivd_Error, log_DBG_m, log_ERR_m, log_FUNC_m, m_bea, m_dataAmount, m_drive_p, m_mediumPos, m_status, m_vol_p, i_BackEndAgent_i::MustReadPosition(), and bea_Volume::Write().

Referenced by Migrate().

                                                                     {
    log_FUNC_m(WriteBlock);

    bool medVolFull = false;

    log_DBG_m(dbg_DETAIL, "Parse block & update fields...");
    try {
        a_fri.BlockScan(a_blkBuf);
    }
    catch (...) {
        // Any error in Block Scan means disk buffer error;
        log_DBG_m(dbg_LOW, "*** Input disk buffer is not OK. ****");
        m_status = i_DATA_ERROR;
        throw;
    };

    if (m_bea.MustReadPosition(m_vol_p->GetMedium())) {
        UInt32_t mediumPos = m_vol_p->GetPosition();

        if (mediumPos == m_mediumPos) {
            // Position is OK.
        }
        else {
            ostringstream sstr;

            // Verify medium position to detect any unexpected change
            // of position which may result in data loss.
            if (mediumPos > m_mediumPos) {
                log_ERR_m(
                        "Medium position (" << mediumPos << ")"
                    << " is larger than expected (" << m_mediumPos << "). "
                    << "Job: " << m_bea.GetJobID() << " "
                    << "Medium/volume: "
                    << m_drive_p->GetMedium()->GetBarcode() << "/"
                    << m_vol_p->GetVolumeNumber() );

                sstr << "Medium position larger than expected. See error.log.";
            }
            else if (mediumPos < m_mediumPos) {
                log_ERR_m(
                        "Medium position (" << mediumPos << ")"
                    << " is smaller than expected (" << m_mediumPos << "). "
                    << "Job: " << m_bea.GetJobID() << " "
                    << "Medium/volume: "
                    << m_drive_p->GetMedium()->GetBarcode() << "/"
                    << m_vol_p->GetVolumeNumber() );

                if (mediumPos > 0) {
                    sstr
                        << "Data loss detected. Medium was overwritten. See error.log."
                        << "Medium/volume: "
                        << m_drive_p->GetMedium()->GetBarcode() << "/"
                        << m_vol_p->GetVolumeNumber();
                }
                else {
                    sstr
                        << "Medium position changed to 0. Aborting. See error.log."
                        << "Medium/volume: "
                        << m_drive_p->GetMedium()->GetBarcode() << "/"
                        << m_vol_p->GetVolumeNumber();
                }
            }
            // Position doesn't match. Throw exception.
            throw ivd_Error(ie_DATA_CORRUPTION, sstr.str(), true);
        }
    }

    // Prevent invalid entries from being written to FRI/FSC
    if (m_mediumPos < m_vol_p->GetStartOfDataPosition()) {
        ostringstream sstr;
        sstr << "m_mediumPos = " << m_mediumPos << ", but should be >= 3";
        throw ivd_InternalError(ie_DATA_CORRUPTION, sstr.str());
    }

    log_DBG_m(dbg_DETAIL, "Writing block to medium on position: " << m_mediumPos);
    try {
        m_vol_p->Write(a_blkBuf);
    }
    catch (ivd_Error &ie) {
        if (ie.GetError() == ie_MEDIUM_EOM) {
            log_DBG_m(dbg_LOW, "End of media detected. Will append FRI.");
            medVolFull = true;
        }
        else {
            throw;
        }
    }
    m_dataAmount += m_vol_p->GetBlockSize();

    log_DBG_m(dbg_DETAIL, "Block written. Append to FRI...");

    a_fri.BlockWritten(m_mediumPos);

    // Update member to next expected medium position.
    ++m_mediumPos;

    return medVolFull;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Reimplemented from cmn_Thread.

Definition at line 58 of file bea_migration.h.

Definition at line 77 of file bea_migration.h.

Referenced by Migrate(), and WriteBlock().

i_FSC_var bea_MigrationThread::m_fsc [private]

Definition at line 73 of file bea_migration.h.

Referenced by bea_MigrationThread(), and FRIVolumeStart().

Definition at line 76 of file bea_migration.h.

Referenced by CheckFRI(), Migrate(), PrepareVolume(), and WriteBlock().

Definition at line 81 of file bea_migration.h.

Definition at line 79 of file bea_migration.h.

Referenced by Migrate(), Run(), WriteBlock(), and ~bea_MigrationThread().


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