Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

STL WebServer

, 8 May 2000
A set of classes written in STL that implement a web server
// TransactionFile.cpp: implementation of the TransactionFile class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "TransactionFile.h"


#include <sstream>
using namespace std;

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////
// operator <<
//
// Purpose:		stream operators for file

void operator << ( stringstream & strm, TransactionFile & file )
{
	// get buffer
	long	sz     = file.size();
	TCHAR * buffer = new TCHAR[sz+1];
	if ( !buffer )
		return;

	// if read in, put buffer into stream
	if ( file.read(buffer,sz) )
	{
		buffer[sz] = '\0';
		strm << buffer;
	}

	// release buffer
	delete buffer;
}

void operator << ( TransactionFile & file, stringstream & strm )
{
	// get buffer
	long    sz     = strm.str().size();
	TCHAR * buffer = (TCHAR *) strm.str().c_str();
	if ( !buffer )
		return;

	// write buffer to file
	file.write(buffer,sz);
}


/////////////////////////////////////////////////////////////
// TransactionFile



TransactionFile::TransactionFile () :
	Lock(),
	SysEvent(),
	m_hFile(0),						// handle to file
	m_readOffset(0),				// current read offset
	m_writeOffset(0),				// current write offset
	m_readWait(INFINITE),			// time (ms) to wait after read
	m_writeWait(INFINITE),			// time (ms) to wait after write
	m_openFlags(0),					// flags used to open file
	m_name("")						// name of file

{
	SysEvent::create();
}

TransactionFile::~TransactionFile () 
{
	destroyLock();
	SysEvent::release();
	close();
}


void TransactionFile::showLastError ()
{
	LPVOID lpMsgBuf;
	DWORD  error = GetLastError();
	FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | 
				   FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,    
				   NULL,
				   error,
				   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
				   (LPTSTR) &lpMsgBuf,    0,    NULL );		  // Process any inserts in lpMsgBuf.

	// Display the string.
	AtlTrace("%s\n",(const char *) lpMsgBuf);

	// Free the buffer.
	LocalFree( lpMsgBuf );
}



bool TransactionFile::invalidFile ()
{
	if ( m_hFile == INVALID_HANDLE_VALUE )
		return true;
	else
		return false;
}

bool TransactionFile::create ( string & fileName )
{
	DWORD openFlags = CREATE_ALWAYS;
	return open(fileName,openFlags);
}

bool TransactionFile::open ( string & fileName )
{
	DWORD openFlags = OPEN_ALWAYS;
	return open(fileName,openFlags);
}


bool TransactionFile::openAlways ( string & fileName )
{
	DWORD openFlags = OPEN_ALWAYS;
	return open(fileName,openFlags);
}

bool TransactionFile::open ( string & fileName, DWORD openFlags )
{
	if ( !lock() )
		return false;

	// open the file
	m_hFile = 
	CreateFile( fileName.c_str(),
				GENERIC_READ | GENERIC_WRITE,
				FILE_SHARE_READ | FILE_SHARE_WRITE,
				NULL,
				openFlags,
				FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 
				0 );

	unlock();

	if ( m_hFile == INVALID_HANDLE_VALUE )
	{
		showLastError();
		return false;
	}

	// store file info
	m_openFlags = openFlags;
	m_name = fileName;
	m_readOffset = 0;
	m_writeOffset = 0;

	return true;
}

void TransactionFile::close ()
{
	if ( !lock() )
		return;

	if ( m_hFile == INVALID_HANDLE_VALUE )
		return;

	::CloseHandle(m_hFile);
	m_hFile = INVALID_HANDLE_VALUE;

	unlock();
}


bool TransactionFile::offsetPosition ( DWORD offset, bool read )
{
	if ( !lock() )
		return false;

	if ( m_hFile == INVALID_HANDLE_VALUE )
		return false;

	if ( read )
		m_readOffset  += offset;
	else
		m_writeOffset += offset;

	unlock();
	return true;
}


bool TransactionFile::setPosition ( DWORD position, bool read )
{
	if ( !lock() )
		return false;

	if ( m_hFile == INVALID_HANDLE_VALUE )
		return false;

	if ( read )
		m_readOffset  = position;
	else
		m_writeOffset = position;

	unlock();
	return true;
}


void TransactionFile::clear ()
{
	if ( !lock() )
		return;

	if ( m_hFile == INVALID_HANDLE_VALUE )
		return;

	::CloseHandle(m_hFile);
	DeleteFile( m_name.c_str() );

	bool success = 
	open(m_name,m_openFlags);

	unlock();
}

long TransactionFile::size ()
{
	if ( !lock() )
		return 0;

	if ( m_hFile == INVALID_HANDLE_VALUE )
		return 0;

	DWORD dwSize =
	::GetFileSize(m_hFile, NULL);

	unlock();
	return dwSize;
}

bool TransactionFile::write ( LPTSTR pBuffer, DWORD noToWrite, bool wait )
{
	if ( !lock() )
		return false;

	// set overlap for write
	OVERLAPPED overlap;

	HANDLE hEvent      = getEvent();
	overlap.hEvent     = hEvent;
	overlap.Offset     = m_writeOffset;
	overlap.OffsetHigh = 0;

	bool success = false;
	try
	{
		// write to file
		DWORD noWritten = 0;
		if ( WriteFile(m_hFile,(LPVOID)pBuffer,noToWrite,&noWritten,&overlap) != 0 )
			success = true;

		if ( wait && m_writeWait > 0 )
		{
			DWORD result = WaitForSingleObject( hEvent, m_writeWait );
			switch ( result )
			{
				case WAIT_OBJECT_0:
					break;

				case WAIT_ABANDONED:
				case WAIT_TIMEOUT:
				default:
					return false;

			}
		}

		// if write success update write offset
		if ( noWritten == noToWrite )
			m_writeOffset += noWritten;

	}
	catch(...)
	{}


	unlock();

	return success;
}

bool TransactionFile::read ( LPTSTR pBuffer, DWORD noToRead, bool wait )
{
	//if ( !lock() )
	//	return false;

	// set overlap for write
	OVERLAPPED overlap;

	HANDLE hEvent      = getEvent();
	overlap.hEvent     = hEvent;
	overlap.Offset     = m_readOffset;
	overlap.OffsetHigh = 0;

	bool success = false;
	try
	{
		// read from file
		DWORD noRead;
		DWORD result = ReadFile(m_hFile,(LPVOID)pBuffer,noToRead,&noRead,&overlap);
		if ( result != 0 )
			success = true;

		if ( wait && m_readWait > 0 )
		{
			DWORD result = WaitForSingleObject( hEvent, m_readWait );
			switch ( result )
			{
				case WAIT_OBJECT_0:
					break;

				case WAIT_ABANDONED:
				case WAIT_TIMEOUT:
				default:
					return false;

			}
		}

		// if read success update read offset 
		if ( noRead == noToRead )
			m_readOffset += noRead;

	}
	catch(...)
	{}

	unlock();

	return success;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

David Hubbard

United States United States
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150414.1 | Last Updated 9 May 2000
Article Copyright 2000 by David Hubbard
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid