www.pudn.com > GEOPC_modified_2005621145656299.rar > GROUP.CPP, change:2005-06-08,size:9602b


// Group.cpp 
// 
//  This file contains the implementation of  
//  the 'core' of the XXXGroup Object for the OPC Sample server. 
// 
// 
//	(c) COPYRIGHT 1996,1997 INTELLUTION INC. 
// ALL RIGHTS RESERVED 
// 
// Original Author: Al Chisholm 
// 
// Modification Log: 
//  Vers    Date   By    Notes 
//  ----  -------- ---   ----- 
//  0.00  11/18/96 ACC 
//  0.90  04/02/97 acc   add Async support 
// 
// todo 
// <zzz should clearing group active clear any datachange bits? probably 
// or perhaps setting group active should do MarkAsChanged on all items 
// or perhaps this should be done only if ADF_PRIMEFIRST ?> 
// 
 
 
#define WIN32_LEAN_AND_MEAN 
#include "implconnect.h" 
#include "OPCXXX.h" 
 
extern CRITICAL_SECTION	CritSec; 
 
///////////////////////////////////////////////////////////////////////////// 
// Constructor /Destructor functions 
// 
 
/////////////////////////////////////// 
// OPCGroup() 
//   Constructor for the OPC Sample Group. 
// 
/////////////////////////////////////// 
XXXGroup::XXXGroup( LPUNKNOWN pOuter) 
{ 
	int	j; 
 
	mRefCount = 0; 
 
	// Record Parent server 
	// 
	m_ParentServer = (XXXServer *)pOuter; 
 
	// Initizlize member variables 
	// 
	m_ServerGroupHandle = 0; 
	m_ClientGroupHandle = 0; 
	m_dwRevisedRate = 0; 
	m_bActive = FALSE; 
	m_szName = 0; 
 
	// Clear out 'tear-off' interface ptrs 
	// The interfaces will be created as needed in QueryInterface 
	// 
	m_pIXXXGSM = 0; 
	m_pIXXXPGSM = 0;	// optional 
	m_pIXXXSIO = 0; 
	m_pIXXXASIO = 0; 
	m_pIXXXIM = 0; 
	m_pIXXXDO = 0; 
	m_pIXXXASIO2=0; 
	m_pCImpIConnPointContainer=NULL; 
	m_pCImpIConnPoint=NULL; 
 
	// async state variables used by DataObject  
	// 
	m_AsyncReadActive = 0; 
	m_AsyncReadCancel = 0; 
	m_AsyncReadTID = 0; 
	m_AsyncReadList = 0; 
	m_AsyncReadSource = OPC_DS_CACHE; 
 
	m_AsyncWriteActive = 0; 
	m_AsyncWriteCancel = 0; 
	m_AsyncWriteTID = 0; 
	m_AsyncWriteList = 0; 
 
	m_RefreshTID = 0; 
	m_RefreshCancel = 0; 
	m_RefreshSource = OPC_DS_CACHE; 
	m_RefreshActive = 0; 
 
	m_scan = 0; 
 
	// Clear out the 'items' 
	// This simple example only holds 100 items 
	// A real implementation would use some sort 
	// of container or linked list 
	// 
	for (j=0; j<N_ITEMS; j++) 
	{ 
		m_items[j].inuse = 0; 
		m_items[j].pItem = NULL; 
	} 
} 
 
 
 
/////////////////////////////////////// 
// ~XXXGroup() 
//   Destructor for the OPC Sample Group. 
// 
/////////////////////////////////////// 
XXXGroup::~XXXGroup( void) 
{ 
	int	j; 
 
	// Enter critical section whenever deleting anything 
	// 
	EnterCriticalSection(&CritSec); 
 
	// Free memory associated with group name 
	// 
	if(m_szName) WSTRFree(m_szName, NULL); 
 
	// Delete all the Group level tear off interfaces 
	// 
	if(m_pIXXXGSM) delete m_pIXXXGSM; 
//	if(m_pIXXXPGSM) delete m_pIXXXPGSM;	// optional  
	if(m_pIXXXSIO) delete m_pIXXXSIO; 
	if(m_pIXXXASIO) delete m_pIXXXASIO; 
	if(m_pIXXXIM) delete m_pIXXXIM; 
	if(m_pIXXXDO) delete m_pIXXXDO; 
 
	// Clean up any Async stuff 
	// 
 
	if(m_AsyncReadList) pIMalloc->Free(m_AsyncReadList); // should be 0 already 
	if(m_AsyncWriteList) pIMalloc->Free(m_AsyncWriteList); 
 
	 
	// Also free any memory associated with the ITEMS 
	// 
	for (j=0; j<N_ITEMS; j++) 
	{ 
		// This release should delete the item 
		// (unless some badly behaved program is holding another interface) 
		// 
		if(m_items[j].inuse) 
		{ 
			m_items[j].inuse = 0; 
			m_items[j].pItem->Release(); 
		} 
	} 
	LeaveCriticalSection(&CritSec); 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// IUnknown functions 
// 
 
/////////////////////////////////////// 
// IUnknown::AddRef() 
//   Standard IUnknown implementation 
// 
/////////////////////////////////////// 
STDMETHODIMP_(ULONG) XXXGroup::AddRef( void) 
{ 
	return ++mRefCount; 
} 
 
 
 
/////////////////////////////////////// 
// IUnknown::Release() 
//   Standard IUnknown implementation 
// 
/////////////////////////////////////// 
STDMETHODIMP_(ULONG) XXXGroup::Release( void) 
{ 
	ULONG currentCount = --mRefCount; 
 
	// If no references left for this group 
	if ( currentCount == 0) 
	{ 
		// Then delete this group. 
		delete this; 
	} 
	return currentCount; 
} 
 
 
/////////////////////////////////////// 
// IUnknown::QueryInterface() 
//   Standard IUnknown implementation 
// 
/////////////////////////////////////// 
 
STDMETHODIMP XXXGroup::QueryInterface( REFIID iid, LPVOID* ppInterface) 
{ 
	if ( ppInterface == NULL) 
		return E_INVALIDARG; 
 
	if ( iid == IID_IUnknown ) 
		*ppInterface = (IUnknown*) this; 
 
	else if ( iid == IID_IOPCGroupStateMgt) 
	{ 
		if(m_pIXXXGSM == 0) m_pIXXXGSM = new IXXXGSM(this); 
		*ppInterface = m_pIXXXGSM; 
	} 
	else if ( iid == IID_IOPCPublicGroupStateMgt) 
	{ 
		if(m_pIXXXPGSM == 0) m_pIXXXPGSM = 0;	// optional (notimplemented) 
		*ppInterface = m_pIXXXPGSM; 
	} 
	else if ( iid == IID_IOPCAsyncIO2) 
	{ 
		if(m_pIXXXASIO2 == 0) m_pIXXXASIO2 = new IXXXASIO2(this) ; 
		*ppInterface = m_pIXXXASIO2; 
	} 
	else if ( iid == IID_IOPCSyncIO) 
	{ 
		if(m_pIXXXSIO == 0) m_pIXXXSIO = new IXXXSIO(this) ; 
		*ppInterface = m_pIXXXSIO; 
	} 
	else if ( iid == IID_IOPCAsyncIO) 
	{ 
		if(m_pIXXXASIO == 0) m_pIXXXASIO = new IXXXASIO(this) ; 
		*ppInterface = m_pIXXXASIO; 
	} 
	else if (iid == IID_IConnectionPointContainer) 
	{ 
		 
		if (NULL == m_pCImpIConnPoint) 
		{ 
			m_pCImpIConnPoint = new CImpIConnectionPoint(this, IID_IOPCDataCallback); 
			if (NULL == m_pCImpIConnPoint) 
			{ 
				return E_OUTOFMEMORY; 
			} 
		//	OPC_TRACE("COPCDrvServer::QueryInterface() Created new 'CImpIConnectionPoint(this, IID_IOPCShutdown)'" ); 
		} 
 
		// Create the connection point container 
		if (NULL == m_pCImpIConnPointContainer) 
		{ 
			m_pCImpIConnPointContainer = new CImpIConnectionPointContainer(this, &m_pCImpIConnPoint, 1); 
			if (NULL == m_pCImpIConnPointContainer) 
			{ 
				return E_OUTOFMEMORY; 
			} 
			//	OPC_TRACE("COPCDrvServer::QueryInterface() Created new 'CImpIConnectionPointContainer(this, &m_pCImpIConnPoint, 1)'" ); 
		} 
 
		// Set it up 
		*ppInterface = static_cast<IConnectionPointContainer *>(m_pCImpIConnPointContainer); 
 
		//szIntf = "IConnectionPointContainer"; 
	} 
	else if ( iid == IID_IOPCItemMgt) 
	{ 
		if(m_pIXXXIM == 0) m_pIXXXIM = new IXXXIM(this) ; 
		*ppInterface = m_pIXXXIM; 
	} 
	else if ( iid == IID_IDataObject) 
	{ 
		if(m_pIXXXDO == 0) m_pIXXXDO = new IXXXDO(this); 
		*ppInterface = m_pIXXXDO; 
	} 
 
	else 
	{ 
		*ppInterface = NULL; 
	} 
	 
	if ( *ppInterface == NULL) 
		return E_NOINTERFACE; 
 
	// Addref the group for each tear off interface created 
	// (This is equivalent to ppInterface->AddRef() which delegates back here) 
	// 
	AddRef(); 
	return S_OK; 
} 
 
 
/////////////////////////////////////// 
// XXXGroup::GetItemList() 
// Create a list of all the item attributes in Local Memory 
// 
// Note that local heap is used  
// and that caller must free the list using FreeItemList 
// 
void		XXXGroup::GetItemList( OPCITEMATTRIBUTES **AttrList, int *ItemCount) 
{ 
	int	j, count = 0; 
	OPCITEMATTRIBUTES *myAttr; 
 
	*ItemCount = 0; 
 
	// First pass - count items in use 
	// 
	for (j=0; j<ItemHandles(); j++) 
	{ 
		if(ItemValid(j)) count++; 
	} 
	if(!count)  
	{ 
		return; 
	} 
 
	*AttrList = myAttr = new OPCITEMATTRIBUTES[count]; 
	if (myAttr == NULL) 
	{ 
		return; 
	} 
 
	// Second pass - figure out what to return and do it 
	// 
	for (j=0; j<ItemHandles(); j++) 
	{ 
		if(ItemValid(j))  
		{ 
			// Copy the needed items... 
			ItemPtr(j)->IAGet(&myAttr[*ItemCount]); 
			(*ItemCount)++; 
		} 
	} 
} 
 
 
 
/////////////////////////////////////// 
// XXXGroup::FreeItemList() 
// Free a list of item attributes 
// 
//		The strings in the ATTRs 
//		The Attrs themselves  
// 
void		XXXGroup::FreeItemList( OPCITEMATTRIBUTES *AttrList, int ItemCount) 
{ 
	int	j; 
 
	if(!ItemCount) return; 
 
	for (j=0; j<ItemCount; j++) 
	{ 
		// Free the contents of the IA 
		IAFree(&AttrList[j], NULL); 
	} 
	delete [] AttrList; 
} 
 
 
 
 
 
/////////////////////////////////////// 
// XXXGroup::AsyncHelper 
// 
// This method handles all ASYNC logic for the group. 
// Note that we respond to async reads & writes  
// at faster than the update rate. 
// 
// The DataObject and ConnectionPoint logic are very similar 
// 
void		XXXGroup::AsyncHelper( DWORD tics ) 
{ 
	// 'Scan' the values at the update rate 
	// and check for OnDataChange 
	// 
	m_scan -= tics; 
	if(m_scan <= 0)  
	{ 
		// 'Scan'the hardware (in this case execute the simulator) 
		// 
		Scan(); 
 
		// If IAdviseSink active then check for OnDataChange 
		// 
		if (m_pCImpIConnPoint && (m_pCImpIConnPoint->m_pCallBack) ) 
		{ 
//			CheckDOOnDataTimeChange();	//DataObject with time 
			CheckDOOnDataChange();		//DataObject without time 
		} 
 
		m_scan = m_dwRevisedRate; 
	} 
 
	// If IAdviseSink active then check for Async Operations 
	// 
		if (m_pIXXXDO && ((m_pIXXXDO->m_datatimeCallback) || (m_pIXXXDO->m_dataCallback))) 
	{ 
		CheckDORefresh(); 
		CheckDOAsyncRead(); 
	} 
	if (m_pIXXXDO && m_pIXXXDO->m_writeCallback) 
	{ 
	//	CheckDOAsyncWrite(); 
	} 
 
} 
 
 
 
/////////////////////////////////////// 
// XXXGroup::Scan 
// 
// Group Scanner - called at UpdateRate 
// This keeps the local data cache up to date. 
// It also marks items as changed for OnDataChange 
// 
void		XXXGroup::Scan( void ) 
{ 
	int j; 
	// Normally we would fetch fresh data for the group here. 
	// But in this sample we just simulate data... 
	// 
	// *** Add Server Specific Code *** 
	// 
	for (j=0; j<ItemHandles(); j++) 
	{ 
		if(ItemValid(j)) 
		{ 
			ItemPtr(j)->Simulate(); 
		} 
	} 
}