Public Member Functions | Private Member Functions | Private Attributes

bea_DupWriteThread Class Reference
[IVD Back-End Agent]

#include <bea_mediumdup.h>

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

List of all members.

Public Member Functions

 bea_DupWriteThread (i_BackEndAgent_i &a_bea, bea_Drive *const a_drive_p, UInt32_t a_volSize, bool a_appendVol, bool a_srcMediumFull)
virtual ~bea_DupWriteThread ()
virtual void Run (void *arg)

Private Member Functions

void WriteMedVolume ()
void AppendVolume ()

Private Attributes

 log_CLASSID_m
i_BackEndAgent_im_bea
bea_Drive *const m_drive_p
UInt32_t m_volSize
bool m_appendVol
bool m_srcMediumFull
UInt32_t m_volChunks
i_CompletionStatus_e m_status

Detailed Description

Definition at line 73 of file bea_mediumdup.h.


Constructor & Destructor Documentation

bea_DupWriteThread::bea_DupWriteThread ( i_BackEndAgent_i a_bea,
bea_Drive *const   a_drive_p,
UInt32_t  a_volSize,
bool  a_appendVol,
bool  a_srcMediumFull 
)

Definition at line 300 of file bea_mediumdup.cpp.

References cmn_ThreadCounter::Inc(), log_FUNC_A_m, m_bea, and i_BackEndAgent_i::m_threadCounter.

  : m_bea(a_bea),
    m_drive_p(a_drive_p),
    m_volSize(a_volSize),
    m_appendVol(a_appendVol),
    m_srcMediumFull(a_srcMediumFull),
    m_volChunks(0),
    m_status(i_UNKNOWN) {

    log_FUNC_A_m(
        bea_DupWriteThread,
        " size: " << a_volSize <<
        " append: " << (a_appendVol? "YES" : "NO") );

    m_bea.m_threadCounter.Inc();
}

Here is the call graph for this function:

bea_DupWriteThread::~bea_DupWriteThread (  )  [virtual]

Definition at line 324 of file bea_mediumdup.cpp.

References 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_status, i_BackEndAgent_i::m_threadCounter, and i_BackEndAgent_i::ReleaseResources().

                                        {

    log_FUNC_m(~bea_MediumDupThread);

    try {
        m_bea.ReleaseResources();
    }
    catch (...) {
        // Ignore all exceptions at this point
    }

    try {
        if (m_bea.IsAborted()) {
            log_DBG_m(dbg_LOW, "Duplication 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_DupWriteThread::AppendVolume (  )  [private]

Definition at line 519 of file bea_mediumdup.cpp.

References bea_Medium::AppendVolume(), dbg_LOW, dbg_NORM, evt_ERROR, evt_WARNING, i_BackEndAgent_i::GetBarcode(), bea_Medium::GetBarcode(), bea_Medium::GetCurrentVolume(), bea_Volume::GetEstimRemainingSize(), bea_Volume::GetEstimTotalSize(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), i_BackEndAgent_i::GetMedVolType(), i_BackEndAgent_i::GetRM(), bea_Volume::GetSize(), log_DBG_m, log_ERR_m, log_FUNC_m, log_WriteEvent(), m_bea, m_drive_p, m_srcMediumFull, m_volChunks, m_volSize, rmdb_MEDIUM_FULL, and rmdb_SYSTEM_VOLUME.

Referenced by Run().

                                      {
    log_FUNC_m(AppendVolume);

    bea_Medium* med = m_drive_p->GetMedium();
    bea_Volume *const vol = med->GetCurrentVolume();

    UInt32_t appendSize(0);

    if ( ( m_bea.GetMedVolType() == rmdb_SYSTEM_VOLUME  && !m_srcMediumFull )
        || m_volChunks < 3) {
        // Create target volume of approx the same size as the source
        // if the volume is not yet closed or it is a system volume 
        // on medium which is not full
        bool mediumFull(false);

        if (m_bea.GetMedVolType() == rmdb_SYSTEM_VOLUME) {

            try {
                i_ResourceManager_var rm = m_bea.GetRM();
                i_Medium_t_var rmMedium = rm->SelectMedium(CORBA::string_dup(med->GetBarcode().c_str()));

                if ((rmMedium->status & rmdb_MEDIUM_FULL) == rmdb_MEDIUM_FULL) {
                 mediumFull = true;
                 log_DBG_m(dbg_NORM, "Medium is full: append system volume  at the end of data (not configured size).");
                }
            }
            catch(...) {
                // Ignore all exceptions at this point.
                ostringstream sstr;
                sstr << "Cannot get medium status from RM";

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

        if (!mediumFull) {
            // Calculate compressed usage of the volume
            UInt32_t total = vol->GetEstimTotalSize();
            UInt32_t used = ( (total - vol->GetEstimRemainingSize()) * vol->GetSize())/total; // MB
    
            if (m_volSize > used) {
                // append size + used size = volume size in RMDB
                appendSize = m_volSize - used;
            }
            else {
                appendSize = 0;
                log_ERR_m(
                    "Duplication: " <<
                    "Volume size in RMDB is smaller than total data on volume. " << endl <<
                    "RMDB: " << m_volSize << ", compressed data: " << used);
    
                log_WriteEvent(evt_ERROR,
                    "Duplication detected volume size mismatch. See error.log for details", "",
                    m_bea.GetJobID(), m_bea.GetBarcode() );
    
            };
    
            log_DBG_m(dbg_NORM, endl <<
                "Source volume is not closed or is system volume." << endl <<
                "Estimated total : " << vol->GetEstimTotalSize() << endl <<
                "Estimated used  : " << (vol->GetEstimTotalSize() - vol->GetEstimRemainingSize()) << endl <<
                "Compressed used : " << used << endl <<
                "Append size     : " << appendSize << endl <<
                "New volume size : " << (appendSize+used) << endl <<
                "Src volume size : " << m_volSize);
        }
    }
    else {
        log_DBG_m(dbg_LOW,
            "Source volume is closed. Append volume at the end of data.");
    }

    log_DBG_m(dbg_LOW, "Appending volume: " << appendSize << " MB");

    med->AppendVolume(appendSize);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_DupWriteThread::Run ( void *  arg  )  [virtual]

Reimplemented from cmn_Thread.

Definition at line 358 of file bea_mediumdup.cpp.

References AppendVolume(), bea_OPWRITE, dbg_LOW, i_BackEndAgent_i::HandleError(), i_SUCCEDED, log_DBG_m, log_FUNC_m, m_appendVol, m_bea, m_status, and WriteMedVolume().

                                      {
    log_FUNC_m(Run);

    try {
        WriteMedVolume();
        if (m_appendVol) {
            AppendVolume();
        }
        m_status = i_SUCCEDED;
        log_DBG_m(dbg_LOW, "Completed duplication writing task.");
    }
    catch(ivd_Error &ie) {
        m_status = m_bea.HandleError(ie, bea_OPWRITE);
    }
    catch(...) {
        log_DBG_m(dbg_LOW, "Error while duplicating medium volume.");
        if (m_status == i_SUCCEDED) {
            m_status = i_UNKNOWN;
        }
    }
}

Here is the call graph for this function:

void bea_DupWriteThread::WriteMedVolume (  )  [private]

Definition at line 382 of file bea_mediumdup.cpp.

References bea_Medium::ChangeVolume(), cmn_File::CloseF(), dbg_LOW, dbg_NORM, cmn_File::DeleteF(), df_VOLHDR_REC_SIZE, cmn_Global::dirs, ivd_Directories::diskbuf, bea_Volume::Flush(), fom_READ, g_cmn, bea_Medium::GetCurrentVolume(), bea_Medium::GetCurVolNumber(), i_BackEndAgent_i::GetDiskBufferFS(), ivd_BaseException::GetError(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), i_BackEndAgent_i::GetMedVolBlockSize(), i_BackEndAgent_i::GetMedVolID(), i_BackEndAgent_i::GetMedVolNumber(), i_BackEndAgent_i::GetMedVolType(), ie_DATA_CORRUPTION, i_BackEndAgent_i::IsAborted(), ivd_Error, log_DBG_m, log_FUNC_m, m_bea, m_drive_p, m_volChunks, cmn_File::OpenF(), cmn_File::ReadF(), bea_Volume::Rewind(), bea_Volume::SetBlockSize(), i_BackEndAgent_i::WaitForResources(), bea_Volume::Write(), bea_Volume::WriteFileMarks(), and bea_Volume::WriteVolHdr().

Referenced by Run().

                                        {
    log_FUNC_m(WriteMedVolume);

    log_DBG_m(dbg_LOW,
        "Started writing medium volume. Job ID: " << m_bea.GetJobID());

    m_bea.WaitForResources();

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

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

    // Get names of files of volume chunks
    list<string> chunkNames;
    {
        cmn_DirLst chunkFiles(
            g_cmn.dirs.diskbuf + m_bea.GetDiskBufferFS(), "", m_bea.GetMedVolID() );

        string name;
        while ( (name = chunkFiles.GetNextName()) != "") {
            chunkNames.push_back(name);
        }
        chunkNames.sort();
    }

    m_volChunks = chunkNames.size();

    log_DBG_m(dbg_LOW, "Number of chunks to be written: " << m_volChunks);

    if (m_volChunks == 0) {
        log_DBG_m(dbg_LOW, "No volume chunks found.");
        return;
    }

    bea_Volume* const vol = m_drive_p->GetMedium()->GetCurrentVolume();
    vol->SetBlockSize(m_bea.GetMedVolBlockSize());
    vol->Rewind();

    // Iterate over the list of volume chunk names
    list<string>::const_iterator name_i;
    UInt32_t chunkNum(0);

    for (name_i = chunkNames.begin();
         name_i != chunkNames.end() && !m_bea.IsAborted();
         ++name_i) {

        cmn_Path chunkName = g_cmn.dirs.diskbuf + m_bea.GetDiskBufferFS()+ (*name_i);

        log_DBG_m(dbg_NORM, "Reading file " << chunkName);

        cmn_File copyFile(chunkName);
        copyFile.OpenF(fom_READ);

        UInt32_t bytes(0);
        if (chunkNum == 0) {
            log_DBG_m(dbg_NORM, "Writing volume header.");
            vector<UInt8_t> hdrBlock(df_VOLHDR_REC_SIZE, 0);

            bytes = copyFile.ReadF(&(hdrBlock[0]), df_VOLHDR_REC_SIZE);

            if (bytes == df_VOLHDR_REC_SIZE) {
                vol->WriteVolHdr(&(hdrBlock[0]));
            }
            else {
                log_MARKLINE_m;
                ostringstream sstr;
                sstr
                    << "Read " << bytes << "bytes but expecting "
                    << df_VOLHDR_REC_SIZE << " bytes. "
                    << "Possible disk buffer file system corruption.";

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

        do {
            UInt32_t blockSize(m_bea.GetMedVolBlockSize());
            vector<UInt8_t> block(blockSize, 0);

            bytes = copyFile.ReadF(&(block[0]), blockSize);

            if (bytes == blockSize) {
                try {
                    vol->Write(&(block[0]));
                }
                catch (ivd_Error &ie) {
                    if (ie.GetError() == ie_MEDIUM_EOM) {
                        log_DBG_m(dbg_NORM,
                            "Early EOM on Write - ignore for Duplication");
                    } else {
                        throw;
                    }
                }
            }
            else if (bytes != 0) {
                log_MARKLINE_m;
                ostringstream sstr;
                sstr
                    << "Read " << bytes << "bytes but expecting "
                    << blockSize << " bytes. "
                    << "Possible disk buffer file system corruption.";

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

        } while (bytes > 0 && !m_bea.IsAborted());

        if (   (chunkNum == 0)                                  // header
            || ((chunkNames.size() > 2) && (chunkNum == 1))     // between data and fri
            || (m_bea.GetMedVolType() == rmdb_SYSTEM_VOLUME)) {

            // Write file marks after header and after FRIs on system volume

            vol->WriteFileMarks(1);
        }

        copyFile.CloseF();
        copyFile.DeleteF();
        //cmn_File::DeleteFile(chunkName);
        chunkNum++;
    };

    vol->Flush();

    log_DBG_m(dbg_LOW, "Sucessfully completed writing medium volume.");
}

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 88 of file bea_mediumdup.h.

Definition at line 96 of file bea_mediumdup.h.

Referenced by Run().

Definition at line 94 of file bea_mediumdup.h.

Referenced by AppendVolume(), and WriteMedVolume().

Definition at line 97 of file bea_mediumdup.h.

Referenced by AppendVolume().

Definition at line 100 of file bea_mediumdup.h.

Referenced by Run(), and ~bea_DupWriteThread().

Definition at line 98 of file bea_mediumdup.h.

Referenced by AppendVolume(), and WriteMedVolume().

Definition at line 95 of file bea_mediumdup.h.

Referenced by AppendVolume().


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