📄 server.cpp
字号:
if (pGroup == m_pGroupHead)
m_pGroupHead = pNext;
// Decrement the group count:
--m_cdwGroups;
// Delete the group object:
delete pGroup;
}
else
{
// Since CKGroup object was not deleted, it should be flagged as invalid
// becuase it no longer has an associated OPC Group in OPC Server.
pGroup->SetValid (false);
}
}
// **************************************************************************
// RemoveAllGroups ()
//
// Description:
// Remove all OPC Groups from OPC server, and delete associated CKGroup
// objects if asked.
//
// Parameters:
// bool bDelete Delete group objects after removing. true by
// default.
//
// Returns:
// void
// **************************************************************************
void CKServer::RemoveAllGroups (bool bDelete /* = true */)
{
// Start with the head of linked list and work our way up chain:
CKGroup *pGroup = m_pGroupHead;
// Remove OPC Groups and delete assoicated CKGroup objects:
if (bDelete)
{
// Work our way up linked list. pGroup will be NULL when we reach
// end, and we will then break out of loop.
while (pGroup)
{
// Get the group's next item before we delete group. The
// next item will be the new head of linked list.
m_pGroupHead = pGroup->GetNext ();
// Remove and delete:
RemoveGroup (pGroup, bDelete);
// Next group to processes is the new head of the list:
pGroup = m_pGroupHead;
}
}
// Just remove the OPC Groups:
else
{
// Work our way up linked list. pGroup will be NULL when we reach
// end, and we will then break out of loop.
while (pGroup)
{
// Remove the group:
RemoveGroup (pGroup, bDelete);
// Process next group in list:
pGroup = pGroup->GetNext ();
}
}
}
#define MAXGROUPNAMELEN 32 // impose a limit when generating a name
// **************************************************************************
// GenerateGroupName ()
//
// Description:
// Check to see if a group name is in use. If it is, then modify name so
// that it is unique to this server.
//
// Parameters:
// CString &strName Group name. Must not be input as empty.
// Will be modified if needed.
//
// Returns:
// bool - true if success
// **************************************************************************
bool CKServer::GenerateGroupName (CString &strName)
{
ASSERT (!strName.IsEmpty ());
// If FindGroup() returns true, then name is in use and we need to
// generate a new group name unique to this server:
if (FindGroup (strName))
{
TCHAR szName [MAXGROUPNAMELEN + 1];
TCHAR szSuffix [16];
LPTSTR pch;
int nSuffix;
// Make a copy of the group name. Use a TCHAR array so it will be
// fast & easy to check each character using pointer math.
lstrcpyn (szName, strName, _countof (szName));
// Point to the last character (the -1 is needed since arrays are 0-based):
pch = &szName [lstrlen (szName) - 1];
//////////////////////////////////////////////////////////////
// Create a numerical suffix that should make name unique //
//////////////////////////////////////////////////////////////
// If the last character is a number, then we will interpret all digits
// a end of string as a suffix. Once that suffix is parsed off, we will
// increment it for the new name.
if (_istdigit (*pch))
{
// Back up until we hit a non-digit:
while (_istdigit (*pch))
--pch;
// Adjust forward one character so we now point to first
// digit in numerical suffix:
++pch;
// Determine the current suffix and increment:
nSuffix = _ttol (pch) + 1;
}
// Otherwise simply start a new series with the suffix "1":
else
{
// Move forwared one character so we'll be pointing at
// string's NULL terminator:
++pch;
nSuffix = 1;
}
//////////////////////////////////////////////////////////
// Add new numerical suffix and validate resulting name //
//////////////////////////////////////////////////////////
do
{
// Trim any existing numeric suffix from the name. (pch should
// be pointing at first digit of suffix it it exists, or NULL
// terminator of string if not.)
*pch = 0;
// Convert the suffix we just created to a string:
wsprintf (szSuffix, _T("%d"), nSuffix);
// Determine the length of name minus existing numerical suffix, if any:
int nNameLen = lstrlen (szName);
// Determin the length of the suffix we just created:
int nSuffixLen = lstrlen (szSuffix);
// If the name with new suffix will be longer than allowable maximum
// (for logging) then truncate:
if (nNameLen + nSuffixLen > MAXGROUPNAMELEN)
{
// Compute the number of characters we need to hack off:
int nDif = MAXGROUPNAMELEN - (nNameLen + nSuffixLen);
ASSERT (nDif < 0);
// Adjust the length in preparation to truncate:
nNameLen += nDif;
pch += nDif;
// Check for remaining chars and return false if we just can't fit
// the suffix:
if (nNameLen < 1)
return (false);
// If we make it here, then we can go ahead and truncate the name
// by replacing the nNameLen'th character with a NULL terminator:
szName [nNameLen] = 0;
}
// Append the suffix to the name:
lstrcat (szName, szSuffix);
// Validate the resulting name. If FindGroup returns false, then
// we know the new name is not currently in use.
if (!FindGroup (szName))
{
// New name is not in use. Assing it to strName for output and
// return true to indicate successful processing.
strName = szName;
return (true);
}
// If we make it here, we know new name is no good. Increment the suffix
// and try again. We will continue to loop unitl the suffix results in a
// good name or string length becomes too long.
} while (++nSuffix > 0);
// If we make it to here (not likely), then we've run out of
// options. Return false to indicate that we had problems.
ASSERT (FALSE);
return (false);
}
// If we made it here, then specified name is not presently in use.
// No need to change it. Just return true to indicate we successfully
// processed name.
return (true);
}
// **************************************************************************
// FindGroup ()
//
// Description:
// Search list of groups attached to this server for one with specified name.
//
// Parameters:
// LPCTSTR lpszName Pointer to name string.
//
// Returns:
// bool - true if group found.
// **************************************************************************
bool CKServer::FindGroup (LPCTSTR lpszName)
{
// Start with first group in linked list and work our way up the chain:
CKGroup *pGroup = m_pGroupHead;
// Keep looping we hit the end of the link list (where pGroup will be NULL):
while (pGroup)
{
// If the name of the current group is the same as lpszName, then
// we can break out of loop. Return true to indicate that group
// was found.
if (lstrcmpi (lpszName, pGroup->GetName ()) == 0)
return (true);
// Look at next group in list next time around:
pGroup = pGroup->GetNext ();
}
// If we make it here, then we have looked at all of the groups in the
// list and didn't find one with specified name. Return false to
// indicate group was not found.
return (false);
}
// **************************************************************************
// GetGroup ()
//
// Description:
// Get pointer to group with specified name.
//
// Parameters:
// LPCTSTR lpszName Pointer to name string.
//
// Returns:
// CKGroup* - Pointer to group object, NULL if group not found.
// **************************************************************************
CKGroup* CKServer::GetGroup (LPCTSTR lpszName)
{
// Start with first group in linked list and work our way up the chain:
CKGroup *pGroup = m_pGroupHead;
// Keep looping we hit the end of the link list (where pGroup will be NULL):
while (pGroup)
{
// If the name of the current group is the same as lpszName, then
// we can break out of loop. Return pointer to group.
if (lstrcmpi (lpszName, pGroup->GetName ()) == 0)
return (pGroup);
// Look at next group in list next time around:
pGroup = pGroup->GetNext ();
}
// If we make it here, then we have looked at all of the groups in the
// list and didn't find one with specified name. Return NULL to indicate
// group was not found.
return (NULL);
}
/////////////////////////////////////////////////////////////////////////////
// CKServer manipulators
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// SetProgID ()
//
// Description:
// Set Prog ID of OPC Server we will be associated with.
//
// Parameters:
// CString &strProgID Prog ID.
//
// Returns:
// void
// **************************************************************************
void CKServer::SetProgID (CString &strProgID)
{
ASSERT (!strProgID.IsEmpty ());
// Save Prog ID string as a member variable:
m_strProgID = strProgID;
}
// **************************************************************************
// SetRemoteMachine ()
//
// Description:
// Set name of machine associated OPC Server will be running on.
//
// Parameters:
// CString &strRemoteMachine Name of remote machine, NULL if local.
//
// Returns:
// void
// **************************************************************************
void CKServer::SetRemoteMachine (CString &strRemoteMachine)
{
// Save machine name string as a member variables. This string will be
// empty if server will be running on the local machine.
m_strRemoteMachine = strRemoteMachine;
}
/////////////////////////////////////////////////////////////////////////////
// CKServer serialization
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// Serialize ()
//
// Description:
// Save or load server properties.
//
// Parameters:
// CArchive &ar The archive to save or load server properties.
//
// Returns:
// void
// **************************************************************************
void CKServer::Serialize (CArchive &ar)
{
// Save server properties:
if (ar.IsStoring ())
{
//////////////////////////////
// Save archive properties //
//////////////////////////////
// Output current archive version. If we add server properties that
// must be made persistent, then we will have to update the archive
// version so we know how to read the additional data.
ar << CURRENT_VERSION;
//////////////////////////////
// Save server properties //
//////////////////////////////
// Output info about associated OPC Server:
ar << m_strProgID << m_strRemoteMachine;
// Output flags in bit field:
ar.Write (&m_bfFlags, sizeof (m_bfFlags));
// Output number of groups so we will know how many block of group
// data follows when we read this archive later:
ar << m_cdwGroups;
//////////////////////////////////
// Serialize all of our groups //
//////////////////////////////////
//Start with head of linked list:
CKGroup *pGroup = m_pGroupHead;
// Keep looping we hit the end of the link list (where pGroup will be NULL):
while (pGroup)
{
// Call group's serialize function so that it can add its properties
// to the archive:
pGroup->Serialize (ar);
// Process next group next time around:
pGroup = pGroup->GetNext ();
}
}
// Load server properties:
else
{
DWORD dwSchema;
DWORD dwIndex;
//////////////////////////////
// Load archive properties //
//////////////////////////////
ar >> dwSchema;
// dwSchema is really the archive version.
switch (dwSchema)
{
case VERSION_1:
//////////////////////////////
// Load server properties //
//////////////////////////////
// Input info about associated OPC Server:
ar >> m_strProgID >> m_strRemoteMachine;
// Input flags in bit field:
ar.Read (&m_bfFlags, sizeof (m_bfFlags));
// Input number of groups so we will know how many block of group
// data follows:
ar >> m_cdwGroups;
//////////////////////////////////
// Serialize all of our groups //
//////////////////////////////////
// Start with an empty linked list:
ASSERT (m_pGroupHead == NULL);
// Loop over expected number of groups:
for (dwIndex = 0; dwIndex < m_cdwGroups; dwIndex++)
{
CKGroup *pGroup = NULL;
// Wrap group serialization with exception handler in case
// there is a problem, such as bad archive version etc.
try
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -