Public Member Functions | Private Member Functions | Private Attributes

df_FRI Class Reference
[IVD Data format.]

#include <df.h>

Collaboration diagram for df_FRI:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 df_FRI (cmn_UUID_t &a_partID, cmn_UUID_t &a_poolID, UInt32_t a_blkSize)
virtual ~df_FRI ()
UInt8_tMediumVolumeStart (const cmn_UUID_t &a_medVolID, UInt32_t a_medPos, ivd_MigrationID_t a_migrationID, UInt32_t a_copyNumber, UInt32_t a_mediumKey, UInt32_t a_medVolNum, i_FSC_ptr a_fsc)
 Start processing FRI for new medium volume.
void MediumVolumeEnd (UInt32_t a_status)
 End processing FRI for new medium volume.
void MediumVolumeClosed (const string &a_medVolID)
 Medium Volume is closed and Disk FRI can be removed.
void BlockScan (UInt8_t *a_blkBuf)
 Parse IVD Data Format and update File record (copyID & nrOfCopies).
void BlockWritten (UInt32_t a_medPos)
 Append FRI records from last block to Disk FRI, return Split info to FSC.
const vector< df_SplitInfo > & GetSplits () const

Private Member Functions

void FlushCurrentSplit ()

Private Attributes

 log_CLASSID_m
df_BlockScanner m_scanner
 Scanner used for parsing IVD Data blocks.
UInt32_t m_blkSize
cmn_UUID_t m_partID
cmn_UUID_t m_poolID
cmn_UUID_t m_curMedVolID
 Disk FRI file.
df_Writerm_diskFRI
UInt32_t m_medStartPos
UInt32_t m_medCurPos
UInt32_t m_recNum
UInt32_t m_streamType
UInt64_t m_streamSize
string m_streamName
bool m_streamToFRI
vector< df_RecCmn_t * > m_friRec
 FRI records from last block (saved for BlockWritten() method).
df_SplitInfo m_curSplit
vector< df_SplitInfom_splits
UInt8_tm_contBlk
 Continuation block buffer - used in case file spans multiple volumes.
df_BlockHeader_tm_contBlkHdr
 Pointers into m_contBlk buffer (NULL if they do not exist).
df_RecCmn_tm_contFile
df_RecCmn_tm_contBSS

Detailed Description

Definition at line 818 of file df.h.


Constructor & Destructor Documentation

df_FRI::df_FRI ( cmn_UUID_t a_partID,
cmn_UUID_t a_poolID,
UInt32_t  a_blkSize 
)

Definition at line 48 of file df_fri.cpp.

References blk_Data_c, df_BF_CONTINUED, df_SplitInfo::fileID, log_FUNC_m, m_contBlk, m_contBlkHdr, m_curSplit, and df_BlockProxyWriter::WriteBlockHeader().

    : m_scanner(blk_Data_c, a_blkSize),
      m_blkSize(a_blkSize),
      m_partID(a_partID),
      m_poolID(a_poolID),
      m_diskFRI(NULL),
      m_recNum(0),
      m_streamType(0),
      m_streamToFRI(false),
      m_contFile(NULL),
      m_contBSS(NULL) {

    log_FUNC_m(df_FRI);

    m_curSplit.fileID = 0;

    // Allocate contBlk and mark that no record are present yet
    m_contBlk    = new UInt8_t[a_blkSize];
    m_contBlkHdr = df_Writer::WriteBlockHeader(m_contBlk, blk_Data_c, 
                                               df_BF_CONTINUED, 0);

}

Here is the call graph for this function:

df_FRI::~df_FRI (  )  [virtual]

Definition at line 75 of file df_fri.cpp.

References dbg_LOW, df_FRIS_ABORTED, log_DBG_m, log_FUNC_m, m_contBlk, m_diskFRI, MediumVolumeEnd(), and NULL.

                {
    log_FUNC_m(~df_FRI);

    try {
        if (m_diskFRI != NULL) {
            log_DBG_m(dbg_LOW,
                "FRI Data stream not properly terminated. Terminating now.");

            MediumVolumeEnd(df_FRIS_ABORTED);
            // ensure that FRI writer is properly killed
            delete m_diskFRI;
        }

        delete [] m_contBlk;
    }
    catch (ivd_Exception &ie) {
        log_DBG_m(dbg_LOW,
            "Ignoring exception in DTOR." << endl <<
            "Error: " << ie);
    }
}

Here is the call graph for this function:


Member Function Documentation

void df_FRI::BlockScan ( UInt8_t a_blkBuf  ) 

Parse IVD Data Format and update File record (copyID & nrOfCopies).

TODO: non-DATA Raw blocks need to be appended too!!!

Definition at line 100 of file df_fri.cpp.

References df_BlockScanner::GetNextRecord(), log_FUNC_m, m_friRec, m_scanner, and df_BlockScanner::SetBlock().

Referenced by bea_MigrationThread::WriteBlock().

                                        {

    log_FUNC_m(BlockScan);

    // start from empty FRI record 
    m_friRec.clear();

    if (!m_scanner.SetBlock(a_blkBuf)) {
        return;     // raw block - nothing to parse
    } 
  
    while (df_RecCmn_t *cmnRec_p = m_scanner.GetNextRecord()) {
        // save record pointer for FRI extraction after write
        m_friRec.push_back(cmnRec_p);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void df_FRI::BlockWritten ( UInt32_t  a_medPos  ) 

Append FRI records from last block to Disk FRI, return Split info to FSC.

Definition at line 148 of file df_fri.cpp.

References df_BlockProxyWriter::Allocate(), df_RecByteStreamStart_t::allStreamSize, df_SplitInfo::blockOffset, df_RecByteStreamStart_t::chunkOffset, df_SplitInfo::chunkOffset, df_RecFile_t::chunkSize, df_SplitInfo::chunkSize, cmn_Num2Str(), df_RecEmbeddedData_t::data, df_SplitInfo::dataType, dbg_DETAIL, df_RF_CONTINUED, df_SS_COMPLETE, df_ST_ALTDATA, df_ST_META, evt_WARNING, df_SplitInfo::fileID, df_SplitInfo::fileName, df_SplitInfo::fileSize, df_RecCmn_t::flags, FlushCurrentSplit(), hton(), df_RecByteStreamStart_t::idFile, df_RecFile_t::idFile, df_RecFile_t::idMig, df_RecFile_t::idParent, df_RecFile_t::idParentOld, ie_DF_INVSEQ, ie_FATAL_ERROR, df_SplitInfo::lastSplit, log_DBG_m, log_FUNC_m, log_WriteEvent(), log_WRN_m, m_blkSize, m_contBlk, m_contBSS, m_contFile, m_curSplit, m_diskFRI, m_friRec, m_medCurPos, m_recNum, m_streamName, m_streamSize, m_streamToFRI, m_streamType, df_SplitInfo::migrationID, df_BlockProxyWriter::Move(), df_RecFile_t::name, df_RecFile_t::nameOld, df_SplitInfo::noCopies, ntoh(), NULL, df_RecFile_t::numCopies, ivd_VarData_t::offset, df_SplitInfo::oldFileName, df_SplitInfo::oldOwnerID, df_SplitInfo::ownerID, rec_BSEnd_c, rec_BSStart_c, rec_EmbData_c, rec_FileEnd_c, rec_FileHdr_c, df_RecCmn_t::seqNum, ivd_VarData_t::size, df_RecCmn_t::size, size, df_StandardAttr_t::size, df_SplitInfo::splitOffset, df_SplitInfo::splitSize, df_RecByteStreamEnd_t::status, df_RecFile_t::stdAttr, df_RecByteStreamStart_t::streamName, df_RecByteStreamStart_t::streamSize, df_RecEmbeddedData_t::streamType, df_RecByteStreamEnd_t::streamType, and df_RecByteStreamStart_t::streamType.

Referenced by bea_MigrationThread::WriteBlock().

                                           {

    log_FUNC_m(BlockWritten);

    m_medCurPos = a_medPos;
    
    // Prevent invalid medium position to be stored to FSC and FRI
    if (a_medPos < 3) {
        log_MARKLINE_m;
        throw ivd_InternalError(ie_FATAL_ERROR,
            string("Invalid medium position: ") + cmn_Num2Str(a_medPos) );
    }

    if (m_friRec.empty()) {
        // no records ==> RAW block
        if (!m_curSplit.fileID) {
            throw ivd_DFError(ie_DF_INVSEQ, 0,
                              "No File record before RAW block");
        }

        m_curSplit.splitSize += m_blkSize; 
    }    

    for (UInt32_t i=0; i < m_friRec.size(); ++i) {
        bool toFRI = false;

        if (m_friRec[i]->type == rec_FileHdr_c) {
            df_RecFile_t *file_p = df_GetSpecificRec<df_RecFile_t>(m_friRec[i]);

            m_curSplit.dataType     = ivd_ATTR_d;
            m_curSplit.lastSplit    = false;        // we do not know yet
            m_curSplit.blockOffset  = a_medPos;

            m_curSplit.fileID       = static_cast<ivd_FileID_t>(ntoh(file_p->idFile));
            m_curSplit.migrationID  = ntoh(file_p->idMig);
            m_curSplit.fileSize     = ntoh(file_p->stdAttr.size);
            m_curSplit.chunkSize    = ntoh(file_p->chunkSize);
            m_curSplit.ownerID      = static_cast<ivd_FileID_t>(ntoh(file_p->idParent));
            m_curSplit.oldOwnerID   = static_cast<ivd_FileID_t>(ntoh(file_p->idParentOld));
            m_curSplit.fileName     = ((char*)m_friRec[i] +
                                       ntoh(file_p->name.offset));
            m_curSplit.oldFileName  = ((char*)m_friRec[i] +
                                       ntoh(file_p->nameOld.offset));

            m_curSplit.chunkOffset  = 0;
            m_curSplit.splitOffset  = 0;
            m_curSplit.noCopies     = ntoh(file_p->numCopies);
            m_curSplit.splitSize    = 0;

            log_DBG_m(dbg_DETAIL,
                "File Start: " << m_curSplit.fileID <<
                " copies: " << m_curSplit.noCopies);

            toFRI = true;

            // Copy File record to continuation block
            m_contFile = reinterpret_cast<df_RecCmn_t*>(m_contBlk +
                                                        sizeof(*m_contBlkHdr));
            memcpy(m_contFile, m_friRec[i], ntoh(m_friRec[i]->size));
            m_contFile->flags = hton(ntoh(m_contFile->flags) | df_RF_CONTINUED);

        }
        else if (m_friRec[i]->type == rec_FileEnd_c) {

            if (!m_curSplit.fileID) {
                throw ivd_DFError(ie_DF_INVSEQ, 0,
                                  "No File record before FileEnd");
            }
            m_curSplit.lastSplit = true;

            log_DBG_m(dbg_DETAIL, "File End: " << m_curSplit.fileID);

            // end of file -> save split info for current file
            FlushCurrentSplit();

            toFRI = true;

            // Remove file record from continuation block
            m_contFile = 0;
        }
        else if (m_friRec[i]->type == rec_BSStart_c) {
            df_RecByteStreamStart_t *bss_p = df_GetSpecificRec<df_RecByteStreamStart_t>(m_friRec[i]);

            if (!m_curSplit.fileID) {
                throw ivd_DFError(ie_DF_INVSEQ, 0,
                                  "No File record before BSStart");
            }

            m_curSplit.dataType     |= ntoh(bss_p->streamType);
            m_curSplit.chunkOffset  = ntoh(bss_p->chunkOffset);

            if (ntoh(m_friRec[i]->flags) & df_RF_CONTINUED) {
                m_curSplit.splitOffset = ntoh(bss_p->allStreamSize);
                m_curSplit.splitSize   = 0;
            }
            
            m_streamType = ntoh(bss_p->streamType);
            
            if (m_streamType == df_ST_META) {
/* +++ Temporary fix to solve the problem 2106. Large meta-data blocks are skipped. +++ */
                if (ntoh(bss_p->streamSize) > m_blkSize) {
                    m_streamToFRI = false;
                    
                    UInt64_t fileID = ntoh(bss_p->idFile);
                    const char* name = m_friRec[i]->GetVarDataNet(bss_p->streamName);
                    ostringstream sstr;
                    sstr << "Large meta-data stream skipped from FRI and FSC. " 
                        << "File ID= " << fileID << ", name= " << name
                        << " size= " << ntoh(bss_p->streamSize);
                    log_WriteEvent(evt_WARNING, sstr.str());
                }
                else {
/* +++ End of temporary fix to solve the problem 2106. +++ */
                    m_streamToFRI = true;
                }
            }
            else { // for ADS is stored only BSS and BSE, no data. see "else if (... rec_EmbData_c)"
                m_streamToFRI = (m_streamType == df_ST_ALTDATA); 
            }
            
            m_streamName = ((char*)m_friRec[i] + ntoh(bss_p->streamName.offset));
            m_streamSize = ntoh(bss_p->streamSize);
            
            toFRI = m_streamToFRI;

            // Copy BSS record to continuation block
            if (!m_contFile) {
                throw ivd_DFError(ie_DF_INVSEQ, 0,
                                  "No File record before BSStart");
            }
            m_contBSS = reinterpret_cast<df_RecCmn_t*>(m_contBlk +
                                                       sizeof(*m_contBlkHdr) +
                                                       ntoh(m_contFile->size));
            memcpy(m_contBSS, m_friRec[i], ntoh(m_friRec[i]->size));
            m_contBSS->flags = hton(ntoh(m_contBSS->flags) | df_RF_CONTINUED);

        }
        else if (m_friRec[i]->type == rec_BSEnd_c) {
            df_RecByteStreamEnd_t *bse_p = df_GetSpecificRec<df_RecByteStreamEnd_t>(m_friRec[i]);
            
            if (!m_curSplit.fileID) {
                throw ivd_DFError(ie_DF_INVSEQ, 0,
                                  "No File record before BSEnd");
            }

            if (!(m_curSplit.dataType & ntoh(bse_p->streamType))) {
                throw ivd_DFError(ie_DF_INVSEQ, 0,
                                  "No BSStart record before BSEnd");
            }

            UInt32_t st = ntoh(bse_p->streamType);
            log_DBG_m(dbg_DETAIL,
                "BSE stream type  FileID = " << m_curSplit.fileID <<
                " byte stream type = " << st <<
                " data Type = " << m_curSplit.dataType <<
                " BS status " << ntoh(bse_p->status));

            // remove stream type if data is not ready.
            if (ntoh(bse_p->status) != df_SS_COMPLETE) {
                m_curSplit.dataType     &= ~st;
                log_DBG_m(dbg_DETAIL,
                    "Stream is not complete. FileID = " << m_curSplit.fileID <<
                    " remove byte stream type = " << st <<
                    "  data Type = " << m_curSplit.dataType);
            }

            toFRI = m_streamToFRI;

            m_streamType  = 0;
            m_streamSize = 0;
            m_streamName.clear();
            m_streamToFRI = false;
            
            // Clear BSS record in continuation block
            m_contBSS = 0;

        }
        else if (m_friRec[i]->type == rec_EmbData_c) {
            df_RecEmbeddedData_t *eData_p = df_GetSpecificRec<df_RecEmbeddedData_t>(m_friRec[i]);

            if (!m_curSplit.fileID) {
                throw ivd_DFError(ie_DF_INVSEQ, 0,
                                  "No File record before EmbData");
            }

            if (!(m_curSplit.dataType & ntoh(eData_p->streamType))) {
                throw ivd_DFError(ie_DF_INVSEQ, 0,
                                  "No BSStart record before EmbData");
            }

            m_curSplit.splitSize += ntoh(eData_p->data.size);

            if (m_streamType != df_ST_ALTDATA)
                toFRI = m_streamToFRI;
            else {
                toFRI = false;
            }

        } else {
            log_WRN_m("Warning: No parse for this record type! Got type:" << 
                      string((char*)(&m_friRec[i]->type), 
                             sizeof(m_friRec[i]->type)));
        }

        // copy all records beside DATA stream to FRI
        if (toFRI) {
            UInt32_t recSize = ntoh(m_friRec[i]->size);

            UInt8_t* recBuf = m_diskFRI->Allocate(recSize);
            if (recBuf == NULL) {
                log_WRN_m("Null FRI block. May be a problem if not at EOD of FRI.");
                return;
            }

            df_RecCmn_t *friRec = reinterpret_cast<df_RecCmn_t*>(recBuf);

            memcpy(friRec, m_friRec[i], recSize);

            // update record sequence number to FRI sequence number
            friRec->seqNum = ntoh(++m_recNum);

            m_diskFRI->Move(recSize);
        }
    } // for (each friRec)
}

Here is the call graph for this function:

Here is the caller graph for this function:

void df_FRI::FlushCurrentSplit (  )  [private]

Definition at line 119 of file df_fri.cpp.

References df_BlockProxyWriter::Allocate(), df_SplitInfo::blockOffset, df_SplitInfo::dataType, df_SplitInfo::fileID, log_FUNC_m, log_WRN_m, m_curSplit, m_diskFRI, m_recNum, df_BlockProxyWriter::Move(), NULL, df_SplitInfo::splitOffset, df_SplitInfo::splitSize, and df_Packer::WriteRecFRISplitInfo().

Referenced by BlockWritten(), and MediumVolumeEnd().

                               {

    log_FUNC_m(FlushCurrentSplit);

    UInt32_t recSize = sizeof(df_RecCmn_t) + sizeof(df_RecFRISpInfo_t);

    UInt8_t* recBuf = m_diskFRI->Allocate(recSize);
    
    if (recBuf == NULL) {
        log_WRN_m("Null FRI block. May be a problem if not at EOD of FRI.");
        return;
    }

    df_Packer::WriteRecFRISplitInfo(m_curSplit.fileID, 
                                    m_curSplit.splitOffset,
                                    m_curSplit.splitSize,
                                    m_curSplit.dataType,
                                    ++m_recNum,
                                    m_curSplit.blockOffset,
                                    recBuf,
                                    recSize);

    m_diskFRI->Move(recSize);

    // mark that we need to get new File record (even if continued)
    m_curSplit.fileID = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const vector<df_SplitInfo>& df_FRI::GetSplits (  )  const [inline]

Definition at line 869 of file df.h.

                                                  {
        return m_splits;
    };

void df_FRI::MediumVolumeClosed ( const string &  a_medVolID  ) 

Medium Volume is closed and Disk FRI can be removed.

Disk FRI file will be closed.

Definition at line 614 of file df_fri.cpp.

References cmn_File::DeleteF(), cmn_Global::dirs, ivd_Directories::fri, g_cmn, ie_IMPOSSIBLE, log_FUNC_m, and m_diskFRI.

                                                        {

    log_FUNC_m(MediumVolumeClosed);

    if (m_diskFRI) {
        throw ivd_InternalError(ie_IMPOSSIBLE, 
                                "Current volume not ended yet");
    }

    cmn_File    friFile(g_cmn.dirs.fri + a_medVolID);

    friFile.DeleteF();
}

Here is the call graph for this function:

void df_FRI::MediumVolumeEnd ( UInt32_t  a_status  ) 

End processing FRI for new medium volume.

If there is still split info left it is returned. Disk FRI file will be closed.

Definition at line 526 of file df_fri.cpp.

References df_BlockProxyWriter::Allocate(), dbg_LOW, df_ALIGN_m, df_FRIS_ABORTED, df_FS_ERROR, df_Writer::EndOfData(), df_SplitInfo::fileID, FlushCurrentSplit(), ie_IMPOSSIBLE, log_DBG_m, log_FUNC_m, log_WRN_m, m_curMedVolID, m_curSplit, m_diskFRI, m_medCurPos, m_medStartPos, m_partID, m_poolID, m_recNum, m_streamName, m_streamSize, m_streamToFRI, m_streamType, df_SplitInfo::migrationID, df_BlockProxyWriter::Move(), NULL, df_SplitInfo::splitSize, df_Writer::WaitAllReaders(), df_Packer::WriteRecBSEndRaw(), df_Packer::WriteRecFileEndRaw(), and df_Packer::WriteRecFRIEnd().

Referenced by bea_MigrationThread::FRIVolumeEnd(), and ~df_FRI().

                                              {

    log_FUNC_m(MediumVolumeEnd);

    if (!m_diskFRI) {
        throw ivd_InternalError(ie_IMPOSSIBLE, 
                                "Volume not started yet");
    }

    // if this is last block on medium volume -> flush current split (if any)
    if (m_curSplit.fileID != 0) {
        if (a_status != df_FRIS_ABORTED) {
            FlushCurrentSplit();
        }
        else {
            if (m_streamType != 0) {
                if (m_streamToFRI) {
                    log_DBG_m(dbg_LOW, "Migration aborted. Writing BSEn.");
                
                    UInt32_t recSize = df_ALIGN_m(sizeof(df_RecCmn_t)
                                    + sizeof(df_RecByteStreamEnd_t)
                                    + m_streamName.length() 
                                    + 1);
                                            
                    UInt8_t* recBuf = m_diskFRI->Allocate(recSize);
                                
                    df_Packer::WriteRecBSEndRaw(
                        m_curSplit.fileID,
                        df_FS_ERROR, 
                        m_streamType, 
                        m_streamSize, 
                        m_curSplit.splitSize,
                        m_streamName,
                        0, 
                        recBuf);
                }
            }
            
            FlushCurrentSplit();
            
            log_DBG_m(dbg_LOW, "Migration aborted. Writing FEnd.");
            
            UInt32_t recSize = df_ALIGN_m(sizeof(df_RecCmn_t) 
                             + sizeof(df_RecFileEnd_t));
            UInt8_t* recBuf = m_diskFRI->Allocate(recSize);
            
            df_Packer::WriteRecFileEndRaw(m_curSplit.fileID,
                                          m_curSplit.migrationID,
                                          df_FS_ERROR,
                                          0, 
                                          recBuf,
                                          0);
        }
    }

    // Write FRIEnd record
    UInt32_t recSize = sizeof(df_RecCmn_t) + sizeof(df_RecFRIEnd_t);
    UInt8_t* recBuf = m_diskFRI->Allocate(recSize);
    
    if (recBuf != NULL) {
        df_Packer::WriteRecFRIEnd(m_curMedVolID,
                                m_poolID,
                                m_partID,
                                m_medStartPos,
                                m_medCurPos,
                                a_status,
                                ++m_recNum,
                                recBuf,
                                recSize);

        m_diskFRI->Move(recSize);
    }
    else {
        log_WRN_m("NULL block pointer for FRI. No reader available.");
    }

    // notify writer that we have no more data
    m_diskFRI->EndOfData();

    // Wait for all reader threads to finish.
    // May throw exception if reader sets it.
    m_diskFRI->WaitAllReaders();

    delete m_diskFRI;
    m_diskFRI = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

UInt8_t * df_FRI::MediumVolumeStart ( const cmn_UUID_t a_medVolID,
UInt32_t  a_medPos,
ivd_MigrationID_t  a_migrationID,
UInt32_t  a_copyNumber,
UInt32_t  a_mediumKey,
UInt32_t  a_medVolNum,
i_FSC_ptr  a_fsc 
)

Start processing FRI for new medium volume.

This will open/create Disk FRI file for above medium and all FRI data will be appended to Disk FRI file. Function returns continuation block (or 0 if not needed) - caller has to free the returned block with delete []!

Definition at line 375 of file df_fri.cpp.

References df_BlockProxyWriter::Allocate(), df_RecByteStreamStart_t::allStreamSize, bbt_DISK_FRI, blk_FRI_c, dbg_LOW, dbg_NORM, df_RF_SPLITTED, df_RecCmn_t::flags, df_BlockScanner::GetNextBlkNum(), df_BlockScanner::GetNextRecNum(), df_BlockScanner::GetStreamLeft(), df_Writer::Go(), hton(), ie_DF_EOD, ie_IMPOSSIBLE, log_DBG_m, log_ERR_m, log_FUNC_m, m_blkSize, m_contBlk, m_contBlkHdr, m_contBSS, m_contFile, m_curMedVolID, m_diskFRI, m_medCurPos, m_medStartPos, m_partID, m_poolID, m_recNum, m_scanner, df_BlockProxyWriter::Move(), df_Writer::NewFRIBuffer(), ntoh(), NULL, df_BlockScanner::Reset(), df_RecCmn_t::seqNum, df_BlockHeader_t::seqNum, df_RecCmn_t::size, df_RecByteStreamStart_t::streamOffset, df_RecByteStreamStart_t::streamSize, df_RecByteStreamStart_t::streamSplitSize, cmn_UUID_t::ToString(), df_BlockHeader_t::used, and df_Packer::WriteRecFRIStart().

Referenced by bea_MigrationThread::FRIVolumeStart().

                               {

    log_FUNC_m(MediumVolumeStart);

    if (m_diskFRI) {
        throw ivd_InternalError(
            ie_IMPOSSIBLE, "Previous volume not ended yet");
    }

    m_curMedVolID = a_medVolID;
    m_medStartPos = m_medCurPos = a_medPos;
    m_recNum      = 0;

/*
    TODO:
    OPen the FRI file and read the last block for append.
    If it can't be scanned, write it back to df_Writer as is.
*/
    m_diskFRI = new df_Writer(blk_FRI_c, bbt_DISK_FRI, m_blkSize);
    m_diskFRI->NewFRIBuffer(
        m_curMedVolID.ToString(),
        a_migrationID,
        a_copyNumber,
        a_mediumKey,
        a_medVolNum,
        a_fsc);

    m_diskFRI->Go();

    // Write FRIStart record
    UInt32_t recSize = sizeof(df_RecCmn_t) + sizeof(df_RecFRIStart_t);
    UInt8_t* recBuf = m_diskFRI->Allocate(recSize);
    
    if (recBuf == NULL) {
        log_MARKLINE_m;
        throw ivd_DFError(ie_DF_EOD, 0, "Unexpected EOD in FRI buffer.", true);
    }

    df_Packer::WriteRecFRIStart(m_curMedVolID,
                                m_poolID,
                                m_partID,
                                m_medStartPos,
                                ++m_recNum,
                                recBuf,
                                recSize);

    m_diskFRI->Move(recSize);

    // if there is file still not completed -> send continuation record
    if (m_contFile) {

        // update sequence number in continuation block
        m_contBlkHdr->seqNum = hton(m_scanner.GetNextBlkNum() - 1);

        // update block used field in continuation block header
        UInt32_t nextRecNum = m_scanner.GetNextRecNum();
        UInt32_t blockUsed = sizeof(*m_contBlkHdr);

        if (m_contBSS) {

            log_DBG_m(dbg_LOW, "Calculating data for the split.");
        
            blockUsed += ntoh(m_contBSS->size);
            m_contBSS->seqNum = hton(--nextRecNum);

            df_RecByteStreamStart_t *bss_p = df_GetSpecificRec<df_RecByteStreamStart_t>(m_contBSS);

            // ** Create new BSS for the split
            UInt64_t streamSize = ntoh(bss_p->streamSize);
            UInt64_t streamOffset = ntoh(bss_p->streamOffset);
            UInt64_t streamSplitSize = ntoh(bss_p->streamSplitSize);

            log_DBG_m(dbg_NORM, "StreamSize      : " << streamSize);
            log_DBG_m(dbg_NORM, "StreamOffset    : " << streamOffset);
            log_DBG_m(dbg_NORM, "StreamSplitSize : " << streamSplitSize);

            // ** Calculate total split size
            UInt64_t splitSize = streamSize - streamOffset;
            
            if (  streamSplitSize > 0
               || ntoh(m_contBSS->flags) & df_RF_SPLITTED) {
                if (splitSize < streamSplitSize) {
                    log_ERR_m(
                        "StreamSplitSize > (StreamSize - StreamOffset): " <<
                        "Possible internal error!!");
                }
                splitSize = streamSplitSize;
            }
            log_DBG_m(dbg_LOW, "Size of this stream: " << splitSize);
            
            // ** Calculate new split stream sizes
            
            UInt64_t writtenSplitSize = splitSize - m_scanner.GetStreamLeft();
            UInt64_t leftSplitSize = m_scanner.GetStreamLeft();

            // AllStreamSize is AllStreamSize reduced by current stream offset
            // increased by size of current stream written up to now
            bss_p->allStreamSize = hton(
                ntoh(bss_p->allStreamSize) + writtenSplitSize );

            // Current StreamOffset (for new medium volume) is 
            // size of stream reduced for stream bytes left (not written yet)
            bss_p->streamOffset  = hton( streamOffset + writtenSplitSize );
                                        
            // Already split stream is split again
            if (streamSplitSize > 0) {
                bss_p->streamSplitSize = hton(leftSplitSize);
                
                log_DBG_m(dbg_NORM,
                    "Splitting a split. New splitStreamSize : " <<
                    m_scanner.GetStreamLeft() );
            }
            
            log_DBG_m(dbg_LOW,
                "ContBSS: streamSplitSize: " << ntoh(bss_p->streamSplitSize) << endl <<
                "streamSize              : " << ntoh(bss_p->streamSize) << endl <<
                "allStreamSize           : " << ntoh(bss_p->allStreamSize) << endl <<
                "streamOffset            : " << ntoh(bss_p->streamOffset));
        }

        blockUsed += ntoh(m_contFile->size);
        m_contFile->seqNum = hton(--nextRecNum);

        m_contBlkHdr->used = hton(blockUsed);

        // allocate return block - call should delete it
        UInt8_t *retBlk = new UInt8_t[m_blkSize];
        memcpy(retBlk, m_contBlk, blockUsed);

        // reset record pointer for new medium
        m_contFile = 0;
        m_contBSS  = 0;

        // reset scanner - new medium may start with contBlock
        m_scanner.Reset();

        // return continuation block
        return retBlk;
    }

    return 0;   // first medium or continuation block not needed
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 871 of file df.h.

Definition at line 881 of file df.h.

Referenced by BlockWritten(), and MediumVolumeStart().

Continuation block buffer - used in case file spans multiple volumes.

Definition at line 905 of file df.h.

Referenced by BlockWritten(), df_FRI(), MediumVolumeStart(), and ~df_FRI().

Pointers into m_contBlk buffer (NULL if they do not exist).

Definition at line 908 of file df.h.

Referenced by df_FRI(), and MediumVolumeStart().

Definition at line 910 of file df.h.

Referenced by BlockWritten(), and MediumVolumeStart().

Definition at line 909 of file df.h.

Referenced by BlockWritten(), and MediumVolumeStart().

Disk FRI file.

Definition at line 887 of file df.h.

Referenced by MediumVolumeEnd(), and MediumVolumeStart().

Definition at line 901 of file df.h.

Referenced by BlockWritten(), df_FRI(), FlushCurrentSplit(), and MediumVolumeEnd().

FRI records from last block (saved for BlockWritten() method).

Definition at line 899 of file df.h.

Referenced by BlockScan(), and BlockWritten().

Definition at line 890 of file df.h.

Referenced by BlockWritten(), MediumVolumeEnd(), and MediumVolumeStart().

Definition at line 889 of file df.h.

Referenced by MediumVolumeEnd(), and MediumVolumeStart().

Definition at line 883 of file df.h.

Referenced by MediumVolumeEnd(), and MediumVolumeStart().

Definition at line 884 of file df.h.

Referenced by MediumVolumeEnd(), and MediumVolumeStart().

Definition at line 892 of file df.h.

Referenced by BlockWritten(), FlushCurrentSplit(), MediumVolumeEnd(), and MediumVolumeStart().

Scanner used for parsing IVD Data blocks.

Definition at line 879 of file df.h.

Referenced by BlockScan(), and MediumVolumeStart().

Definition at line 902 of file df.h.

string df_FRI::m_streamName [private]

Definition at line 895 of file df.h.

Referenced by BlockWritten(), and MediumVolumeEnd().

Definition at line 894 of file df.h.

Referenced by BlockWritten(), and MediumVolumeEnd().

bool df_FRI::m_streamToFRI [private]

Definition at line 896 of file df.h.

Referenced by BlockWritten(), and MediumVolumeEnd().

Definition at line 893 of file df.h.

Referenced by BlockWritten(), and MediumVolumeEnd().


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