senator22 0 Newbie Poster

I am relatively new to C++ programming but conversant with C# programming. I am currently working on connecting to Avaya Aura Contact Centre RTD tables. The issue I am having is that the compiled software download from Avaya website connects to the server and download data to the console screen, but I intend to write the data to excel or text file.

The SDK gotten from Avaya is in C++ and after compiling the program it did not fetch me the tables to the console screen neither do I have it in my text or excel sheet. The SDK looks ambigous and will appreciate if anyone can see why it behave so. Here below is the rtdapp.cpp file of the SDK.

/*
*********************************************************************
This console program will request skillset statistic. Then it will
print out the skillset name and the number of agents availabe for this
skillset on the console screen. This program will run until the sleep_time
(input argument) expires
A global statistic cache link list is created to store the statistics. The
output will be from this cache.
Other than the main and the data stream callback function, four utility
functions are implemented. They are:
- newRows : add new rows into the statistic cache
- deleteRows : delete rows from the statistic cache
- updateRows : update statistic cache content
- displayCache : display statistic cache content
*********************************************************************
*/

#include <stdio.h>
#include <stdlib.h>
#include <nirtdtyp.h>
#include <nirtdapi.h>

#include <tchar.h>
#include <windows.h>
#include <stdio.h>

#if _MSC_VER >= 1310
#include <iostream>
#include <fstream>
using namespace std;
#else
#include <iostream.h>
#include <fstream.h>
#include <strstrea.h>  
#endif
#include <stdlib.h> 
#include <conio.h>
#include <time.h>
#include <math.h>
#include <fstream>

// structure definition

// skillset statistic link list item
typedef struct stStatItem {
	NIrtd_stValue skillsetId;
	NIrtd_stValue numAgtAv;
	stStatItem* next;
} S_stStatItem;

// global statistic link list structure
typedef struct stStatList {
	ULONG numItem;
	stStatItem* startList;
} S_stStatList;


// global variable declaration

// global statistic cache
S_stStatList stat_list;

// authorization structure used by login and name cache
NIrtd_tAPIauth authInfo = NIrtd_NullAuth;

// This function will insert new rows into the global cache list
void newRows(NIrtd_stTable* newTable)
{
	// structure used to stored temporary row
	NIrtd_tRow tempRow = NIrtd_NullRow;

	// return code
	ULONG rc = NIrtd_eOK;

	for (ULONG i=0; i < newTable->numberofrows ; i++)
	{
		// copy the new row content to temp row
		rc = NIrtd_allocateRow(&tempRow, newTable, i);
		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy new row, rc = %d", rc);
			return;
		}
		
		S_stStatItem * tempStatItem =(S_stStatItem *) malloc( sizeof(stStatItem) );
		tempStatItem->next = NULL;

		// allocate the value structures in the tempStatItem
		rc = NIrtd_allocateValue(&tempStatItem->skillsetId);
		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure, rc = %d", rc);
			free(tempStatItem);
			return;
		}

		rc = NIrtd_allocateValue(&tempStatItem->numAgtAv);

		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure, rc = %d", rc);
			NIrtd_freeValue(&tempStatItem->skillsetId);
			free(tempStatItem);
			return;
		}

		// copy the skillset id
		rc = NIrtd_getCol(&tempStatItem->skillsetId, &tempRow, 0);

		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot copy skillsetId out, rc = %d", rc);
			NIrtd_freeValue(&tempStatItem->skillsetId);
			NIrtd_freeValue(&tempStatItem->numAgtAv);
			free(tempStatItem);
			return;
		}

		// copy the number of agt avai. value
		rc = NIrtd_getCol(&tempStatItem->numAgtAv, &tempRow, 1);

		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot copy agt avai., rc = %d", rc);
			NIrtd_freeValue(&tempStatItem->skillsetId);
			NIrtd_freeValue(&tempStatItem->numAgtAv);
			free(tempStatItem);
			return;
		}

		// if there is nothing in the cache list
		if (stat_list.numItem == 0)
		{
			stat_list.startList = tempStatItem;
		}
		else
		{
			// find the end of the list an added in
			S_stStatItem* loopStatItem = stat_list.startList;

			while( loopStatItem->next != NULL)
			{
				loopStatItem = loopStatItem->next;
			}
			loopStatItem->next = tempStatItem;
		}
		stat_list.numItem++;
		// free up tempRow for next round
		rc = NIrtd_freeRow(&tempRow);
	}
}


// This function will remove rows from the global statistic cache list
void deleteRows(NIrtd_stTable* deleteTable)
{
	// structure used to stored temporary row
	NIrtd_tRow tempRow = NIrtd_NullRow;

	// return code
	ULONG rc = NIrtd_eOK;

	for (ULONG i=0; i < deleteTable->numberofrows; i++)
	{
		if (stat_list.numItem == 0)
		{
			printf("\nNo Item to be removed");
			return;
		}

		// copy the delete row content to temp row
		rc = NIrtd_allocateRow(&tempRow, deleteTable, i);

		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy new row, rc = %d", rc);
			return;
		}

		// value structure used to store the deleted skillset info
		NIrtd_stValue deletedSkillset;
		rc = NIrtd_allocateValue(&deletedSkillset);

		if (rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure to store deleted skillset, rc = %d", rc);
			NIrtd_freeRow(&tempRow);
			return;
		}

		// copy the deleted skillset id value into the deletedSkillset struct.
		NIrtd_getCol(&deletedSkillset, &tempRow, 0);

		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy the deleted skillset id, rc = %d", rc);
			NIrtd_freeRow(&tempRow);
			NIrtd_freeValue(&deletedSkillset);
			return;
		}

		// flag to indicate whether the deleted item is in the list or not
		int found = FALSE;

		// address of the previous statItem's next pointer
		S_stStatItem** pPrevItemLink = &stat_list.startList;

		for (ULONG j = 0; (j < stat_list.numItem ) && (found != TRUE) ; j++)
		{
			if ( ( (*pPrevItemLink)->skillsetId).number == deletedSkillset.number)
			{
				// temporary storage for the deleted item's next pointer
				S_stStatItem* pDeleteItemNext = (*pPrevItemLink)->next;
				NIrtd_freeValue(& (*pPrevItemLink)->skillsetId );
				NIrtd_freeValue(& (*pPrevItemLink)->numAgtAv );
				free(*pPrevItemLink);
				*pPrevItemLink = pDeleteItemNext;
				stat_list.numItem--;
				found = TRUE;
			}
			else
			{
				pPrevItemLink = & (*pPrevItemLink)->next;
			}
		}

		// free up the deletedSkillset structure
		NIrtd_freeValue(&deletedSkillset);
		
		// free up tempRow for next round
		NIrtd_freeRow(&tempRow);
	}
}


// This function will update the global statistic cache list
void updateRows(NIrtd_stTable* updateTable)
{
	// structure used to stored temporary row
	NIrtd_tRow tempRow = NIrtd_NullRow;
	// return code
	ULONG rc = NIrtd_eOK;

	for (ULONG i=0; i < updateTable->numberofrows; i++)
	{
		if (stat_list.numItem == 0)
		{
			printf("\nNo Item to update");
			return;
		}

		// copy the update row content to temp row
		rc = NIrtd_allocateRow(&tempRow, updateTable, i);

		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy update row, rc = %d", rc);
			return;
		}
		
		// value structure used to store the deleted skillset info
		NIrtd_stValue updateSkillset;
		rc = NIrtd_allocateValue(&updateSkillset);
		if (rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure to store update skillset, rc = %d", rc);
			NIrtd_freeRow(&tempRow);
			return;
		}

		
		// value structure used to store the agt available value
		NIrtd_stValue agtAvValue;
		rc = NIrtd_allocateValue(&agtAvValue);
		if (rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure to store the agt available value, rc = %d", rc);
			NIrtd_freeRow(&tempRow);
			return;
		}
		
		// copy the udpate skillset id value into the deletedSkillset struct.
		rc = NIrtd_getCol(&updateSkillset, &tempRow, 0);
		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy the update skillset id, rc = %d", rc);
			NIrtd_freeValue(&updateSkillset);
			NIrtd_freeValue(&agtAvValue);
			NIrtd_freeRow(&tempRow);
			return;
		}

		// flag to indicate whether the udpate item is in the list or not
		int found = FALSE;

		// address of the previous statItem's next pointer
		S_stStatItem* tempStatItem = stat_list.startList;

		for (ULONG j = 0; (j < stat_list.numItem ) && (found != TRUE) ; j++)
		{
			if ( (tempStatItem->skillsetId).number == updateSkillset.number && updateSkillset.number != 0)
			{
				// copy the update agt available value
				rc = NIrtd_getCol(&agtAvValue, &tempRow, 1);
				if (rc != NIrtd_eOK)
				{
					printf("\nCannot get the agt available value, rc = %d", rc);
					NIrtd_freeValue(&updateSkillset);
					NIrtd_freeValue(&agtAvValue);
					NIrtd_freeRow(&tempRow);
					return;
				}

				rc = NIrtd_cpValue(&(tempStatItem->numAgtAv), &agtAvValue);

				if (rc != NIrtd_eOK)
				{
					printf("\nCannot copy the agt available value, rc = %d", rc);
					NIrtd_freeValue(&updateSkillset);
					NIrtd_freeValue(&agtAvValue);
					NIrtd_freeRow(&tempRow);
					return;
				}
				
				found = TRUE;
			}
			else
			{
				tempStatItem = tempStatItem->next;
			}
		}
		
		// free up the updateSkillset structure
		NIrtd_freeValue(&updateSkillset);

		// free up the agt. available structure
		NIrtd_freeValue(&agtAvValue);
		
		// free up tempRow for next round
		NIrtd_freeRow(&tempRow);
	}
}


// this function will display the statistic content on screen
void displayCache()
{
	ULONG rc;

	// address of the previous statItem's next pointer
	S_stStatItem* tempStatItem = stat_list.startList;
	
	// temporary structure used to hold skillset name
	NIrtd_stName tempSkillsetName;

	for (ULONG j = 0; j < stat_list.numItem ; j++)
	{
		// allocate the name structure
		rc = NIrtd_allocateName(&tempSkillsetName);
		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot allocate name structure for skillset name");
			return;
		}
		
		rc = NIrtd_getName(&authInfo, NIrtd_SKLST_SKILLSET_ID, &(tempStatItem->skillsetId), &tempSkillsetName);

		if ( rc == NIrtd_eOK )
		{
			printf("\nRow %d : %s %d", j, tempSkillsetName.last_name, (tempStatItem->numAgtAv).number);
			


			 ofstream ofs("C:\\segema.xls", ofstream::out);     
      if (ofs.good())   { // if opening is successful
            // iterate through lines of sample text
            //for (int i = 0; i < 5; i++)
                  // and print every line to the file
                  ofs << ("\nRow %d : %s %d", j, tempSkillsetName.last_name, (tempStatItem->numAgtAv).number) << endl;
            // close the file
            ofs.close();
      } else
            // otherwise print a message
            cout << "ERROR: can't open file for writing." << endl;




	  tempStatItem = tempStatItem->next;
		}
		
		// cannot find the name in name cache
		else if (rc == NIrtd_eNOT_FOUND)
		{
			// go to the server directly to retrieve the name
			rc = NIrtd_getFailedName(&authInfo, NIrtd_SKLST_SKILLSET_ID, &(tempStatItem->skillsetId), &tempSkillsetName);
			if (rc != NIrtd_eOK)
			{
				printf("\nCannot find the skillset name in server");
				return;
			}
			
			printf("\nRow %d : %s %d", j, tempSkillsetName.last_name, (tempStatItem->numAgtAv).number);
			tempStatItem = tempStatItem->next;
		}
		else
		{
			printf("\nOther error in getting name cache : %d", rc);
			return;
		}
		
		NIrtd_freeName(&tempSkillsetName);
	}
	
	printf("\n\n");
}


// call back function
ULONG callback_function(ULONG return_code, NIrtd_tRequestId requestId, NIrtd_stTableGroup *tableGroup, void *yourPointer)
{
	printf("\nCallback function:");
	bool recovery = false;

	if (return_code == NIrtd_eOK)
	{
		if (tableGroup->deletedValues.numberofrows > 0)
		{
			printf("\nDelete rows arrived %d", tableGroup->deletedValues.numberofrows);
			deleteRows(&(tableGroup->deletedValues));
		}

		if (tableGroup->newValues.numberofrows > 0)
		{
			printf("\nNew rows arrived %d", tableGroup->newValues.numberofrows);
			newRows(&(tableGroup->newValues));
		}
		
		if (tableGroup->deltaValues.numberofrows > 0)
		{
			updateRows(&(tableGroup->deltaValues));
		}

		displayCache();
		
		//free the internally allocated space for data.
		NIrtd_freeTableGroup(tableGroup);
	}
	else if (NIrtd_eSTART_RECOVERY == return_code) {
		printf("\nRecovery Started");
		recovery = true;
	} 
	else if (NIrtd_eOK_RECOVERY == return_code) {
		printf("\nRecovery Successful");
		recovery = true;
	} 
	else if (NIrtd_eBAD_RECOVERY == return_code) {
		printf("\nRecovery Delayed");
		recovery = true;
	}


	if (recovery) {
		stat_list.numItem = 0;
		stat_list.startList = NULL;

		if (tableGroup != NULL)
			NIrtd_freeTableGroup(tableGroup);
	}
	return NIrtd_eOK;
}

#ifdef UNICODE
void wmain(short argc, TCHAR *argv[])
#else
void main(short argc, char *argv[])
#endif
{
	TCHAR ipAddress[100];	// server IP address
	TCHAR username[100];	// user login name
	TCHAR password[100];	// user login password
	int    refresh_rate = 0;	// refresh rate 

	// if sleep time is specified , use the user input sleep time
	if (argc < 5)
	{
		printf("rtdapp [server_ip] [user_login_name] [user_password] [refresh_rate]");
		return;
	}
	_tcscpy(ipAddress, argv[1]); 
	_tcscpy(username, argv[2]); 
	_tcscpy(password, argv[3]); 
	refresh_rate = _ttoi(argv[4]); 
  
	_tprintf(_T("\n\tUsername   : '%s'\n"), username);
	_tprintf(_T("\tPassword   : '%s'\n"), password);
	_tprintf(_T("\tIP Address : '%s'\n"), ipAddress);  
 	_tprintf(_T("\tRefresh    : '%d'\n"), refresh_rate); 
	
	// initialize global variable
	stat_list.numItem = 0;
	stat_list.startList = NULL;

	// setup the required variables
	// return code from API
	ULONG rc = NIrtd_eOK;

	rc = NIrtd_setRecovery(90000,10000);

	if (rc == NIrtd_eLIMIT_REACHED)
	{
		printf("failed to set up the Recovery: return code = %d", rc);
		return;
	}

	rc = NIrtd_eOK;
	// Query structure
	NIrtd_tQuery query = NIrtd_NullQuery;

	// Query request id return from the start data stream function
	NIrtd_tRequestId requestId = NIrtd_NullRequestId;
	
	// Perform login to the server
	printf("Trying to log in...");
	rc = NIrtd_login(&authInfo, ipAddress, username, password);

	if (rc != NIrtd_eOK)
	{
		printf("failed to login: return code = %d", rc);
		return;
	}
	else
	{
		printf("success : return code = %d", rc);
	}
	
	// setup name cache for SkillsetID to SkillsetName translation
	rc = NIrtd_getNameCacheforDataColumn(&authInfo, NIrtd_SKLST_SKILLSET_ID);

	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_getNameCacheforDataColumn failed : rc = %d", rc);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_getNameCacheforDataColumn succeeded.");
	}
	
	// setup query
	// allocate and initialize the query structure
	rc = NIrtd_allocateQuery(&query, NIrtd_INTRVL_SKLST);
	
	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_allocateQuery failed : rc = %d", rc);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_allocateQuery succeeded.");
	}
	
	// select skillset ID as the first column
	rc = NIrtd_selectColumn(&query, NIrtd_SKLST_SKILLSET_ID);

	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_selectColumn failed : rc = %d", rc);
		rc = NIrtd_freeQuery(&query);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_SKLST_SKILLSET_ID Column selected.");
	}
	
	// select number of agent available as the second column
	rc = NIrtd_selectColumn(&query, NIrtd_SKLST_AGENT_AVAIL);

	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_selectColumn failed : rc = %d", rc);
		rc = NIrtd_freeQuery(&query);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_SKLST_AGENT_AVAIL Column selected.");
	}

	// start data stream
	rc = NIrtd_startDataStream(&authInfo, &query, refresh_rate * 1000, callback_function, (void *)NULL, &requestId);
	






	 ofstream ofs("C:\\segema.xls", ofstream::out);     
      if (ofs.good())   { // if opening is successful
            // iterate through lines of sample text
            //for (int i = 0; i < 5; i++)
                  // and print every line to the file
                  ofs << rc << endl;
            // close the file
            ofs.close();
      } else
            // otherwise print a message
            cout << "ERROR: can't open file for writing." << endl;











	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_startDataStream failed : rc = %d", rc);
		rc = NIrtd_freeQuery(&query);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_startDataStream succeeded.");
	}
	
	// sleep until timer expired
	while (true) {
		// sleep until timer expired
		Sleep(300);

		if('q' == _getch())  {
			_tprintf(_T("\n\nRequest to stop - accepted !!\n")); 
			break;
		}
	} 

	// free name cache
	rc = NIrtd_removeNameCacheforDataColumn(&authInfo, NIrtd_SKLST_SKILLSET_ID);

	// stop data stream before exit
	rc = NIrtd_stopDataStream(&authInfo, requestId);
	
	// deallocate all structures allocated
	rc = NIrtd_freeQuery(&query);

	// perform logout
	rc = NIrtd_logout(&authInfo);
}

/*
*********************************************************************
This console program will request skillset statistic. Then it will
print out the skillset name and the number of agents availabe for this
skillset on the console screen. This program will run until the sleep_time
(input argument) expires
A global statistic cache link list is created to store the statistics. The
output will be from this cache.
Other than the main and the data stream callback function, four utility
functions are implemented. They are:
- newRows : add new rows into the statistic cache
- deleteRows : delete rows from the statistic cache
- updateRows : update statistic cache content
- displayCache : display statistic cache content
*********************************************************************
*/

#include <stdio.h>
#include <stdlib.h>
#include <nirtdtyp.h>
#include <nirtdapi.h>

#include <tchar.h>
#include <windows.h>
#include <stdio.h>

#if _MSC_VER >= 1310
#include <iostream>
#include <fstream>
using namespace std;
#else
#include <iostream.h>
#include <fstream.h>
#include <strstrea.h>  
#endif
#include <stdlib.h> 
#include <conio.h>
#include <time.h>
#include <math.h>
#include <fstream>

// structure definition

// skillset statistic link list item
typedef struct stStatItem {
	NIrtd_stValue skillsetId;
	NIrtd_stValue numAgtAv;
	stStatItem* next;
} S_stStatItem;

// global statistic link list structure
typedef struct stStatList {
	ULONG numItem;
	stStatItem* startList;
} S_stStatList;


// global variable declaration

// global statistic cache
S_stStatList stat_list;

// authorization structure used by login and name cache
NIrtd_tAPIauth authInfo = NIrtd_NullAuth;

// This function will insert new rows into the global cache list
void newRows(NIrtd_stTable* newTable)
{
	// structure used to stored temporary row
	NIrtd_tRow tempRow = NIrtd_NullRow;

	// return code
	ULONG rc = NIrtd_eOK;

	for (ULONG i=0; i < newTable->numberofrows ; i++)
	{
		// copy the new row content to temp row
		rc = NIrtd_allocateRow(&tempRow, newTable, i);
		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy new row, rc = %d", rc);
			return;
		}
		
		S_stStatItem * tempStatItem =(S_stStatItem *) malloc( sizeof(stStatItem) );
		tempStatItem->next = NULL;

		// allocate the value structures in the tempStatItem
		rc = NIrtd_allocateValue(&tempStatItem->skillsetId);
		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure, rc = %d", rc);
			free(tempStatItem);
			return;
		}

		rc = NIrtd_allocateValue(&tempStatItem->numAgtAv);

		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure, rc = %d", rc);
			NIrtd_freeValue(&tempStatItem->skillsetId);
			free(tempStatItem);
			return;
		}

		// copy the skillset id
		rc = NIrtd_getCol(&tempStatItem->skillsetId, &tempRow, 0);

		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot copy skillsetId out, rc = %d", rc);
			NIrtd_freeValue(&tempStatItem->skillsetId);
			NIrtd_freeValue(&tempStatItem->numAgtAv);
			free(tempStatItem);
			return;
		}

		// copy the number of agt avai. value
		rc = NIrtd_getCol(&tempStatItem->numAgtAv, &tempRow, 1);

		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot copy agt avai., rc = %d", rc);
			NIrtd_freeValue(&tempStatItem->skillsetId);
			NIrtd_freeValue(&tempStatItem->numAgtAv);
			free(tempStatItem);
			return;
		}

		// if there is nothing in the cache list
		if (stat_list.numItem == 0)
		{
			stat_list.startList = tempStatItem;
		}
		else
		{
			// find the end of the list an added in
			S_stStatItem* loopStatItem = stat_list.startList;

			while( loopStatItem->next != NULL)
			{
				loopStatItem = loopStatItem->next;
			}
			loopStatItem->next = tempStatItem;
		}
		stat_list.numItem++;
		// free up tempRow for next round
		rc = NIrtd_freeRow(&tempRow);
	}
}


// This function will remove rows from the global statistic cache list
void deleteRows(NIrtd_stTable* deleteTable)
{
	// structure used to stored temporary row
	NIrtd_tRow tempRow = NIrtd_NullRow;

	// return code
	ULONG rc = NIrtd_eOK;

	for (ULONG i=0; i < deleteTable->numberofrows; i++)
	{
		if (stat_list.numItem == 0)
		{
			printf("\nNo Item to be removed");
			return;
		}

		// copy the delete row content to temp row
		rc = NIrtd_allocateRow(&tempRow, deleteTable, i);

		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy new row, rc = %d", rc);
			return;
		}

		// value structure used to store the deleted skillset info
		NIrtd_stValue deletedSkillset;
		rc = NIrtd_allocateValue(&deletedSkillset);

		if (rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure to store deleted skillset, rc = %d", rc);
			NIrtd_freeRow(&tempRow);
			return;
		}

		// copy the deleted skillset id value into the deletedSkillset struct.
		NIrtd_getCol(&deletedSkillset, &tempRow, 0);

		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy the deleted skillset id, rc = %d", rc);
			NIrtd_freeRow(&tempRow);
			NIrtd_freeValue(&deletedSkillset);
			return;
		}

		// flag to indicate whether the deleted item is in the list or not
		int found = FALSE;

		// address of the previous statItem's next pointer
		S_stStatItem** pPrevItemLink = &stat_list.startList;

		for (ULONG j = 0; (j < stat_list.numItem ) && (found != TRUE) ; j++)
		{
			if ( ( (*pPrevItemLink)->skillsetId).number == deletedSkillset.number)
			{
				// temporary storage for the deleted item's next pointer
				S_stStatItem* pDeleteItemNext = (*pPrevItemLink)->next;
				NIrtd_freeValue(& (*pPrevItemLink)->skillsetId );
				NIrtd_freeValue(& (*pPrevItemLink)->numAgtAv );
				free(*pPrevItemLink);
				*pPrevItemLink = pDeleteItemNext;
				stat_list.numItem--;
				found = TRUE;
			}
			else
			{
				pPrevItemLink = & (*pPrevItemLink)->next;
			}
		}

		// free up the deletedSkillset structure
		NIrtd_freeValue(&deletedSkillset);
		
		// free up tempRow for next round
		NIrtd_freeRow(&tempRow);
	}
}


// This function will update the global statistic cache list
void updateRows(NIrtd_stTable* updateTable)
{
	// structure used to stored temporary row
	NIrtd_tRow tempRow = NIrtd_NullRow;
	// return code
	ULONG rc = NIrtd_eOK;

	for (ULONG i=0; i < updateTable->numberofrows; i++)
	{
		if (stat_list.numItem == 0)
		{
			printf("\nNo Item to update");
			return;
		}

		// copy the update row content to temp row
		rc = NIrtd_allocateRow(&tempRow, updateTable, i);

		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy update row, rc = %d", rc);
			return;
		}
		
		// value structure used to store the deleted skillset info
		NIrtd_stValue updateSkillset;
		rc = NIrtd_allocateValue(&updateSkillset);
		if (rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure to store update skillset, rc = %d", rc);
			NIrtd_freeRow(&tempRow);
			return;
		}

		
		// value structure used to store the agt available value
		NIrtd_stValue agtAvValue;
		rc = NIrtd_allocateValue(&agtAvValue);
		if (rc != NIrtd_eOK)
		{
			printf("\nCannot allocate value structure to store the agt available value, rc = %d", rc);
			NIrtd_freeRow(&tempRow);
			return;
		}
		
		// copy the udpate skillset id value into the deletedSkillset struct.
		rc = NIrtd_getCol(&updateSkillset, &tempRow, 0);
		if (rc != NIrtd_eOK)
		{
			printf("\nCannot copy the update skillset id, rc = %d", rc);
			NIrtd_freeValue(&updateSkillset);
			NIrtd_freeValue(&agtAvValue);
			NIrtd_freeRow(&tempRow);
			return;
		}

		// flag to indicate whether the udpate item is in the list or not
		int found = FALSE;

		// address of the previous statItem's next pointer
		S_stStatItem* tempStatItem = stat_list.startList;

		for (ULONG j = 0; (j < stat_list.numItem ) && (found != TRUE) ; j++)
		{
			if ( (tempStatItem->skillsetId).number == updateSkillset.number && updateSkillset.number != 0)
			{
				// copy the update agt available value
				rc = NIrtd_getCol(&agtAvValue, &tempRow, 1);
				if (rc != NIrtd_eOK)
				{
					printf("\nCannot get the agt available value, rc = %d", rc);
					NIrtd_freeValue(&updateSkillset);
					NIrtd_freeValue(&agtAvValue);
					NIrtd_freeRow(&tempRow);
					return;
				}

				rc = NIrtd_cpValue(&(tempStatItem->numAgtAv), &agtAvValue);

				if (rc != NIrtd_eOK)
				{
					printf("\nCannot copy the agt available value, rc = %d", rc);
					NIrtd_freeValue(&updateSkillset);
					NIrtd_freeValue(&agtAvValue);
					NIrtd_freeRow(&tempRow);
					return;
				}
				
				found = TRUE;
			}
			else
			{
				tempStatItem = tempStatItem->next;
			}
		}
		
		// free up the updateSkillset structure
		NIrtd_freeValue(&updateSkillset);

		// free up the agt. available structure
		NIrtd_freeValue(&agtAvValue);
		
		// free up tempRow for next round
		NIrtd_freeRow(&tempRow);
	}
}


// this function will display the statistic content on screen
void displayCache()
{
	ULONG rc;

	// address of the previous statItem's next pointer
	S_stStatItem* tempStatItem = stat_list.startList;
	
	// temporary structure used to hold skillset name
	NIrtd_stName tempSkillsetName;

	for (ULONG j = 0; j < stat_list.numItem ; j++)
	{
		// allocate the name structure
		rc = NIrtd_allocateName(&tempSkillsetName);
		if ( rc != NIrtd_eOK)
		{
			printf("\nCannot allocate name structure for skillset name");
			return;
		}
		
		rc = NIrtd_getName(&authInfo, NIrtd_SKLST_SKILLSET_ID, &(tempStatItem->skillsetId), &tempSkillsetName);

		if ( rc == NIrtd_eOK )
		{
			printf("\nRow %d : %s %d", j, tempSkillsetName.last_name, (tempStatItem->numAgtAv).number);
			


			 ofstream ofs("C:\\segema.xls", ofstream::out);     
      if (ofs.good())   { // if opening is successful
            // iterate through lines of sample text
            //for (int i = 0; i < 5; i++)
                  // and print every line to the file
                  ofs << ("\nRow %d : %s %d", j, tempSkillsetName.last_name, (tempStatItem->numAgtAv).number) << endl;
            // close the file
            ofs.close();
      } else
            // otherwise print a message
            cout << "ERROR: can't open file for writing." << endl;




	  tempStatItem = tempStatItem->next;
		}
		
		// cannot find the name in name cache
		else if (rc == NIrtd_eNOT_FOUND)
		{
			// go to the server directly to retrieve the name
			rc = NIrtd_getFailedName(&authInfo, NIrtd_SKLST_SKILLSET_ID, &(tempStatItem->skillsetId), &tempSkillsetName);
			if (rc != NIrtd_eOK)
			{
				printf("\nCannot find the skillset name in server");
				return;
			}
			
			printf("\nRow %d : %s %d", j, tempSkillsetName.last_name, (tempStatItem->numAgtAv).number);
			tempStatItem = tempStatItem->next;
		}
		else
		{
			printf("\nOther error in getting name cache : %d", rc);
			return;
		}
		
		NIrtd_freeName(&tempSkillsetName);
	}
	
	printf("\n\n");
}


// call back function
ULONG callback_function(ULONG return_code, NIrtd_tRequestId requestId, NIrtd_stTableGroup *tableGroup, void *yourPointer)
{
	printf("\nCallback function:");
	bool recovery = false;

	if (return_code == NIrtd_eOK)
	{
		if (tableGroup->deletedValues.numberofrows > 0)
		{
			printf("\nDelete rows arrived %d", tableGroup->deletedValues.numberofrows);
			deleteRows(&(tableGroup->deletedValues));
		}

		if (tableGroup->newValues.numberofrows > 0)
		{
			printf("\nNew rows arrived %d", tableGroup->newValues.numberofrows);
			newRows(&(tableGroup->newValues));
		}
		
		if (tableGroup->deltaValues.numberofrows > 0)
		{
			updateRows(&(tableGroup->deltaValues));
		}

		displayCache();
		
		//free the internally allocated space for data.
		NIrtd_freeTableGroup(tableGroup);
	}
	else if (NIrtd_eSTART_RECOVERY == return_code) {
		printf("\nRecovery Started");
		recovery = true;
	} 
	else if (NIrtd_eOK_RECOVERY == return_code) {
		printf("\nRecovery Successful");
		recovery = true;
	} 
	else if (NIrtd_eBAD_RECOVERY == return_code) {
		printf("\nRecovery Delayed");
		recovery = true;
	}


	if (recovery) {
		stat_list.numItem = 0;
		stat_list.startList = NULL;

		if (tableGroup != NULL)
			NIrtd_freeTableGroup(tableGroup);
	}
	return NIrtd_eOK;
}

#ifdef UNICODE
void wmain(short argc, TCHAR *argv[])
#else
void main(short argc, char *argv[])
#endif
{
	TCHAR ipAddress[100];	// server IP address
	TCHAR username[100];	// user login name
	TCHAR password[100];	// user login password
	int    refresh_rate = 0;	// refresh rate 

	// if sleep time is specified , use the user input sleep time
	if (argc < 5)
	{
		printf("rtdapp [server_ip] [user_login_name] [user_password] [refresh_rate]");
		return;
	}
	_tcscpy(ipAddress, argv[1]); 
	_tcscpy(username, argv[2]); 
	_tcscpy(password, argv[3]); 
	refresh_rate = _ttoi(argv[4]); 
  
	_tprintf(_T("\n\tUsername   : '%s'\n"), username);
	_tprintf(_T("\tPassword   : '%s'\n"), password);
	_tprintf(_T("\tIP Address : '%s'\n"), ipAddress);  
 	_tprintf(_T("\tRefresh    : '%d'\n"), refresh_rate); 
	
	// initialize global variable
	stat_list.numItem = 0;
	stat_list.startList = NULL;

	// setup the required variables
	// return code from API
	ULONG rc = NIrtd_eOK;

	rc = NIrtd_setRecovery(90000,10000);

	if (rc == NIrtd_eLIMIT_REACHED)
	{
		printf("failed to set up the Recovery: return code = %d", rc);
		return;
	}

	rc = NIrtd_eOK;
	// Query structure
	NIrtd_tQuery query = NIrtd_NullQuery;

	// Query request id return from the start data stream function
	NIrtd_tRequestId requestId = NIrtd_NullRequestId;
	
	// Perform login to the server
	printf("Trying to log in...");
	rc = NIrtd_login(&authInfo, ipAddress, username, password);

	if (rc != NIrtd_eOK)
	{
		printf("failed to login: return code = %d", rc);
		return;
	}
	else
	{
		printf("success : return code = %d", rc);
	}
	
	// setup name cache for SkillsetID to SkillsetName translation
	rc = NIrtd_getNameCacheforDataColumn(&authInfo, NIrtd_SKLST_SKILLSET_ID);

	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_getNameCacheforDataColumn failed : rc = %d", rc);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_getNameCacheforDataColumn succeeded.");
	}
	
	// setup query
	// allocate and initialize the query structure
	rc = NIrtd_allocateQuery(&query, NIrtd_INTRVL_SKLST);
	
	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_allocateQuery failed : rc = %d", rc);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_allocateQuery succeeded.");
	}
	
	// select skillset ID as the first column
	rc = NIrtd_selectColumn(&query, NIrtd_SKLST_SKILLSET_ID);

	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_selectColumn failed : rc = %d", rc);
		rc = NIrtd_freeQuery(&query);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_SKLST_SKILLSET_ID Column selected.");
	}
	
	// select number of agent available as the second column
	rc = NIrtd_selectColumn(&query, NIrtd_SKLST_AGENT_AVAIL);

	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_selectColumn failed : rc = %d", rc);
		rc = NIrtd_freeQuery(&query);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_SKLST_AGENT_AVAIL Column selected.");
	}

	// start data stream
	rc = NIrtd_startDataStream(&authInfo, &query, refresh_rate * 1000, callback_function, (void *)NULL, &requestId);
	






	 ofstream ofs("C:\\segema.xls", ofstream::out);     
      if (ofs.good())   { // if opening is successful
            // iterate through lines of sample text
            //for (int i = 0; i < 5; i++)
                  // and print every line to the file
                  ofs << rc << endl;
            // close the file
            ofs.close();
      } else
            // otherwise print a message
            cout << "ERROR: can't open file for writing." << endl;











	if (rc != NIrtd_eOK)
	{
		printf("\nNIrtd_startDataStream failed : rc = %d", rc);
		rc = NIrtd_freeQuery(&query);
		rc = NIrtd_logout(&authInfo);
		return;
	}
	else
	{
		printf("\nNIrtd_startDataStream succeeded.");
	}
	
	// sleep until timer expired
	while (true) {
		// sleep until timer expired
		Sleep(300);

		if('q' == _getch())  {
			_tprintf(_T("\n\nRequest to stop - accepted !!\n")); 
			break;
		}
	} 

	// free name cache
	rc = NIrtd_removeNameCacheforDataColumn(&authInfo, NIrtd_SKLST_SKILLSET_ID);

	// stop data stream before exit
	rc = NIrtd_stopDataStream(&authInfo, requestId);
	
	// deallocate all structures allocated
	rc = NIrtd_freeQuery(&query);

	// perform logout
	rc = NIrtd_logout(&authInfo);
}

My observation is that the in the main column "(argc < 5)" is the cause of the problem, and removing it causes the program to halt execution and does not run

Thanks in advance for your quick response