/*****************************************************************************/
/* SOURCE FILE */
/*****************************************************************************/
/*
$Archive: $
$Revision: $
$Date: $
$Author: $
Description: implementation of class VMDataTransferBlock
TOOL And XML FORMS License
==========================
Except where otherwise noted, all of the documentation
and software included in the TOOL package is
copyrighted by Michael Swartzendruber.
Copyright (C) 2005 Michael John Swartzendruber.
All rights reserved.
Access to this code, whether intentional or accidental,
does NOT IMPLY any transfer of rights.
This software is provided "as-is," without any express
or implied warranty. In no event shall the author be held
liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for
any purpose, including commercial applications, and to
alter and redistribute it, provided that the following
conditions are met:
1. All redistributions of source code files must retain
all copyright notices that are currently in place,
and this list of conditions without modification.
2. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
3. If you use this software in another product, an acknowledgment
in the product documentation would be appreciated but is
not required.
4. Modified versions in source or binary form must be plainly
marked as such, and must not be misrepresented as being
the original software.
*/
static char OBJECT_ID[] = "$Revision: $ : $Date: $";
/*****************************************************************************/
#include "../../../stdafx.h"
#include "VMDataTypeMemMappedFile.h"
/*****************************************************************************/
/*
FUNCTION NAME: VMDataTransferBlock
DESCRIPTION: ctor. Creates the base class, then immediately requests
a buffer from the mmf
INPUT: pchName - the name of the mmf to use
dwSize - the size of the mmf to create
RETURNS:
*/
VMDataTransferBlock::VMDataTransferBlock( char* pchName, DWORD dwSize )
: VMMemMappedFile( pchName, TRUE, dwSize )
{
m_pvRawData = GetBufferFromMemMappedFile();
m_poCurRecHeader = (VMDataTransferHeader*)m_pvRawData;
if ( CreatedMapping() )
{
WriteHeader( 0, 0, 0, 0 );
}
m_iCurrentRecord = 0;
}
/* end of function "VMDataTransferBlock" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: ~VMDataTransferBlock
DESCRIPTION: dtor. frees up the buffer owned by this class
INPUT: void
RETURNS: void
*/
VMDataTransferBlock::~VMDataTransferBlock( void )
{
if( m_pvRawData )
{
::UnmapViewOfFile( m_pvRawData );
}
}
/* end of function "~VMDataTransferBlock" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: PostProcessReadData
DESCRIPTION: required by base class. does nothing
INPUT: lpMemMappedDataBuffer - the read buffer from the mmf
lpYourData - the buffer passed to the read function
RETURNS: 0
*/
long VMDataTransferBlock::PostProcessReadData( LPVOID lpMemMappedDataBuffer, LPVOID lpYourData )
{
return( 0 );
}
/* end of function "PostProcessReadData" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: PreProcessWriteData
DESCRIPTION: required by base class. does nothing
INPUT: lpMemMappedDataBuffer - pointer to mmf buffer
lpToYourData - the buffer you supplied to the Write method
buffersize - the size of YourData buffer
RETURNS: 0
*/
long VMDataTransferBlock::PreProcessWriteData( void* pvMemMappedDataBuffer,
void* pvToYourData,
DWORD dwBufferSize )
{
return( 0 );
}
/* end of function "PreProcessWriteData" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: ClearAll
DESCRIPTION: 'erase' all data from the block.
INPUT: void
RETURNS: void
*/
void VMDataTransferBlock::ClearAll( void )
{
m_poCurRecHeader = (VMDataTransferHeader*)m_pvRawData;
WriteHeader( 0, 0, 0, 0 );
AppendHeader( 0, 0, 0, 0 );
}
/* end of function "ClearAll" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: WriteHeader
DESCRIPTION: if m_poCurRecHeader is valid, then writes the parameters given
to that header.
INPUT: iRecType - the type of record to write
ulRecSize - the size of the record for this header
ulReccount - the number of records following this header
ulFflags - header flags
RETURNS: OKAY if successful, or MISSING_HEADER if m_poCurRecHeader is bad
*/
long VMDataTransferBlock::WriteHeader( int iRecType,
unsigned long ulRecSize,
unsigned long ulRecCount,
unsigned long ulFlags )
{
if ( !m_poCurRecHeader )
{
return( MISSING_HEADER );
}
m_poCurRecHeader->m_chRecType = iRecType;
m_poCurRecHeader->m_ulRecSize = ulRecSize;
m_poCurRecHeader->m_ulRecCount = ulRecCount;
m_poCurRecHeader->m_ulFlags = ulFlags;
m_poCurRecHeader->m_chStatus = ( iRecType && ulRecSize && ulRecCount ) ? 1 : 0;
return( OKAY );
}
/* end of function "WriteHeader" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: AppendHeader
DESCRIPTION: adds a new header to the end of the mmf
INPUT: iRecType - the type of record to append
ulRecSize - the size of the record associated with the header
ulRecCount - the number of records for the header
ulFlags - header flags
RETURNS: TRUE on success, an error code otherwise
*/
long VMDataTransferBlock::AppendHeader( int iRecType,
unsigned long ulRecSize,
unsigned long ulRecCount,
unsigned long ulFlags )
{
if ( !LockBuffer() )
{
return( LOCK_FAILURE );
}
// locate next available header (last one)
//
for( GetFirstHeader( iRecType );
m_poCurRecHeader;
GetNextHeader( iRecType ) )
{
// if no more room
//
if ( m_poCurRecHeader >= (VMDataTransferHeader*)( (char*)MoveToEnd() - ( HEADER_SIZE * 2 ) ) )
{
return( BLOCK_FULL );
}
// rectype 0 is null header at end of block
//
if ( !m_poCurRecHeader->m_chRecType )
{
m_poCurRecHeader->m_chStatus = 0; // can't be any actual records yet
m_poCurRecHeader->m_chRecType = iRecType;
m_poCurRecHeader->m_ulRecSize = ulRecSize;
m_poCurRecHeader->m_ulRecCount = ulRecCount;
m_poCurRecHeader->m_ulFlags = ulFlags;
// write null header to next slot
//
VMDataTransferHeader* poNextHeader = m_poCurRecHeader + 1;
poNextHeader->m_chStatus = 0;
poNextHeader->m_chRecType = 0;
poNextHeader->m_ulRecSize = 0;
poNextHeader->m_ulRecCount = 0;
break;
}
}
ReleaseBuffer();
return TRUE;
}
/* end of function "AppendHeader" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: GetNextHeader
DESCRIPTION: finds the next occurance of type: rectype in the MMF relative
to m_poCurRecHeader
INPUT: iRecType - the type of record to locate
RETURNS: a pointer to the header on success or NULL if it can not
be found
*/
VMDataTransferHeader* VMDataTransferBlock::GetNextHeader( int iRecType )
{
if ( !m_poCurRecHeader )
{
return( GetFirstHeader( iRecType ) );
}
for( ; ; )
{
m_poCurRecHeader = (VMDataTransferHeader*)( (char*)m_poCurRecHeader
+ ( m_poCurRecHeader->DataSize() + HEADER_SIZE ) );
if ( !m_poCurRecHeader->m_chRecType )
{
return( m_poCurRecHeader );
}
if( GetRecType() == iRecType )
{
return( m_poCurRecHeader );
}
}
return( NULL );
}
/* end of function "GetNextHeader" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: GetFirstHeader
DESCRIPTION: finds the first occurance of a record of type: rectype in
the mmf
INPUT: rectype - the type of record to locate
RETURNS: a pointer to the first header of that type
*/
VMDataTransferHeader* VMDataTransferBlock::GetFirstHeader( int iRecType )
{
m_poCurRecHeader = (VMDataTransferHeader*)m_pvRawData;
if ( !GetRecType() || GetRecType() == iRecType )
{
return( m_poCurRecHeader );
}
else
{
return( GetNextHeader( iRecType ) );
}
return( m_poCurRecHeader );
}
/* end of function "GetFirstHeader" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: ReadFirstRecord
DESCRIPTION: finds the first occurance of a record of type rectype
INPUT: rectype - the type of the record to get
buf - not used
RETURNS: a pointer to the record, or NULL if it wasn't found
*/
void* VMDataTransferBlock::ReadFirstRecord( int iRecType, void* pvBuffer )
{
return( ReadRecord( iRecType, 0, pvBuffer ) );
}
/* end of function "readFirstRecord" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: ReadRecord
DESCRIPTION: reads a specific data record from the mmf of type rectype.
The record to be read is defined by the recNum parameter
INPUT: iRecType - the type of record to read
iRecNum - defines the ocurrance of the record to read
pvBuffer - not used
RETURNS: a pointer to the record, or NULL if it could not be found
*/
void* VMDataTransferBlock::ReadRecord( int iRecType, int iRecNum, void* pvBuffer )
{
int iCurrentRecord = 0;
void* pvData = NULL;
for ( GetFirstHeader( iRecType ); m_poCurRecHeader; GetNextHeader( iRecType ) )
{
if ( !m_poCurRecHeader || m_poCurRecHeader->m_chRecType != iRecType )
{
break;
}
if ( iRecNum < ( iCurrentRecord + GetRecCount() ) ) // found it
{
pvData = (char*)m_poCurRecHeader
+ ( HEADER_SIZE + ( GetRecSize() * ( iRecNum - iCurrentRecord ) ) );
break;
}
else
{
iCurrentRecord += GetRecCount();
}
}
return( pvData );
}
/* end of function "ReadRecord" */
/*****************************************************************************/
/*****************************************************************************/
/*
FUNCTION NAME: AppendData
DESCRIPTION: adds record(s) of the type specified by rectype to the
mmf.
INPUT: iRecType - the type of record to add
pvData - a pointer to the record data
iNumRecs - the number of the records in data
RETURNS: OKAY on no errors.
*/
long VMDataTransferBlock::AppendData( int iRecType, void* pvData, int iNumRecs )
{
if ( !LockBuffer() )
{
return( LOCK_FAILURE );
}
// accept the first header of rectype
// since only supporting ONE header for now...
//
m_poCurRecHeader = GetFirstHeader( iRecType );
if ( !m_poCurRecHeader || m_poCurRecHeader->m_chRecType == 0 ) // make sure header is correct
{
return( MISSING_HEADER );
}
// find free area
//
char* pchOut = (char*)m_poCurRecHeader + ( HEADER_SIZE + GetDataSize() );
if ( pchOut > (char*)MoveToEnd() - ( ( GetRecSize() * iNumRecs ) + HEADER_SIZE ) )
{
return( BLOCK_FULL );
}
// copy the data
//
memcpy( pchOut, pvData, GetRecSize() * iNumRecs );
// update the header
//
m_poCurRecHeader->m_ulRecCount += iNumRecs;
m_poCurRecHeader->m_chStatus = true;
// write null header after the data
//
pchOut += GetRecSize() * iNumRecs;
memset( pchOut, 0, HEADER_SIZE );
ReleaseBuffer();
return( OKAY );
}
/* end of function "AppendData" */
/*****************************************************************************/
/*****************************************************************************/
/* Check-in history */
/*
*$Log: $
*/
/*****************************************************************************/