Zyre::

Event class

An event read from a Zyre network.

Refs: - github.com/zeromq/zyre#readme

Public Class Methods

Zyre::Event.from_node( node ) → event

Read the next event from the given Zyre::Node and wrap it in a Zyre::Event.

static VALUE
rzyre_event_s_from_node( VALUE klass, VALUE node )
{
        zyre_t *node_ptr = rzyre_get_node( node );
        zyre_event_t *event;

        assert( node_ptr );

        event = rb_thread_call_without_gvl2( rzyre_read_event, (void *)node_ptr, RUBY_UBF_IO, 0 );

        if ( event ) {
                const char *event_type = zyre_event_type( event );
                VALUE event_type_s = rb_utf8_str_new_cstr( event_type );
                VALUE event_class = rb_funcall( klass, rb_intern("type_by_name"), 1, event_type_s );
                VALUE event_instance;

                if ( !RTEST(event_class) ) {
                        rb_raise( rb_eRuntimeError, "Unhandled event type '%s'", event_type );
                }

                event_instance = rb_class_new_instance( 0, NULL, event_class );

                RTYPEDDATA_DATA( event_instance ) = event;

                return event_instance;
        } else {
                return Qnil;
        }
}
Zyre::Event.synthesize( type, peer_uuid, **fields ) → event

Create an event in memory without going through a Zyre::Node. This is useful for testing.

uuid = UUID.generate event = Zyre::Event.synthesized( :ENTER, uuid, peer_name: ‘node1’ ) expect( some_system.handle_event(event) ).to have_handled_an_enter_event

static VALUE
rzyre_event_s_synthesize( int argc, VALUE *argv, VALUE klass )
{
        VALUE rval, event_type, peer_uuid, kwargs, event_class;
        VALUE kwvals[5] = { Qundef, Qundef, Qundef, Qundef, Qundef };
        static ID keyword_ids[5];
        zyre_event_t *ptr = NULL;

        // Parse the arguments + keyword arguments
        if ( !keyword_ids[0] ) {
                CONST_ID( keyword_ids[0], "peer_name" );
                CONST_ID( keyword_ids[1], "headers" );
                CONST_ID( keyword_ids[2], "peer_addr" );
                CONST_ID( keyword_ids[3], "group" );
                CONST_ID( keyword_ids[4], "msg" );
        }

        rzyre_log( "debug", "Scanning %d synthesize args.", argc );
        rb_scan_args( argc, argv, "2:", &event_type, &peer_uuid, &kwargs );
        if ( RTEST(kwargs) ) {
                rzyre_log( "debug", "  scanning keyword args: %s", RSTRING_PTR(rb_inspect(kwargs)) );
                rb_get_kwargs( kwargs, keyword_ids, 0, 5, kwvals );
        }

        // Translate the event type argument into the appropriate class and instantiate it
        rzyre_log( "debug", "Creating an instance of a %s event.", RSTRING_PTR(rb_inspect(event_type )) );
        event_class = rb_funcall( klass, rb_intern("type_by_name"), 1, event_type );

        if ( RTEST(event_class) ) {
                event_type = rb_funcall( event_class, rb_intern("type_name"), 0 );
        } else {
                rb_raise( rb_eArgError, "don't know how to create %s events",
                        RSTRING_PTR(rb_inspect(event_type)) );
        }

        rval = rb_class_new_instance( 0, NULL, event_class );

        // Set up the zyre_event memory for the object
        RTYPEDDATA_DATA( rval ) = ptr = (zyre_event_t *) zmalloc( sizeof *ptr );

        // Set the values that are required for every event type
        ptr->type = rzyre_copy_string( event_type );
        ptr->peer_uuid = rzyre_copy_string( peer_uuid );

        // Set the peer_name or default it if it wasn't specified
        rzyre_log( "debug", "Starting type-specific setup." );
        if ( !RB_TYPE_P(kwvals[0], T_UNDEF) ) {
                ptr->peer_name = rzyre_copy_string( kwvals[0] );
        } else {
                ptr->peer_name = (char *) zmalloc( 2 + 6 + 1 );
                assert( ptr->peer_name );
                bzero( ptr->peer_name, 2 + 6 + 1 );
                strncpy( ptr->peer_name, "S-", 2 );
                memcpy( ptr->peer_name + 2, ptr->peer_uuid, 6 );
        }

        if ( streq(ptr->type, "ENTER") ) {
                ptr->peer_addr = rzyre_copy_required_string( kwvals[2], "peer_addr" );
                ptr->headers = rzyre_zhash_from_rhash( kwvals[1] );
        }
        else if ( streq(ptr->type, "JOIN") ) {
                ptr->group = rzyre_copy_required_string( kwvals[3], "group" );
        }
        else if ( streq(ptr->type, "LEAVE") ) {
                ptr->group = rzyre_copy_required_string( kwvals[3], "group" );
        }
        else if ( streq(ptr->type, "WHISPER") ) {
                if ( RB_TYPE_P(kwvals[4], T_UNDEF) )
                        rb_raise( rb_eArgError, "missing required field :msg" );

                rzyre_log( "debug", "Making a WHISPER zmsg from the :msg value: %s",
                        RSTRING_PTR(rb_inspect(kwvals[4])) );
                ptr->msg = rzyre_make_zmsg_from( kwvals[4] );
        }
        else if ( streq(ptr->type, "SHOUT") ) {
                if ( RB_TYPE_P(kwvals[4], T_UNDEF) )
                        rb_raise( rb_eArgError, "missing required field :msg" );

                rzyre_log( "debug", "Making a SHOUT zmsg from the :msg value: %s",
                        RSTRING_PTR(rb_inspect(kwvals[4])) );
                ptr->group = rzyre_copy_required_string( kwvals[3], "group" );
                ptr->msg = rzyre_make_zmsg_from( kwvals[4] );
        }
        else if ( streq(ptr->type, "LEADER") ) {
                ptr->group = rzyre_copy_required_string( kwvals[3], "group" );
        }

        rzyre_log_obj( rval, "debug", "Synthesized a %s event.", ptr->type );

        return rval;
}
type_by_name( name )

Given the name of an event type, return the Zyre::Event subclass that corresponds to it.

# File lib/zyre/event.rb, line 35
def self::type_by_name( name )
        capname = name.to_s.capitalize
        classobj = self.const_get( capname )
rescue NameError => err
        self.log.debug( err )
        return nil
end
type_name()

Return the event type as Zyre refers to it.

# File lib/zyre/event.rb, line 45
def self::type_name
        return self.name[ /.*::(\w+)/, 1 ].upcase
end

Public Instance Methods

event_group

Returns the group name that a SHOUT event was sent to

static VALUE
rzyre_event_group( VALUE self ) {
        zyre_event_t *ptr = rzyre_get_event( self );
        const char *group_str = zyre_event_group( ptr );

        if ( group_str ) {
                return rb_str_new2( group_str );
        } else {
                return Qnil;
        }
}
event_header( name )

Returns value of the header name from the message headers obtained by ENTER. Return nil if no value was found.

static VALUE
rzyre_event_header( VALUE self, VALUE name ) {
        zyre_event_t *ptr = rzyre_get_event( self );
        const char *name_str = StringValueCStr( name );
        const char *value_str = zyre_event_header( ptr, name_str );

        if ( value_str ) {
                return rb_str_new2( value_str );
        } else {
                return Qnil;
        }
}
event_headers

Returns the event headers, or NULL if there are none

static VALUE
rzyre_event_headers( VALUE self ) {
        zyre_event_t *ptr = rzyre_get_event( self );
        zhash_t *headers = zyre_event_headers( ptr );
        VALUE rhash = rb_hash_new();
        const char *key, *val;

        if ( headers ) {
                val = (const char *)zhash_first( headers );
                while( val ) {
                        key = zhash_cursor( headers );
                        rb_hash_aset( rhash, rb_str_new2(key), rb_str_new2(val) );
                        val = (const char *)zhash_next( headers );
                }
        }

        return rhash;
}
inspect()

Return a string describing this event, suitable for debugging.

# File lib/zyre/event.rb, line 71
def inspect
        details = self.inspect_details
        details = ' ' + details unless details.start_with?( ' ' )

        return "#<%p:%#016x%s>" % [
                self.class,
                self.object_id,
                details,
        ]
end
inspect_details()

Provide the details of the inspect message. Defaults to an empty string.

# File lib/zyre/event.rb, line 84
def inspect_details
        return ''
end
is_multipart?()
Alias for: multipart?
match( criteria )

Returns true if the specified criteria match attribute of the event.

# File lib/zyre/event.rb, line 55
def match( criteria )
        return criteria.all? do |key, val|
                self.respond_to?( key ) && self.public_send( key ) == val
        end
end
msg

Some convenience aliases

Alias for: msg
msg

Returns the data from the first frame of the message from the receiver.

static VALUE
rzyre_event_msg( VALUE self ) {
        zyre_event_t *ptr = rzyre_get_event( self );
        zmsg_t *msg = zyre_event_msg( ptr );
        VALUE rval = Qnil;

        if ( msg ) {
                zframe_t *frame = zmsg_first( msg );
                byte *data = zframe_data( frame );

                rval = rb_enc_str_new( (const char *)data, zframe_size(frame), rb_ascii8bit_encoding() );
                rb_obj_freeze( rval );
        }

        return rval;
}
Also aliased as: message
msg_size → int

Return the number of frames present in the event’s message (if it has one). Returns nil if there is no message.

static VALUE
rzyre_event_msg_size( VALUE self )
{
        zyre_event_t *ptr = rzyre_get_event( self );
        zmsg_t *msg = zyre_event_msg( ptr );
        VALUE rval = Qnil;

        if ( msg ) {
                rval = INT2FIX( zmsg_size(msg) );
        }

        return rval;
}
multipart?()

Returns true if the receiving event has a multipart message.

# File lib/zyre/event.rb, line 63
def multipart?
        size = self.msg_size
        return size && size > 1
end
Also aliased as: is_multipart?
multipart_msg

Returns the data from every frame of the message from the receiver.

static VALUE
rzyre_event_multipart_msg( VALUE self ) {
        zyre_event_t *ptr = rzyre_get_event( self );
        zmsg_t *msg = zyre_event_msg( ptr );
        VALUE rval = rb_ary_new();

        if ( msg ) {
                zframe_t *frame = zmsg_first( msg );

                while ( frame ) {
                        char *str = zframe_strdup( frame );
                        VALUE data = rb_enc_str_new( str, zframe_size(frame), rb_ascii8bit_encoding() );

                        rb_obj_freeze( data );
                        rb_ary_push( rval, data );

                        free( str );
                        frame = zmsg_next( msg );
                }
        }

        return rval;
}
peer_addr

Return the sending peer’s ipaddress as a string

static VALUE
rzyre_event_peer_addr( VALUE self ) {
        zyre_event_t *ptr = rzyre_get_event( self );
        const char *addr_str = zyre_event_peer_addr( ptr );

        if ( addr_str ) {
                return rb_str_new2( addr_str );
        } else {
                return Qnil;
        }

}
peer_name

Return the sending peer’s public name as a string

static VALUE
rzyre_event_peer_name( VALUE self ) {
        zyre_event_t *ptr = rzyre_get_event( self );
        const char *name_str = zyre_event_peer_name( ptr );

        return rb_str_new2( name_str );
}
peer_uuid → str

Return the sending peer’s uuid as a string

static VALUE
rzyre_event_peer_uuid( VALUE self ) {
        zyre_event_t *ptr = rzyre_get_event( self );
        const char *uuid_str = zyre_event_peer_uuid( ptr );

        return rb_str_new2( uuid_str );
}
print

Print event to zsys log

type → str

Returns event type as a Symbol. Possible values are: :ENTER, :EXIT, :JOIN, :LEAVE, :EVASIVE, :WHISPER, and :SHOUT and for the local node: :STOP

static VALUE
rzyre_event_type( VALUE self )
{
        zyre_event_t *ptr = rzyre_get_event( self );
        const char *type_str = zyre_event_type( ptr );
        const VALUE type = rb_str_new2( type_str );

        return rb_to_symbol( type );
}