3 /* stoken - simple/static token ring */
5 /* Copyright (c) 2005 Alexandre Colucci. */
6 /* Copyright (c) 2005 Martin Quinson. */
7 /* All rights reserved. */
9 /* This program is free software; you can redistribute it and/or modify it
10 * under the terms of the license (GNU LGPL) which comes with this package. */
15 /*#define NBLOOPS 30000*/
17 XBT_LOG_NEW_DEFAULT_CATEGORY(SimpleToken,"Messages specific to this example");
19 /* Function prototypes */
20 int node (int argc,char *argv[]);
23 /* **********************************************************************
25 * **********************************************************************/
27 /* Global private data */
29 gras_socket_t sock; /* server socket on which I hear */
30 int remaining_loop; /* number of loops to do until done */
31 int create; /* whether I have to create the token */
32 gras_socket_t tosuccessor; /* how to connect to the successor on ring */
36 /* Callback function */
37 static int node_cb_stoken_handler(gras_msg_cb_ctx_t ctx, void *payload) {
41 /* 1. Get the payload into the msg variable, and retrieve my caller */
42 int msg=*(int*)payload;
43 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
46 /* 2. Retrieve the node's state (globals) */
47 node_data_t *globals=(node_data_t*)gras_userdata_get();
49 /* 3. Log which predecessor connected */
50 int supersteps = 1; /* only log every superstep loop */
51 if (NBLOOPS >= 1000) {
53 } else if (NBLOOPS >= 100) {
55 } else if (NBLOOPS <=10) {
58 if (globals->create && (! (globals->remaining_loop % supersteps))) {
59 INFO1("Begin a new loop. Still to do: %d", globals->remaining_loop);
60 } else if (! (globals->remaining_loop % supersteps)) {
61 VERB3("Got token(%d) from %s remaining_loop=%d",
62 msg, gras_socket_peer_name(expeditor),globals->remaining_loop);
65 /* 4. If the right shouldn't be stopped yet */
66 if (globals->remaining_loop > 0) {
69 DEBUG3("Send token(%d) to %s:%d", msg,
70 gras_socket_peer_name(globals->tosuccessor),
71 gras_socket_peer_port(globals->tosuccessor));
73 /* 5. Send the token as payload of a stoken message to the successor */
75 gras_msg_send(globals->tosuccessor, "stoken", &msg);
77 /* 6. Deal with errors */
79 gras_socket_close(globals->sock);
80 RETHROW0("Unable to forward token: %s");
85 /* DO NOT CLOSE THE expeditor SOCKET since the client socket is
86 reused by our predecessor.
87 Closing this side would thus create troubles */
89 /* 7. Decrease the remaining_loop integer. */
90 globals->remaining_loop -= 1;
92 /* 8. Repport the hop number to the user at the end */
93 if (globals->remaining_loop == -1 && globals->create) {
94 INFO1("Shut down the token-ring. There was %d hops.",msg);
97 /* 9. Tell GRAS that we consummed this message */
99 } /* end_of_node_cb_stoken_handler */
101 int node (int argc,char *argv[]) {
102 node_data_t *globals;
110 /* 1. Init the GRAS infrastructure and declare my globals */
111 gras_init(&argc,argv);
112 globals=gras_userdata_new(node_data_t);
115 /* 2. Get the successor's address. The command line overrides
116 defaults when specified */
121 myport=atoi(argv[1]);
123 peerport=atoi(argv[3]);
126 /* 3. Save successor's address in global var */
127 globals->remaining_loop=NBLOOPS;
129 globals->tosuccessor = NULL;
131 if (!gras_os_getpid() % 100)
132 INFO4("Launch node %d (successor on %s:%d; listening on %d)",
133 gras_os_getpid(), host,peerport, myport);
135 /* 4. Create my master socket for listening */
136 globals->sock = gras_socket_server(myport);
137 gras_os_sleep(1.0); /* Make sure all server sockets are created */
139 /* 5. Create socket to the successor on the ring */
140 DEBUG2("Connect to my successor on %s:%d",host,peerport);
142 globals->tosuccessor = gras_socket_client(host,peerport);
144 /* 6. Register the known messages. */
145 gras_msgtype_declare("stoken", gras_datadesc_by_name("int"));
147 /* 7. Register my callback */
148 gras_cb_register("stoken",&node_cb_stoken_handler);
150 /* 8. One node has to create the token at startup.
151 It's specified by a command line argument */
152 if (argc >= 5 && !strncmp("--create-token", argv[4],strlen("--create-token")))
155 if (globals->create) {
158 globals->remaining_loop = NBLOOPS - 1;
160 INFO3("Create the token (with value %d) and send it to %s:%d",
161 token, host, peerport);
164 gras_msg_send(globals->tosuccessor, "stoken", &token);
166 RETHROW0("Unable to send the freshly created token: %s");
170 /* 8. Wait up to 10 seconds for an incomming message to handle */
171 while (globals->remaining_loop > (globals->create ? -1 : 0)) {
172 gras_msg_handle(10.0);
174 DEBUG1("looping (remaining_loop=%d)", globals->remaining_loop);
177 gras_os_sleep(1.0); /* FIXME: if the sender quited, receive fail */
179 /* 9. Free the allocated resources, and shut GRAS down */
180 gras_socket_close(globals->sock);
181 gras_socket_close(globals->tosuccessor);