Exemplo n.º 1
0
static int
s_recv_from_zyre (s_agent_t *self)
{
    zyre_event_t *event = zyre_event_new (self->zyre);
    if (zyre_event_type (event) == ZYRE_EVENT_SHOUT
    && streq (zyre_event_group (event), "DROPS")) {
        zmsg_t *msg = zyre_event_msg (event);
        char *operation = zmsg_popstr (msg);
        
        if (streq (operation, "CREATE")) {
            char *filename = zmsg_popstr (msg);
            zframe_t *frame = zmsg_pop (msg);
            zfile_t *file = zfile_new (self->path, filename);
            zfile_output (file);
            fwrite (zframe_data (frame), 1, zframe_size (frame), zfile_handle (file));
            zfile_destroy (&file);
            zframe_destroy (&frame);
            zstr_send (self->pipe, filename);
            free (filename);
        }
        free (operation);
    }
    zyre_event_destroy (&event);
    return 0;
}
Exemplo n.º 2
0
void
zyre_event_test (bool verbose)
{
    printf (" * zyre_event: ");

    //  @selftest
    //  Create two nodes
    zyre_t *node1 = zyre_new ("node1");
    assert (node1);
    zyre_set_header (node1, "X-HELLO", "World");
    zyre_set_verbose (node1);
    if (zyre_start (node1)) {
        zyre_destroy (&node1);
        printf ("OK (skipping test, no UDP discovery)\n");
        return;
    }
    zyre_join (node1, "GLOBAL");
    
    zyre_t *node2 = zyre_new ("node2");
    assert (node2);
    zyre_set_verbose (node2);
    int rc = zyre_start (node2);
    assert (rc == 0);
    zyre_join (node2, "GLOBAL");
    
    //  Give time for them to interconnect
    zclock_sleep (250);

    //  One node shouts to GLOBAL
    zmsg_t *msg = zmsg_new ();
    zmsg_addstr (msg, "Hello, World");
    zyre_shout (node1, "GLOBAL", &msg);
    zclock_sleep (100);

    //  Parse ENTER
    zyre_event_t *event = zyre_event_new (node2);
    assert (zyre_event_type (event) == ZYRE_EVENT_ENTER);
    char *sender = zyre_event_sender (event);
    assert (sender);
    char *name = zyre_event_name (event);
    assert (name);
    assert (streq (name, "node1"));
    char *address = zyre_event_address (event);
    assert (address);
    char *header = zyre_event_header (event, "X-HELLO");
    assert (header);
    zyre_event_destroy (&event);
    
    //  Parse JOIN
    event = zyre_event_new (node2);
    assert (zyre_event_type (event) == ZYRE_EVENT_JOIN);
    zyre_event_destroy (&event);
    
    //  Parse SHOUT
    event = zyre_event_new (node2);
    assert (zyre_event_type (event) == ZYRE_EVENT_SHOUT);
    assert (streq (zyre_event_group (event), "GLOBAL"));
    msg = zyre_event_msg (event);
    char *string = zmsg_popstr (msg);
    assert (streq (string, "Hello, World"));
    free (string);
    zyre_event_destroy (&event);
    
    zyre_destroy (&node1);
    zyre_destroy (&node2);
    //  @end
    printf ("OK\n");
}
Exemplo n.º 3
0
int main() {

    if (!getenv("ENDPOINT")) {
        fprintf (stderr, "variable ENDPOINT must be declared\n");
        exit (EXIT_FAILURE);
    }

    char *endpoint = strdup(getenv("ENDPOINT"));

    //1. start malamute
    zactor_t *broker = s_broker(endpoint);

    //2. shout about it through zyre
    zyre_t *node = zyre_new (getenv("USER"));
    assert (node);
    char * UUID = strdup (zyre_uuid (node));
    zsys_info ("UUID: %s", UUID);
    bool to_shout = true;

    //zyre_set_verbose (node);
    zyre_start (node);
    zyre_join (node, "MALAMUTE");

    zpoller_t *poller = zpoller_new(zyre_socket (node), NULL);

    time_t last_leader_shout;

    // 3. get the comments
    while (!zsys_interrupted) {

        zsock_t *which = zpoller_wait(poller, 1000);

        if (time(NULL) - last_leader_shout > 5) {
            to_shout = true;
            zstr_free (&UUID);
            UUID = strdup (zyre_uuid (node));
            zstr_free (&endpoint);
            endpoint = strdup (getenv("ENDPOINT"));
            zactor_destroy (&broker);
            broker = s_broker (endpoint);
        }

        if (!which && to_shout) {
            zyre_shouts (node, "MALAMUTE", "%s", endpoint);
            continue;
        }

        zyre_event_t *event = zyre_event_new (node);
        if (!event)
            continue;

        switch (zyre_event_type (event)) {
            case ZYRE_EVENT_SHOUT:
                {
                int r = strcmp (UUID, zyre_event_sender (event));
                if (!r)
                    last_leader_shout = time(NULL);
                if (r >= 0)
                    goto event_destroy;

                zsys_debug ("UUID: %s, sender: %s, strcmp: %d",
                        UUID,
                        zyre_event_sender (event),
                        r
                        );

                to_shout = false;
                zstr_free (&UUID);
                UUID = strdup (zyre_event_sender (event));
                zstr_free (&endpoint);
                zmsg_t *msg = zyre_event_msg (event);
                endpoint = strdup (zmsg_popstr(msg));

                zactor_destroy (&broker);
                broker = s_broker (endpoint);
                zclock_sleep(1000);

                break;
                }

        }

event_destroy:
        zyre_event_destroy (&event);
    }

    zpoller_destroy (&poller);
    zstr_free (&UUID);
    zstr_free (&endpoint);
    zyre_destroy (&node);
    zactor_destroy (&broker);
}
Exemplo n.º 4
0
///
//  Returns the incoming message payload; the caller can modify the
//  message but does not own it and should not destroy it.         
QZmsg * QZyreEvent::msg ()
{
    QZmsg *rv = new QZmsg (zyre_event_msg (self));
    return rv;
}
Exemplo n.º 5
0
///
//  Returns the incoming message payload (currently one frame)
zmsg_t *QmlZyreEvent::msg () {
    return zyre_event_msg (self);
};
Exemplo n.º 6
0
 zmsg_t* message() const
 {
     return zyre_event_msg(m_self);
 }
Exemplo n.º 7
0
void
ztask_monitor_api_loop (ztask_monitor_api_t *self)
{
	zyre_t *node = zyre_new();
	zyre_set_header(node, "X-ZTASK-MON", "TASK MON");
	zyre_start(node);
	zyre_dump(node);
	if (self->pub_port >= 0)
		zclock_log("Publisher is listening on port %d ...", self->pub_port);

	zpoller_t *poller = zpoller_new (zyre_socket (node), NULL);

	uint64_t reap_at = zclock_time () + self->pub_timeout;

	zyre_event_t *event;
	while (!zsys_interrupted) {
        void *which = zpoller_wait (poller, self->pub_timeout);
        if (zpoller_terminated (poller)) {
            break;
        }
		if (which == zyre_socket (node)) {
			event = zyre_event_new(node);
			if (!event)
				break;
			if (zyre_event_type(event) == ZYRE_EVENT_ENTER) {
			}
			else
			if (zyre_event_type(event) == ZYRE_EVENT_EXIT) {
				char *data = (char *) zhash_lookup(self->nodes,
						(const char *) zyre_event_sender(event));
				if (data) {
					zhash_delete(self->nodes,
							(const char *) zyre_event_sender(event));
					free(data);
				}

			}
			else
			if (zyre_event_type(event) == ZYRE_EVENT_WHISPER) {
				zmsg_t *msg = zyre_event_msg(event);
				char *cpu_str = zmsg_popstr(msg);
				char *mem_rss_str = zmsg_popstr(msg);
				if (self->pub_sock) {
					char *data = (char *) zhash_lookup(self->nodes,
							(const char *) zyre_event_sender(event));
					if (data) {
						zhash_delete(self->nodes,
								(const char *) zyre_event_sender(event));
						free(data);
					}
					if (asprintf(&data, "{\"id\":\"%s\",%s,%s}",
							zyre_event_sender(event), cpu_str, mem_rss_str) < 0)
				        data = NULL;
					zhash_insert(self->nodes,
							(const char *) zyre_event_sender(event), data);

				}
				else {
					zclock_log("From %s", zyre_event_sender(event));
					zclock_log("     %s", cpu_str);
					zclock_log("     %s", mem_rss_str);
				}
				free(cpu_str);
				free(mem_rss_str);
			}
			zyre_event_destroy(&event);
		}

		if (zclock_time() >= reap_at) {
			reap_at = zclock_time() + self->pub_timeout;

			if (self->pub_sock) {
				char *data = ztask_monitor_api_json (self);
				if (data) {
					zmsg_t *msg = zmsg_new();
					zmsg_addstr(msg, data);
					zclock_log("Sending %s ...", data);
					zmsg_send(&msg, self->pub_sock);
					free(data);
				}
			}
		}

	}

	zyre_stop(node);
	zpoller_destroy (&poller);
	zyre_destroy(&node);

	//  Cleanup of self->nodes
//	char *wk = (char *) zhash_first (self->nodes);
//	while (wk) {
//		zhash_delete (self->nodes, wk);
////		free (data);
//		wk = (char *) zhash_first (self->nodes);
//	}
}
Exemplo n.º 8
0
JNIEXPORT jlong JNICALL
Java_org_zeromq_zyre_ZyreEvent__1_1msg (JNIEnv *env, jclass c, jlong self)
{
    jlong msg_ = (jlong) zyre_event_msg ((zyre_event_t *) self);
    return msg_;
}
Exemplo n.º 9
0
void
ztask_run_manager_loop (ztask_run_manager_t *self)
{
    assert (self);

    if (!self->packetizer) {
        zclock_log ("E: No packetizer set !!!");
        return;
    }

    //  Setting network interface if neede
    if (self->node_interface)
        zyre_set_interface(self->node, self->node_interface);

    zyre_set_header (self->node, "X-ZTASK-RUN", "ZTASK RUN");

    zyre_start (self->node);
    zyre_dump (self->node);
    zclock_sleep (10);
//    ztask_packetizer_dump (self->packetizer);

    ztask_packet_t *packet;
    int request_sent = 0;
    zyre_event_t *event;
    while (!zsys_interrupted) {

        if (ztask_packetizer_is_finished (self->packetizer))
            break;

        event = zyre_event_new (self->node);
        if (!event)
            break;
        if (zyre_event_type (event) == ZYRE_EVENT_ENTER) {
            //  Ignoring nodes which don't have service X-ZTASK-NODE defined
            if (zyre_event_header (event, "X-ZTASK-NODE")) {
                zhash_insert (self->nodes, zyre_event_sender (event),"");
                ztask_log_debug (self->log, "Adding node -> workers=%ld", zhash_size (self->nodes));
            } else {
                //  TODO disconnect worker (zyre peer) somehow
            }
        }
        else
        if (zyre_event_type (event) == ZYRE_EVENT_EXIT) {
            if (zhash_lookup (self->nodes, zyre_event_sender (event))) {
                ztask_log_debug (self->log, "Removing node -> workers=%ld", zhash_size (self->nodes));
                zhash_delete (self->nodes, zyre_event_sender (event));
                //  Cleanup packetizer in case ztask_node was killed
                request_sent -= ztask_packetizer_running_node_cleanup (self->packetizer, zyre_event_sender (event));
            }
        }
        else
        if (zyre_event_type (event) == ZYRE_EVENT_WHISPER) {

            //  Ingoring whispers when they are not from our nodes
            if (!zhash_lookup(self->nodes, zyre_event_sender (event))) {
                ztask_log_warning (self->log, "W: Ingoring whisper from %s", zyre_event_sender (event));
                zyre_event_destroy (&event);
                continue;
            }
            zmsg_t *msg_report = zyre_event_msg(event);
            char *str_msg = zmsg_popstr (msg_report);
            if (streq(str_msg, "REQUEST")) {
                //  Let's handle request
                packet = ztask_packetizer_next_packet (self->packetizer);
                if (packet) {
                    char *cmd;
                    if ( asprintf (&cmd, "%s", ztask_packet_cmd (packet)) < 0)
                         cmd = NULL;
                    assert (cmd);
                    zmsg_t *msg = zmsg_new ();
                    zmsg_addstr (msg, "REQUEST");
                    zmsg_addstrf (msg, "%s_%ld", zyre_uuid (self->node), ztask_packet_id (packet));
                    zmsg_addstr (msg, cmd);
                    zyre_whisper (self->node, zyre_event_sender (event), &msg);
                    ztask_packet_set_node (packet, zyre_event_sender (event));
                    request_sent++;
                    ztask_packetizer_info (self->packetizer, request_sent);
                    ztask_log_debug (self->log, "ID=%s_%ld cmd='%s' running=%d", zyre_uuid (self->node), ztask_packet_id (packet), cmd, request_sent);
                    free (cmd);
                }
                else {
                    zmsg_t *msg = zmsg_new ();
                    zmsg_addstr (msg, "NO_PACKETS");
                    zyre_whisper (self->node, zyre_event_sender (event), &msg);
                }

            }
            else
            if (streq(str_msg, "REPORT")) {
                //  It's report
                char *str_id = zmsg_popstr (msg_report);
                char *str_pid_rc = zmsg_popstr (msg_report);

                ztask_log_debug (self->log, "REPORT ID=%s rc=%s", str_id, str_pid_rc);
                ztask_packetizer_report (self->packetizer, str_id, str_pid_rc);
                request_sent--;
                ztask_packetizer_info (self->packetizer, request_sent);
                free (str_id);
                free (str_pid_rc);
            }
            else {
                ztask_log_error (self->log, "E: ztask_run_manager_loop : Wrong message %s", str_msg);
                assert (false);
            }
            free (str_msg);
        }

        zyre_event_destroy (&event);
    }

    //  FIXME : simplify zhash_foreach()
    zlist_t *keys = zhash_keys (self->nodes);
    char *key = (char *) zlist_first (keys);
    while (key) {
        zmsg_t *msg = zmsg_new ();
        zmsg_addstr (msg, "END");
        zyre_whisper (self->node, key, &msg);
        key = (char *) zlist_next (keys);
    }
    zlist_destroy (&keys);

    // wait for shout to be delivered
    zclock_sleep (100);

    ztask_packetizer_summary(self->packetizer, 0);

    zyre_stop (self->node);
}
Exemplo n.º 10
0
int main (int argc, char *argv [])
{
    int argn = 1;
    if (argn == argc
    ||  streq (argv [argn], "-h") || streq (argv [argn], "--help")) {
        puts ("midicast [-v] [-p port] [-i interface]");
        puts ("Reads MIDI events from port and sends to Zyre MIDI group");
        puts (" -h, --help: this help");
        puts (" -v, --verbose: trace events as they happen");
        puts (" -p, --port: specify port name, e.g. '-p hw:1,0,0'");
        puts (" -i, --interface: specify WiFi interface, e.g. '-i wlan0'");
        return 0;
    }
    char *midi_port_name = "hw:2,0";
    char *wifi_interface = NULL;
    bool verbose = false;
    while (argn < argc) {
        if (streq (argv [argn], "-p") || streq (argv [argn], "--port"))
            midi_port_name = argv [++argn];
        else
        if (streq (argv [argn], "-i") || streq (argv [argn], "--interface"))
            wifi_interface = argv [++argn];
        else
        if (streq (argv [argn], "-v") || streq (argv [argn], "--verbose"))
            verbose = true;
        argn++;
    }

    snd_rawmidi_t *output;
    int rc = snd_rawmidi_open (NULL, &output, midi_port_name, SND_RAWMIDI_SYNC);
    if (rc < 0) {
        zsys_error ("cannot open port \"%s\": %s", midi_port_name, snd_strerror (rc));
        return 0;
    }
    zsys_info ("forwarding MIDI cast to %s", midi_port_name);

    zyre_t *zyre = zyre_new (NULL);
    if (wifi_interface)
        zyre_set_interface (zyre, wifi_interface);
    zyre_start (zyre);
    zyre_join (zyre, "MIDI");
    zsys_info ("this player is %s", zyre_name (zyre));

    while (!zsys_interrupted) {
        zyre_event_t *event = zyre_event_new (zyre);
        if (!event) {
            printf (" interrupted\n");
            break;
        }
        if (zyre_event_type (event) == ZYRE_EVENT_JOIN)
            zsys_info ("[%s] player joined", zyre_event_peer_name (event));
        else
        if (zyre_event_type (event) == ZYRE_EVENT_LEAVE)
            zsys_info ("[%s] player left", zyre_event_peer_name (event));
        else
        if (zyre_event_type (event) == ZYRE_EVENT_SHOUT) {
            if (streq (zyre_event_group (event), "MIDI")) {
                zframe_t *frame = zmsg_first (zyre_event_msg (event));
                //  Forward the MIDI event
                snd_rawmidi_write (output, zframe_data (frame), zframe_size (frame));

                if (verbose) {
                    printf ("%zd:", zframe_size (frame));
                    int byte_nbr;
                    for (byte_nbr = 0; byte_nbr < zframe_size (frame); byte_nbr++)
                        printf (" %02X", zframe_data (frame) [byte_nbr]);
                    printf ("\n");
                }
            }
        }
        zyre_event_destroy (&event);
    }
    snd_rawmidi_close (output);
    zyre_destroy (&zyre);
	return 0;
}
Exemplo n.º 11
0
static void
zsync_node_recv_from_zyre (zsync_node_t *self)
{
    zsync_peer_t *sender;
    char *zyre_sender;
    zuuid_t *sender_uuid;
    zmsg_t *zyre_in, *zyre_out, *fm_msg;
    zlist_t *fpaths, *fmetadata;
    
    zyre_event_t *event = zyre_event_recv (self->zyre);
    zyre_sender = zyre_event_sender (event); // get tmp uuid

    switch (zyre_event_type (event)) {
        case ZYRE_EVENT_ENTER:
            printf("[ND] ZS_ENTER: %s\n", zyre_sender);
            zhash_insert (self->zyre_peers, zyre_sender, NULL);
            break;        
        case ZYRE_EVENT_JOIN:
            printf ("[ND] ZS_JOIN: %s\n", zyre_sender);
            //  Obtain own current state
            zsync_msg_send_req_state (self->zsync_pipe);
            zsync_msg_t *msg_state = zsync_msg_recv (self->zsync_pipe);
            assert (zsync_msg_id (msg_state) == ZSYNC_MSG_RES_STATE);
            uint64_t state = zsync_msg_state (msg_state); 
            //  Send GREET message
            zyre_out = zmsg_new ();
            zs_msg_pack_greet (zyre_out, zuuid_data (self->own_uuid), state);
            zyre_whisper (self->zyre, zyre_sender, &zyre_out);
            break;
        case ZYRE_EVENT_LEAVE:
            break;
        case ZYRE_EVENT_EXIT:
            /*
            printf("[ND] ZS_EXIT %s left the house!\n", zyre_sender);
            sender = zhash_lookup (self->zyre_peers, zyre_sender);
            if (sender) {
                // Reset Managers
                zmsg_t *reset_msg = zmsg_new ();
                zmsg_addstr (reset_msg, zsync_peer_uuid (sender));
                zmsg_addstr (reset_msg, "ABORT");
                zmsg_send (&reset_msg, self->file_pipe);
                reset_msg = zmsg_new ();
                zmsg_addstr (reset_msg, zsync_peer_uuid (sender));
                zmsg_addstr (reset_msg, "ABORT");
                zmsg_send (&reset_msg, self->credit_pipe);
                // Remove Peer from active list
                zhash_delete (self->zyre_peers, zyre_sender);
            }*/
            break;
        case ZYRE_EVENT_WHISPER:
        case ZYRE_EVENT_SHOUT:
            printf ("[ND] ZS_WHISPER: %s\n", zyre_sender);
            sender = zhash_lookup (self->zyre_peers, zyre_sender);
            zyre_in = zyre_event_msg (event);
            zs_msg_t *msg = zs_msg_unpack (zyre_in);
            switch (zs_msg_get_cmd (msg)) {
                case ZS_CMD_GREET:
                    // Get perm uuid
                    sender_uuid = zuuid_new ();
                    zuuid_set (sender_uuid, zs_msg_uuid (msg));
                    sender = zsync_node_peers_lookup (self, zuuid_str (sender_uuid));
                    if (!sender) {
                        sender = zsync_peer_new (zuuid_str (sender_uuid), 0x0);
                        zlist_append (self->peers, sender);
                    } 
                    assert (sender);
                    zhash_update (self->zyre_peers, zyre_sender, sender);
                    zsync_peer_set_zyre_state (sender, ZYRE_EVENT_JOIN);
                    // Get current state for sender
                    uint64_t remote_current_state = zs_msg_get_state (msg);
                    printf ("[ND] current state: %"PRId64"\n", remote_current_state);
                    // Lookup last known state
                    uint64_t last_state_local = zsync_peer_state (sender);
                    printf ("[ND] last known state: %"PRId64"\n", zsync_peer_state (sender));
                    // Send LAST_STATE if differs 
                    if (remote_current_state >= last_state_local) {
                        zmsg_t *lmsg = zmsg_new ();
                        zs_msg_pack_last_state (lmsg, last_state_local);
                        zyre_whisper (self->zyre, zyre_sender, &lmsg);
                    }  
                    break;
                case ZS_CMD_LAST_STATE:
                    assert (sender);
                    zyre_out = zmsg_new ();
                    //  Gets updates from client
                    uint64_t last_state_remote = zs_msg_get_state (msg);
                    zsync_msg_send_req_update (self->zsync_pipe, last_state_remote);
                    zsync_msg_t *msg_upd = zsync_msg_recv (self->zsync_pipe);
                    assert (zsync_msg_id (msg_upd) == ZSYNC_MSG_UPDATE);
                    //  Send UPDATE
                    zyre_out = zsync_msg_update_msg (msg_upd);
                    zyre_whisper (self->zyre, zyre_sender, &zyre_out);
                    break;
                case ZS_CMD_UPDATE:
                    printf ("[ND] UPDATE\n");
                    assert (sender);
                    uint64_t state = zs_msg_get_state (msg);
                    zsync_peer_set_state (sender, state); 
                    zsync_node_save_peers (self);

                    fmetadata = zs_msg_get_fmetadata (msg);
                    zmsg_t *zsync_msg = zmsg_new ();
                    zs_msg_pack_update (zsync_msg, zs_msg_get_state (msg), fmetadata);
                    
                    zsync_msg_send_update (self->zsync_pipe, zsync_peer_uuid (sender), zsync_msg);
                    break;
                case ZS_CMD_REQUEST_FILES:
                    printf ("[ND] REQUEST FILES\n");
                    fpaths = zs_msg_fpaths (msg);
                    zmsg_t *fm_msg = zmsg_new ();
                    zmsg_addstr (fm_msg, zsync_peer_uuid (sender));
                    zmsg_addstr (fm_msg, "REQUEST");
                    char *fpath = zs_msg_fpaths_first (msg);
                    while (fpath) {
                        zmsg_addstr (fm_msg, fpath);
                        printf("[ND] %s\n", fpath);
                        fpath = zs_msg_fpaths_next (msg);
                    }
                    zmsg_send (&fm_msg, self->file_pipe);
                    break;
                case ZS_CMD_GIVE_CREDIT:
                    printf("[ND] GIVE CREDIT\n");
                    fm_msg = zmsg_new ();
                    zmsg_addstr (fm_msg, zsync_peer_uuid (sender));
                    zmsg_addstr (fm_msg, "CREDIT");
                    zmsg_addstrf (fm_msg, "%"PRId64, zs_msg_get_credit (msg));
                    zmsg_send (&fm_msg, self->file_pipe);
                    break;
                case ZS_CMD_SEND_CHUNK:
                    printf("[ND] SEND_CHUNK (RCV)\n");
                    // Send receival to credit manager
                    zframe_t *zframe = zs_msg_get_chunk (msg);
                    uint64_t chunk_size = zframe_size (zframe);
                    zsync_credit_msg_send_update (self->credit_pipe, zsync_peer_uuid (sender), chunk_size);
                    // Pass chunk to client
                    byte *data = zframe_data (zframe);
                    zchunk_t *chunk = zchunk_new (data, chunk_size);
                    char *path = zs_msg_get_file_path (msg);
                    uint64_t seq = zs_msg_get_sequence (msg);
                    uint64_t off = zs_msg_get_offset (msg);
                    zsync_msg_send_chunk (self->zsync_pipe, chunk, path, seq, off);
                    break;
                case ZS_CMD_ABORT:
                    // TODO abort protocol managed file transfer
                    printf("[ND] ABORT\n");
                    break;
                default:
                    assert (false);
                    break;
            }
            
            zs_msg_destroy (&msg);
            break;
        default:
            printf("[ND] Error command not found\n");
            break;
    }
    zyre_event_destroy (&event);
}
Exemplo n.º 12
0
 zmsg_t* message() const {
   return zyre_event_msg(e_);
 }