1 /* stoken - simple/static token ring */
3 /* Copyright (c) 2005 Alexandre Colucci. */
4 /* Copyright (c) 2005 Martin Quinson. */
5 /* All rights reserved. */
7 /* This program is free software; you can redistribute it and/or modify it
8 * under the terms of the license (GNU LGPL) which comes with this package. */
13 /*#define NBLOOPS 30000*/
15 XBT_LOG_NEW_DEFAULT_CATEGORY(SimpleToken,
16 "Messages specific to this example");
18 /* Function prototypes */
19 int node(int argc, char *argv[]);
22 /* **********************************************************************
24 * **********************************************************************/
26 /* Global private data */
28 gras_socket_t sock; /* server socket on which I hear */
29 int remaining_loop; /* number of loops to do until done */
30 int create; /* whether I have to create the token */
31 gras_socket_t tosuccessor; /* how to connect to the successor on ring */
32 double start_time; /* to measure the elapsed time. Only used by the
33 node that creates the token */
37 /* Callback function */
38 static int node_cb_stoken_handler(gras_msg_cb_ctx_t ctx, void *payload)
43 /* 1. Get the payload into the msg variable, and retrieve my caller */
44 int msg = *(int *) payload;
45 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
48 /* 2. Retrieve the node's state (globals) */
49 node_data_t *globals = (node_data_t *) gras_userdata_get();
51 /* 3. Log which predecessor connected */
52 int supersteps = 1; /* only log every superstep loop */
53 if (NBLOOPS >= 1000) {
55 } else if (NBLOOPS >= 100) {
57 } else if (NBLOOPS <= 10) {
60 if (globals->create && (!(globals->remaining_loop % supersteps))) {
61 INFO1("Begin a new loop. Still to do: %d", globals->remaining_loop);
62 } else if (!(globals->remaining_loop % supersteps)) {
63 VERB3("Got token(%d) from %s remaining_loop=%d",
64 msg, gras_socket_peer_name(expeditor), globals->remaining_loop);
67 /* 4. If the right shouldn't be stopped yet */
68 if (globals->remaining_loop > 0) {
71 DEBUG3("Send token(%d) to %s:%d", msg,
72 gras_socket_peer_name(globals->tosuccessor),
73 gras_socket_peer_port(globals->tosuccessor));
75 /* 5. Send the token as payload of a stoken message to the successor */
77 gras_msg_send(globals->tosuccessor, "stoken", &msg);
79 /* 6. Deal with errors */
82 gras_socket_close(globals->sock);
83 RETHROW0("Unable to forward token: %s");
88 /* DO NOT CLOSE THE expeditor SOCKET since the client socket is
89 reused by our predecessor.
90 Closing this side would thus create troubles */
92 /* 7. Decrease the remaining_loop integer. */
93 globals->remaining_loop -= 1;
95 /* 8. Repport the hop number to the user at the end */
96 if (globals->remaining_loop == -1 && globals->create) {
97 double elapsed = gras_os_time() - globals->start_time;
98 INFO1("Shut down the token-ring. There was %d hops.", msg);
99 VERB1("Elapsed time: %g", elapsed);
102 /* 9. Tell GRAS that we consummed this message */
104 } /* end_of_node_cb_stoken_handler */
106 int node(int argc, char *argv[])
108 node_data_t *globals;
116 /* 1. Init the GRAS infrastructure and declare my globals */
117 gras_init(&argc, argv);
118 globals = gras_userdata_new(node_data_t);
121 /* 2. Get the successor's address. The command line overrides
122 defaults when specified */
127 myport = atoi(argv[1]);
129 peerport = atoi(argv[3]);
132 /* 3. Save successor's address in global var */
133 globals->remaining_loop = NBLOOPS;
135 globals->tosuccessor = NULL;
137 if (!gras_os_getpid() % 100 || gras_if_RL())
138 INFO3("Launch node listening on %d (successor on %s:%d)",
139 myport, host, peerport);
141 /* 4. Register the known messages. */
142 gras_msgtype_declare("stoken", gras_datadesc_by_name("int"));
144 /* 5. Create my master socket for listening */
145 globals->sock = gras_socket_server(myport);
146 gras_os_sleep(1.0); /* Make sure all server sockets are created */
148 /* 6. Create socket to the successor on the ring */
149 DEBUG2("Connect to my successor on %s:%d", host, peerport);
151 globals->tosuccessor = gras_socket_client(host, peerport);
153 /* 7. Register my callback */
154 gras_cb_register("stoken", &node_cb_stoken_handler);
156 /* 8. One node has to create the token at startup.
157 It's specified by a command line argument */
159 && !strncmp("--create-token", argv[4], strlen("--create-token")))
162 if (globals->create) {
165 globals->start_time = gras_os_time();
167 globals->remaining_loop = NBLOOPS - 1;
169 INFO3("Create the token (with value %d) and send it to %s:%d",
170 token, host, peerport);
173 gras_msg_send(globals->tosuccessor, "stoken", &token);
175 RETHROW0("Unable to send the freshly created token: %s");
179 /* 8. Wait up to 10 seconds for an incomming message to handle */
180 while (globals->remaining_loop > (globals->create ? -1 : 0)) {
183 DEBUG1("looping (remaining_loop=%d)", globals->remaining_loop);
186 gras_os_sleep(1.0); /* FIXME: if the sender quited, receive fail */
188 /* 9. Free the allocated resources, and shut GRAS down */
189 gras_socket_close(globals->sock);
190 gras_socket_close(globals->tosuccessor);