la_SCSILibrary Class Reference
[IVD Library Agent]

#include <la_scsi.h>

Collaboration diagram for la_SCSILibrary:

Collaboration graph
[legend]

List of all members.


Detailed Description

Definition at line 30 of file la_scsi.h.


Public Member Functions

 la_SCSILibrary ()
 ~la_SCSILibrary ()
void SetDeviceID (string a_deviceID)
void Open ()
void Close ()
const string & GetVendorID () const
const string & GetProductID () const
const string & GetProductRevision () const
const string & GetSerialNumber () const
string GetSCSIID () const
void Inventory (bool a_force, vector< data_ElementStatus::ElemStatus_t > &a_elem)
 Does an inventory and read element status.
void Load (UInt16_t a_slot, UInt16_t a_drive, const string &a_barcode)
 Load a tape from a slot into a drive.
void Unload (UInt16_t a_drive, UInt16_t a_slot, const string &a_barcode)
 Unload a tape from a drive into a slot.
bool MustRequestEject ()
void SetDriveIDs (vector< DriveInfo > &a_driveIDs)
UInt16_t GetNumDrives ()
bool HasBarcodeReader ()

Private Member Functions

vector
< data_ElementStatus::ElemStatus_t
Status (UInt16_t a_from, UInt16_t a_count, data_ElementStatus::ElemType_t a_type)
 Returns the status of elements in the specified range and of specified type.
void ReadElementAssignment ()
void EjectMedium (UInt16_t a_drive, const string &a_barcode)
void HandleDriveError (const ivd_Error &a_ie, UInt32_t a_drv, const string &a_bc)
UInt16_t GetTransElemAddr (UInt16_t a_seqNum)
UInt16_t GetSlotElemAddr (UInt16_t a_seqNum)
UInt16_t GetImpExElemAddr (UInt16_t a_seqNum)
UInt16_t GetDriveElemAddr (UInt16_t a_seqNum)

Private Attributes

 log_CLASSID_m
cmn_Mutex m_library_x
cmn_Mutex m_drives_x
scsi_IOm_scsi
string m_deviceID
vector< DriveInfom_driveID
 Device IDs of the drives that are used at Unload operation with some specific libraries.
bool m_hasBarcodeReader
bool m_hasMICReader
bool m_mustRequestEject
UInt16_t m_transStartAddr
UInt16_t m_transNum
UInt16_t m_slotStartAddr
UInt16_t m_slotNum
UInt16_t m_impexStartAddr
UInt16_t m_impexNum
UInt16_t m_driveStartAddr
UInt16_t m_driveNum

Classes

class  DriveInfo

Constructor & Destructor Documentation

la_SCSILibrary::la_SCSILibrary (  ) 

Definition at line 43 of file la_scsi.cpp.

References log_FUNC_m, and m_scsi.

00044     : m_scsi(NULL),
00045     // Defaults. Can change after open. Check with capabilities.
00046       m_hasBarcodeReader(true),
00047       m_hasMICReader(true),
00048       m_mustRequestEject(false) {
00049 
00050     log_FUNC_m(la_SCSILibrary);
00051 
00052 #if TGT_OS_linux
00053     m_scsi = new scsi_LnxSG("");
00054 #elif TGT_OS_windows
00055     m_scsi = new scsi_WinSG("");
00056 #endif
00057 }

la_SCSILibrary::~la_SCSILibrary (  ) 

Definition at line 59 of file la_scsi.cpp.

References Close(), log_FUNC_m, m_scsi, and NULL.

00059                                 {
00060     log_FUNC_m(~la_SCSILibrary);
00061 
00062     if (m_scsi != NULL) {
00063         Close();
00064         delete m_scsi; m_scsi = NULL;
00065     }
00066 }

Here is the call graph for this function:


Member Function Documentation

void la_SCSILibrary::SetDeviceID ( string  a_deviceID  ) 

Definition at line 68 of file la_scsi.cpp.

References log_FUNC_m, m_deviceID, m_scsi, and scsi_IO::SetDeviceID().

Referenced by i_LibraryAgentSCSI_i::Reconfigure().

00068                                                   {
00069     log_FUNC_m(SetDeviceID);
00070 
00071     m_deviceID = a_deviceID;
00072     m_scsi->SetDeviceID(a_deviceID);
00073 }

Here is the call graph for this function:

Here is the caller graph for this function:

void la_SCSILibrary::Open (  ) 

Definition at line 75 of file la_scsi.cpp.

References scsi_IO::Close(), dbg_LOW, dbg_NORM, cmn_Global::dirs, dt_MEDIUM_CHANGER, ivd_Directories::etc, evt_ERROR, cfg_LibraryFile::FindLibrary(), g_cmn, scsi_IO::GetDeviceType(), scsi_IO::GetProductID(), scsi_IO::GetVendorID(), ie_LA_INVDEVTYPE, ie_LA_OPEN, ie_LA_UNSUPPORTED, ivd_Error, log_DBG_m, log_ERR_m, log_FUNC_m, log_MARKLINE_m, log_WriteEvent(), cfg_Library::m_bcReader, m_deviceID, m_driveNum, m_driveStartAddr, cfg_Library::m_eject, m_hasBarcodeReader, m_impexNum, m_impexStartAddr, m_mustRequestEject, m_scsi, m_slotNum, m_slotStartAddr, m_transNum, m_transStartAddr, NULL, scsi_IO::Open(), pf_File::Parse(), ReadElementAssignment(), scsi_GetDeviceTypeText(), and scsi_IO::WaitToBecomeReady().

Referenced by i_LibraryAgentSCSI_i::Reconfigure().

00075                           {
00076     log_FUNC_m(Open);
00077 
00078     m_scsi->Open();
00079 
00080     if (m_scsi->GetDeviceType() != dt_MEDIUM_CHANGER) {
00081         log_MARKLINE_m;
00082         m_scsi->Close();
00083 
00084         ostringstream sstr;
00085         sstr
00086             << "The device is not medium changer but "
00087             << scsi_GetDeviceTypeText(m_scsi->GetDeviceType()) << ". "
00088             << "Check the configuration.";
00089 
00090         log_WriteEvent(evt_ERROR, sstr.str(), "", 0, m_deviceID);
00091 
00092         throw ivd_Error(ie_LA_INVDEVTYPE,
00093             string("a_deviceID: ") + m_deviceID +
00094             string(" type: ") +
00095             scsi_GetDeviceTypeText(m_scsi->GetDeviceType()),
00096             true);
00097     }
00098     try {
00099 
00100         log_DBG_m(dbg_NORM, "Waiting the library to become ready.");
00101         m_scsi->WaitToBecomeReady();
00102 
00103         ReadElementAssignment();
00104         log_DBG_m(dbg_LOW, 
00105             "Element assignment: " << endl <<
00106             " trans : " << m_transStartAddr << " " << m_transNum << endl <<
00107             " slot  : " << m_slotStartAddr << " " << m_slotNum << endl <<
00108             " impex : " << m_impexStartAddr << " " << m_impexNum << endl <<
00109             " drive : " << m_driveStartAddr << " " << m_driveNum );
00110     }
00111     catch (ivd_Error &ie) {
00112         m_scsi->Close();
00113         log_ERR_m(
00114             "Can't read element assignent addresses. Device " <<
00115             m_deviceID << endl << " Error: " << ie);
00116 
00117         throw ivd_Error(
00118             ie_LA_OPEN, "Can't read element assignment addresses");
00119     }
00120     catch (ivd_SysError &ie) {
00121         m_scsi->Close();
00122         log_ERR_m(
00123             "Can't read element assignent addresses. Device " <<
00124             m_deviceID << endl << " Error: " << ie);
00125 
00126         throw ivd_Error(
00127             ie_LA_OPEN, "Can't read element assignment addresses");
00128     }
00129 
00130     {
00131         pf_File libraryCfg;
00132         libraryCfg.Parse(g_cmn.dirs.etc + "library.cfg");
00133         cfg_LibraryFile lf(libraryCfg);
00134         
00135         const cfg_Library* lib = lf.FindLibrary(
00136             m_scsi->GetVendorID(), m_scsi->GetProductID() );
00137             
00138         if (lib == NULL) {
00139             ostringstream sstr;
00140             sstr
00141                 << "Device: " << m_deviceID << " "
00142                 << "Vendor: \'" << m_scsi->GetVendorID() << "\' "
00143                 << "Product: \'" << m_scsi->GetProductID() << "\' ";
00144                 
00145             m_scsi->Close();
00146             throw ivd_Error(ie_LA_UNSUPPORTED, sstr.str());
00147         }
00148         
00149         m_mustRequestEject = lib->m_eject;
00150         m_hasBarcodeReader = lib->m_bcReader;
00151         
00152         log_DBG_m(dbg_LOW,
00153             endl <<
00154             "Barcode reader available: " << m_hasBarcodeReader << endl <<
00155             "Request eject on unload : " << m_mustRequestEject);
00156     }
00157 }

Here is the call graph for this function:

Here is the caller graph for this function:

void la_SCSILibrary::Close (  ) 

Definition at line 159 of file la_scsi.cpp.

References scsi_IO::Close(), scsi_IO::IsOpen(), log_FUNC_m, and m_scsi.

Referenced by i_LibraryAgentSCSI_i::Reconfigure(), i_LibraryAgentSCSI_i::~i_LibraryAgentSCSI_i(), and ~la_SCSILibrary().

00159                            {
00160     log_FUNC_m(Close);
00161     if (m_scsi->IsOpen()) {
00162         m_scsi->Close();
00163     }
00164 }

Here is the call graph for this function:

Here is the caller graph for this function:

const string& la_SCSILibrary::GetVendorID (  )  const [inline]

Definition at line 50 of file la_scsi.h.

References scsi_IO::GetVendorID(), and m_scsi.

Referenced by i_LibraryAgentSCSI_i::UpdateIDs().

00050 {return m_scsi->GetVendorID(); };

Here is the call graph for this function:

Here is the caller graph for this function:

const string& la_SCSILibrary::GetProductID (  )  const [inline]

Definition at line 51 of file la_scsi.h.

References scsi_IO::GetProductID(), and m_scsi.

Referenced by i_LibraryAgentSCSI_i::UpdateIDs().

00051 {return m_scsi->GetProductID(); };

Here is the call graph for this function:

Here is the caller graph for this function:

const string& la_SCSILibrary::GetProductRevision (  )  const [inline]

Definition at line 52 of file la_scsi.h.

References scsi_IO::GetProductRevision(), and m_scsi.

Referenced by i_LibraryAgentSCSI_i::UpdateIDs().

00052 {return m_scsi->GetProductRevision(); };

Here is the call graph for this function:

Here is the caller graph for this function:

const string& la_SCSILibrary::GetSerialNumber (  )  const [inline]

Definition at line 53 of file la_scsi.h.

References scsi_IO::GetProductSerialNumber(), and m_scsi.

Referenced by i_LibraryAgentSCSI_i::UpdateIDs().

00053 {return m_scsi->GetProductSerialNumber(); };

Here is the call graph for this function:

Here is the caller graph for this function:

string la_SCSILibrary::GetSCSIID (  )  const [inline]

Definition at line 54 of file la_scsi.h.

References scsi_IO::GetSCSIID(), and m_scsi.

Referenced by i_LibraryAgentSCSI_i::UpdateIDs().

00054 {return m_scsi->GetSCSIID(); };

Here is the call graph for this function:

Here is the caller graph for this function:

void la_SCSILibrary::Inventory ( bool  a_force,
vector< data_ElementStatus::ElemStatus_t > &  a_elem 
)

Does an inventory and read element status.

Definition at line 189 of file la_scsi.cpp.

References dbg_DETAIL, dbg_LOW, dbg_NORM, data_ElementStatus::et_DRIVE, data_ElementStatus::et_IMPEX, data_ElementStatus::et_SLOT, evt_WARNING, scsi_IO::IOCtl(), log_DBG_m, log_FUNC_A_m, log_WriteEvent(), m_driveNum, m_driveStartAddr, m_impexNum, m_impexStartAddr, m_library_x, m_scsi, m_slotNum, m_slotStartAddr, ReadElementAssignment(), Status(), and scsi_IO::WaitToBecomeReady().

Referenced by i_LibraryAgentSCSI_i::Inventory().

00191                                                         {
00192 
00193     log_FUNC_A_m(Inventory, "force: " << (a_force? "Yes" : "No") );
00194 
00195     cmn_MutexLock l(m_library_x);
00196 
00197     if (a_force) {
00198         log_DBG_m(dbg_LOW,
00199             "Starting Init Element Status. " <<
00200             "May last some time.");
00201 
00202         cdb_InitElementStatus  init;
00203         m_scsi->IOCtl(init);
00204 
00205         log_DBG_m(dbg_LOW, "Init Element Status complete. ");
00206     };
00207 
00208     m_scsi->WaitToBecomeReady();
00209 
00210     // Was done on open. But just to be sure.
00211     ReadElementAssignment();
00212 
00213     // Execute Status of all elements
00214     vector<data_ElementStatus::ElemStatus_t> drives;
00215     vector<data_ElementStatus::ElemStatus_t> slots;
00216     vector<data_ElementStatus::ElemStatus_t> impex;
00217 
00218     if (m_driveNum > 0) {
00219         drives = Status(m_driveStartAddr, m_driveNum, data_ElementStatus::et_DRIVE);
00220 
00221         if (drives.size() != m_driveNum) {
00222             ostringstream sstr;
00223             sstr
00224                 << "Status reported different number of drives than element assignment. "
00225                 << drives.size() << " vs. " << m_driveNum;
00226 
00227             log_WriteEvent(evt_WARNING, sstr.str());
00228         }
00229     }
00230     else {
00231         log_DBG_m(dbg_NORM, "No drives reported by the library?");
00232         log_WriteEvent(evt_WARNING, "Library reported no drives.");
00233     };
00234 
00235     if (m_slotNum > 0) {
00236         slots  = Status(m_slotStartAddr,  m_slotNum,  data_ElementStatus::et_SLOT);
00237         if (slots.size() != m_slotNum) {
00238             ostringstream sstr;
00239             sstr
00240                 << "Status reported different number of slots than element assignment. "
00241                 << slots.size() << " vs. " << m_slotNum;
00242 
00243             log_WriteEvent(evt_WARNING, sstr.str());
00244         }
00245     }
00246     else {
00247         log_DBG_m(dbg_NORM, "No slots reported by the library?");
00248         log_WriteEvent(evt_WARNING, "Library reported no slots.");
00249     };
00250 
00251     if (m_impexNum > 0) {
00252         impex  = Status(m_impexStartAddr, m_impexNum, data_ElementStatus::et_IMPEX);
00253         if (impex.size() != m_impexNum) {
00254             ostringstream sstr;
00255             sstr
00256                 << "Status reported different number of import/export slots than element assignment. "
00257                 << impex.size() << " vs. " << m_impexNum;
00258 
00259             log_WriteEvent(evt_WARNING, sstr.str());
00260         }
00261     }
00262     else {
00263         log_DBG_m(dbg_NORM, "No import/export slots reported by the library.");
00264     };
00265 
00266     // Fill RMDB with new values
00267 
00268     for (UInt32_t i = 0; i < drives.size(); i++) {
00269         // NOTE: Correcting _physical_ address to IVD logical number
00270         drives[i].slot -= (m_driveStartAddr-1);
00271         a_elem.push_back(drives[i]);
00272     }
00273     for (UInt32_t i = 0; i < slots.size(); i++) {
00274         // NOTE: Correcting _physical_ address to IVD logical number
00275         slots[i].slot -= (m_slotStartAddr-1);
00276         a_elem.push_back(slots[i]);
00277     }
00278     for (UInt32_t i = 0; i < impex.size(); i++) {
00279         // NOTE: Correcting _physical_ address to IVD logical number
00280         impex[i].slot -= (m_impexStartAddr-1);
00281         a_elem.push_back(impex[i]);
00282     }
00283     log_DBG_m(dbg_DETAIL, "All elements added to elem vector.");
00284 }

Here is the call graph for this function:

Here is the caller graph for this function:

void la_SCSILibrary::Load ( UInt16_t  a_slot,
UInt16_t  a_drive,
const string &  a_barcode 
)

Load a tape from a slot into a drive.

IVD sequence numbers are used and are converted internally to low level (hardware) numbers.

Parameters:
a_barcode Expected barcode to be tested before loading the medium. Throws an exception if the barcode does not match.

Definition at line 296 of file la_scsi.cpp.

References cmn_Num2Str(), dbg_NORM, data_ElementStatus::et_SLOT, GetDriveElemAddr(), GetSlotElemAddr(), ie_INVALID_ARG, ie_LA_INVBARCODE, scsi_IO::IOCtl(), ivd_Error, log_DBG_m, log_FUNC_A_m, log_MARKLINE_m, m_hasBarcodeReader, m_library_x, m_scsi, m_transStartAddr, cdb_MoveMedium::SetDestination(), cdb_MoveMedium::SetSource(), cdb_MoveMedium::SetTransport(), Status(), and scsi_IO::WaitToBecomeReady().

Referenced by i_LibraryAgentSCSI_i::Load().

00296                                                                                     {
00297     log_FUNC_A_m(Load,
00298         "slot: " << a_slot << " drv: " << a_drive << " bc: " << a_barcode);
00299 
00300     if (a_slot == 0) {
00301         throw ivd_Error(ie_INVALID_ARG, "Slot number is zero.");
00302     }
00303     else if (a_drive == 0) {
00304         throw ivd_Error(ie_INVALID_ARG, "Drive number is zero.");
00305     }
00306 
00307     cmn_MutexLock l(m_library_x);
00308 
00309     cdb_MoveMedium  mv;
00310 
00311     UInt16_t slotL = GetSlotElemAddr(a_slot);
00312     UInt16_t driveL = GetDriveElemAddr(a_drive);
00313 
00314     log_DBG_m(dbg_NORM,
00315         "Move from slot " << a_slot << " (" << slotL << ") "
00316         "to drive " << a_drive << " (" << driveL << ") " );
00317 
00318     // SCSI reset might have occured. Check if necessary to become ready.
00319     m_scsi->WaitToBecomeReady();
00320 
00321     // Check if the barcode in the slot matches expected
00322     vector<data_ElementStatus::ElemStatus_t> est =
00323         Status(slotL, 1, data_ElementStatus::et_SLOT);
00324 
00325     if (est.size() < 1) {
00326         log_MARKLINE_m;
00327         throw ivd_Error(ie_LA_INVBARCODE,
00328             string("Element status can't be read for slot # ") +
00329             cmn_Num2Str(a_slot) +
00330             string("Does the slot exist and contain a medium?") );
00331     }
00332     if (   m_hasBarcodeReader
00333         && est[0].full
00334         && string(est[0].barcode) != a_barcode) {
00335 
00336         log_MARKLINE_m;
00337         throw ivd_Error(ie_LA_INVBARCODE,
00338             string("Slot # ") + cmn_Num2Str(a_slot) +
00339             string(" bc: ") + string(est[0].barcode) +
00340             string(" expected: ") + a_barcode);
00341     }
00342 
00343     // Just take the first robotic arm for now (DDS changer uses 0)
00344     mv.SetTransport(m_transStartAddr);
00345     mv.SetSource(slotL);
00346     mv.SetDestination(driveL);
00347 
00348     log_DBG_m(dbg_NORM, "Moving medium.");
00349     m_scsi->IOCtl(mv);
00350 }

Here is the call graph for this function:

Here is the caller graph for this function:

void la_SCSILibrary::Unload ( UInt16_t  a_drive,
UInt16_t  a_slot,
const string &  a_barcode 
)

Unload a tape from a drive into a slot.

IVD sequence numbers are used and are converted internally to low level (hardware) numbers.

Parameters:
a_barcode Expected barcode to be tested before loading the medium. Throws an exception if the barcode does not match.

Definition at line 362 of file la_scsi.cpp.

References cmn_Num2Str(), dbg_NORM, EjectMedium(), data_ElementStatus::et_DRIVE, GetDriveElemAddr(), GetSlotElemAddr(), ie_INVALID_ARG, ie_LA_INVBARCODE, scsi_IO::IOCtl(), ivd_Error, log_DBG_m, log_FUNC_A_m, log_MARKLINE_m, m_hasBarcodeReader, m_library_x, m_mustRequestEject, m_scsi, m_transStartAddr, cdb_MoveMedium::SetDestination(), cdb_MoveMedium::SetSource(), cdb_MoveMedium::SetTransport(), Status(), and scsi_IO::WaitToBecomeReady().

Referenced by i_LibraryAgentSCSI_i::Unload().

00362                                                                                       {
00363     log_FUNC_A_m(Unload,
00364         "drv: " << a_drive << " slot: " << a_slot << " bc: " << a_barcode);
00365 
00366     if (a_slot == 0) {
00367         throw ivd_Error(ie_INVALID_ARG, "Slot number is zero.");
00368     }
00369     else if (a_drive == 0) {
00370         throw ivd_Error(ie_INVALID_ARG, "Drive number is zero.");
00371     }
00372 
00373     UInt16_t slotL, driveL;
00374 
00375     {
00376         cmn_MutexLock l(m_library_x);
00377 
00378         slotL = GetSlotElemAddr(a_slot);
00379         driveL = GetDriveElemAddr(a_drive);
00380 
00381         log_DBG_m(dbg_NORM,
00382             "Move from drive " << a_drive << " (" << driveL << ") "
00383             "to slot " << a_slot << " (" << slotL << ") " );
00384 
00385         // SCSI reset might have occured. Check if necessary to become ready.
00386         m_scsi->WaitToBecomeReady();
00387 
00388         // Check if the barcode in the slot matches expected
00389         vector<data_ElementStatus::ElemStatus_t> est =
00390             Status(driveL, 1, data_ElementStatus::et_DRIVE);
00391 
00392         if (est.size() < 1) {
00393             log_MARKLINE_m;
00394             throw ivd_Error(ie_LA_INVBARCODE,
00395                 string("Element status can't be read for drive # ") +
00396                 cmn_Num2Str(a_drive) +
00397                 string("Does the drive exist and contain a medium?") );
00398         }
00399         if (   m_hasBarcodeReader
00400             && est[0].full
00401             && string(est[0].barcode) != a_barcode) {
00402 
00403             log_MARKLINE_m;
00404             throw ivd_Error(ie_LA_INVBARCODE,
00405                 string("Drive # ") + cmn_Num2Str(a_drive) +
00406                 string(" bc: ") + string(est[0].barcode) +
00407                 string(" expected: ") + a_barcode);
00408         }
00409     } // protected by mutex to here
00410 
00411     if (m_mustRequestEject) {
00412         EjectMedium(a_drive, a_barcode);
00413     }
00414 
00415     {
00416         cmn_MutexLock l(m_library_x);
00417         cdb_MoveMedium  mv;
00418 
00419         // Just take the first robotic arm for now (DDS changer uses 0)
00420         mv.SetTransport(m_transStartAddr);
00421         mv.SetSource(driveL);
00422         mv.SetDestination(slotL);
00423 
00424         log_DBG_m(dbg_NORM, "Moving medium.");
00425 
00426         m_scsi->IOCtl(mv);
00427     } // protected by mutex to here
00428 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool la_SCSILibrary::MustRequestEject (  ) 

Definition at line 166 of file la_scsi.cpp.

References m_mustRequestEject.

Referenced by i_LibraryAgentSCSI_i::Reconfigure(), and i_LibraryAgentSCSI_i::Unload().

00166                                       {
00167     return this->m_mustRequestEject;
00168 }

Here is the caller graph for this function:

void la_SCSILibrary::SetDriveIDs ( vector< DriveInfo > &  a_driveIDs  ) 

Referenced by i_LibraryAgentSCSI_i::Reconfigure(), and i_LibraryAgentSCSI_i::Unload().

Here is the caller graph for this function:

UInt16_t la_SCSILibrary::GetNumDrives (  ) 

Definition at line 180 of file la_scsi.cpp.

References m_driveNum.

Referenced by i_LibraryAgentSCSI_i::ReadDriveInfo().

00180                                       {
00181     return m_driveNum;
00182 }

Here is the caller graph for this function:

bool la_SCSILibrary::HasBarcodeReader (  ) 

Definition at line 170 of file la_scsi.cpp.

References m_hasBarcodeReader.

Referenced by i_LibraryAgentSCSI_i::Inventory().

00170                                       {
00171     return this->m_hasBarcodeReader;
00172 }

Here is the caller graph for this function:

vector< data_ElementStatus::ElemStatus_t > la_SCSILibrary::Status ( UInt16_t  a_from,
UInt16_t  a_count,
data_ElementStatus::ElemType_t  a_type 
) [private]

Returns the status of elements in the specified range and of specified type.

Definition at line 438 of file la_scsi.cpp.

References dbg_LOW, ivd_BaseException::GetError(), data_ElementStatus::GetReportSize(), ie_SCSI_ILREQ, scsi_IO::IOCtl(), log_DBG_m, log_ERR_m, log_FUNC_A_m, m_deviceID, m_hasBarcodeReader, m_scsi, data_ElementStatus::ParseElemStatus(), scsi_TIMEOUT_LONG_d, cdb_ReadElementStatus::SetCurData(), cdb_ReadElementStatus::SetDeviceId(), cdb_ReadElementStatus::SetElementNum(), cdb_ReadElementStatus::SetStartAddr(), cdb_ReadElementStatus::SetType(), and cdb_ReadElementStatus::SetVolTag().

Referenced by Inventory(), Load(), and Unload().

00441                                          {
00442 
00443     log_FUNC_A_m(Status,
00444         "from: " << a_from << " count: " << a_count <<
00445         " type: " << (int)a_type );
00446 
00447     UInt32_t reportSize(
00448         a_count * sizeof(data_ESDescriptor_t) +
00449         sizeof(data_ESHdr_t) +
00450         sizeof(data_ESPageHdr_t) );
00451         
00452     data_ElementStatus      est(reportSize);
00453     cdb_ReadElementStatus   res(est);
00454 
00455     res.SetType(a_type);
00456     res.SetStartAddr(a_from);
00457     res.SetElementNum(a_count);
00458 
00459     // Most probably must these be set to false
00460     res.SetCurData(false);
00461     res.SetDeviceId(false);
00462 
00463     // try status with barcodes first
00464     bool barcodeStatus = m_hasBarcodeReader;
00465 
00466     while (1) {
00467         try {
00468             res.SetVolTag(barcodeStatus);
00469             m_scsi->IOCtl(res, scsi_TIMEOUT_LONG_d);
00470             break;
00471         }
00472         catch (ivd_Error &ie) {
00473             if (ie.GetError() == ie_SCSI_ILREQ && barcodeStatus) {
00474                 log_DBG_m(dbg_LOW,
00475                     "Most probably barcodes not supported by the library. " <<
00476                     "Retrying without barcodes.");
00477                 barcodeStatus = false;
00478             }
00479             else {
00480                 log_ERR_m("Can't perform RES CDB on " << m_deviceID);
00481                 throw;
00482             }
00483         }
00484     } // while
00485 
00486     vector<data_ElementStatus::ElemStatus_t> elemStatus;
00487 
00488     if (est.GetReportSize() > reportSize) {
00489         // reportSize is too small. Increase and retry.
00490         data_ElementStatus      est2(est.GetReportSize());
00491         cdb_ReadElementStatus   res(est2);
00492 
00493         res.SetType(a_type);
00494         res.SetStartAddr(a_from);
00495         res.SetElementNum(a_count);
00496 
00497         // Most probably must these be set to false
00498         res.SetCurData(false);
00499         res.SetDeviceId(false);
00500 
00501         res.SetVolTag(barcodeStatus);
00502 
00503         m_hasBarcodeReader = barcodeStatus;
00504 
00505         m_scsi->IOCtl(res, scsi_TIMEOUT_LONG_d);
00506 
00507         // OK. We have the status. Let's extract it out.
00508         est2.ParseElemStatus(elemStatus);
00509     }
00510     else {
00511         // OK. We have the status. Let's extract it out.
00512         est.ParseElemStatus(elemStatus);
00513     }
00514     return elemStatus;
00515 }

Here is the call graph for this function:

Here is the caller graph for this function:

void la_SCSILibrary::ReadElementAssignment (  )  [private]

Definition at line 694 of file la_scsi.cpp.

References data_ModeElemAddr_t::addr, data_ModeElemAddr_t::blk, data_ModeHdr_t::blkDescLen, cmn_Num2Str(), data_ModeElemAddrPage_t::code, dbg_NORM, data_ModeElemAddrPage_t::deviceAddr, data_ModeElemAddrPage_t::deviceNumber, data_Mode_t::elem, data_Mode::GetModeStruct(), data_Mode_t::hdr, ie_DATA_CORRUPTION, data_ModeElemAddrPage_t::impexAddr, data_ModeElemAddrPage_t::impexNumber, scsi_IO::IOCtl(), log_DBG_m, log_FUNC_m, log_MARKLINE_m, m_driveNum, m_driveStartAddr, m_impexNum, m_impexStartAddr, m_scsi, m_slotNum, m_slotStartAddr, m_transNum, m_transStartAddr, ntoh(), data_Mode::pg_ELEMADDR, data_ModeElemAddrPage_t::storageAddr, data_ModeElemAddrPage_t::storageNumber, data_ModeElemAddrPage_t::transpAddr, and data_ModeElemAddrPage_t::transpNumber.

Referenced by Inventory(), and Open().

00694                                            {
00695     log_FUNC_m(ReadElementAssignment);
00696 
00697     data_Mode ea(data_Mode::pg_ELEMADDR);
00698     cdb_ModeSense  modesns(ea);
00699 
00700     log_DBG_m(dbg_NORM, "Getting exchanger element assignment page.");
00701     m_scsi->IOCtl(modesns);
00702 
00703     const data_Mode_t               &eaData = ea.GetModeStruct();
00704     const data_ModeElemAddrPage_t   &eaPage =
00705         (eaData.hdr.blkDescLen == 0)
00706         ? (eaData.elem.addr)
00707         : (eaData.elem.blk.addr);
00708 
00709     if (eaPage.code != data_Mode::pg_ELEMADDR) {
00710         log_MARKLINE_m;
00711         throw ivd_InternalError(
00712             ie_DATA_CORRUPTION,
00713             string("MODE SELECT: Expected Page Element Address (0x1D), got ") +
00714             cmn_Num2Str(eaPage.code, true) );
00715     }
00716 
00717     scsi_Wrapper16 addrW(eaPage.transpAddr);
00718     scsi_Wrapper16 transW(eaPage.transpNumber);
00719     m_transStartAddr    = ntoh(addrW);
00720     m_transNum          = ntoh(transW);
00721 
00722     addrW = eaPage.storageAddr;
00723     transW = eaPage.storageNumber;
00724     m_slotStartAddr    = ntoh(addrW);
00725     m_slotNum          = ntoh(transW);
00726 
00727     addrW = eaPage.impexAddr;
00728     transW = eaPage.impexNumber;
00729     m_impexStartAddr    = ntoh(addrW);
00730     m_impexNum          = ntoh(transW);
00731 
00732     addrW = eaPage.deviceAddr;
00733     transW = eaPage.deviceNumber;
00734     m_driveStartAddr    = ntoh(addrW);
00735     m_driveNum          = ntoh(transW);
00736 }

Here is the call graph for this function:

Here is the caller graph for this function:

void la_SCSILibrary::EjectMedium ( UInt16_t  a_drive,
const string &  a_barcode 
) [private]

Definition at line 517 of file la_scsi.cpp.

References scsi_IO::Close(), cmn_Num2Str(), dbg_NORM, dt_TAPE, evt_ERROR, evt_WARNING, scsi_IO::GetDeviceType(), ivd_BaseException::GetError(), ivd_BaseException::GetFriendly(), HandleDriveError(), ie_BEA_INVDEVTYPE, ie_LA_OUTOFRANGE, ie_LA_UNCONFIGURED, ie_SCSI_NO_MEDIUM, scsi_IO::IOCtl(), ivd_Error, log_DBG_m, log_ERR_m, log_FUNC_m, log_WriteEvent(), log_WRN_m, m_driveID, m_drives_x, NULL, scsi_IO::Open(), scsi_GetDeviceTypeText(), and scsi_IO::WaitToBecomeReady().

Referenced by Unload().

00517                                                                           {
00518     log_FUNC_m(EjectMedium);
00519 
00520     log_DBG_m(dbg_NORM, "Ejecting medium from drive #" << a_drive);
00521 
00522     if (a_drive == 0 || ( a_drive > m_driveID.size()) ) {
00523         throw ivd_Error(
00524             ie_LA_OUTOFRANGE,
00525             cmn_Num2Str(a_drive) + " > " +
00526             cmn_Num2Str(m_driveID.size()) );
00527     };
00528 
00529     scsi_IO* drive_p(NULL);
00530     auto_ptr<scsi_IO> drive_ap(NULL);
00531     string driveDevID;
00532     {
00533         cmn_MutexLock l(m_drives_x);
00534 
00535         driveDevID = m_driveID[a_drive - 1].scsiID;
00536         if ( driveDevID.empty() ) {
00537 
00538             log_WRN_m("Medium eject attempted on non-configured drive index: " << a_drive);
00539 
00540             throw ivd_Error(
00541                 ie_LA_UNCONFIGURED,
00542                 string("Drive index ") + cmn_Num2Str(a_drive) );
00543         };
00544 
00545 #if TGT_OS_linux
00546         drive_p = new scsi_LnxSG(driveDevID);
00547 #elif TGT_OS_windows
00548         drive_p = new scsi_WinSG(driveDevID);
00549 #endif
00550 
00551         // Auto pointer will de-allocate allocated object
00552         drive_ap.reset(drive_p);
00553     }
00554 
00555     try {
00556         drive_p->Open();
00557 
00558         if (drive_p->GetDeviceType() != dt_TAPE) {
00559             ostringstream sstr;
00560             sstr
00561                 << "Expected a tape drive to eject medium, but found "
00562                 << scsi_GetDeviceTypeText(drive_p->GetDeviceType())
00563                 << ".";
00564             log_WriteEvent(evt_ERROR, sstr.str());
00565 
00566             throw ivd_Error(ie_BEA_INVDEVTYPE,
00567                 string("a_scsiID: ") + driveDevID +
00568                 string(" type: ") +
00569                 scsi_GetDeviceTypeText(drive_p->GetDeviceType()));
00570         };
00571 
00572         drive_p->WaitToBecomeReady();
00573 
00574         cdb_LoadUnload unload(false);
00575         drive_p->IOCtl(unload);
00576 
00577         drive_p->Close();
00578     }
00579     catch (ivd_Error &ie) {
00580         if (ie.GetError() == ie_SCSI_NO_MEDIUM) {
00581             ostringstream sstr;
00582             sstr
00583                 << "No medium in drive with index " << a_drive
00584                 << ". Will try to move medium anyway.";
00585             log_WriteEvent(evt_WARNING, sstr.str());
00586         }
00587         else {
00588             log_WRN_m(
00589                 "Caught ivd_Error when trying to eject the medium from " <<
00590                 a_drive << " " << driveDevID << ". Error: " << endl <<
00591                 ie);
00592 
00593             ostringstream sstr;
00594             sstr
00595                 << "Eject medium on unload FAILED. Possible hardware problem. ("
00596                 << ie.GetFriendly() << ").";
00597 
00598             log_WriteEvent(evt_ERROR, sstr.str());
00599             HandleDriveError(ie, a_drive, a_barcode);
00600             throw;
00601         }
00602     }
00603     catch (ivd_BaseException &ie) {
00604         log_ERR_m(
00605             "Caught ivd_Exception when trying to eject the medium from " <<
00606             a_drive << " " << driveDevID << ". Error: " << endl <<
00607             ie);
00608 
00609         ostringstream sstr;
00610         sstr
00611             << "Eject medium on unload FAILED. Possible hardware problem. ("
00612             << ie.GetFriendly() << ").";
00613 
00614         log_WriteEvent(evt_ERROR, sstr.str());
00615 
00616         throw;
00617     }
00618     catch (...) {
00619         log_ERR_m(
00620             "Caught unknown exception when trying to eject the medium from " <<
00621             a_drive << " " << driveDevID << ".");
00622 
00623         log_WriteEvent(evt_ERROR,
00624             "Eject medium on unload FAILED. Possible hardware problem.");
00625 
00626         throw;
00627     }
00628 }

Here is the call graph for this function:

Here is the caller graph for this function:

void la_SCSILibrary::HandleDriveError ( const ivd_Error a_ie,
UInt32_t  a_drv,
const string &  a_bc 
) [private]

Definition at line 631 of file la_scsi.cpp.

References dbg_LOW, evt_ERROR, evt_WARNING, ivd_BaseException::GetError(), ivd_BaseException::GetFriendly(), ie_SCSI_HOST, ie_SCSI_HWERR, ie_SCSI_MEDERR, ie_SCSI_NOT_READY, ie_SCSI_PROTECTED, ipc_EXEC_m, log_DBG_m, log_FUNC_m, log_WriteEvent(), m_driveID, ipc_Corba::ResolveRM(), and rmdb_MEDIUM_UNUSABLE.

Referenced by EjectMedium().

00632                                                                {
00633     
00634     log_FUNC_m(HandleDriveError);
00635 
00636     try {
00637         i_ResourceManager_var rm;
00638         i_Drive_t_var drv;
00639         ipc_EXEC_m (
00640             CORBA::Object_var obj = ipc_Corba::ResolveRM();
00641             rm = i_ResourceManager::_narrow(obj);
00642             drv = rm->SelectDriveByKey(m_driveID[a_drv - 1].drvKey);
00643         );
00644 
00645         switch (a_ie.GetError()) {
00646             case ie_SCSI_HOST:
00647             case ie_SCSI_HWERR:
00648             case ie_SCSI_MEDERR:
00649             case ie_SCSI_NOT_READY:
00650                 {
00651                     log_DBG_m (dbg_LOW, "Setting drive error for drive " << a_drv);
00652                     ipc_EXEC_m (
00653                         rm->DriveError(m_driveID[a_drv - 1].drvKey);
00654                     );
00655                     ostringstream sdrive;
00656                     sdrive
00657                         << "Drive " <<  string(drv->driveName)
00658                         << " marked bad.";
00659                     log_WriteEvent(evt_ERROR, sdrive.str());
00660                 }
00661                 // intentionally continuing to the next case
00662             case ie_SCSI_PROTECTED:
00663                 if (a_ie.GetError() != ie_SCSI_HWERR) {
00664                     ipc_EXEC_m (
00665                         rm->MediumStatusSet(
00666                             CORBA::string_dup(a_bc.c_str()), rmdb_MEDIUM_UNUSABLE);
00667                     );
00668                     ostringstream smedium;
00669                     smedium << "Medium bc:" << a_bc << " marked as unusable.";
00670                     log_WriteEvent(evt_ERROR, smedium.str());
00671                 }
00672                 break;
00673             default:
00674                 {
00675                     ostringstream sstr;
00676                     sstr
00677                         << "Ignoring error when unloading medium from drive: "
00678                         << a_ie.GetFriendly();
00679                     log_WriteEvent(evt_WARNING, sstr.str());
00680                 }
00681                 break;
00682         };
00683     }
00684     catch(const ivd_Exception& ie) {
00685         log_DBG_m(dbg_LOW, "Ignore exception when marking drive/medium: " << ie.GetFriendly());
00686     }
00687     catch (...) {
00688         log_DBG_m(dbg_LOW, "Ignore exception when marking drive/medium.");
00689     }
00690 }

Here is the call graph for this function:

Here is the caller graph for this function:

UInt16_t la_SCSILibrary::GetTransElemAddr ( UInt16_t  a_seqNum  )  [private]

Definition at line 739 of file la_scsi.cpp.

References ie_INVALID_ARG, ivd_Error, log_FUNC_A_m, m_transNum, and m_transStartAddr.

00739                                                            {
00740     if ((a_seqNum - 1) > m_transNum) {
00741         log_FUNC_A_m(GetTransElemAddr, "seqNum: " << a_seqNum);
00742         throw ivd_Error(ie_INVALID_ARG, "Sequence number out of range.", true);
00743     }
00744     return (m_transStartAddr + (a_seqNum - 1));
00745 }

UInt16_t la_SCSILibrary::GetSlotElemAddr ( UInt16_t  a_seqNum  )  [private]

Definition at line 747 of file la_scsi.cpp.

References ie_INVALID_ARG, ivd_Error, log_FUNC_A_m, m_slotNum, and m_slotStartAddr.

Referenced by Load(), and Unload().

00747                                                            {
00748     if ((a_seqNum - 1) > m_slotNum) {
00749         log_FUNC_A_m(GetSlotElemAddr, "seqNum: " << a_seqNum);
00750         throw ivd_Error(ie_INVALID_ARG, "Sequence number out of range.", true);
00751     }
00752     return (m_slotStartAddr + (a_seqNum - 1));
00753 }

Here is the caller graph for this function:

UInt16_t la_SCSILibrary::GetImpExElemAddr ( UInt16_t  a_seqNum  )  [private]

Definition at line 755 of file la_scsi.cpp.

References ie_INVALID_ARG, ivd_Error, log_FUNC_A_m, m_impexNum, and m_impexStartAddr.

00755                                                            {
00756     if ((a_seqNum - 1) > m_impexNum) {
00757         log_FUNC_A_m(GetImpExElemAddr, "seqNum: " << a_seqNum);
00758         throw ivd_Error(ie_INVALID_ARG, "Sequence number out of range.", true);
00759     }
00760     return (m_impexStartAddr + (a_seqNum - 1));
00761 }

UInt16_t la_SCSILibrary::GetDriveElemAddr ( UInt16_t  a_seqNum  )  [private]

Definition at line 763 of file la_scsi.cpp.

References ie_INVALID_ARG, ivd_Error, log_FUNC_A_m, m_driveNum, and m_driveStartAddr.

Referenced by Load(), and Unload().

00763                                                            {
00764     if ((a_seqNum - 1) > m_driveNum) {
00765         log_FUNC_A_m(GetDriveElemAddr, "seqNum: " << a_seqNum);
00766         throw ivd_Error(ie_INVALID_ARG, "Sequence number out of range.", true);
00767     }
00768     return (m_driveStartAddr + (a_seqNum - 1));
00769 }

Here is the caller graph for this function:


Member Data Documentation

Definition at line 71 of file la_scsi.h.

Definition at line 73 of file la_scsi.h.

Referenced by Inventory(), Load(), and Unload().

Definition at line 74 of file la_scsi.h.

Referenced by EjectMedium().

string la_SCSILibrary::m_deviceID [private]

Definition at line 77 of file la_scsi.h.

Referenced by Open(), SetDeviceID(), and Status().

Device IDs of the drives that are used at Unload operation with some specific libraries.

Definition at line 83 of file la_scsi.h.

Referenced by EjectMedium(), and HandleDriveError().

Definition at line 87 of file la_scsi.h.

Referenced by HasBarcodeReader(), Load(), Open(), Status(), and Unload().

Definition at line 88 of file la_scsi.h.

Definition at line 89 of file la_scsi.h.

Referenced by MustRequestEject(), Open(), and Unload().

Definition at line 93 of file la_scsi.h.

Referenced by GetTransElemAddr(), Load(), Open(), ReadElementAssignment(), and Unload().

Definition at line 94 of file la_scsi.h.

Referenced by GetTransElemAddr(), Open(), and ReadElementAssignment().

Definition at line 96 of file la_scsi.h.

Referenced by GetSlotElemAddr(), Inventory(), Open(), and ReadElementAssignment().

Definition at line 97 of file la_scsi.h.

Referenced by GetSlotElemAddr(), Inventory(), Open(), and ReadElementAssignment().

Definition at line 99 of file la_scsi.h.

Referenced by GetImpExElemAddr(), Inventory(), Open(), and ReadElementAssignment().

Definition at line 100 of file la_scsi.h.

Referenced by GetImpExElemAddr(), Inventory(), Open(), and ReadElementAssignment().

Definition at line 102 of file la_scsi.h.

Referenced by GetDriveElemAddr(), Inventory(), Open(), and ReadElementAssignment().

Definition at line 103 of file la_scsi.h.

Referenced by GetDriveElemAddr(), GetNumDrives(), Inventory(), Open(), and ReadElementAssignment().


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

Generated on Mon Feb 27 19:42:34 2012 for OPENARCHIVE by  doxygen 1.5.6