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

bea_TapeMedium Class Reference
[IVD Back-End Agent]

#include <bea_tapemedium.h>

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

List of all members.

Public Member Functions

 bea_TapeMedium (scsi_IO *const a_scsiIO_p)
virtual void ChangeVolume (UInt32_t a_volNum, UInt32_t a_block=0)
virtual UInt32_t ReadCurrentVolume ()
virtual void Format (vector< UInt32_t > a_volSizes, bool a_duplAITMode)
virtual void AppendVolume (UInt32_t a_volSize)

Protected Member Functions

virtual ~bea_TapeMedium ()
virtual void Refresh ()

Private Member Functions

void RefreshTapeInfo ()
void RefreshMemoryInfo ()
void DetectAITWORM ()
void DetectLTOWORM ()
void RefreshCompressionState ()

Private Attributes

 log_CLASSID_m
scsi_IO *const m_scsiIO_p
auto_ptr< bea_MediumMemorym_mediumMem

Detailed Description

Definition at line 42 of file bea_tapemedium.h.


Constructor & Destructor Documentation

bea_TapeMedium::bea_TapeMedium ( scsi_IO *const   a_scsiIO_p  ) 

Definition at line 55 of file bea_tapemedium.cpp.

References bmf_AIT, bmf_LTO, bmf_SAIT, dbg_LOW, log_DBG_m, log_FUNC_m, bea_Medium::m_mediumFamily, m_mediumMem, RefreshMemoryInfo(), RefreshTapeInfo(), and bea_Medium::SetMediumMem().

    : m_scsiIO_p(a_scsiIO_p) {

    log_FUNC_m(bea_TapeMedium);

    RefreshTapeInfo();

    switch (m_mediumFamily) {
        case bmf_AIT: {
            m_mediumMem.reset(new bea_MicMemory(a_scsiIO_p));
            log_DBG_m(dbg_LOW, "MIC Object created.");
            break;
        }
        case bmf_LTO:
        case bmf_SAIT: {
            m_mediumMem.reset(new bea_MamMemory(a_scsiIO_p));
            log_DBG_m(dbg_LOW, "MAM Object created.");
            break;
        }
        default: {
            log_DBG_m(dbg_LOW, "No CM Object created.");
            break;
        }
    } // switch (m_mediumFamily)
    SetMediumMem(m_mediumMem.get());

    // Detect CM and refresh data from CM
    RefreshMemoryInfo();
}

Here is the call graph for this function:

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

Definition at line 87 of file bea_tapemedium.cpp.

References log_FUNC_m.


Member Function Documentation

void bea_TapeMedium::AppendVolume ( UInt32_t  a_volSize  )  [virtual]

Implements bea_Medium.

Definition at line 341 of file bea_tapemedium.cpp.

References bmf_AIT, bea_Medium::GetMediumFamily(), ie_BEA_FORMAT, scsi_IO::IOCtl(), ivd_Error, log_FUNC_A_m, m_scsiIO_p, data_Mode::pg_AIT_APPENDPART, data_Mode::pg_PART, Refresh(), scsi_TIMEOUT_FORMAT_d, data_Mode::SetPage(), and data_Mode::SetPartitions().

                                                    {
    log_FUNC_A_m(AppendVolume, "size: " << a_volSize);

    if (GetMediumFamily() != bmf_AIT) {
        log_MARKLINE_m;
        throw ivd_Error(
            ie_BEA_FORMAT, "Appending volumes on non-AIT medium not possible.");
    };

    data_Mode pi(data_Mode::pg_PART);
    cdb_ModeSense  partInfo(pi);
    m_scsiIO_p->IOCtl(partInfo);

    pi.SetPage(data_Mode::pg_AIT_APPENDPART);

    vector<UInt32_t> psize;
    psize.push_back(a_volSize);

    pi.SetPartitions(psize);
    cdb_ModeSelect partSel(pi);
    m_scsiIO_p->IOCtl(partSel, scsi_TIMEOUT_FORMAT_d);

    // Re-read object properties.
    Refresh();
}

Here is the call graph for this function:

void bea_TapeMedium::ChangeVolume ( UInt32_t  a_volNum,
UInt32_t  a_block = 0 
) [virtual]

Implements bea_Medium.

Definition at line 108 of file bea_tapemedium.cpp.

References dbg_NORM, bea_Medium::DoMediumLogging(), bea_Medium::GetCurrentVolume(), ivd_BaseException::GetError(), bea_Medium::GetJobID(), bea_Volume::GetVolumeNumber(), ie_INVALID_ARG, ie_MEDIUM_BLANK, ie_MEDIUM_EOD, bea_Volume::InvalidateEOD(), scsi_IO::IOCtl(), log_DBG_m, log_FUNC_A_m, log_WriteEvent(), bea_Medium::m_barcode, m_scsiIO_p, ReadCurrentVolume(), cdb_Locate::SetBlockNum(), bea_Medium::SetCurrentVolume(), cdb_Locate::SetPartitionNum(), and str.

                                                                     {
    log_FUNC_A_m(ChangeVolume,
        "volume: " << a_volNum <<
        " blk: " << a_block);

    if (a_volNum < 1) {
        throw ivd_InternalError(
            ie_INVALID_ARG, "Media volume number must be greater than 0.");
    };

    UInt32_t curVolume = ReadCurrentVolume();
    cdb_Locate  pos;

    GetCurrentVolume()->InvalidateEOD();  // sets m_atEOD = false;

    if (curVolume != a_volNum) {
        pos.SetPartitionNum(UInt8_t(a_volNum) - 1);
    }
    pos.SetBlockNum(a_block);

    bool retried(false);

    if (DoMediumLogging()) {
        ostringstream str;
        str << "Vol " << GetCurrentVolume()->GetVolumeNumber()
            << ": Changing to volume " << a_volNum << "...";

        log_WriteEvent(str.str(), "", GetJobID(), m_barcode);
    }

    while (true) {
        try {
            m_scsiIO_p->IOCtl(pos);
            SetCurrentVolume(a_volNum);
            break;
        }
        catch (const ivd_Error &ie) {
            if (ie.GetError() == ie_MEDIUM_BLANK ||
                ie.GetError() == ie_MEDIUM_EOD ||
                ie.GetError() == ie_MEDIUM_EOM) {

                if (a_block == 0) {
                    log_DBG_m(dbg_NORM,
                        "Got blank check on positioning to the beginning. Ignore.");
                    break;
                }
                else {
                    throw;
                }
            }
            else if (!retried && ie.GetError() == ie_SCSI_NOT_READY) {
                log_DBG_m(dbg_NORM,
                    "Not yet ready. Try once more.");
                retried = true;
            }
            else {
                throw;
            }
        }
    };
}

Here is the call graph for this function:

void bea_TapeMedium::DetectAITWORM (  )  [private]

Definition at line 596 of file bea_tapemedium.cpp.

References data_Mode_t::ait, data_ModeAIT_t::aitPage, dbg_NORM, ivd_BaseException::GetFriendly(), data_Mode::GetModeStruct(), scsi_IO::IOCtl(), log_DBG_m, log_FUNC_m, m_scsiIO_p, data_Mode::pg_AITCFG, bea_Medium::SetWORM(), and data_ModeAITConfigPage_t::worm.

Referenced by RefreshTapeInfo().

                                   {
    log_FUNC_m(DetectAITWORM);

    try {
        data_Mode ad(data_Mode::pg_AITCFG);
        cdb_ModeSense  aitInfo(ad);
        m_scsiIO_p->IOCtl(aitInfo);

        if (ad.GetModeStruct().ait.aitPage.worm == 1) {
            log_DBG_m(dbg_NORM, "AIT WORM tape detected.");

            SetWORM(true);
        }
    }
    catch (const ivd_Error &ie) {
        log_DBG_m(dbg_NORM, "Can't detect AIT WORM: " << ie.GetFriendly());
    }
    catch (...) {
        log_DBG_m(dbg_NORM, "ERROR: Can't detect AIT WORM.");
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_TapeMedium::DetectLTOWORM (  )  [private]

Definition at line 618 of file bea_tapemedium.cpp.

References dbg_LOW, dbg_NORM, ivd_BaseException::GetFriendly(), scsi_IO::IOCtl(), data_Mode::IsMediumWORM(), log_DBG_m, log_FUNC_m, m_scsiIO_p, data_Mode::pg_DEVCFG, and bea_Medium::SetWORM().

Referenced by RefreshTapeInfo().

                                   {
    log_FUNC_m(DetectLTOWORM);

    try {
        data_Mode       devCfg(data_Mode::pg_DEVCFG);
        cdb_ModeSense   modeSns(devCfg);

        m_scsiIO_p->IOCtl(modeSns);
        bool ltoWORM(devCfg.IsMediumWORM());
        log_DBG_m(dbg_LOW, "LTO medium type WORM: " << ltoWORM);
        SetWORM(ltoWORM);
    }
    catch (const ivd_Error &ie) {
        log_DBG_m(dbg_NORM, "Can't detect LTO WORM: " << ie.GetFriendly());
    }
    catch (...) {
        log_DBG_m(dbg_NORM, "ERROR: Can't detect LTO WORM.");
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_TapeMedium::Format ( vector< UInt32_t a_volSizes,
bool  a_duplAITMode 
) [virtual]

Implements bea_Medium.

Definition at line 172 of file bea_tapemedium.cpp.

References df_TCMMedium_t::barcode, bmf_AIT, bmf_LTO, bmf_SAIT, bmf_VXA, bmt_AIT5, dbg_LOW, dbg_NORM, bea_Volume::Erase(), evt_WARNING, bea_Medium::GetBarcode(), ivd_BaseException::GetFriendly(), bea_Medium::GetJobID(), bea_Medium::GetMediumFamily(), scsi_IO::GetProductID(), scsi_IO::GetProductRevision(), scsi_IO::GetProductSerialNumber(), scsi_IO::GetVendorID(), bea_Medium::GetVolume(), bea_Medium::GetVolumeCount(), ie_BEA_FORMAT, scsi_IO::IOCtl(), bea_Medium::IsWORM(), ivd_Error, df_TCMMedium_t::loadCount, log_DBG_m, log_FUNC_A_m, log_WriteEvent(), m_mediumMem, bea_Medium::m_mediumType, m_scsiIO_p, mode_AIT, mode_DDS, data_Mode::pg_AITCFG, data_Mode::pg_PART, df_TCMMedium_t::productID, bea_Volume::ReadVolInfoFromHeader(), Refresh(), df_TCMMedium_t::revisionID, bea_Volume::Rewind(), scsi_TIMEOUT_FORMAT_d, df_TCMMedium_t::serialNumber, data_Mode::SetAITMode(), data_Mode::SetAITUnloadAtPBOT(), data_Mode::SetPartitions(), df_TCMMedium_t::vendorID, VOL_BLANK, and VOL_OTHER.

                                                                           {
    log_FUNC_A_m(Format, "# volumes:" << a_volSizes.size() );

    if (IsWORM()) {
        if (GetVolumeCount() > 1) {
            log_MARKLINE_m;
            throw ivd_Error(
                ie_BEA_FORMAT, "WORM medium: medium already has volumes.");
        };

        // Verify volume type and prevent formatting non-blank media.
        if (GetVolume(1)->GetVolumeType() == VOL_OTHER) {
            GetVolume(1)->ReadVolInfoFromHeader();
        }

        if (GetVolume(1)->GetVolumeType() != VOL_BLANK) {
            log_MARKLINE_m;
            throw ivd_Error(ie_BEA_FORMAT, "WORM medium: volume is not blank.");
        }
    } // if (IsWORM())

    UInt32_t oldLoadCount(0);

    if (m_mediumMem->IsValid()) {
        try {
            // Get old CM volume note
            oldLoadCount = m_mediumMem->GetMediumRecord().loadCount;
        }
        catch (ivd_Exception &ie) {
            log_DBG_m(dbg_LOW, "Get medium record failed. " << ie);
        };
    };

    switch (GetMediumFamily()) {
        case bmf_LTO:
        case bmf_VXA:
        case bmf_SAIT: {
            log_DBG_m(dbg_LOW,
                "Dummy format of LTO/SAIT/VXA medium (1 volume): Erasing single medium volume.");
            if (a_volSizes.size() == 1) {
                GetVolume(1)->Rewind();
                GetVolume(1)->Erase();
            }
            else {
                log_MARKLINE_m;
                throw ivd_Error(
                    ie_BEA_FORMAT, "Multi-volume format of non-AIT tape medium not possible.");
            }
            break;
        }
        case bmf_AIT: {
            // Acquire current settings
            data_Mode ad(data_Mode::pg_AITCFG);
            data_Mode pi(data_Mode::pg_PART);

            cdb_ModeSense  aitInfo(ad);
            cdb_ModeSense  partInfo(pi);

            log_DBG_m(dbg_NORM, "Getting AIT/medium volume info.");
            m_scsiIO_p->IOCtl(aitInfo);
            m_scsiIO_p->IOCtl(partInfo);

            // Set new settings and media volume sizes
            if ( a_volSizes.size() != 1 
                 ||  a_duplAITMode 
                 ||  m_mediumType == bmt_AIT5 ){
                log_DBG_m(dbg_NORM, "Setting AIT mode.");
                ad.SetAITMode(mode_AIT);
            }
            else {
                log_DBG_m(dbg_NORM, "Setting DDS mode.");
                ad.SetAITMode(mode_DDS);             
            }

            if ( m_mediumType == bmt_AIT5){
                log_DBG_m(dbg_NORM, "AIT5: setting ulpbot bit");
                ad.SetAITUnloadAtPBOT(1);
            }

            cdb_ModeSelect aitSel(ad);
            m_scsiIO_p->IOCtl(aitSel);

            pi.SetPartitions(a_volSizes);
            cdb_ModeSelect partSel(pi);

            // Format tape (MIC content is lost).
            log_DBG_m(dbg_LOW, "Creating medium volumes. (Will take a long time > 60 minutes.");
            m_scsiIO_p->IOCtl(partSel, scsi_TIMEOUT_FORMAT_d);
            log_DBG_m(dbg_NORM, "Medium volumes created. ");

            break;
        }
        default: {
            log_MARKLINE_m;
            throw ivd_Error(
            ie_BEA_FORMAT, "Unsupported tape medium family!");
            break;
        }
    }
    Refresh();
    m_mediumMem->ClearRecords();

    if (m_mediumMem->IsDetected()) {
        try {
            df_TCMMedium_t mediumNote;

            mediumNote.loadCount = oldLoadCount;

            memcpy(mediumNote.barcode, GetBarcode().data(), GetBarcode().length());
            mediumNote.barcode[GetBarcode().length()] = '\0';

            // NOTE: It does not include the trailing \0
            memcpy(
                mediumNote.vendorID,
                m_scsiIO_p->GetVendorID().data(),
                m_scsiIO_p->GetVendorID().length() );

            // NOTE: It does not include the trailing \0
            memcpy(
                mediumNote.productID,
                m_scsiIO_p->GetProductID().data(),
                m_scsiIO_p->GetProductID().length() );

            // NOTE: It does not include the trailing \0
            memcpy(
                mediumNote.revisionID,
                m_scsiIO_p->GetProductRevision().data(),
                m_scsiIO_p->GetProductRevision().length() );

            // NOTE: Trailing \0 is provided by constructor, which sets
            // everything to 0.
            memcpy(
                mediumNote.serialNumber,
                m_scsiIO_p->GetProductSerialNumber().data(),
                m_scsiIO_p->GetProductSerialNumber().length() );

            m_mediumMem->UpdateMediumRecord(mediumNote);
            m_mediumMem->Write();

            log_DBG_m(dbg_LOW,
                "Available space in CM after format: " <<
                m_mediumMem->GetAvailable() );
        }
        catch (ivd_Exception &ie) {
            ostringstream sstr;
            sstr
                << "Creating records in CM FAILED ("
                << ie.GetFriendly() << ").";

            log_WriteEvent(
                evt_WARNING,
                sstr.str(),
                "",
                GetJobID(),
                GetBarcode());
        }
        catch(...) {
            log_WriteEvent(
                evt_WARNING,
                "Creating records in CM FAILED.",
                "",
                GetJobID(),
                GetBarcode());
        }
    } // if (m_mediumMem->IsDetected())
}

Here is the call graph for this function:

UInt32_t bea_TapeMedium::ReadCurrentVolume (  )  [virtual]

Implements bea_Medium.

Definition at line 93 of file bea_tapemedium.cpp.

References dbg_DETAIL, data_Mode::GetCurPartNumber(), bea_Medium::GetCurVolNumber(), scsi_IO::IOCtl(), log_DBG_m, log_FUNC_m, m_scsiIO_p, data_Mode::pg_DEVCFG, and bea_Medium::SetCurrentVolume().

Referenced by ChangeVolume(), and RefreshTapeInfo().

                                           {
    log_FUNC_m(ReadCurrentVolume);

    data_Mode       devCfg(data_Mode::pg_DEVCFG);
    cdb_ModeSense   modeSns(devCfg);

    m_scsiIO_p->IOCtl(modeSns);
    log_DBG_m(dbg_DETAIL,"Current partition: " << (devCfg.GetCurPartNumber() + 1))
    SetCurrentVolume(devCfg.GetCurPartNumber() + 1);

    return GetCurVolNumber();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_TapeMedium::Refresh (  )  [protected, virtual]

Implements bea_Medium.

Definition at line 369 of file bea_tapemedium.cpp.

References log_FUNC_m, RefreshMemoryInfo(), and RefreshTapeInfo().

Referenced by AppendVolume(), and Format().

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_TapeMedium::RefreshCompressionState (  )  [private]

Definition at line 641 of file bea_tapemedium.cpp.

References bea_hsmCompression_c(), cmn_GetEnvVariable(), cmn_StrUpperCase(), dbg_LOW, data_Mode::GetCompressionStatus(), scsi_IO::IOCtl(), log_DBG_m, log_FUNC_m, m_scsiIO_p, data_Mode::pg_COMPRESSION, and data_Mode::SetCompressionStatus().

Referenced by RefreshTapeInfo().

                                             {
    log_FUNC_m(RefreshCompressionInfo);

    string hsmCompression = cmn_GetEnvVariable(bea_hsmCompression_c);
    cmn_StrUpperCase(hsmCompression);
    if (hsmCompression != "ON" && hsmCompression != "OFF") {
        log_DBG_m(dbg_LOW, "Compression variable not set");
        return;
    }
    log_DBG_m(dbg_LOW, bea_hsmCompression_c << " = " << hsmCompression << ".");    

    data_Mode ci(data_Mode::pg_COMPRESSION);
    cdb_ModeSense  compressInfo(ci);
    
    m_scsiIO_p->IOCtl(compressInfo);
    
    bool compressOldValue = ci.GetCompressionStatus();

    if (hsmCompression.compare("OFF") == 0) {   // Turn compression OFF
        ci.SetCompressionStatus(false);
    }
    else {                                      // Turn compression ON
        ci.SetCompressionStatus(true);
    }

    // Set new status only if new value is not equal to old value
    if (compressOldValue != ci.GetCompressionStatus()) 
    {
        cdb_ModeSelect compressSel(ci);
        m_scsiIO_p->IOCtl(compressSel);         
    }    
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_TapeMedium::RefreshMemoryInfo (  )  [private]

Definition at line 555 of file bea_tapemedium.cpp.

References df_TCMMedium_t::barcode, dbg_NORM, ivd_BaseException::GetFriendly(), bea_Medium::GetVolumeCount(), log_DBG_m, log_FUNC_m, bea_Medium::m_barcode, m_mediumMem, and bea_Medium::m_serialNum.

Referenced by bea_TapeMedium(), and Refresh().

                                       {
    log_FUNC_m(RefreshMemoryInfo);

    //
    // Medium memory refresh must follow detection of medium volumes
    //
    m_mediumMem->Refresh(GetVolumeCount());

    try {
        if (m_mediumMem->IsValid()) {
            const df_TCMMedium_t med = m_mediumMem->GetMediumRecord();
            m_barcode.assign( reinterpret_cast<const char*>(med.barcode) );
        }
    }
    catch (ivd_Error &ie) {
        log_DBG_m(dbg_NORM,
            "Can't check if CM is valid: " << ie.GetFriendly());
    }
    catch (...) {
        log_DBG_m(dbg_NORM,
            "ERROR: Can't check if CM is valid.");
    }

    try {
        m_serialNum = m_mediumMem->GetSerialNumber();
        log_DBG_m(dbg_NORM, "** Medium serial number:" << endl <<
            "Serial number: " << m_serialNum << endl <<
            "Manufacturer : " << m_mediumMem->GetManufacturer() << endl <<
            "Secondary ID : " << int(m_mediumMem->GetSecondaryID()) << endl <<
            "Checksum     : " << int(m_mediumMem->GetChecksum()) );
    }
    catch (ivd_Error &ie) {
        log_DBG_m(dbg_NORM,
        "Can't read medium serial number or manufacturer: " << ie.GetFriendly());
    }
    catch (...) {
        log_DBG_m(dbg_NORM,
            "ERROR: Can't read medium serial number or manufacturer.");
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_TapeMedium::RefreshTapeInfo (  )  [private]

Definition at line 379 of file bea_tapemedium.cpp.

References bea_Medium::AddVolume(), bmf_AIT, bmf_DDS, bmf_LTO, bmf_SAIT, bmf_VXA, bmt_DDS1, bmt_DDS2, bmt_DDS3, bmt_DDS4, bmt_LTO, bmt_LTO2, bmt_LTO3, bmt_LTO4, bmt_LTO5, bmt_LTO6, bmt_VXA320, dbg_DETAIL, dbg_LOW, dbg_NORM, bea_Medium::DeleteVolumes(), DetectAITWORM(), DetectLTOWORM(), data_Density::GetAssigningOrg(), data_Density::GetBitsPerMM(), data_Density::GetCapacity(), data_Mode::GetDensityCode(), data_Density::GetDensityCount(), data_Density::GetDensityName(), data_Density::GetDescription(), data_Density::GetMediaWidth(), data_Mode::GetPartCount(), data_Mode::GetPartSize(), data_Density::GetPrimaryCode(), data_Density::GetSecondaryCode(), bea_Medium::GetSize(), data_Density::GetTracks(), ie_FATAL_ERROR, ie_MEDIUM_MEDERR, scsi_IO::IOCtl(), ivd_Error, log_DBG_m, log_FUNC_m, bea_Medium::m_barcode, bea_Medium::m_mediumFamily, bea_Medium::m_mediumType, m_scsiIO_p, bea_Medium::m_serialNum, data_Mode::pg_DEVCFG, data_Mode::pg_PART, ReadCurrentVolume(), RefreshCompressionState(), bea_Medium::SetSize(), bea_Medium::SetWORM(), and size.

Referenced by bea_TapeMedium(), and Refresh().

                                     {

    log_FUNC_m(RefreshTapeInfo);

    m_barcode.clear();
    m_serialNum.clear();
    m_mediumFamily = bmf_UNKNOWN;
    m_mediumType = bmt_UNKNOWN;
    SetWORM(false);

    // Delete old volume information (not in Cartridge memory!)
    DeleteVolumes();

    ReadCurrentVolume();

    // Try to get density code from the block descriptor.
    data_Mode       devCfg(data_Mode::pg_DEVCFG);
    cdb_ModeSense   modeSns(devCfg);

    m_scsiIO_p->IOCtl(modeSns);
    m_mediumType = devCfg.GetDensityCode();


    // See codes in the SCSI standard (SCSI Stream Commands 2, Table A.3)
    // and SCSI specification documents of tape drive vendors.
    switch (m_mediumType) {
        case bmt_DDS1:
        case bmt_DDS2:
        case bmt_DDS3:
        case bmt_DDS4:
        {
            m_mediumFamily = bmf_DDS;
            break;
        }
        case bmt_VXA320:
        {
            m_mediumFamily = bmf_VXA;
            break;
        }
        default:
        {
            m_mediumFamily = m_mediumType;
            break;
        }
    }
    log_DBG_m(dbg_NORM,
        "** Medium density info of the loaded medium:" << endl <<
        "Primary code   : " << int(m_mediumType) << endl <<
        "Secondary code : " << int(m_mediumFamily) );

    // Try to get more density information for non-DDS and non-VXA media:
    if (   (m_mediumFamily != bmf_DDS)
        && (m_mediumFamily != bmf_VXA) ) {
        // Report density for the loaded medium
        data_Density        dens;
        cdb_ReportDensity   dc(dens, true);
        m_scsiIO_p->IOCtl(dc);

        if (dens.GetDensityCount() < 1) {
            log_MARKLINE_m;
            throw ivd_InternalError(
            ie_FATAL_ERROR,
            "CHECK THIS: Get Density Support didn't return any records.");
        }
        else if (dens.GetDensityCount() > 1) {
            log_MARKLINE_m;
            throw ivd_InternalError(
            ie_FATAL_ERROR,
            "CHECK THIS: Get Density Support returned more than one record.");
        }
        log_DBG_m(dbg_NORM,
            "** Medium density info of the loaded medium:" << endl <<
            "Primary code   : " << int(dens.GetPrimaryCode(0)) << endl <<
            "Secondary code : " << int(dens.GetSecondaryCode(0)) << endl <<
            "Bits per mm    : " << dens.GetBitsPerMM(0) << endl <<
            "Media width    : " << dens.GetMediaWidth(0) << endl <<
            "Tracks         : " << dens.GetTracks(0) << endl <<
            "Capacity       : " << dens.GetCapacity(0) << endl <<
            "Assigning org  : " << dens.GetAssigningOrg(0) << endl <<
            "Name           : " << dens.GetDensityName(0) << endl <<
            "Description    : " << dens.GetDescription(0) );

        m_mediumType = UInt32_t(dens.GetPrimaryCode(0));
        m_mediumFamily = UInt32_t(dens.GetSecondaryCode(0));

        if (   m_mediumType == bmt_LTO
            || m_mediumType == bmt_LTO2
            || m_mediumType == bmt_LTO3
            || m_mediumType == bmt_LTO4
            || m_mediumType == bmt_LTO5 
            || m_mediumType == bmt_LTO6 ) {

            RefreshCompressionState();

            // both LTO and SAIT reports same value (40h), so...
            const string sait("SAIT-1");
            const string densName(dens.GetDensityName(0), 0, sait.length());

            log_DBG_m(dbg_DETAIL,
            "sait: \'" << sait << "\' densName: \'" << densName << "\'");

            if (densName == sait) {
                log_DBG_m(dbg_LOW, "Detected Sony SAIT medium.");
                m_mediumType = bmt_SAIT1;
                m_mediumFamily = bmf_SAIT;
            } // if (densName == sait)
            else {
                m_mediumFamily = bmf_LTO;
            }
        }
        // Store medium's declared total capacity
        SetSize(dens.GetCapacity(0));
    } // if (m_mediumFamily != bmf_DDS)

    // LTO has only one medium volume and does not support
    // mode medium partitions page.
    // It is valid to define its medium volume this way.
    switch (m_mediumFamily) {
        case bmf_LTO:
        case bmf_SAIT:
        {
            DetectLTOWORM();
            data_Density        dens;
            cdb_ReportDensity   dc(dens, true);
            m_scsiIO_p->IOCtl(dc);

            AddVolume(
                new bea_TapeVolume( m_scsiIO_p, this, 1, dens.GetCapacity(0)) );
            break;
        }
        case bmf_AIT:
        {
            DetectAITWORM();
            data_Mode       pi(data_Mode::pg_PART);
            cdb_ModeSense   partInfo(pi);

            UInt32_t medSize(0);

            log_DBG_m(dbg_NORM, "Getting medium volume info");
            m_scsiIO_p->IOCtl(partInfo);

            log_DBG_m(dbg_LOW, "Medium volumes: " << (int)pi.GetPartCount());
            for (UInt8_t i = 0; i < pi.GetPartCount(); i++) {
                UInt32_t size(pi.GetPartSize(i));

                // We treat zero-size volumes as medium error
               if (size == 0) {
                    log_MARKLINE_m;
                    throw ivd_Error(ie_MEDIUM_MEDERR,
                        "Reported medium volume size is 0.", true);
                }
                AddVolume(new bea_TapeVolume( m_scsiIO_p, this, (i+1), size) );

                medSize += size;

                // If the sum of reported volumes is twice the size of the
                // declared medium size, then this is a medium error.
                if (GetSize() > 0 && medSize > (GetSize()*2) ) {
                    log_MARKLINE_m;
                    ostringstream sstr;
                    sstr << "Reported medium volume sizes are too large: " << medSize;
                    throw ivd_Error(ie_MEDIUM_MEDERR, sstr.str(), true);
                }
            };
            log_DBG_m(dbg_NORM, "Sum of volume sizes: " << medSize);
            if (m_mediumFamily == bmf_DDS) {
                log_DBG_m(dbg_LOW, "DDS size: " << medSize);
                SetSize(medSize);
            }
            break;
        }
    } // switch (m_mediumFamily)
    RefreshCompressionState();
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Reimplemented from bea_Medium.

Definition at line 59 of file bea_tapemedium.h.

Reimplemented from bea_Medium.

Definition at line 67 of file bea_tapemedium.h.

Referenced by bea_TapeMedium(), Format(), and RefreshMemoryInfo().


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