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. */
17 XBT_LOG_NEW_DEFAULT_CATEGORY(Token,"Messages specific to this example");
19 /* register messages which may be sent */
20 static void register_messages(void) {
21 gras_msgtype_declare("stoken", gras_datadesc_by_name("int"));
24 /* Function prototypes */
25 int node (int argc,char *argv[]);
28 /* **********************************************************************
30 * **********************************************************************/
32 /* Global private data */
34 gras_socket_t sock; /* server socket on which I hear */
35 int remaining_loop; /* loop to do until done */
36 int create; /* I have to create the token */
37 gras_socket_t tosuccessor; /* how to connect to next peer on ring */
41 /* Callback function */
42 static int node_cb_stoken_handler(gras_socket_t expeditor,
47 /* 1. Get the payload into the msg variable */
48 int msg=*(int*)payload_data;
51 /* 2. Retrieve the node's state (globals) */
52 node_data_t *globals=(node_data_t*)gras_userdata_get();
54 /* 3. Log which predecessor connected */
56 if (NBLOOPS >= 1000) {
58 } else if (NBLOOPS > 100) {
61 if (globals->create && (! (globals->remaining_loop % supersteps))) {
62 INFO1("Begin a new loop. Still to do: %d", globals->remaining_loop);
63 } else if (! (globals->remaining_loop % supersteps)) {
64 VERB3("Got token(%d) from %s remaining_loop=%d",
65 msg, gras_socket_peer_name(expeditor),globals->remaining_loop);
68 if (globals->remaining_loop > 0) {
72 /* 5. I forward it to my successor */
73 DEBUG3("Send token(%d) to %s:%d",
75 gras_socket_peer_name(globals->tosuccessor),
76 gras_socket_peer_port(globals->tosuccessor));
79 /* 6. Send it as payload of a stoken message to the successor */
80 errcode = gras_msg_send(globals->tosuccessor,
81 gras_msgtype_by_name("stoken"), &msg);
83 /* 7. Deal with errors */
84 if (errcode != no_error) {
85 ERROR1("Unable to forward token: %s\n", xbt_error_name(errcode));
86 gras_socket_close(globals->sock);
92 /* DO NOT CLOSE THE expeditor SOCKET since the client socket is
93 reused by our predecessor.
94 Closing this side would thus create troubles */
96 /* 9. Decrease the remaining_loop integer. */
97 globals->remaining_loop -= 1;
99 /* 10. Repport the hop number to the user at the end */
100 if (globals->remaining_loop == -1 && globals->create) {
101 INFO1("Shut down the token-ring. There was %d hops.",msg);
104 /* 11. Tell GRAS that we consummed this message */
106 } /* end_of_node_cb_stoken_handler */
109 int node (int argc,char *argv[]) {
111 node_data_t *globals;
114 /* 1. Init the GRAS infrastructure and declare my globals */
115 gras_init(&argc,argv);
116 globals=gras_userdata_new(node_data_t);
119 /* 2. Get the successor's address. The command line overrides
120 defaults when specified */
121 const char *host = "127.0.0.1";
125 myport=atoi(argv[1]);
127 peerport=atoi(argv[3]);
130 /* 3. Save successor's address in global var */
131 globals->remaining_loop=NBLOOPS;
133 globals->tosuccessor = NULL;
135 INFO4("Launch node %d (successor on %s:%d; listening on %d)",
136 gras_os_getpid(), host,peerport, myport);
138 /* 4. Create my master socket for listening */
139 if ((errcode=gras_socket_server(myport,&(globals->sock)))) {
140 CRITICAL1("Error %s encountered while opening the server socket. Bailing out.",
141 xbt_error_name(errcode));
144 gras_os_sleep(1.0); /* Make sure all server sockets are created */
147 /* 5. Create socket to the successor on the ring */
148 DEBUG2("Connect to my successor on %s:%d",host,peerport);
150 if ((errcode=gras_socket_client(host,peerport,
151 &(globals->tosuccessor)))) {
152 ERROR1("Unable to connect to the node (got %s). Bailing out.",
153 xbt_error_name(errcode));
158 /* 6. Register the known messages. This function is called twice here,
159 but it's because this file also acts as regression test.
160 No need to do so yourself of course. */
162 register_messages(); /* just to make sure it works ;) */
164 /* 7. Register my callback */
165 gras_cb_register(gras_msgtype_by_name("stoken"),&node_cb_stoken_handler);
168 /* 8. One node has to create the token at startup.
169 It's specified by a command line argument */
170 if (argc >= 5 && !strncmp("--create-token", argv[4],strlen(argv[4])))
173 if (globals->create) {
176 globals->remaining_loop = NBLOOPS - 1;
178 INFO3("Create the token (with value %d) and send it to %s:%d",
179 token, host, peerport);
181 errcode = gras_msg_send(globals->tosuccessor,
182 gras_msgtype_by_name("stoken"), &token);
184 if (errcode != no_error) {
185 fprintf(stderr, "Unable send 'stoken' to successor (%s)\n",
186 xbt_error_name(errcode));
191 /* 8. Wait up to 10 seconds for an incomming message to handle */
192 while (globals->remaining_loop > (globals->create ? -1 : 0)) {
193 errcode = gras_msg_handle(10.0);
195 /* 9. Housekeeping */
196 if (errcode != no_error) {
197 ERROR1("Got error %s in msg_handle", xbt_error_name(errcode));
201 DEBUG1("looping (remaining_loop=%d)", globals->remaining_loop);
204 gras_os_sleep(1.0); /* FIXME: if the sender quited, receive fail */
206 /* 9. Free the allocated resources, and shut GRAS down */
207 gras_socket_close(globals->sock);
208 gras_socket_close(globals->tosuccessor);