Classes | Public Types | Public Member Functions | Protected Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes

bea_DiskVolume Class Reference
[IVD Back-End Agent]

#include <bea_diskvolume.h>

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

List of all members.

Classes

class  VolFile

Public Types

enum  dv_FileType_e {
  dv_HeaderFile, dv_DataFile,
  dv_FRIFile
}

Public Member Functions

 bea_DiskVolume (bea_Medium *const a_medium_p, UInt32_t a_volNumber, UInt32_t a_volSize)
virtual UInt32_t GetPosition ()
virtual void Erase ()
virtual void WriteFileMarks (UInt32_t a_count=1)
virtual void Flush ()
virtual void SeekEOD ()
virtual void Rewind ()
virtual void SeekBlock (UInt32_t a_block)
virtual void SeekFileMark (Int32_t a_relativeFM)

Protected Member Functions

virtual ~bea_DiskVolume ()
virtual void WriteRaw (const UInt8_t *a_buf, UInt32_t a_size)
virtual void ReadRaw (UInt8_t *a_buf, UInt32_t a_size)
virtual void ReadEstimSizes ()
 Reads estimated overall and remaining capacity of this medium volume.

Private Member Functions

void ReparseFiles ()
dv_FileType_e GetTypeFromExt (const string &a_extStr)
void CreateNewFile ()
void ExtendToFullBlock (cmn_File &a_file, ivd_FilePosition_t a_filePos, UInt32_t a_blkSize)
void ReadVolInfo ()
void WriteVolInfo ()

Static Private Member Functions

static string CreateOffsetFileName (UInt32_t a_offset, dv_FileType_e a_type)

Private Attributes

 log_CLASSID_m
cmn_Path m_dvPath
cmn_File m_dvinfo
vector< VolFilem_files
UInt32_t m_curFile

Detailed Description

Definition at line 60 of file bea_diskvolume.h.


Member Enumeration Documentation

Enumerator:
dv_HeaderFile 
dv_DataFile 
dv_FRIFile 

Definition at line 80 of file bea_diskvolume.h.

{dv_HeaderFile, dv_DataFile, dv_FRIFile};


Constructor & Destructor Documentation

bea_DiskVolume::bea_DiskVolume ( bea_Medium *const   a_medium_p,
UInt32_t  a_volNumber,
UInt32_t  a_volSize 
)

Definition at line 64 of file bea_diskvolume.cpp.

References dbg_NORM, log_DBG_m, log_FUNC_A_m, m_dvPath, ReadVolInfo(), ReparseFiles(), and bea_Volume::SetDeclaredSize().

  : bea_Volume(a_medium_p, a_volNumber, a_size),
    m_dvPath(bea_DiskMedium::GetDiskMediumPath(a_medium_p->GetBarcode()) +
             bea_DiskMedium::VolDirName(a_volNumber)),
    m_dvinfo( m_dvPath + dv_VOLINFO ),
    m_curFile(0) {

    log_FUNC_A_m(bea_DiskVolume,
        "location: " << m_dvPath << " num: " << a_volNumber << " size: " << a_size);

    if (a_size > 0) {
        log_DBG_m(dbg_NORM, "Setting default declared volume size to: " << a_size);
        SetDeclaredSize(a_size);
    };

    ReadVolInfo();
    ReparseFiles();
}

Here is the call graph for this function:

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

Definition at line 88 of file bea_diskvolume.cpp.

References log_FUNC_m.

                                {
    log_FUNC_m(~bea_DiskVolume);

//    WriteVolInfo();
}


Member Function Documentation

void bea_DiskVolume::CreateNewFile (  )  [private]

Definition at line 874 of file bea_diskvolume.cpp.

References bea_DiskVolume::VolFile::blkOffset, cmn_File::CloseF(), CreateOffsetFileName(), dbg_LOW, dbg_NORM, dv_HeaderFile, file, bea_DiskVolume::VolFile::file, fom_CREATE_NEW, bea_Volume::GetBlockSize(), cmn_File::GetFullPathRef(), ie_DATA_CORRUPTION, log_DBG_m, log_FUNC_m, m_curFile, m_dvPath, m_files, cmn_File::OpenF(), S_IREAD, cmn_File::SetFullPath(), bea_DiskVolume::VolFile::size, and bea_DiskVolume::VolFile::type.

Referenced by WriteFileMarks(), and WriteRaw().

                                   {
    log_FUNC_m(CreateNewFile);

    cmn_Path filePath( m_dvPath );

    VolFile vol;
    UInt32_t blkOffset(0);
    if (m_files.size() == 0) {
        //make .hdr file.
        filePath += CreateOffsetFileName(0, dv_HeaderFile);
        vol.type = dv_HeaderFile;
    }
    else {
        UInt32_t absOffset(0);
        UInt32_t relOffset(0);
        if (m_files.size() == 1) {
            //make .vdf
            vol.type = dv_DataFile;
            relOffset = 2;
        }
        else if (m_files.size() == 2) {
            //make .fri
            vol.type = dv_FRIFile;

            VolFile& f = m_files[m_files.size() - 1];
            absOffset = f.blkOffset;
            relOffset = f.size/GetBlockSize();
        }
        else {
            ostringstream sstr;
            sstr
                << "All files of the volume " << m_dvPath
                << " already exist.";
            throw ivd_InternalError(ie_DATA_CORRUPTION, sstr.str());
        }

        log_DBG_m(dbg_NORM,
            "Offset of file: " << absOffset << " Offset in file: " << relOffset);

        // Simulate tape: each file mark uses one SCSI block
        blkOffset = absOffset + relOffset + 1;
        filePath += CreateOffsetFileName(blkOffset, vol.type);
    }

    log_DBG_m(dbg_LOW, "Creating new file:" << filePath);

    vol.file.SetFullPath(filePath);
    vol.file.OpenF(fom_CREATE_NEW);
    vol.file.CloseF();

    // Change permissions to allow access only for the owner
#if TGT_OS_windows
    (void)chmod(filePath.c_str(), S_IREAD|S_IWRITE);
#elif TGT_OS_linux
    (void)chmod(filePath.c_str(), S_IRUSR | S_IWUSR);
#endif

    vol.size = 0;
    vol.blkOffset = blkOffset;

    log_DBG_m(dbg_NORM, "vol.file.PATH:" << vol.file.GetFullPathRef() <<
                        " vol.size:" << vol.size <<
                        " vol.blkOffset:" << vol.blkOffset);

    if (m_files.size() > 0) {
        cmn_File& file = m_files[m_curFile].file;
        file.CloseF();
    }

    m_files.push_back(vol);
    m_curFile = m_files.size() - 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

string bea_DiskVolume::CreateOffsetFileName ( UInt32_t  a_offset,
dv_FileType_e  a_type 
) [static, private]

Definition at line 836 of file bea_diskvolume.cpp.

References dv_DataFile, dv_FRIFile, and dv_HeaderFile.

Referenced by CreateNewFile().

                                                                                   {

    ostringstream ostr;
    ostr
        << std::setw(8)
        << std::setfill('0')
        << a_offset;

    switch (a_type) {
        case dv_HeaderFile: ostr << dv_HEADER_EXT; break;
        case dv_DataFile: ostr << dv_DATA_EXT; break;
        case dv_FRIFile: ostr << dv_FRI_EXT; break;
    };

    return ostr.str();

}

Here is the caller graph for this function:

void bea_DiskVolume::Erase (  )  [virtual]

Implements bea_Volume.

Definition at line 329 of file bea_diskvolume.cpp.

References cmn_File::CloseF(), dbg_DETAIL, dbg_NORM, cmn_File::DeleteF(), file, fom_READWRITE, cmn_File::GetCurrentPosF(), bea_Volume::InvalidateSizes(), cmn_File::IsOpen(), log_DBG_m, log_FUNC_m, bea_Volume::m_atEOD, m_curFile, m_files, cmn_File::OpenF(), cmn_File::SeekEndF(), size, and cmn_File::TruncF().

Referenced by WriteFileMarks(), and WriteRaw().

                           {
    log_FUNC_m(Erase);

//    WriteVolInfo();
    InvalidateSizes();

    if (m_files.size() == 0) {
        return;
    }

    UInt32_t deletedFiles(0);
    for (UInt32_t i(m_curFile+1); i < m_files.size(); ++i) {
        log_DBG_m(dbg_DETAIL, "Deleting file: " << i);
        cmn_File& file = m_files[i].file;
        file.DeleteF();
        ++deletedFiles;
    }

    cmn_File& file = m_files[m_curFile].file;

    ivd_FilePosition_t pos(0);
    if (file.IsOpen()) {
        pos = file.GetCurrentPosF();
        file.CloseF();
    }
    file.OpenF(fom_READWRITE);

    if (pos == 0) {
        if (m_files[m_curFile].size > 0 || deletedFiles == 0) {
            log_DBG_m(dbg_DETAIL,
                "Positioned at the beginning of file. Deleting file: " << m_curFile);
            file.DeleteF();
            --m_curFile;
        }
        else {
            log_DBG_m(dbg_DETAIL,
                "Erase already deleted files after empty file: " << m_curFile);
        }
    }
    else {
        log_DBG_m(dbg_DETAIL,
            "Truncating file " << m_curFile << " on position: " << pos);
        file.TruncF(pos);
        file.SeekEndF();
    }

    if (m_curFile+1 < m_files.size()) {
        m_files.resize(m_curFile+1);
    };

    log_DBG_m(dbg_NORM,
        "Files left after erasing: " << m_files.size() << ".");

    m_atEOD = true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_DiskVolume::ExtendToFullBlock ( cmn_File a_file,
ivd_FilePosition_t  a_filePos,
UInt32_t  a_blkSize 
) [private]

Definition at line 947 of file bea_diskvolume.cpp.

References ivd_BaseException::GetFriendly(), ie_MEDIUM_MEDERR, ivd_Error, log_FUNC_m, log_WRN_m, m_dvPath, and cmn_File::TruncF().

Referenced by ReadRaw(), and SeekEOD().

                                   {

    log_FUNC_m(ExtendToFullBlock);

    Int32_t remainder = a_filePos % a_blkSize;
    if (remainder != 0) {
        ivd_FilePosition_t extSize = a_filePos + a_blkSize - remainder;
        log_WRN_m(
                "Disk medium error (size mismatch): " << m_dvPath <<
                " Autocorrecting: Extending file to next block: " << extSize);
        try {
            a_file.TruncF(extSize);
        }
        catch (const ivd_SysError& se) {
            ostringstream sstr;
            sstr << "Disk medium error (extending failed): " << m_dvPath;
            throw ivd_Error(ie_MEDIUM_MEDERR, sstr.str(), se.GetFriendly() );
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_DiskVolume::Flush (  )  [virtual]

Implements bea_Volume.

Definition at line 418 of file bea_diskvolume.cpp.

References file, cmn_File::IsOpen(), log_FUNC_m, m_curFile, m_files, and cmn_File::SyncF().

                           {
    log_FUNC_m(Flush);

    cmn_File& file = m_files[m_curFile].file;
    if (file.IsOpen()) {
        file.SyncF();
    }

//    WriteVolInfo();
}

Here is the call graph for this function:

UInt32_t bea_DiskVolume::GetPosition (  )  [virtual]

Implements bea_Volume.

Definition at line 168 of file bea_diskvolume.cpp.

References bea_DiskVolume::VolFile::blkOffset, df_VOLHDR_REC_SIZE, bea_DiskVolume::VolFile::file, file, bea_Volume::GetBlockSize(), cmn_File::GetCurrentPosF(), cmn_File::IsOpen(), log_FUNC_m, m_curFile, and m_files.

Referenced by ReadRaw(), SeekBlock(), and SeekEOD().

                                     {
    log_FUNC_m(GetPosition);

    const VolFile& file = m_files[m_curFile];
    UInt32_t position(file.blkOffset);

    if (file.file.IsOpen()) {
        if (file.file.GetCurrentPosF() == 0) {
            position += 0;
        }
        else {
            ivd_FilePosition_t pos(file.file.GetCurrentPosF());

            // Special handling for volume header block, which occupies one
            // fixed-size block.
            if (m_curFile == 0) {
                if (pos < df_VOLHDR_REC_SIZE) {
                    position = 0;
                }
                else {
                    position = 1 + ( (pos - df_VOLHDR_REC_SIZE) / GetBlockSize() );
                }
            }
            else {
                position += pos / GetBlockSize();
            }
        }
    }
    return position;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bea_DiskVolume::dv_FileType_e bea_DiskVolume::GetTypeFromExt ( const string &  a_extStr  )  [private]

Definition at line 856 of file bea_diskvolume.cpp.

References dv_DATA_EXT, dv_FRI_EXT, dv_HEADER_EXT, ie_MEDIUM_MEDERR, and ivd_Error.

Referenced by ReparseFiles().

                                                                                 {

    if (a_extStr.compare(dv_HEADER_EXT) == 0) {
        return dv_HeaderFile;
    }
    else if (a_extStr.compare(dv_DATA_EXT) == 0) {
        return dv_DataFile;
    }
    else if (a_extStr.compare(dv_FRI_EXT) == 0) {
        return dv_FRIFile;
    }
    else {
        throw ivd_Error(ie_MEDIUM_MEDERR, string("Wrong extension: ") + a_extStr);
    };
}

Here is the caller graph for this function:

void bea_DiskVolume::ReadEstimSizes (  )  [protected, virtual]

Reads estimated overall and remaining capacity of this medium volume.

It stores the values so that they can be retrieved by Get* methods. This method converts sizes to MB.

Implements bea_Volume.

Definition at line 674 of file bea_diskvolume.cpp.

References ivd_FileSystemSize_t::bytesFree, ivd_FileSystemSize_t::bytesTotal, cfg_MEGABYTE, dbg_DETAIL, dbg_LOW, dbg_NORM, bea_Medium::GetCurVolNumber(), cmn_File::GetFileSystemSize(), bea_Volume::GetSize(), bea_Volume::GetVolumeNumber(), ie_INVALID_ARG, ivd_Error, log_DBG_m, log_FUNC_m, log_WRN_m, m_dvPath, m_files, bea_Volume::m_medium_p, and bea_Volume::SetEstimatedSizes().

                                    {
    log_FUNC_m(ReadEstimSizes);

    if (m_medium_p->GetCurVolNumber() != GetVolumeNumber()) {
        throw ivd_Error(
            ie_INVALID_ARG,
            "Estimated sizes can only be read for current volume.");
    };

    UInt32_t estimSize(GetSize());
    UInt64_t sumOfFiles(0);
    UInt32_t estimFree(0);
    for (UInt32_t i(0); i < m_files.size(); i++) {
        // Re-read file allocated sizes.
        ivd_FileInfo_t info;
        m_files[i].file.StatF(info);

        sumOfFiles += info.allocated;
    }
    sumOfFiles /= cfg_MEGABYTE;
    log_DBG_m(dbg_DETAIL, "sumOfFiles:" << sumOfFiles);

    if (sumOfFiles <= estimSize) {
        estimFree = estimSize - sumOfFiles;
        log_DBG_m(dbg_DETAIL, "estimFree:" << estimFree);
    }
    else {
        log_WRN_m("Sum of file size bigger that actual space.");
        estimFree = 0;
    };

    {
        cmn_File info(m_dvPath);
        ivd_FileSystemSize_t fsSize;
        info.GetFileSystemSize(fsSize);

        log_DBG_m(dbg_NORM, "fsSize.bytesTotal:" << fsSize.bytesTotal <<
                            ", fsSize.bytesFree:" << fsSize.bytesFree);

        if ( (fsSize.bytesTotal/cfg_MEGABYTE) < estimSize) {
            estimSize = fsSize.bytesTotal/cfg_MEGABYTE;
            log_DBG_m(dbg_LOW,
                "File system size is smaller than declared size. Using " <<
                estimSize);
        }

        if ( (fsSize.bytesFree/cfg_MEGABYTE) < estimFree) {
            estimFree = fsSize.bytesFree/cfg_MEGABYTE;
            log_DBG_m(dbg_LOW,
                "File system free space is smaller than declared size. Using " <<
                estimFree);
        }
    };

    log_DBG_m(dbg_NORM,
        "Estimated capacity info [MB]:" <<
        " total: " << estimSize << " free : " << estimFree);

    SetEstimatedSizes(estimSize, estimFree);
}

Here is the call graph for this function:

void bea_DiskVolume::ReadRaw ( UInt8_t a_buf,
UInt32_t  a_size 
) [protected, virtual]

Implements bea_Volume.

Definition at line 256 of file bea_diskvolume.cpp.

References cmn_File::CloseF(), dbg_NORM, ExtendToFullBlock(), file, fom_READWRITE, bea_Volume::GetBlockSize(), cmn_File::GetCurrentPosF(), ivd_BaseException::GetFriendly(), GetPosition(), ie_DATA_CORRUPTION, ie_MEDIUM_BLANK, ie_MEDIUM_EOD, ie_MEDIUM_FILEMARK, ie_MEDIUM_ILENGTH, ie_MEDIUM_MEDERR, cmn_File::IsOpen(), ivd_Error, log_DBG_m, log_FUNC_m, log_WRN_m, m_curFile, m_dvPath, m_files, cmn_File::OpenF(), and cmn_File::ReadF().

                                                            {
    log_FUNC_m(ReadRaw);

    if ( m_files.size() == 0 ||
        (m_files.size() == 1 && m_files[0].size == 0) ) {
        throw ivd_Error(ie_MEDIUM_BLANK);
    }

    if (m_files.size() <= m_curFile) {
        throw ivd_InternalError(ie_DATA_CORRUPTION, "m_curFile >= #files");
    }

    cmn_File& file = m_files[m_curFile].file;

    if (!file.IsOpen()) {
        file.OpenF(fom_READWRITE);
    }

    UInt32_t toRead(a_size);
    if (GetPosition() == 0) {
        toRead = df_VOLHDR_REC_SIZE;
    }

    UInt32_t readAmount(0);
    try {
        readAmount = file.ReadF(a_buf, toRead);
    }
    catch (const ivd_SysError& se) {
        ostringstream sstr;
        sstr << "Disk medium error: " << m_dvPath;
        throw ivd_Error(ie_MEDIUM_MEDERR, sstr.str(), se.GetFriendly());
    };

    if (readAmount == 0) {
        if (m_curFile == (m_files.size()-1) ) {
            throw ivd_Error(ie_MEDIUM_EOD, "End of disk volume reached.");
        }
        else {
            log_DBG_m(dbg_NORM, "File mark reached. Skip over to next file.");
            file.CloseF();
            ++m_curFile;
            throw ivd_Error(ie_MEDIUM_FILEMARK, "Disk medium filemark reached.");
        }
    }

    if (readAmount < toRead) {
        if ( (m_curFile + 1) == m_files.size() && m_curFile > 0) {
            ivd_FilePosition_t pos = file.GetCurrentPosF();
            bea_DiskVolume::ExtendToFullBlock(file, pos, GetBlockSize());
        }
        else {
            log_WRN_m(
                "Read less that requested on non-last file.");
        }

        ostringstream sstr;
        sstr
            << "Read less (" << readAmount
            << ") than block size (" << toRead << ").";

        throw ivd_Error(ie_MEDIUM_ILENGTH, "File too short.", sstr.str());
    }

    if (toRead < a_size) {
        ostringstream sstr;
        sstr << "Attempt to read more (" << a_size
            << ") than block size (" << toRead << ").";
        throw ivd_Error(ie_MEDIUM_ILENGTH, sstr.str());
    }
}

Here is the call graph for this function:

void bea_DiskVolume::ReadVolInfo (  )  [private]

Definition at line 97 of file bea_diskvolume.cpp.

References cmn_File::CloseF(), dbg_LOW, dbg_NORM, fom_READ, ivd_BaseException::GetError(), ivd_BaseException::GetFriendly(), cmn_File::GetFullPathRef(), bea_Volume::GetSize(), ie_MEDIUM_MEDERR, ivd_Error, log_DBG_m, log_FUNC_m, m_dvinfo, cmn_File::OpenF(), cmn_File::ReadF(), bea_Volume::SetDeclaredSize(), dv_Info_t::size, and WriteVolInfo().

Referenced by bea_DiskVolume().

                                 {
    log_FUNC_m(ReadVolInfo);

    dv_Info_t info;

    try {
        m_dvinfo.OpenF(fom_READ);
        m_dvinfo.ReadF(&info, sizeof(info));
        m_dvinfo.CloseF();

        log_DBG_m(dbg_LOW, "Disk volume size: " << info.size);
        SetDeclaredSize(info.size);
    }
    catch (const ivd_Error& ie) {
        log_DBG_m(dbg_LOW, "Can't read volume info: " << ie.GetFriendly() );
        throw ivd_Error(ie_MEDIUM_MEDERR,
            string("Can't read volume info: ") + m_dvinfo.GetFullPathRef(),
            ie.GetFriendly(),
            true);
    }
    catch (const ivd_SysError& ie) {
        if (ie.GetError() == ENOENT) {
            if (GetSize() > 0) {
                log_DBG_m(dbg_NORM, "vol.info doesn't exist. Creating new.");
                WriteVolInfo();
            }
            else {
                log_DBG_m(dbg_LOW,
                    "Volume info doesn't exist, but no new size specified: " <<
                    ie.GetFriendly() );
                throw ivd_Error(ie_MEDIUM_MEDERR,
                    string("Can't read volume info: ") + m_dvinfo.GetFullPathRef(),
                    ie.GetFriendly(),
                    true);
            }
        }
        else {
            log_DBG_m(dbg_LOW, "Can't read volume info: " << ie.GetFriendly() );
            throw ivd_Error(ie_MEDIUM_MEDERR,
                string("Can't read volume info: ") + m_dvinfo.GetFullPathRef(),
                ie.GetFriendly(),
                true);
        };
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_DiskVolume::ReparseFiles (  )  [private]

Definition at line 737 of file bea_diskvolume.cpp.

References val_Integer::Bind(), val_Value::Conv(), dbg_DETAIL, dbg_LOW, dbg_NORM, dv_FRIFile, dv_HeaderFile, dv_VOLINFO, cmn_DirLst::GetNextName(), GetTypeFromExt(), ie_MEDIUM_MEDERR, ift_FILE, ivd_Error, log_DBG_m, log_FUNC_m, m_dvPath, m_files, and cmn_File::StatF().

Referenced by bea_DiskVolume().

                                  {
    log_FUNC_m(ReparseFiles);
    // Scan for <offset>.[hdr|dta|fri] files

    list<string> volFNames;
    {
        cmn_DirLst volFiles(m_dvPath, "");
        string name;
        name = volFiles.GetNextName();
        while ( name.size() > 0 ) {
            cmn_Path fullName(m_dvPath + name);
            ivd_FileType_e type;
            {
                cmn_File entry(fullName);
                ivd_FileInfo_t stat;
                entry.StatF(stat);
                type = stat.type;
            }
            
            string firstChar = name.substr(0, 1); //bug 8417 ignore all hidden files (e.g. sh_history)
                        
            if ( (name.compare(".") == 0) ||
                (name.compare("..") == 0) ||
                (firstChar.compare(".") == 0) ||
                (name.compare(dv_VOLINFO) == 0) ) {

                log_DBG_m(dbg_DETAIL, "Skipped file.");
            }
            else {
                if (type != ift_FILE) {
                    log_MARKLINE_m;
                    ostringstream sstr;
                    sstr << m_dvPath << ": Found non-file entry \'" << name << "\'";
                    log_DBG_m(dbg_LOW, "Entry type: " << type);

                    throw ivd_Error(ie_MEDIUM_MEDERR, sstr.str());
                };
                volFNames.push_back(name);
            }
            name = volFiles.GetNextName();
        }
        volFNames.sort();
    }

    list<string>::const_iterator name_i;
    UInt32_t idx(0);
    for (name_i = volFNames.begin(); name_i != volFNames.end(); ++name_i) {
        const string& fn(*name_i);
        string::size_type dotPos = fn.find_first_of('.');
        if (dotPos == string::npos || dotPos == 0) {
            log_MARKLINE_m;
            throw ivd_Error(ie_MEDIUM_MEDERR,
                string("Invalid disk volume name: ") + fn);
        }

        string offsetStr(fn.substr(0, dotPos));
        string extStr(fn.substr(dotPos));

        VolFile volFile;
        val_Integer iv("Offset", val_Limit(0, UINT_MAX));
        iv.Bind(volFile.blkOffset);
        iv.Conv(offsetStr);

        volFile.type = GetTypeFromExt(extStr);
        volFile.file.SetFullPath(m_dvPath + fn);

        if (idx == 0) {
            if (volFile.type != dv_HeaderFile) {
                throw ivd_Error(ie_MEDIUM_MEDERR,
                    "Header file not on the first place.");
            }
            else if (volFile.blkOffset != 0) {
                throw ivd_Error(ie_MEDIUM_MEDERR,
                    "Block offset for header larger that 0.");
            }
        }
        else if (idx < (volFNames.size()-1)) {
            if (volFile.type == dv_FRIFile) {
                throw ivd_Error(ie_MEDIUM_MEDERR,
                    "FRI file not on the last place.");
            }
        }

        ivd_FileInfo_t info;
        volFile.file.StatF(info);
        volFile.size = info.size;

        m_files.push_back(volFile);

        log_DBG_m(dbg_NORM, "Found valid file: " << fn);

        ++idx;
    }

}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_DiskVolume::Rewind (  )  [virtual]

Implements bea_Volume.

Definition at line 585 of file bea_diskvolume.cpp.

References bea_Volume::DoMediumLogging(), bea_Medium::GetBarcode(), bea_Volume::GetJobID(), bea_Volume::GetVolumeNumber(), log_FUNC_m, log_WriteEvent(), bea_Volume::m_medium_p, and SeekBlock().

                            {
    log_FUNC_m(Rewind);

    if (DoMediumLogging()) {
        ostringstream sstr;
        sstr << "Vol " << GetVolumeNumber()
            << ": Rewind...";

        log_WriteEvent(
            sstr.str(), "",
            GetJobID(),
            m_medium_p->GetBarcode());
    }

    SeekBlock(0);
}

Here is the call graph for this function:

void bea_DiskVolume::SeekBlock ( UInt32_t  a_block  )  [virtual]

Implements bea_Volume.

Definition at line 492 of file bea_diskvolume.cpp.

References bea_DiskVolume::VolFile::blkOffset, cmn_File::CloseF(), dbg_DETAIL, dbg_LOW, bea_Volume::DoMediumLogging(), bea_DiskVolume::VolFile::file, fom_READ, bea_Medium::GetBarcode(), bea_Volume::GetBlockSize(), bea_Volume::GetJobID(), GetPosition(), bea_Volume::GetVolumeNumber(), ie_FATAL_ERROR, ie_MEDIUM_EOM, bea_Volume::InvalidateEOD(), bea_Volume::InvalidateSizes(), ivd_Error, log_DBG_m, log_FUNC_A_m, log_WriteEvent(), m_curFile, m_dvPath, m_files, bea_Volume::m_medium_p, cmn_File::OpenF(), cmn_File::SeekF(), and bea_DiskVolume::VolFile::size.

Referenced by Rewind().

                                               {
    log_FUNC_A_m(SeekBlock, " blk: " << a_block);

    if (DoMediumLogging()) {
        ostringstream sstr;
        sstr << "Vol " << GetVolumeNumber()
            << ": Seeking to " << a_block << "...";

        log_WriteEvent(
            sstr.str(), "",
            GetJobID(),
            m_medium_p->GetBarcode());
    }

    InvalidateSizes();
    InvalidateEOD();

    if (m_files.size() == 0) {
        if (a_block > 0) {
            throw ivd_Error(ie_MEDIUM_EOM, "Disk volume is empty. Already on EOM.");
        }
        else {
            return;
        }
    }

    UInt32_t tgtFile(UINT_MAX);
    UInt32_t relOffset(0);

    cmn_File& cf = m_files[m_curFile].file;
    cf.CloseF();

    if (a_block == 0) {
        tgtFile = 0;
        relOffset = 0;
        VolFile& tf = m_files[tgtFile];
        tf.file.OpenF(fom_READ);
        tf.file.SeekF(0);
    }
    else {
        for (UInt32_t i(0); i < m_files.size(); ++i) {
            if (m_files[i].blkOffset > a_block) {
                tgtFile = i-1;
                break;
            }
        }

        // Try the last file
        if (tgtFile == UINT_MAX) {
            tgtFile = m_files.size()-1;
        }

        VolFile& tf = m_files[tgtFile];
        tf.file.OpenF(fom_READ);

        relOffset = a_block - tf.blkOffset;
        ivd_FilePosition_t seekPos(static_cast<ivd_FilePosition_t>(relOffset) * GetBlockSize());

        if (seekPos > tf.size) {
            log_MARKLINE_m;
#if TGT_OS_linux
#warning Check consistency of the file size (see SeekEOD).
#endif
            if (tgtFile == m_files.size()-1) {
                throw ivd_Error(ie_MEDIUM_EOM, "Seek over the EOD.");
            }
            else {
                throw ivd_InternalError(ie_FATAL_ERROR,
                    "Invalid internal calculation.",
                    string("Seek over the size of the file."));
            }
        };
        tf.file.SeekF(seekPos);
    }

    m_curFile = tgtFile;

    log_DBG_m(dbg_DETAIL, "Volume:" << m_dvPath <<
        " CurrentFile:" << m_curFile );

    // Verify that new position is OK.
    UInt32_t newPosition(GetPosition());
    if ( newPosition != a_block ) {
        log_DBG_m(dbg_LOW, "CurrentPosition: " << newPosition << " a_blk: " << a_block);

        throw ivd_InternalError(ie_FATAL_ERROR,
            "Invalid internal calculation.",
            string("GetPosition() returns value different from a_block."));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bea_DiskVolume::SeekEOD (  )  [virtual]

Implements bea_Volume.

Definition at line 431 of file bea_diskvolume.cpp.

References cmn_File::CloseF(), dbg_DETAIL, df_VOLHDR_REC_SIZE, bea_Volume::DoMediumLogging(), ExtendToFullBlock(), fom_READWRITE, bea_Medium::GetBarcode(), bea_Volume::GetBlockSize(), bea_Volume::GetJobID(), GetPosition(), bea_Volume::GetVolumeNumber(), ie_MEDIUM_MEDERR, ivd_Error, log_DBG_m, log_FUNC_m, log_WriteEvent(), bea_Volume::m_atEOD, m_curFile, m_dvPath, m_files, bea_Volume::m_medium_p, cmn_File::OpenF(), and cmn_File::SeekEndF().

                             {
    log_FUNC_m(SeekEOD);

    if (DoMediumLogging()) {
        ostringstream sstr;
        sstr << "Vol " << GetVolumeNumber()
            << ": Seeking to EOD...";

        log_WriteEvent(
            sstr.str(), "",
            GetJobID(),
            m_medium_p->GetBarcode());
    }

    if (m_files.size() == 0) {
        m_curFile = 0;
    }
    else {
        cmn_File& cf = m_files[m_curFile].file;
        cf.CloseF();

        m_curFile = m_files.size()-1;
        cmn_File& lf = m_files[m_curFile].file;
        lf.OpenF(fom_READWRITE);
        ivd_FilePosition_t filePos = lf.SeekEndF();

        //
        // Check consistency of the file: EOD must be either:
        // - at the end of the header: size is known
        // - EOF position must be divisible by block size
        //
        if (m_curFile == 0) {
            if ( filePos != df_VOLHDR_REC_SIZE + GetBlockSize() ) {
                ostringstream sstr;
                sstr << "Disk medium error (header size mismatch): " << m_dvPath;
                throw ivd_Error(ie_MEDIUM_MEDERR, sstr.str());
            }
        }
        else {
            ExtendToFullBlock(lf, filePos, GetBlockSize());
        }
    }
    m_atEOD = true;

    if (DoMediumLogging()) {
        ostringstream sstr;
        sstr << "Vol " << GetVolumeNumber()
            << ": At EOD (" << GetPosition() << ")";

        log_WriteEvent(
            sstr.str(), "",
            GetJobID(),
            m_medium_p->GetBarcode());
    }

    log_DBG_m(dbg_DETAIL,
        "Volume:" << m_dvPath << " CurrentFile:" << m_curFile);
}

Here is the call graph for this function:

void bea_DiskVolume::SeekFileMark ( Int32_t  a_relativeFM  )  [virtual]

Implements bea_Volume.

Definition at line 604 of file bea_diskvolume.cpp.

References cmn_File::CloseF(), dbg_NORM, bea_Volume::DoMediumLogging(), bea_DiskVolume::VolFile::file, fom_READWRITE, bea_Medium::GetBarcode(), bea_Volume::GetJobID(), bea_Volume::GetVolumeNumber(), ie_MEDIUM_BLANK, ie_MEDIUM_EOD, bea_Volume::InvalidateEOD(), ivd_Error, log_DBG_m, log_FUNC_A_m, log_WriteEvent(), bea_Volume::m_atEOD, m_curFile, m_files, bea_Volume::m_medium_p, cmn_File::OpenF(), and cmn_File::SeekEndF().

                                                      {
    log_FUNC_A_m(SeekFileMark, "relativeFM: " << a_relativeFM);

    if (DoMediumLogging()) {
        ostringstream sstr;
        sstr << "Vol " << GetVolumeNumber()
            << ": Seeking " << a_relativeFM << " filemark(s) forward...";

        log_WriteEvent(
            sstr.str(), "",
            GetJobID(),
            m_medium_p->GetBarcode());
    }

    InvalidateEOD();

    if (m_files.size() == 0) {
        if (a_relativeFM > 0) {
            log_MARKLINE_m;
            throw ivd_Error(ie_MEDIUM_BLANK);
        }
        else {
            m_curFile = 0;
            return;
        }
    }

    VolFile& cf = m_files[m_curFile];
    cf.file.CloseF();

    Int32_t absFile = m_curFile + a_relativeFM;

    if (absFile < 0) {
        m_curFile = 0;
        return;
    }

    // Seeking over the end of medium
    if (UInt32_t(absFile) >= m_files.size()) {
        m_curFile = m_files.size()-1;
        VolFile& tf = m_files[m_curFile];
        tf.file.OpenF(fom_READWRITE);
        (void)tf.file.SeekEndF();
        m_atEOD = true;
        throw ivd_Error(ie_MEDIUM_EOD, "Seek over the disk volume boundaries.");
    }

    // Positioning to proper file
    m_curFile = absFile;
    VolFile& tf = m_files[m_curFile];
    tf.file.OpenF(fom_READWRITE);

    log_DBG_m(dbg_NORM, "Positioned to file: " << m_curFile);

    // This is the same as the tape: negative seek positions just before
    // the file mark.
    if (a_relativeFM < 0) {
        log_DBG_m(dbg_NORM, "Reverse file mark seek -> positioning to end of file.");
        (void)tf.file.SeekEndF();
    }
}

Here is the call graph for this function:

void bea_DiskVolume::WriteFileMarks ( UInt32_t  a_count = 1  )  [virtual]

Implements bea_Volume.

Definition at line 387 of file bea_diskvolume.cpp.

References CreateNewFile(), dbg_LOW, bea_Volume::DoMediumLogging(), Erase(), bea_Medium::GetBarcode(), bea_Volume::GetJobID(), bea_Volume::GetVolumeNumber(), log_DBG_m, log_FUNC_A_m, log_WriteEvent(), bea_Volume::m_atEOD, m_files, and bea_Volume::m_medium_p.

                                                    {
    log_FUNC_A_m(WriteFileMarks, "count: " << a_count);

//    WriteVolInfo();

    if (DoMediumLogging()) {
        ostringstream sstr;
        sstr << "Vol " << GetVolumeNumber()
            << ": Writing filemark(s) "<< a_count << "...";

        log_WriteEvent(
            sstr.str(), "",
            GetJobID(),
            m_medium_p->GetBarcode());
    }

    if (!m_atEOD) {
        Erase();
    }

    for (UInt32_t i(0); i < a_count; ++i) {
        CreateNewFile();
    }

    log_DBG_m(dbg_LOW, "Currently " << m_files.size() << " files on volume.");

    m_atEOD = true;
}

Here is the call graph for this function:

void bea_DiskVolume::WriteRaw ( const UInt8_t a_buf,
UInt32_t  a_size 
) [protected, virtual]

Implements bea_Volume.

Definition at line 201 of file bea_diskvolume.cpp.

References CreateNewFile(), Erase(), file, fom_READWRITE, cmn_File::GetCurrentPosF(), ivd_BaseException::GetError(), ivd_BaseException::GetFriendly(), cmn_File::GetFullPathRef(), ie_MEDIUM_MEDERR, ie_MEDIUM_OVERFLOW, cmn_File::IsOpen(), ivd_Error, log_FUNC_m, log_WRN_m, bea_Volume::m_atEOD, m_curFile, m_dvPath, m_files, cmn_File::OpenF(), cmn_File::TruncF(), and cmn_File::WriteF().

                                                                   {
    log_FUNC_m(WriteRaw);

    if (!m_atEOD) {
        Erase();
    }

    if (m_files.empty()) {
        CreateNewFile();
    }

    cmn_File& file = m_files[m_curFile].file;

    if (!file.IsOpen()) {
        file.OpenF(fom_READWRITE);
    }

    try {
        //
        // Atomic append to the file.
        // TODO: Shall this functionality be moved to cmn_File?
        //
        ivd_FileRetSize_t wrote = file.WriteF(a_buf, a_size);

        if (static_cast<UInt32_t>(wrote) < a_size) {
            log_WRN_m(
                "Writing failed. Truncating file to last full block: " <<
                file.GetFullPathRef() );

            ivd_FilePosition_t filePos = file.GetCurrentPosF();
            file.TruncF(filePos - wrote);

            ostringstream sstr;
            sstr << "Disk medium out of space: " << m_dvPath;
            throw ivd_Error(ie_MEDIUM_OVERFLOW, sstr.str(), true);
        }
    }
    catch (const ivd_SysError& se) {
        if (se.GetError() == ENOSPC) {
            ostringstream sstr;
            sstr << "Disk medium out of space: " << m_dvPath;
            throw ivd_Error(ie_MEDIUM_OVERFLOW, sstr.str(), true);
        }
        else {
            ostringstream sstr;
            sstr << "Disk medium error: " << m_dvPath;
            throw ivd_Error(ie_MEDIUM_MEDERR, sstr.str(), se.GetFriendly());
        }
    };

    m_files[m_curFile].size += a_size;
}

Here is the call graph for this function:

void bea_DiskVolume::WriteVolInfo (  )  [private]

Definition at line 145 of file bea_diskvolume.cpp.

References cmn_File::CloseF(), dbg_LOW, fom_CREATE_ALWAYS, fom_WRITE, ivd_BaseException::GetFriendly(), cmn_File::GetFullPathRef(), bea_Volume::GetSize(), ie_MEDIUM_MEDERR, ivd_Error, log_DBG_m, log_FUNC_m, m_dvinfo, cmn_File::OpenF(), dv_Info_t::size, and cmn_File::WriteF().

Referenced by ReadVolInfo().

                                  {
    log_FUNC_m(WriteVolInfo);

    dv_Info_t info;

    info.size = GetSize();

    try {
        m_dvinfo.OpenF(fom_WRITE | fom_CREATE_ALWAYS);
        m_dvinfo.WriteF(&info, sizeof(info));
        m_dvinfo.CloseF();
    }
    catch (const ivd_Exception& ie) {
        log_DBG_m(dbg_LOW, "Can't write volume info: " << ie.GetFriendly() );
        throw ivd_Error(ie_MEDIUM_MEDERR,
            string("Can't write volume info: ") + m_dvinfo.GetFullPathRef(),
            ie.GetFriendly(),
            true);
    }

}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Reimplemented from bea_Volume.

Definition at line 105 of file bea_diskvolume.h.

Definition at line 107 of file bea_diskvolume.h.

Referenced by ReadVolInfo(), and WriteVolInfo().


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