# Event buffer management

To avoid memory leaks, the client application must free the Natural Access event buffer after processing an NMS OAM event. When the buffer must be freed for Natural Access, the flag CTA_INTERNAL_BUFFER is set in the size field. Use ctaFreeBuffer to free the event buffer.

Note: Mask out the flag before using the size buffer.

If the CTA_INTERNAL_BUFFER is not set, the application does not need to free the event buffer, even if the buffer contains data.

For more information about event buffers, refer to the Natural Access Developer's Reference Manual.

## Example

The following code demonstrates how to detect and process an NMS OAM event:

//////////////////////////////////////////////////////////////////////////////
// monitor
//
// Loops monitoring the OA&M system.
static const char *getText( DWORD dwCode );
static void monitor()
{
DWORD dwErr;
for (;;)
{
// Retrieve an event from the event queue.
CTA_EVENT cta_event;
dwErr = ctaWaitEvent( s_ctaqueuehd, &cta_event, 1000 );
if (dwErr != SUCCESS)
{
printf( "Error waiting for event, %s.\n", getText(dwErr) );
return;
}
// Check if buffer is owned by CTA and must be freed by us below.
bool const bCtaOwnsBuf = cta_event.buffer && (cta_event.size &
CTA_INTERNAL_BUFFER);
if (bCtaOwnsBuf)
cta_event.size &= ~CTA_INTERNAL_BUFFER; // clear flag from size
// Process the event.
if (cta_event.id == CTAEVN_WAIT_TIMEOUT)
{
. . .
}
else if (OAM_IS_OAM_EVENT(cta_event.id)) // if it's an NMS OAM event
{
if (!cta_event.buffer)
{
printf( "Error, NMS OAM event has NULL buffer.\n" );
continue;
}
const OAM_MSG * const pOamMsg = (OAM_MSG *)cta_event.buffer;
const char * const pszName = (char*)pOamMsg + pOamMsg->dwOfsSzName;
const char * const pszText = (char*)pOamMsg + pOamMsg->dwOfsSzMessage;
const char *pszSeverity;
switch (pOamMsg->dwSeverity)
{
case CTA_TRACE_SEVERITY_INFO: pszSeverity = "INFO"; break;
case CTA_TRACE_SEVERITY_WARNING: pszSeverity = "WARNING"; break;
default: /* CTA_TRACE_SEVERITY_ERROR */ pszSeverity = "ERROR"; break;
}
time_t t;
unsigned int nMsecs = 0;
dwErr = ctaGetTimeStamp( cta_event.timestamp, (unsigned long*)&t,
&nMsecs );
if (dwErr != SUCCESS)
printf( "Error converting timestamp: %s\n", getText(dwErr) );
// Get the local date and time
char szDateTime[80];
strcpy(szDateTime, ctime(&t));
// Truncate the year and trailing carriage return.
szDateTime[strlen(szDateTime) - 6] = '\0';
printf( "%s - %s", szDateTime, getText(pOamMsg->dwCode) );
if (CTA_IS_DONE_EVENT(pOamMsg->dwCode)) //If DONEevent,show reason code
printf( " %s", getText(cta_event.value) );
printf( " %s", pszSeverity );
printf( " \"%s\"\n%s\n", pszName, pszText );
}
else // else it's a non-NMS OAM event
printf( "%s\n", getText(cta_event.id) );
if (bCtaOwnsBuf)
ctaFreeBuffer( cta_event.buffer ); // our reponsibility to free
} // end for(;;)
}
//////////////////////////////////////////////////////////////////////////////
// getText
//
// Helper function that uses ctaGetText() to format the text for a numeric code
// (error, event, reason, or command code) and returns a pointer to that text.
// This is actually a pointer to a local static buffer. It is not thread-safe
// and will be overwritten by subsequent calls.
// If ctaGetText() fails, formats the numeric code value in hex.
//
// dwCode [in] is the numeric code.
//
// Returns a pointer to the text.
static const char *getText( DWORD dwCode )
{
DWORD const dwBufSize = 80;
static char szBuf[ dwBufSize ];
if (SUCCESS != ctaGetText( s_ctahd, dwCode, szBuf, dwBufSize ))
sprintf( szBuf, "0x%08lx", dwCode );
return szBuf;
}