#include <la_scsi.h>

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_IO * | m_scsi |
| string | m_deviceID |
| vector< DriveInfo > | m_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 |
| 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 }

| 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 }


| 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 }


| 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 }


| 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(); };


| 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(); };


| 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(); };


| 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(); };


| 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().


| 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 }


Load a tape from a slot into a drive.
IVD sequence numbers are used and are converted internally to low level (hardware) numbers.
| 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 }


Unload a tape from a drive into a slot.
IVD sequence numbers are used and are converted internally to low level (hardware) numbers.
| 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 }


| 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 }

| void la_SCSILibrary::SetDriveIDs | ( | vector< DriveInfo > & | a_driveIDs | ) |
Referenced by i_LibraryAgentSCSI_i::Reconfigure(), and i_LibraryAgentSCSI_i::Unload().

| 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 }

| 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 }

| 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 }


| 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 }


| 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 }


| 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 }


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 }
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 }

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 }
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 }

la_SCSILibrary::log_CLASSID_m [private] |
cmn_Mutex la_SCSILibrary::m_library_x [private] |
cmn_Mutex la_SCSILibrary::m_drives_x [private] |
scsi_IO* la_SCSILibrary::m_scsi [private] |
Definition at line 76 of file la_scsi.h.
Referenced by Close(), GetProductID(), GetProductRevision(), GetSCSIID(), GetSerialNumber(), GetVendorID(), Inventory(), la_SCSILibrary(), Load(), Open(), ReadElementAssignment(), SetDeviceID(), Status(), Unload(), and ~la_SCSILibrary().
string la_SCSILibrary::m_deviceID [private] |
vector<DriveInfo> la_SCSILibrary::m_driveID [private] |
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().
bool la_SCSILibrary::m_hasBarcodeReader [private] |
bool la_SCSILibrary::m_hasMICReader [private] |
bool la_SCSILibrary::m_mustRequestEject [private] |
UInt16_t la_SCSILibrary::m_transStartAddr [private] |
Definition at line 93 of file la_scsi.h.
Referenced by GetTransElemAddr(), Load(), Open(), ReadElementAssignment(), and Unload().
UInt16_t la_SCSILibrary::m_transNum [private] |
Definition at line 94 of file la_scsi.h.
Referenced by GetTransElemAddr(), Open(), and ReadElementAssignment().
UInt16_t la_SCSILibrary::m_slotStartAddr [private] |
Definition at line 96 of file la_scsi.h.
Referenced by GetSlotElemAddr(), Inventory(), Open(), and ReadElementAssignment().
UInt16_t la_SCSILibrary::m_slotNum [private] |
Definition at line 97 of file la_scsi.h.
Referenced by GetSlotElemAddr(), Inventory(), Open(), and ReadElementAssignment().
UInt16_t la_SCSILibrary::m_impexStartAddr [private] |
Definition at line 99 of file la_scsi.h.
Referenced by GetImpExElemAddr(), Inventory(), Open(), and ReadElementAssignment().
UInt16_t la_SCSILibrary::m_impexNum [private] |
Definition at line 100 of file la_scsi.h.
Referenced by GetImpExElemAddr(), Inventory(), Open(), and ReadElementAssignment().
UInt16_t la_SCSILibrary::m_driveStartAddr [private] |
Definition at line 102 of file la_scsi.h.
Referenced by GetDriveElemAddr(), Inventory(), Open(), and ReadElementAssignment().
UInt16_t la_SCSILibrary::m_driveNum [private] |
Definition at line 103 of file la_scsi.h.
Referenced by GetDriveElemAddr(), GetNumDrives(), Inventory(), Open(), and ReadElementAssignment().
1.5.6