Exemple #1
0
	bool SendHeartbeat (bool bWithStash) {
		LOGDEBUG (TEXT ("Sending heartbeat message"));
		FudgeStatus status;
		FudgeMsg msg;
		if ((status = FudgeMsg_create (&msg)) != FUDGE_OK) {
			LOGFATAL (TEXT ("Couldn't create message, status ") << status);
			assert (0);
			return false;
		}
		if ((status = ConnectorMessage_setOperation (msg, HEARTBEAT)) != FUDGE_OK) {
			FudgeMsg_release (msg);
			LOGFATAL (TEXT ("Couldn't create message, status ") << status);
			assert (0);
			return false;
		}
		if (bWithStash) {
			m_oStashMutex.Enter ();
			if (m_msgStash) {
				if ((status = ConnectorMessage_setStash (msg, m_msgStash)) != FUDGE_OK) {
					LOGFATAL (TEXT ("Couldn't create message, status ") << status);
					assert (0);
					status = FUDGE_OK;
					// Not good, but can carry on
				}
			}
			m_oStashMutex.Leave ();
		}
		bool bResult = m_poService->Send (MESSAGE_DIRECTIVES_CLIENT, msg);
		FudgeMsg_release (msg);
		return bResult;
	}
	void Run () {
		int nAttempt = 0;
		CNamedPipe *poPipe;
		do {
			if (nAttempt) {
				Sleep (TIMEOUT / 10);
			}
			poPipe = CNamedPipe::ClientWrite (m_pszPipeName);
		} while (!poPipe && (GetLastError () == ENOENT) && (++nAttempt < 10));
		if (poPipe) {
			LOGDEBUG (TEXT ("Client connected"));
			ClientConnect cc;
			memset (&cc, 0, sizeof (cc));
			cc._userName = TEST_USERNAME;
			cc._CPPToJavaPipe = TEST_CPP2JAVA;
			cc._JavaToCPPPipe = TEST_JAVA2CPP;
			cc._languageID = TEST_LANGUAGE;
			cc._debug = TEST_DEBUG;
			FudgeMsg msg;
			ASSERT (ClientConnect_toFudgeMsg (&cc, &msg) == FUDGE_OK);
			FudgeMsgEnvelope env;
			ASSERT (FudgeMsgEnvelope_create (&env, 0, 0, 0, msg) == FUDGE_OK);
			fudge_byte *ptrBuffer;
			fudge_i32 cbBuffer;
			ASSERT (FudgeCodec_encodeMsg (env, &ptrBuffer, &cbBuffer) == FUDGE_OK);
			FudgeMsgEnvelope_release (env);
			FudgeMsg_release (msg);
			ASSERT (poPipe->Write (ptrBuffer, cbBuffer, TIMEOUT) == cbBuffer);
			delete ptrBuffer;
		} else {
			LOGWARN (TEXT ("Couldn't open client pipe, error ") << GetLastError ());
		}
	}
/// Destroys a call slot, releasing any resources.
CSynchronousCallSlot::~CSynchronousCallSlot () {
    FudgeMsg msg = m_msg.Get ();
    if (msg) {
        LOGDEBUG (TEXT ("Releasing message in deleted call slot ") << m_nIdentifier);
        FudgeMsg_release (msg);
    }
}
	void Run () {
		CSettings settings;
		ASSERT (settings.GetConnectionPipe ());
		LOGDEBUG (TEXT ("Connecting to ") << settings.GetConnectionPipe ());
		CNamedPipe *poPipe = CNamedPipe::ClientWrite (settings.GetConnectionPipe ());
		ASSERT (poPipe);
		LOGDEBUG (TEXT ("Client connected"));
		ClientConnect cc;
		memset (&cc, 0, sizeof (cc));
		cc._userName = TEST_USERNAME;
		cc._CPPToJavaPipe = TEST_CPP2JAVA;
		cc._JavaToCPPPipe = TEST_JAVA2CPP;
		cc._languageID = TEST_LANGUAGE;
#ifdef _DEBUG
		cc._debug = FUDGE_TRUE;
#endif /* ifdef _DEBUG */
		FudgeMsg msg;
		ASSERT (ClientConnect_toFudgeMsg (&cc, &msg) == FUDGE_OK);
		FudgeMsgEnvelope env;
		ASSERT (FudgeMsgEnvelope_create (&env, 0, 0, 0, msg) == FUDGE_OK);
		fudge_byte *ptrBuffer;
		fudge_i32 cbBuffer;
		ASSERT (FudgeCodec_encodeMsg (env, &ptrBuffer, &cbBuffer) == FUDGE_OK);
		FudgeMsgEnvelope_release (env);
		FudgeMsg_release (msg);
		LOGDEBUG (TEXT ("Writing connection packet"));
		ASSERT (poPipe->Write (ptrBuffer, cbBuffer, TIMEOUT_CONNECT) == (size_t)cbBuffer);
		LOGDEBUG (TEXT ("Connection packet written"));
		delete ptrBuffer;
		LOGDEBUG (TEXT ("Disconnecting"));
		delete poPipe;
	}
Exemple #5
0
/// Destroys the message entry.
CFudgeMsgInfo::~CFudgeMsgInfo () {
	assert (m_nRefCount == 0);
	FudgeMsg_release (m_msg);
	if (m_pData) {
		free (m_pData);
		g_cbData -= m_cbData;
	}
}
Exemple #6
0
FudgeStatus FudgeCodec_decodeMsg ( FudgeMsgEnvelope * envelope, const fudge_byte * bytes, fudge_i32 numbytes )
{
    FudgeStatus status;
    FudgeMsgHeader header;
    FudgeMsg message;

    if ( ! envelope )
        return FUDGE_NULL_POINTER;

    /* Get the message header and use it to create the envelope and the message */
    if ( ( status = FudgeHeader_decodeMsgHeader ( &header, bytes, numbytes ) ) != FUDGE_OK )
        return status;
    if ( numbytes < header.numbytes )
        return FUDGE_OUT_OF_BYTES;
    if ( ( status = FudgeMsg_create ( &message ) ) != FUDGE_OK )
        return status;

    if ( ( status = FudgeMsgEnvelope_create ( envelope,
                                              header.directives,
                                              header.schemaversion,
                                              header.taxonomy,
                                              message ) ) != FUDGE_OK )
        goto release_message_and_fail;

    /* Envelope now has a message reference */
    FudgeMsg_release ( message );

    /* Advance to the end of the header */
    bytes += sizeof ( FudgeMsgHeader );
    numbytes -= sizeof ( FudgeMsgHeader );

    /* Consume fields */
    if ( ( status = FudgeCodec_decodeMsgFields ( message, bytes, numbytes ) ) != FUDGE_OK )
        goto release_envelope_and_fail;

    return status;

release_envelope_and_fail:
    FudgeMsgEnvelope_release ( *envelope );

release_message_and_fail:
    FudgeMsg_release ( message );
    return status;
}
Exemple #7
0
	void SetStash (FudgeMsg msgStash) {
		m_oStashMutex.Enter ();
		if (m_msgStash) {
			LOGDEBUG (TEXT ("Discarding old stash message"));
			FudgeMsg_release (m_msgStash);
		}
		FudgeMsg_retain (msgStash);
		m_msgStash = msgStash;
		m_oStashMutex.Leave ();
	}
Exemple #8
0
// This must only be called from the thread that creates and connects the pipes. This then
// doesn't need to acquire the pipe semaphore as the object won't be modified concurrently.
// Another thread might be sending, but that's it.
bool CClientService::DispatchAndRelease (FudgeMsgEnvelope env) {
	FudgeMsg msg = FudgeMsgEnvelope_getMessage (env);
	switch (FudgeMsgEnvelope_getDirectives (env)) {
	case MESSAGE_DIRECTIVES_CLIENT : {
		Operation op;
		if (ConnectorMessage_getOperation (msg, &op) == FUDGE_OK) {
			switch (op) {
			case HEARTBEAT :
				LOGDEBUG (TEXT ("Heartbeat received"));
				break;
			case POISON :
				// This shouldn't be sent by the Java stack
				LOGFATAL (TEXT ("Received poison from Java framework"));
				assert (0);
				break;
			case STASH : {
				FudgeMsg msgStash;
				if (ConnectorMessage_getStash (msg, &msgStash) == FUDGE_OK) {
					LOGDEBUG (TEXT ("Storing stash message"));
					m_oStateMutex.Enter ();
					if (m_poRunner) {
						m_poRunner->SetStash (msgStash);
					} else {
						LOGWARN (TEXT ("No runner thread"));
					}
					m_oStateMutex.Leave ();
					FudgeMsg_release (msgStash);
				} else {
					LOGWARN (TEXT ("No stash message attached"));
				}
				break;
						 }
			default :
				LOGWARN (TEXT ("Invalid client message - operation ") << op);
				break;
			}
		} else {
			LOGWARN (TEXT ("Invalid client message"));
		}
		break;
										}
	case MESSAGE_DIRECTIVES_USER :
		m_oMessageReceivedMutex.Enter ();
		if (m_poMessageReceivedCallback) {
			m_poMessageReceivedCallback->OnMessageReceived (msg);
		}
		m_oMessageReceivedMutex.Leave ();
		break;
	default :
		LOGWARN (TEXT ("Unknown message delivery directive ") << FudgeMsgEnvelope_getDirectives (env));
		break;
	}
	FudgeMsgEnvelope_release (env);
	return m_poPipes->IsConnected ();
}
Exemple #9
0
FudgeStatus FudgeCodec_decodeFieldFudgeMsg ( const fudge_byte * bytes, const fudge_i32 width, FudgeFieldData * data )
{
    FudgeMsg submessage;
    FudgeStatus status;

    if ( ( status = FudgeMsg_create ( &submessage ) ) != FUDGE_OK )
        return status;
    if ( ( status = FudgeCodec_decodeMsgFields ( submessage, bytes, width ) ) != FUDGE_OK )
    {
        FudgeMsg_release ( submessage );
        return status;
    }
    data->message = submessage;

    return FUDGE_OK;
}
Exemple #10
0
FudgeStatus FudgeMsg_addFieldMsg ( FudgeMsg message, const FudgeString name, const fudge_i16 * ordinal, FudgeMsg value )
{
    FudgeStatus status;
    FudgeFieldData data;

    if ( ! ( message && value ) )
        return FUDGE_NULL_POINTER;
    if ( ( status = FudgeMsg_retain ( value ) ) != FUDGE_OK )
        return status;
    data.message = value;
    if ( ( status = FudgeMsg_addFieldData ( message, FUDGE_TYPE_FUDGE_MSG, name, ordinal, &data, 0 ) ) != FUDGE_OK )
    {
        FudgeMsg_release ( value );
        return status;
    }
    return FUDGE_OK;
}
Exemple #11
0
void FieldListNode_destroy ( FieldListNode * node )
{
    assert ( node );

    switch ( node->field.type )
    {
        /* Fudge message type: free the message pointer */
        case FUDGE_TYPE_FUDGE_MSG:
            if ( node->field.data.message )
                FudgeMsg_release ( node->field.data.message );
            break;

        /* Fudge string type: free the string pointer */
        case FUDGE_TYPE_STRING:
            if ( node->field.data.string )
                FudgeString_release ( node->field.data.string );
            break;

        /* Primitive type: nothing needs freeing */
        case FUDGE_TYPE_INDICATOR:
        case FUDGE_TYPE_BOOLEAN:
        case FUDGE_TYPE_BYTE:
        case FUDGE_TYPE_SHORT:
        case FUDGE_TYPE_INT:
        case FUDGE_TYPE_LONG:
        case FUDGE_TYPE_FLOAT:
        case FUDGE_TYPE_DOUBLE:
        case FUDGE_TYPE_DATE:
        case FUDGE_TYPE_TIME:
        case FUDGE_TYPE_DATETIME:
            break;

        /* Every other type will store its data in the bytes array */
        default:
            free ( ( fudge_byte * ) node->field.data.bytes );
            break;
    }

    if ( node->field.name )
        FudgeString_release ( node->field.name );
    free ( node );
}
Exemple #12
0
FudgeStatus FudgeMsgEnvelope_release ( FudgeMsgEnvelope envelope )
{
    if ( ! envelope )
        return FUDGE_NULL_POINTER;

    if ( ! FudgeRefCount_decrementAndReturn ( envelope->refcount ) )
    {
        /* Last reference has been released - release the message and destroy the envelope */
        FudgeStatus status;

        if ( ( status = FudgeMsg_release ( envelope->message ) ) != FUDGE_OK )
            return status;

        if ( ( status = FudgeRefCount_destroy ( envelope->refcount ) ) != FUDGE_OK )
            return status;

        FUDGEMEMORY_FREE( envelope );
    }
    return FUDGE_OK;
}
/// Releases the slot back to its parent. This may be called at the same time as a PostAndRelease
/// from a message receiving thread. This must not be called at the same time as GetMessage.
void CSynchronousCallSlot::Release () {
    int nSequence = m_oSequence.IncrementAndGet () & STATE_SEQUENCE_MASK;
    int nState = m_oState.Get (), nAltState;
    FudgeMsg msg;
retry:
    switch (nState & STATE_STATE_MASK) {
    case STATE_IDLE :
        nAltState = m_oState.CompareAndSet (STATE_IDLE | nSequence, nState);
        if (nAltState != nState) {
            LOGDEBUG (TEXT ("Retrying after state shift from ") << nState << TEXT (" to ") << nAltState);
            nState = nAltState;
            goto retry;
        }
        break;
    case STATE_MESSAGE_PRE :
        // A message is being posted; need to wait for the post to complete
        LOGDEBUG (TEXT ("Retrying during call to PostAndRelease on slot ") << m_nIdentifier);
        CThread::Yield ();
        nState = m_oState.Get ();
        goto retry;
    case STATE_MESSAGE_OK :
        // Message has been posted, but not consumed discard it
        msg = m_msg.GetAndSet (NULL);
        if (msg) {
            LOGDEBUG (TEXT ("Discarding message in released slot ") << m_nIdentifier);
            FudgeMsg_release (msg);
        }
        m_oState.Set (STATE_IDLE | nSequence);
        break;
    // STATE_WAITING cannot happen as calls to Release and GetMessage are mutually exclusive for a thread
    case STATE_DONE :
        m_oState.Set (STATE_IDLE | nSequence);
        break;
    default :
        LOGFATAL (TEXT ("Invalid state ") << nState);
        assert (0);
        break;
    }
    m_poOwner->Release (this);
}
Exemple #14
0
/// Finds an existing message entry in the map, or creates a new entry if none is found.
/// The message is returned with an incremented reference count - the caller should call
/// Release when finished with it (unless the reference is offloaded to R).
///
/// @param[in] pData the binary encoding of the message to lock up
/// @param[in] cbData the length of the binary encoding in bytes
CFudgeMsgInfo *CFudgeMsgInfo::GetMessage (const void *pData, size_t cbData) {
	g_oMutex.Enter ();
	FudgeMsg msg = NULL;
	CFudgeMsgInfo *poMessage = NULL;
	void *pDataCopy = NULL;
	do {
		msg = _DecodeFudgeMsg (pData, cbData);
		if (!msg) {
			break;
		}
		TFudgeMsgMap::const_iterator itr = g_oMap.find (msg);
		if (itr != g_oMap.end ()) {
			poMessage = itr->second;
			poMessage->m_nRefCount++;
			break;
		}
		pDataCopy = malloc (cbData);
		if (!pDataCopy) {
			LOGFATAL (TEXT ("Out of memory"));
			break;
		}
		memcpy (pDataCopy, pData, cbData);
		poMessage = new CFudgeMsgInfo (msg, pDataCopy, cbData);
		if (!poMessage) {
			LOGFATAL (TEXT ("Out of memory"));
			break;
		}
		LOGDEBUG (TEXT ("Adding message to map (size = ") << (g_oMap.size () + 1) << TEXT (")"));
		g_oMap.insert (TFudgeMsgMap::value_type (msg, poMessage));
		g_cbData += cbData + MESSAGE_INFO_OVERHEAD;
		pDataCopy = NULL;
	} while (false);
	g_oMutex.Leave ();
	if (msg) FudgeMsg_release (msg);
	if (pDataCopy) free (pDataCopy);
	return poMessage;
}
/// Posts a message to the slot and releases a caller to GetMessage if there is one. Only one
/// thread may call this at any one time.
///
/// @param[in] nSequence sequence counter decoded from the message
/// @param[in] msg message payload
void CSynchronousCallSlot::PostAndRelease (int nSequence, FudgeMsg msg) {
    nSequence &= STATE_SEQUENCE_MASK;
    int nState = m_oState.Get (), nAltState;
retry:
    if ((nState & STATE_SEQUENCE_MASK) != nSequence) {
        LOGDEBUG (TEXT ("Sequence on slot ") << m_nIdentifier << TEXT (" already advanced"));
        FudgeMsg_release (msg);
        return;
    }
    switch (nState & STATE_STATE_MASK) {
    case STATE_IDLE :
        nAltState = m_oState.CompareAndSet (STATE_MESSAGE_PRE | nSequence, nState);
        if (nAltState != nState) {
            LOGDEBUG (TEXT ("Retrying after state shift from ") << nState << TEXT (" to ") << nAltState << TEXT (" on slot ") << m_nIdentifier);
            nState = nAltState;
            goto retry;
        }
        // Now in MESSAGE_PRE state, ready to store message
        msg = m_msg.GetAndSet (msg);
        if (msg) {
            LOGDEBUG (TEXT ("Discarding message already in slot ") << m_nIdentifier);
            FudgeMsg_release (msg);
        }
        // Now advance to MESSAGE_OK state, to indicate message is in the slot
        m_oState.Set (STATE_MESSAGE_OK | nSequence);
        break;
    // STATE_MESSAGE_PRE cannot happen as only one thread should ever call PostAndRelease
    case STATE_MESSAGE_OK :
        LOGWARN (TEXT ("Discarding duplicate message received on slot ") << m_nIdentifier);
        FudgeMsg_release (msg);
        break;
    case STATE_WAITING :
        // Message received with another thread waiting for it
        nAltState = m_oState.CompareAndSet (STATE_MESSAGE_PRE | nSequence, nState);
        if (nAltState != nState) {
            LOGDEBUG (TEXT ("Retrying after state shift from ") << nState << TEXT (" to ") << nAltState << TEXT (" on slot ") << m_nIdentifier);
            nState = nAltState;
            goto retry;
        }
        // Now in MESSAGE_PRE state, ready to store message
        msg = m_msg.GetAndSet (msg);
        if (msg) {
            LOGDEBUG (TEXT ("Discarding message already in slot ") << m_nIdentifier);
            FudgeMsg_release (msg);
        }
        // Now advance to MESSAGE_OK state, to indicate message is in the slot
        m_oState.Set (STATE_MESSAGE_OK | nSequence);
        // There was another thread waiting on the semaphore
        LOGDEBUG (TEXT ("Signalling semaphore on slot ") << m_nIdentifier);
        m_sem.Signal ();
        break;
    case STATE_DONE :
        LOGWARN (TEXT ("Discarding late delivery of message on slot ") << m_nIdentifier);
        FudgeMsg_release (msg);
        break;
    default :
        LOGFATAL (TEXT ("Invalid state ") << nState << TEXT (" on slot ") << m_nIdentifier);
        assert (0);
        FudgeMsg_release (msg);
        break;
    }
}
Exemple #16
0
int main ( int argc, char * argv [ ] )
{
    FudgeStatus status;
    FudgeMsg message;
    FudgeMsgEnvelope envelope;
    AddressDetails * details [ 2 ];
    fudge_i16 ordinal;
    fudge_byte * encoded;
    fudge_i32 encodedsize;

    /* Initialise the Fudge library */
    if ( ( status = Fudge_init ( ) ) )
        fatalFudgeError ( status, "Failed to initialise Fudge library" );

    /* Register the AddressDetails type */
    if ( ( status = FudgeRegistry_registerType ( FUDGE_TYPE_ADDRESSDETAILS,
                    FUDGE_TYPE_PAYLOAD_BYTES,
                    FudgeCodec_decodeFieldAddressDetails,
                    FudgeCodec_encodeFieldAddressDetails,
                    FudgeType_coerceAddressDetails ) ) )
        fatalFudgeError ( status, "Failed to register AddressDetails type" );

    /* Construct and encode two address details */
    details [ 0 ] = constructAddressDetails ( Status_Past, 123, "Fake St.", "Some City", "P05 T4L" );
    details [ 1 ] = constructAddressDetails ( Status_Active, 45, "Faux Road", "Some Town", "FUD 63C" );

    /* Create a message and add the two details */
    if ( ( status = FudgeMsg_create ( &message ) ) )
        fatalFudgeError ( status, "Failed to create Fudge message" );

    for ( ordinal = 0; ordinal < 2; ++ordinal )
        FudgeMsg_addFieldAddressDetails ( message, 0, &ordinal, details [ ordinal ] );

    /* Encode the message */
    if ( ( status = FudgeMsgEnvelope_create ( &envelope, 0, 0, 0, message ) ) )
        fatalFudgeError ( status, "Failed to create Fudge messag envelope" );

    if ( ( status = FudgeCodec_encodeMsg ( envelope, &encoded, &encodedsize ) ) )
        fatalFudgeError ( status, "Failed to encode Fudge message" );

    /* Clean up source details and messge */
    free ( details [ 0 ] );
    free ( details [ 1 ] );
    FudgeMsgEnvelope_release ( envelope );
    FudgeMsg_release ( message );

    /* Decode the message and release the encoded bytes array */
    if ( ( status = FudgeCodec_decodeMsg ( &envelope, encoded, encodedsize ) ) )
        fatalFudgeError ( status, "Failed to decode Fudge message" );
    free ( encoded );

    /* Retrieve, convert and display the fields */
    for ( ordinal = 0; ordinal < 2; ++ordinal )
    {
        FudgeField field;
        FudgeFieldData data;
        FudgeTypePayload payload;
        fudge_i32 datasize;
        char * ascii;

        if ( ( status = FudgeMsg_getFieldByOrdinal ( &field, FudgeMsgEnvelope_getMessage ( envelope ), ordinal ) ) )
            fatalFudgeError ( status, "Failed to find field" );

        /* Convert the field in to a string */
        if ( ( status = FudgeMsg_getFieldAs ( &field, FUDGE_TYPE_STRING, &data, &payload, &datasize ) ) )
            fatalFudgeError ( status, "Failed to convert field to string" );

        /* This is a bit paranoid, but it's checking that the string
           conversion actually resulted in string payload */
        if ( payload != FUDGE_TYPE_PAYLOAD_STRING )
        {
            fprintf ( stderr, "FATAL ERROR: Retrieving field %d as a string returned a non-string!\n", ordinal );
            exit ( 1 );
        }

        FudgeString_convertToASCIIZ ( &ascii, data.string );
        printf ( "Field %d: %s\n", ordinal, ascii );
        free ( ascii );
        FudgeString_release ( data.string );
    }

    /* Clean up */
    FudgeMsgEnvelope_release ( envelope );
    return 0;
}
Exemple #17
0
	~CRunnerThread () {
		LOGDEBUG (TEXT ("Runner thread destroyed"));
		if (m_msgStash) {
			FudgeMsg_release (m_msgStash);
		}
	}