bea_RecallThread Class Reference
[IVD Back-End Agent]

#include <bea_recall.h>

Inheritance diagram for bea_RecallThread:

Inheritance graph
[legend]
Collaboration diagram for bea_RecallThread:

Collaboration graph
[legend]

List of all members.


Detailed Description

Definition at line 33 of file bea_recall.h.


Public Member Functions

 bea_RecallThread (i_BackEndAgent_i &a_bea, bea_Drive *const a_drive_p, bool a_firstCall)

Protected Member Functions

virtual ~bea_RecallThread ()

Private Member Functions

virtual void Run (void *arg)
void Recall ()
void MultiRecall ()

Private Attributes

 log_CLASSID_m
i_BackEndAgent_im_bea
bea_Drivem_drive_p
bea_Volumem_vol_p
UInt64_t m_dataAmount
i_CompletionStatus_e m_status
bool m_multi
bool m_firstCall

Constructor & Destructor Documentation

bea_RecallThread::bea_RecallThread ( i_BackEndAgent_i a_bea,
bea_Drive *const   a_drive_p,
bool  a_firstCall 
)

Definition at line 45 of file bea_recall.cpp.

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

00050   : m_bea(a_bea),
00051     m_drive_p(a_drive_p),
00052     m_vol_p(NULL),
00053     m_dataAmount(0),
00054     m_status(i_UNKNOWN),
00055     m_firstCall(a_firstCall){
00056 
00057     log_FUNC_m(bea_RecallThread);
00058 
00059     m_bea.m_threadCounter.Inc();
00060 }

Here is the call graph for this function:

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

Definition at line 64 of file bea_recall.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.

00064                                     {
00065 
00066     log_FUNC_m(~bea_RecallThread);
00067 
00068     // Decrease the counter imediatelly, because the job might imediatelly call
00069     // UseResources().
00070     m_bea.m_threadCounter.Dec();
00071 
00072     // Close the device before contactacting job
00073     if (m_drive_p != NULL) {
00074         m_drive_p->Close();
00075     }
00076 
00077     // Complete job
00078     try {
00079         if (m_bea.IsAborted()) {
00080             log_DBG_m(dbg_LOW, "Recall aborted. Won't contact job.");
00081         }
00082         else {
00083             ipc_EXEC_m(
00084                 if( !CORBA::is_nil(m_bea.GetJob()) ) {
00085                     log_DBG_m(dbg_LOW, "Completion status: " << m_status);
00086                     i_Job_var job = m_bea.GetJob();
00087                     job->MediumOperationComplete(m_bea.GetBEANumber(), m_status);
00088                 };
00089             );
00090         }
00091     }
00092     catch(...) {
00093         // Ignore all exceptions at this point.
00094     }
00095 }

Here is the call graph for this function:


Member Function Documentation

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

Reimplemented from cmn_Thread.

Definition at line 99 of file bea_recall.cpp.

References bea_OPREAD, dbg_LOW, evt_ERROR, i_BackEndAgent_i::GetBarcode(), i_BackEndAgent_i::GetJobID(), i_BackEndAgent_i::GetMedVolBlockSize(), i_BackEndAgent_i::GetMedVolID(), i_BackEndAgent_i::GetMedVolNumber(), i_BackEndAgent_i::GetPoolID(), i_BackEndAgent_i::HandleError(), i_DATA_ERROR, i_SUCCEDED, i_UNKNOWN, i_BackEndAgent_i::IsAborted(), log_DBG_m, log_ERR_m, log_FUNC_m, log_WriteEvent(), m_bea, m_status, i_BackEndAgent_i::ReadIDs(), Recall(), i_BackEndAgent_i::ReleaseResources(), and i_BackEndAgent_i::VerifyIDs().

00099                                     {
00100     log_FUNC_m(Run);
00101 
00102     try {
00103         try {
00104             Recall();
00105             m_status = i_SUCCEDED;
00106         }
00107         catch(const ivd_DFError &dfe) {
00108             // Recall doesn't read volume header.
00109             // Incorrect medium is detected when trying to read the file.
00110             //
00111             // Check vol ID then for better error reporting.
00112             log_DBG_m(dbg_LOW, "Data format error detected. Checking volume ID.");
00113 
00114             m_bea.ReadIDs(m_bea.GetMedVolNumber(), true);
00115 
00116             m_bea.VerifyIDs(
00117                 m_bea.GetBarcode(),
00118                 m_bea.GetMedVolNumber(),
00119                 m_bea.GetMedVolBlockSize(),
00120                 cmn_UUID_t(m_bea.GetMedVolID()),
00121                 cmn_UUID_t(m_bea.GetPoolID()) );
00122 
00123             // ID check passed: Volume and pool IDs match.
00124             // This is data format error or FSC/media mismatch
00125             ostringstream sstr;
00126             sstr
00127                 << "Data format error on volume "
00128                 << m_bea.GetMedVolNumber()<< ". "
00129                 << "Please verify the situation using FSC vs media check.";
00130 
00131             log_WriteEvent(evt_ERROR, sstr.str(), "RECALL",
00132                 m_bea.GetJobID(), m_bea.GetBarcode() );
00133 
00134             log_ERR_m("Data format error on recall: " << dfe);
00135 
00136             m_status = i_DATA_ERROR;
00137         }
00138     }
00139     catch(const ivd_Error &ie) {
00140         i_CompletionStatus_e status = m_bea.HandleError(ie, bea_OPREAD);
00141 
00142         if (m_status == i_UNKNOWN || m_status == i_SUCCEDED) {
00143             m_status = status;
00144         }
00145     }
00146     catch(const std::exception& ie) {
00147         if (m_bea.IsAborted()) {
00148             log_DBG_m(dbg_LOW,
00149                 "Recall aborted. Received exception: " << ie.what() );
00150         }
00151         else {
00152             ostringstream sstr;
00153             sstr << "Recall failed: " << ie.what();
00154             log_WriteEvent(evt_ERROR, sstr.str(), "",
00155                 m_bea.GetJobID(), m_bea.GetBarcode() );
00156         }
00157 
00158         if (m_status == i_SUCCEDED) {
00159             m_status = i_UNKNOWN;
00160         }
00161     }
00162     catch(...) {
00163         log_WriteEvent(evt_ERROR, "Recall failed. Unknown error.", "",
00164             m_bea.GetJobID(), m_bea.GetBarcode() );
00165 
00166         if (m_status == i_SUCCEDED) {
00167             m_status = i_UNKNOWN;
00168         }
00169     }
00170 
00171     try {
00172         m_bea.ReleaseResources();
00173     }
00174     catch (...) {
00175         // Ignore everything
00176     }
00177 }

Here is the call graph for this function:

void bea_RecallThread::Recall (  )  [private]

Definition at line 181 of file bea_recall.cpp.

References bea_OPREAD, cfg_MEGABYTE, bea_Medium::ChangeVolume(), df_Filter::CheckLeftovers(), cmn_GetEnvVariable(), cmn_Num2Str(), cmn_Str2Num(), dbg_DETAIL, dbg_LOW, dbg_NORM, file_creation_threshold_c(), bea_Volume::GetBlockSize(), i_BackEndAgent_i::GetBufferID(), bea_Medium::GetCurrentVolume(), bea_Medium::GetCurVolNumber(), i_BackEndAgent_i::GetDiskBufferFS(), i_BackEndAgent_i::GetDrive(), ivd_BaseException::GetError(), i_BackEndAgent_i::GetJob(), i_BackEndAgent_i::GetJobID(), bea_Drive::GetMedium(), bea_Medium::GetMediumMem(), i_BackEndAgent_i::GetMedVolBlockSize(), i_BackEndAgent_i::GetMedVolNumber(), bea_Volume::GetPosition(), bea_Medium::GetRMType(), i_BackEndAgent_i::GetSeekThreshold(), bea_Volume::GetVolumeNumber(), i_SUCCEDED, ie_DATA_CORRUPTION, ie_MEDIUM_EOD, ie_MEDIUM_EOM, ie_MEDIUM_FILEMARK, ipc_EXEC_m, i_BackEndAgent_i::IsAborted(), bea_Medium::IsMediumMemValid(), ivd_Error, log_DBG_m, log_FUNC_m, log_MARKLINE_m, i_BackEndAgent_i::LogStats(), m_bea, m_dataAmount, m_drive_p, m_firstCall, m_status, m_vol_p, df_Filter::NextBlockToCopy(), df_Filter::NextInputBlock(), df_Filter::NONE, NULL, df_Filter::ProcEndOfInput(), df_Filter::ProcessingFile(), bea_Volume::Read(), df_Filter::Reset(), bea_Volume::SeekBlock(), bea_Volume::SetBlockSize(), df_Filter::SetConsistencyMode(), df_RecReader::Unpack(), bea_MediumMemory::UpdateAccess(), and i_BackEndAgent_i::WaitForResources().

Referenced by Run().

00181                               {
00182     log_FUNC_m(Recall);
00183 
00184     m_bea.WaitForResources();
00185 
00186     if (m_bea.IsAborted()) {
00187         log_DBG_m(dbg_LOW, "Job aborted (1). Exit.");
00188         return;
00189     }
00190 
00191     log_DBG_m(dbg_LOW, "Starting recall. Job ID: " << m_bea.GetJobID());
00192 
00193     cmn_Time startTime;
00194 
00195     bea_Medium* med_p = m_drive_p->GetMedium();
00196 
00197     if (med_p->GetCurVolNumber() != m_bea.GetMedVolNumber()) {
00198         med_p->ChangeVolume( m_bea.GetMedVolNumber() );
00199     }
00200     m_vol_p = med_p->GetCurrentVolume();
00201     // Set the block size as sent by the recall job,
00202     // because volume identification is not read from volume header for recalls.
00203     m_vol_p->SetBlockSize(m_bea.GetMedVolBlockSize());
00204 
00205     if (med_p->GetCurVolNumber() != m_bea.GetMedVolNumber()) {
00206         med_p->ChangeVolume( m_bea.GetMedVolNumber() );
00207     }
00208 
00209     ivd_MediaType_e type = static_cast<ivd_MediaType_e>(med_p->GetRMType());
00210     bea_Drive* drv_p(m_bea.GetDrive());
00211     UInt64_t seekThreshold(
00212         m_bea.GetSeekThreshold(
00213             drv_p->GetVendorID(), drv_p->GetProductID(), type ) );
00214 
00215     if (seekThreshold == 0) {
00216         seekThreshold = drv_p->GetDefaultSeekThreshold();
00217     }
00218 
00219     log_DBG_m(dbg_LOW, "Seek threshold: " << seekThreshold);
00220     string fileCreationThreshold = cmn_GetEnvVariable(file_creation_threshold_c);
00221 
00222     bool firstSet(true);
00223 
00224     while (true){
00225 
00226         // Get files from Job
00227         i_FileLocationDataList_t_var iFileList;
00228         ipc_EXEC_m(
00229             iFileList = m_bea.GetJob()->GetNextRecallSet();
00230         );
00231         for (UInt32_t i(0); i < iFileList->length(); i++){
00232             log_DBG_m(dbg_DETAIL, "blk:" << iFileList[i].blockOffset <<
00233                 " fileID:" << iFileList[i].fileID <<
00234                 " migID:"  << ivd_MigrationID(iFileList[i].migrationID) <<
00235                 " spltsz:" << iFileList[i].splitSize );
00236         }
00237 
00238         if (iFileList->length() == 0) {
00239             log_DBG_m(dbg_LOW, "Recall finished");
00240             break;
00241         }
00242         //else
00243 
00244         ivd_FileLocVect_t files;
00245         ivd_FileSize_t estDbSize(0);
00246 
00247         // check if file is big enough to enable seek to filesize
00248         log_DBG_m(dbg_DETAIL, "fileCreationThreshold = " << fileCreationThreshold);
00249 
00250         for (UInt32_t i(0); i < iFileList->length(); i++){
00251             files.push_back(ivd_FileLocationData_t(iFileList[i]));
00252             // estimation is too small on purpose (only data stream calculated),
00253             // the actual file will grow a few KB/MB more.
00254             estDbSize += iFileList[i].splitSize;
00255         }
00256 
00257         if (m_firstCall && !fileCreationThreshold.empty()) {
00258             UInt32_t fileCreationThresholdVal = cmn_Str2Num(fileCreationThreshold) * cfg_MEGABYTE;
00259 
00260             if ((fileCreationThresholdVal != 0) && (estDbSize > fileCreationThresholdVal)) {
00261                 log_DBG_m(dbg_DETAIL, "Enable trunc to filesize, fileCreationThresholdVal= " << fileCreationThresholdVal <<
00262                                                             ", estDbSize=" << estDbSize);
00263             }
00264             else {
00265                 estDbSize = 0;
00266                 log_DBG_m(dbg_DETAIL, "Normal writing to diskbuff, fileCreationThresholdVal = " <<
00267                                       fileCreationThresholdVal <<
00268                                       ", estDbSize=" <<
00269                                       estDbSize);
00270             }
00271         }
00272         else {
00273             estDbSize = 0;
00274             log_DBG_m(dbg_DETAIL, "Normal writing to diskbuff, estDbSize=" << estDbSize);
00275         }
00276 
00277 
00278         log_DBG_m(dbg_LOW, "Recall will recall " << files.size() << " files");
00279 
00280         {
00281             UInt32_t nextBlockToCopy(0);
00282             bool     skipping(false);
00283 
00284             //Do append only if this is first Recall and first set of files
00285             bool append = !m_firstCall || !firstSet;
00286             log_DBG_m(dbg_LOW, "append: " << boolalpha << append);
00287 
00288             df_Filter dffilter( m_vol_p->GetBlockSize(),
00289                                 m_bea.GetDiskBufferFS(),
00290                                 cmn_Num2Str(m_bea.GetBufferID()),
00291                                 files,
00292                                 append,
00293                                 estDbSize);
00294             firstSet = false;
00295 
00296             UInt32_t blkPos(files[0].blockOffset);
00297 
00298             // Sanity check: Positions have to be below
00299             if (blkPos < m_vol_p->GetStartOfDataPosition()) {
00300                 log_MARKLINE_m;
00301                 throw ivd_Error(ie_DATA_CORRUPTION,
00302                     "Invalid input parameters: Trying to seek to a medium position in the header.",
00303                     true);
00304             }
00305 
00306             // Don't perform unnecessary seeks, which may throw the contents of
00307             // the drive buffer away.
00308             if (m_vol_p->GetPosition() != blkPos) {
00309                 m_vol_p->SeekBlock(blkPos);
00310             }
00311 
00312             // Job was aborted while seeking to the first position to read
00313             // files from.
00314             if (m_bea.IsAborted()) {
00315                 log_DBG_m(dbg_NORM, "Recall aborted while seeking to first position.");
00316                 dffilter.SetConsistencyMode(df_Filter::NONE);
00317                 break;
00318             }
00319 
00320             UInt8_t* buffer = dffilter.NextInputBlock();
00321             while ( buffer != NULL ) {
00322 
00323                 try {
00324                     m_vol_p->Read(buffer);
00325                     m_dataAmount += m_vol_p->GetBlockSize();
00326                 }
00327                 catch (ivd_Error &ie) {
00328                     if (ie.GetError() == ie_MEDIUM_FILEMARK) {
00329                         //reading finished
00330                         log_DBG_m(dbg_LOW, "reading finished (Filemark).");
00331                         break;
00332                     }
00333                     else if (ie.GetError() == ie_MEDIUM_EOD) {
00334                         log_DBG_m(dbg_LOW, "reading finished (eod).");
00335                         break;
00336                     }
00337                     else if (ie.GetError() == ie_MEDIUM_EOM) {
00338                         log_DBG_m(dbg_LOW, "Early end of volume. Ignore.");
00339                     }
00340                     else {
00341                         // An error has happened when reading data from
00342                         // medium: df_Filter shouldn't check for
00343                         // for consistency of recalled data in this case.
00344                         dffilter.SetConsistencyMode(df_Filter::NONE);
00345                         throw;
00346                     }
00347                 }
00348 
00349                 // Don't parse the data format in the
00350                 // "holes between" the valid files.
00351                 if (nextBlockToCopy <= blkPos) {
00352                     skipping = false;
00353                     dffilter.Unpack(buffer, blkPos);
00354                 }
00355 
00356                 if (!skipping && !dffilter.ProcessingFile()) {
00357                     nextBlockToCopy = dffilter.NextBlockToCopy();
00358                     if (nextBlockToCopy == 0){ //no more files
00359                         log_DBG_m(dbg_NORM, "No more files for processing.");
00360                         break;
00361                     }
00362                     log_DBG_m(dbg_NORM,
00363                         "Filter is not processing file. " <<
00364                         "Skip to block " << nextBlockToCopy <<
00365                         " (current: " << blkPos << ")");
00366                     dffilter.Reset();
00367                     skipping = true;
00368                 }
00369 
00370                 buffer = dffilter.NextInputBlock();
00371 
00372                 if (skipping) {
00373                     UInt64_t sizeGap(nextBlockToCopy - blkPos);
00374                     sizeGap *= m_vol_p->GetBlockSize();
00375                     log_DBG_m(dbg_DETAIL, "gap: " << sizeGap);
00376 
00377                     if (sizeGap > seekThreshold) {
00378                         m_vol_p->SeekBlock(nextBlockToCopy);
00379                         blkPos = m_vol_p->GetPosition();
00380                         skipping = false;
00381                     }
00382                     else {
00383                         // Skipping by reading.
00384                         blkPos++;
00385                     }
00386                 }
00387                 else {
00388                     // Reading.
00389                     blkPos++;
00390                 }
00391 
00392                 if (m_bea.IsAborted()) {
00393                     log_DBG_m(dbg_NORM, "Recall aborted.");
00394                     dffilter.SetConsistencyMode(df_Filter::NONE);
00395                     break;
00396                 }
00397             } // while
00398 
00399             dffilter.ProcEndOfInput();
00400             dffilter.CheckLeftovers();
00401             if (m_bea.IsAborted()) {
00402                 log_DBG_m(dbg_NORM, "Recall aborted.");
00403                 dffilter.SetConsistencyMode(df_Filter::NONE);
00404                 break;
00405             }
00406         }
00407     }//end while //recall finished
00408 
00409     cmn_Time endTime;
00410     cmn_Time diffTime = endTime - startTime;
00411 
00412     m_bea.LogStats(diffTime, m_dataAmount, bea_OPREAD);
00413 
00414     try {
00415         if (m_drive_p->GetMedium()->IsMediumMemValid()) {
00416             bea_MediumMemory* mm = m_drive_p->GetMedium()->GetMediumMem();
00417             mm->UpdateAccess(m_vol_p->GetVolumeNumber());
00418         }
00419     }
00420     catch(ivd_Exception &ie) {
00421         log_DBG_m(dbg_LOW, "Error updating MIC. Ignored: " << ie );
00422     }
00423 
00424     m_status = i_SUCCEDED;
00425 }

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_RecallThread::MultiRecall (  )  [private]


Member Data Documentation

Reimplemented from cmn_Thread.

Definition at line 45 of file bea_recall.h.

Definition at line 52 of file bea_recall.h.

Referenced by bea_RecallThread(), Recall(), Run(), and ~bea_RecallThread().

Definition at line 53 of file bea_recall.h.

Referenced by Recall(), and ~bea_RecallThread().

Definition at line 54 of file bea_recall.h.

Referenced by Recall().

Definition at line 55 of file bea_recall.h.

Referenced by Recall().

Definition at line 56 of file bea_recall.h.

Referenced by Recall(), Run(), and ~bea_RecallThread().

bool bea_RecallThread::m_multi [private]

Definition at line 57 of file bea_recall.h.

Definition at line 58 of file bea_recall.h.

Referenced by Recall().


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

Generated on Mon Feb 27 19:00:37 2012 for OPENARCHIVE by  doxygen 1.5.6