Exemplo n.º 1
0
 double Evaluate(double *x) {
   if (x[0] <= p[16]){
     return region1(x[0],p);
   }
   else if (x[0]  <= p[17]){
     return region2(x[0]-p[16],p);
     }
   else if (x[0]  <= p[18]){
     return region3(x[0]-p[17],p);
     }
   else if (x[0]  <= p[19]){
     return region4(x[0]-p[18],p);
   }
   else {
     return region5(x[0]-p[19],p);
   }
   
 }
void
MessageQueueUtils::sendMessage(int clientRecordId, char menuItemType, char userActionType, char userButton, uint64_t targetHandle, std::wstring userActionSelection)
{

	logger->log(L"MessageQueueUtils::sendMessage");

	//if text to send is too long
	if (userActionSelection.size() > MQCONST_MQSM_TEXT_SIZEC){
		userActionSelection.resize(MQCONST_MQSM_TEXT_SIZEC - 3);
		userActionSelection.append(TEXT("..."));
	}

	try{

		boost::interprocess::windows_shared_memory* sm = new boost::interprocess::windows_shared_memory(
				boost::interprocess::open_only,
				getMqName(clientRecordId).c_str(),
				boost::interprocess::read_write);

		if (sm == NULL){
			logger->log(L"MessageQueueUtils::sendMessage (sm mode) sm == NULL");
			return; //error
		}


		int counter = 0;
		const int MQ_WAIT_TIME = 200;			//[ms]
		const int MAX_MQ_WAIT_COUNTER = 10;		//10 * 200ms = 2s
		bool sentSuccess = false;

		do {

			counter++;

			WaitForSingleObject(smMutex, INFINITE);


			boost::interprocess::mapped_region region1(
					*sm,
					boost::interprocess::read_write,
					MQCONST_MQMIRSM_STATUS_OFFSET,
					MQCONST_MQMIRSM_STATUS_SIZE
				);
			char* mqmirsmStatusPtr = static_cast<char*>(region1.get_address());

			if (*mqmirsmStatusPtr == 'E'){

				boost::interprocess::mapped_region region2(
						*sm,
						boost::interprocess::read_write,
						MQCONST_MQMIRSM_MENUITEMTYPE_OFFSET,
						MQCONST_MQMIRSM_MENUITEMTYPE_SIZE
					);
				char* menuItemTypePtr = static_cast<char*>(region2.get_address());
				*menuItemTypePtr = menuItemType;


				boost::interprocess::mapped_region region3(
						*sm,
						boost::interprocess::read_write,
						MQCONST_MQMIRSM_USERACTIONTYPE_OFFSET,
						MQCONST_MQMIRSM_USERACTIONTYPE_SIZE
					);
				char* userActionTypePtr = static_cast<char*>(region3.get_address());
				*userActionTypePtr = userActionType;


				boost::interprocess::mapped_region region4(
						*sm,
						boost::interprocess::read_write,
						MQCONST_MQMIRSM_USERBUTTON_OFFSET,
						MQCONST_MQMIRSM_USERBUTTON_SIZE
					);
				char* userButtonPtr = static_cast<char*>(region4.get_address());
				*userButtonPtr = userButton;


				boost::interprocess::mapped_region region5(
						*sm,
						boost::interprocess::read_write,
						MQCONST_MQMIRSM_TARGETHANDLE_OFFSET,
						MQCONST_MQMIRSM_TARGETHANDLE_SIZE
					);
				uint64_t* targetHandlePtr = static_cast<uint64_t*>(region5.get_address());
				*targetHandlePtr = targetHandle;


				boost::interprocess::mapped_region region6(
						*sm,
						boost::interprocess::read_write,
						MQCONST_MQMIRSM_TEXTARRAY_OFFSET,
						MQCONST_MQMIRSM_TEXTARRAY_SIZE
					);
				wchar_t* userActionSelectionPtr = static_cast<wchar_t*>(region6.get_address());
				memset(userActionSelectionPtr, 0, MQCONST_MQMIRSM_TEXTARRAY_SIZE);
				memcpy(userActionSelectionPtr, userActionSelection.c_str(), userActionSelection.length() * sizeof(wchar_t));

				//update shared memory status to Message
				*mqmirsmStatusPtr = 'M';

				sentSuccess = true;

			}
			// else wait and repeat try

			ReleaseMutex(smMutex);

			if (!sentSuccess){
				SleepEx(MQ_WAIT_TIME, TRUE);
			}

		} while (sentSuccess == false && counter <= MAX_MQ_WAIT_COUNTER);

		if (!sentSuccess){
			logger->log(L"MessageQueueUtils::sendMessage (sm mode) - MAX_MQ_WAIT_COUNTER exceeded but still sentSuccess == false");
		}

		delete sm;

	} catch (const boost::interprocess::interprocess_exception& ex) {
		logger->log_p(L"MessageQueueUtils::sendMessage (sm mode) interprocess_exception: [%S] native_error=[%d] error_code=[%d]", ex.what(), ex.get_native_error(), ex.get_error_code() );
		return; //error
	} catch (...){
		logger->log(L"MessageQueueUtils::sendMessage (sm mode) EXCEPTION: unknown");
		return; //error
	}

}
/**
 * return true if message was received and variables are available
 */
bool
MessageQueueUtils::tryReceiveMessage(char& menuItemType, char& userActionType, char& userButton, uint64_t& targetHandle, wchar_t*& userActionSelection, size_t uasBuffCSize)
{

	try{

		WaitForSingleObject(smMutex, 100000);


		boost::interprocess::mapped_region region1(
				*mqMirSm,
				boost::interprocess::read_write,
				MQCONST_MQMIRSM_STATUS_OFFSET,
				MQCONST_MQMIRSM_STATUS_SIZE
			);
		char* mqmirsmStatusPtr = static_cast<char*>(region1.get_address());

		if (*mqmirsmStatusPtr != 'M'){
			ReleaseMutex(smMutex);
			return false;
		}


		//there is a new message in the queue (sm mode) *mqmirsmStatusPtr=='M'
		//transfer data from shared memory to variables

		boost::interprocess::mapped_region region2(
				*mqMirSm,
				boost::interprocess::read_only,
				MQCONST_MQMIRSM_MENUITEMTYPE_OFFSET,
				MQCONST_MQMIRSM_MENUITEMTYPE_SIZE
			);
		menuItemType = *(static_cast<char*>(region2.get_address()));

		boost::interprocess::mapped_region region3(
				*mqMirSm,
				boost::interprocess::read_only,
				MQCONST_MQMIRSM_USERACTIONTYPE_OFFSET,
				MQCONST_MQMIRSM_USERACTIONTYPE_SIZE
			);
		userActionType = *(static_cast<char*>(region3.get_address()));

		boost::interprocess::mapped_region region4(
				*mqMirSm,
				boost::interprocess::read_only,
				MQCONST_MQMIRSM_USERBUTTON_OFFSET,
				MQCONST_MQMIRSM_USERBUTTON_SIZE
			);
		userButton = *(static_cast<char*>(region4.get_address()));

		boost::interprocess::mapped_region region5(
				*mqMirSm,
				boost::interprocess::read_only,
				MQCONST_MQMIRSM_TARGETHANDLE_OFFSET,
				MQCONST_MQMIRSM_TARGETHANDLE_SIZE
			);
		targetHandle = *(static_cast<uint64_t*>(region5.get_address()));

		boost::interprocess::mapped_region region6(
				*mqMirSm,
				boost::interprocess::read_only,
				MQCONST_MQMIRSM_TEXTARRAY_OFFSET,
				MQCONST_MQMIRSM_TEXTARRAY_SIZE
			);
		wchar_t* userActionSelectionPtr = static_cast<wchar_t*>(region6.get_address());
		wcsncpy_s(userActionSelection, uasBuffCSize, userActionSelectionPtr, MQCONST_MQMIRSM_TEXTARRAY_SIZEC);


		//update shared memory status to Empty
		*mqmirsmStatusPtr = 'E';
		ReleaseMutex(smMutex);

	} catch (const boost::interprocess::interprocess_exception& ex) {
		logger->log_p(L"MessageQueueUtils::tryReceiveMessage interprocess_exception: [%S] native_error=[%d] error_code=[%d]", ex.what(), ex.get_native_error(), ex.get_error_code() );
		return false;
	} catch (...){
		logger->log(L"MessageQueueUtils::tryReceiveMessage EXCEPTION: unknown");
		return false;
	}

	logger->log_p(L"MessageQueueUtils::tryReceiveMessage (mq mode)  RECEIVED DATA:  menuItemType = [%c] userActionType = [%c] userButton = [%c] targetHandle = [%I64u]",
			menuItemType, userActionType, userButton, targetHandle);

	return true;
}
int
SharedMemoryUtils::getClientInstances(boost::ptr_list<ClientInstanceClass> * clientInstancesListPtr, std::wstring& forThisProfileName)
{

	if (clientInstancesListPtr==NULL){
		logger->log(L"SharedMemoryUtils::getClientInstances clientInstancesListPtr==NULL");
		return -1;
	}

	int count = 0;

	for (int recordNo = 0; recordNo < SMUCONST_CSM_RECORDS_COUNT; recordNo++ ){

		boost::interprocess::mapped_region region1(
			*csm,
			boost::interprocess::read_only,
			SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_STATUS_RECOFFSET,
			SMUCONST_CSM_RECORD_STATUS_SIZE
		);
		char* recordStatusPtr = static_cast<char*>(region1.get_address());

		if (*recordStatusPtr == 'W'){

			boost::interprocess::mapped_region region2(
				*csm,
				boost::interprocess::read_only,
				SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_TYPE_RECOFFSET,
				SMUCONST_CSM_RECORD_TYPE_SIZE
			);
			char* recordTypePtr = static_cast<char*>(region2.get_address());

			if (*recordTypePtr == 'M'){

				boost::interprocess::mapped_region region3(
					*csm,
					boost::interprocess::read_only,
					SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_VISABLETO_RECOFFSET,
					SMUCONST_CSM_RECORD_VISABLETO_SIZE
				);
				wchar_t* recordVisabletoPtr = static_cast<wchar_t*>(region3.get_address());
				std::wstring visableTo = recordVisabletoPtr;

				if (isTokenOnList(forThisProfileName, visableTo)){

					//this instance match all conditions
					//get its name and id (recordNo)
					ClientInstanceClass* clientInstance = new ClientInstanceClass();

					boost::interprocess::mapped_region region4(
						*csm,
						boost::interprocess::read_write,
						SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_RECID_RECOFFSET,
						SMUCONST_CSM_RECORD_RECID_SIZE
					);
					uint16_t* recordIdPtr = static_cast<uint16_t*>(region4.get_address());
					clientInstance->recordId = *recordIdPtr;

					boost::interprocess::mapped_region region5(
						*csm,
						boost::interprocess::read_only,
						SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_DNAME_RECOFFSET,
						SMUCONST_CSM_RECORD_DNAME_SIZE
					);
					wchar_t* displayNamePtr = static_cast<wchar_t*>(region5.get_address());
					clientInstance->displayName = displayNamePtr;


					clientInstancesListPtr->push_back(clientInstance);
					count++;

				}

			}//end if M

		}//end if W

	}//end for

	logger->log_p(L"SharedMemoryUtils::getClientInstances return count = %d", count);
	return count;
}
//recordNo === processCsmId -1
void
SharedMemoryUtils::freeCsmRecord(boost::interprocess::windows_shared_memory& csm, uint16_t recordNo)
{

	logger->log_p(L"freeCsmRecord: recordNo = %u processCsmId = %u", recordNo, recordNo+1);

	//zero type
	boost::interprocess::mapped_region region1(
		csm,
		boost::interprocess::read_write,
		SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_TYPE_RECOFFSET,
		SMUCONST_CSM_RECORD_TYPE_SIZE
	);
	char* recordTypePtr = static_cast<char*>(region1.get_address());
	*recordTypePtr = (char)0;

	//zero keepalive timestamp
	boost::interprocess::mapped_region region2(
		csm,
		boost::interprocess::read_write,
		SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_KAT_RECOFFSET,
		SMUCONST_CSM_RECORD_KAT_SIZE
	);
	time_t* recordKatPtr = static_cast<time_t*>(region2.get_address());
	*recordKatPtr = (time_t)0;

	//zero msm timestamp
	boost::interprocess::mapped_region region3(
		csm,
		boost::interprocess::read_write,
		SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_MSMT_RECOFFSET,
		SMUCONST_CSM_RECORD_MSMT_SIZE
	);
	time_t* recordMsmtPtr = static_cast<time_t*>(region3.get_address());
	*recordMsmtPtr = (time_t)0;

	//zero displayname
	boost::interprocess::mapped_region region4(
		csm,
		boost::interprocess::read_write,
		SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_DNAME_RECOFFSET,
		SMUCONST_CSM_RECORD_DNAME_SIZE
	);
	memset(region4.get_address(), 0, SMUCONST_CSM_RECORD_DNAME_SIZE);

	//zero visableto
	boost::interprocess::mapped_region region5(
		csm,
		boost::interprocess::read_write,
		SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_VISABLETO_RECOFFSET,
		SMUCONST_CSM_RECORD_VISABLETO_SIZE
	);
	memset(region5.get_address(), 0, SMUCONST_CSM_RECORD_VISABLETO_SIZE);

	//status = E
	boost::interprocess::mapped_region region6(
		csm,
		boost::interprocess::read_write,
		SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_STATUS_RECOFFSET,
		SMUCONST_CSM_RECORD_STATUS_SIZE
	);
	char* recordStatusPtr = static_cast<char*>(region6.get_address());
	*recordStatusPtr = 'E';
}
int
SharedMemoryUtils::addRecordToMsm(char type, uint64_t agcHandle, uint64_t accountHandle, uint64_t groupHandle, char status, std::wstring& value)
{

	logger->log_p(L"addRecordToMsm: type=[%c], agcHandle=[%I64u], accountHandle=[%I64u], groupHandle=[%I64u], status=[%c], value=[%s], agcHandle=[%I64u]",
			type, agcHandle, accountHandle, groupHandle, status==NULL?'-':status , value.c_str(), agcHandle);


	//if there is not enought space in current msm - create new one
	if (freeMsmRecordsCount == 0){

		std::size_t msmTotalSize = getMsmTotalSize();
		std::string msmName = getMsmName(processCsmId, nextMsmNumber);

		logger->log_p(L"create new MSM msmName=[%S] " SCNuPTR L" Bytes (schould be 32768 B)",	msmName.c_str(), msmTotalSize);

		boost::interprocess::windows_shared_memory* msm;
		msm = new boost::interprocess::windows_shared_memory(
			boost::interprocess::open_or_create,
			msmName.c_str(),
			boost::interprocess::read_write,
			msmTotalSize
		); //TODO exception handling //TODO delete msm

		//zero shared memory (neccessery if sm was opened(it is old wrong msm from deleted miranda msm record so it contains old bad data))
		boost::interprocess::mapped_region regionToDel(
				*msm,
				boost::interprocess::read_write,
				0,
				msmTotalSize
			);
		memset(regionToDel.get_address(), 0, msmTotalSize);

		//set isLastNodePtr initial value to 0 , will be update at commitCSM()
		boost::interprocess::mapped_region region1(
				*msm,
				boost::interprocess::read_write,
				SMUCONST_MSM_HEADER_ISLAST_OFFSET,
				SMUCONST_MSM_HEADER_ISLAST_SIZE
			);
		char* isLastNodePtr = static_cast<char*>(region1.get_address());
		*isLastNodePtr = '0';

		//TODO - set all records to type 'E'Empty

		msmList.push_back(msm);

		nextMsmNumber++;
		freeMsmRecordsCount = SMUCONST_MSM_RECORDS_COUNT;

	}

	boost::interprocess::windows_shared_memory * currentMsm = &(msmList.back());

	//save data to record
	int actualRecordOffset = SMUCONST_MSM_RECORDS_OFFSET + ((SMUCONST_MSM_RECORDS_COUNT - freeMsmRecordsCount) * SMUCONST_MSM_RECORD_SIZE);

	//char type
	boost::interprocess::mapped_region region1(
		*currentMsm,
		boost::interprocess::read_write,
		actualRecordOffset + SMUCONST_MSM_RECORD_TYPE_RECOFFSET,
		SMUCONST_MSM_RECORD_TYPE_SIZE
	);
	char* recordTypePtr = static_cast<char*>(region1.get_address());
	*recordTypePtr = type;

	//HANDLE agcHandle
	boost::interprocess::mapped_region region2(
		*currentMsm,
		boost::interprocess::read_write,
		actualRecordOffset + SMUCONST_MSM_RECORD_HANDLE_RECOFFSET,
		SMUCONST_MSM_RECORD_HANDLE_SIZE
	);
	uint64_t* agcHandlePtr  = static_cast<uint64_t*>(region2.get_address());
	*agcHandlePtr = agcHandle;

	//HANDLE accountHandle
	boost::interprocess::mapped_region region3(
		*currentMsm,
		boost::interprocess::read_write,
		actualRecordOffset + SMUCONST_MSM_RECORD_ACCOUNTH_RECOFFSET,
		SMUCONST_MSM_RECORD_ACCOUNTH_SIZE
	);
	uint64_t* accountHandlePtr = static_cast<uint64_t*>(region3.get_address());
	*accountHandlePtr = accountHandle;

	//HANDLE groupHandle
	boost::interprocess::mapped_region region4(
		*currentMsm,
		boost::interprocess::read_write,
		actualRecordOffset + SMUCONST_MSM_RECORD_GROUPH_RECOFFSET,
		SMUCONST_MSM_RECORD_GROUPH_SIZE
	);
	uint64_t* groupHandlePtr = static_cast<uint64_t*>(region4.get_address());
	*groupHandlePtr = groupHandle;

	//char status
	boost::interprocess::mapped_region region5(
		*currentMsm,
		boost::interprocess::read_write,
		actualRecordOffset + SMUCONST_MSM_RECORD_STATUS_RECOFFSET,
		SMUCONST_MSM_RECORD_STATUS_SIZE
	);
	char* recordStatusPtr = static_cast<char*>(region5.get_address());
	*recordStatusPtr = status;

	//std::wstring& value
	boost::interprocess::mapped_region region6(
		*currentMsm,
		boost::interprocess::read_write,
		actualRecordOffset + SMUCONST_MSM_RECORD_DNAME_RECOFFSET,
		SMUCONST_MSM_RECORD_DNAME_SIZE
	);
	wchar_t* recordValuePtr = static_cast<wchar_t*>(region6.get_address());
	wcsncpy_s(recordValuePtr, SMUCONST_MSM_RECORD_DNAME_SIZEC, value.c_str(), _TRUNCATE);

	freeMsmRecordsCount --;

	return 0;
}
/**
 *
 * return
 * >0 - id of assigned record
 * -1 - no empty record found
 */
uint16_t
SharedMemoryUtils::allocateRecordInCsm(boost::interprocess::windows_shared_memory& csm, char type, std::wstring& displayName, std::wstring& visableTo, bool doCommitSM)
{

	//try to find first record with status E (Empty) in CSM
	for (unsigned short recordNo = 0; recordNo < SMUCONST_CSM_RECORDS_COUNT; recordNo++ ){
	
		boost::interprocess::mapped_region region1(
			csm,
			boost::interprocess::read_write,
			SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_STATUS_RECOFFSET,
			SMUCONST_CSM_RECORD_STATUS_SIZE
		);
		char* recordStatusPtr = static_cast<char*>(region1.get_address());
		
		if (*recordStatusPtr == 'E'){

			//save new status 'N' (New)
			*recordStatusPtr = 'N';
		
			//save type
			boost::interprocess::mapped_region region2(
				csm,
				boost::interprocess::read_write,
				SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_TYPE_RECOFFSET,
				SMUCONST_CSM_RECORD_TYPE_SIZE
			);
			char* recordTypePtr = static_cast<char*>(region2.get_address());
			*recordTypePtr = type;
			
			//save first keep alive timestamp
			boost::interprocess::mapped_region region3(
				csm,
				boost::interprocess::read_write,
				SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_KAT_RECOFFSET,
				SMUCONST_CSM_RECORD_KAT_SIZE
			);
			time_t* recordKatPtr = static_cast<time_t*>(region3.get_address());
			*recordKatPtr = mfGetCurrentTimestamp();

			//save version
			boost::interprocess::mapped_region region4(
				csm,
				boost::interprocess::read_write,
				SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_VERSION_RECOFFSET,
				SMUCONST_CSM_RECORD_VERSION_SIZE
			);
			uint16_t* recordVersionPtr = static_cast<uint16_t*>(region4.get_address());
			*recordVersionPtr = SMUCONST_CSM_CURRENT_RECORDVERSION;

			//save display name
			boost::interprocess::mapped_region region5(
				csm,
				boost::interprocess::read_write,
				SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_DNAME_RECOFFSET,
				SMUCONST_CSM_RECORD_DNAME_SIZE
			);
			wchar_t* recordDnamePtr = static_cast<wchar_t*>(region5.get_address());
			wcsncpy_s(recordDnamePtr, SMUCONST_CSM_RECORD_DNAME_SIZEC, displayName.c_str(), _TRUNCATE);

			//save visableTo
			boost::interprocess::mapped_region region6(
				csm,
				boost::interprocess::read_write,
				SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_VISABLETO_RECOFFSET,
				SMUCONST_CSM_RECORD_VISABLETO_SIZE
			);
			wchar_t* recordVisabletoPtr = static_cast<wchar_t*>(region6.get_address());
			wcsncpy_s(recordVisabletoPtr, SMUCONST_CSM_RECORD_VISABLETO_SIZEC, visableTo.c_str(), _TRUNCATE);
		
			//get id
			boost::interprocess::mapped_region region7(
				csm,
				boost::interprocess::read_write,
				SMUCONST_CSM_HEADER_SIZE + (recordNo * SMUCONST_CSM_RECORD_SIZE) + SMUCONST_CSM_RECORD_RECID_RECOFFSET,
				SMUCONST_CSM_RECORD_RECID_SIZE
			);
			uint16_t* recordIdPtr = static_cast<uint16_t*>(region7.get_address());
			

			if (doCommitSM){
				*recordStatusPtr = 'W';
			}

			logger->log_p(L"allocateRecordInCsm: allocated record with id (processCsmId): %u", *recordIdPtr);
			
			return *recordIdPtr;
		
		}//end if
	
	}//end for
	
	logger->log(L"allocateRecordInCsm: no empty records in CSM. return -1");
	return -2;
	
}