Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Correct tesh files after patch time commit.
[simgrid.git] / examples / gras / mutual_exclusion / simple_token / simple_token.c
1 /* $Id$ */
2
3 /* stoken - simple/static token ring                                        */
4
5 /* Copyright (c) 2005 Alexandre Colucci.                                    */
6 /* Copyright (c) 2005 Martin Quinson.                                       */
7 /* All rights reserved.                                                     */
8
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. */
11
12 #include "gras.h"
13
14 #define NBLOOPS 3
15 /*#define NBLOOPS 30000*/
16
17 XBT_LOG_NEW_DEFAULT_CATEGORY(SimpleToken,
18                              "Messages specific to this example");
19
20 /* Function prototypes */
21 int node(int argc, char *argv[]);
22
23
24 /* **********************************************************************
25  * Node code
26  * **********************************************************************/
27
28 /* Global private data */
29 typedef struct {
30   gras_socket_t sock;           /* server socket on which I hear */
31   int remaining_loop;           /* number of loops to do until done */
32   int create;                   /* whether I have to create the token */
33   gras_socket_t tosuccessor;    /* how to connect to the successor on ring */
34   double start_time;            /* to measure the elapsed time. Only used by the 
35                                    node that creates the token */
36 } node_data_t;
37
38
39 /* Callback function */
40 static int node_cb_stoken_handler(gras_msg_cb_ctx_t ctx, void *payload)
41 {
42
43   xbt_ex_t e;
44
45   /* 1. Get the payload into the msg variable, and retrieve my caller */
46   int msg = *(int *) payload;
47   gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
48
49
50   /* 2. Retrieve the node's state (globals) */
51   node_data_t *globals = (node_data_t *) gras_userdata_get();
52
53   /* 3. Log which predecessor connected */
54   int supersteps = 1;           /* only log every superstep loop */
55   if (NBLOOPS >= 1000) {
56     supersteps = 100;
57   } else if (NBLOOPS >= 100) {
58     supersteps = 10;
59   } else if (NBLOOPS <= 10) {
60     supersteps = 1;
61   }
62   if (globals->create && (!(globals->remaining_loop % supersteps))) {
63     INFO1("Begin a new loop. Still to do: %d", globals->remaining_loop);
64   } else if (!(globals->remaining_loop % supersteps)) {
65     VERB3("Got token(%d) from %s remaining_loop=%d",
66           msg, gras_socket_peer_name(expeditor), globals->remaining_loop);
67   }
68
69   /* 4. If the right shouldn't be stopped yet */
70   if (globals->remaining_loop > 0) {
71     msg += 1;
72
73     DEBUG3("Send token(%d) to %s:%d", msg,
74            gras_socket_peer_name(globals->tosuccessor),
75            gras_socket_peer_port(globals->tosuccessor));
76
77     /* 5. Send the token as payload of a stoken message to the successor */
78     TRY {
79       gras_msg_send(globals->tosuccessor, "stoken", &msg);
80
81       /* 6. Deal with errors */
82     }
83     CATCH(e) {
84       gras_socket_close(globals->sock);
85       RETHROW0("Unable to forward token: %s");
86     }
87
88   }
89
90   /* DO NOT CLOSE THE expeditor SOCKET since the client socket is
91      reused by our predecessor.
92      Closing this side would thus create troubles */
93
94   /* 7. Decrease the remaining_loop integer. */
95   globals->remaining_loop -= 1;
96
97   /* 8. Repport the hop number to the user at the end */
98   if (globals->remaining_loop == -1 && globals->create) {
99     double elapsed = gras_os_time() - globals->start_time;
100     INFO1("Shut down the token-ring. There was %d hops.", msg);
101     VERB1("Elapsed time: %g", elapsed);
102   }
103
104   /* 9. Tell GRAS that we consummed this message */
105   return 0;
106 }                               /* end_of_node_cb_stoken_handler */
107
108 int node(int argc, char *argv[])
109 {
110   node_data_t *globals;
111
112   const char *host;
113   int myport;
114   int peerport;
115
116   xbt_ex_t e;
117
118   /* 1. Init the GRAS infrastructure and declare my globals */
119   gras_init(&argc, argv);
120   globals = gras_userdata_new(node_data_t);
121
122
123   /* 2. Get the successor's address. The command line overrides
124      defaults when specified */
125   host = "127.0.0.1";
126   myport = 4000;
127   peerport = 4000;
128   if (argc >= 4) {
129     myport = atoi(argv[1]);
130     host = argv[2];
131     peerport = atoi(argv[3]);
132   }
133
134   /* 3. Save successor's address in global var */
135   globals->remaining_loop = NBLOOPS;
136   globals->create = 0;
137   globals->tosuccessor = NULL;
138
139   if (!gras_os_getpid() % 100 || gras_if_RL())
140     INFO3("Launch node listening on %d (successor on %s:%d)",
141           myport, host, peerport);
142
143   /* 4. Register the known messages.  */
144   gras_msgtype_declare("stoken", gras_datadesc_by_name("int"));
145
146   /* 5. Create my master socket for listening */
147   globals->sock = gras_socket_server(myport);
148   gras_os_sleep(1.0);           /* Make sure all server sockets are created */
149
150   /* 6. Create socket to the successor on the ring */
151   DEBUG2("Connect to my successor on %s:%d", host, peerport);
152
153   globals->tosuccessor = gras_socket_client(host, peerport);
154
155   /* 7. Register my callback */
156   gras_cb_register("stoken", &node_cb_stoken_handler);
157
158   /* 8. One node has to create the token at startup. 
159      It's specified by a command line argument */
160   if (argc >= 5
161       && !strncmp("--create-token", argv[4], strlen("--create-token")))
162     globals->create = 1;
163
164   if (globals->create) {
165     int token = 0;
166
167     globals->start_time = gras_os_time();
168
169     globals->remaining_loop = NBLOOPS - 1;
170
171     INFO3("Create the token (with value %d) and send it to %s:%d",
172           token, host, peerport);
173
174     TRY {
175       gras_msg_send(globals->tosuccessor, "stoken", &token);
176     } CATCH(e) {
177       RETHROW0("Unable to send the freshly created token: %s");
178     }
179   }
180
181   /* 8. Wait up to 10 seconds for an incomming message to handle */
182   while (globals->remaining_loop > (globals->create ? -1 : 0)) {
183     gras_msg_handle(-1);
184
185     DEBUG1("looping (remaining_loop=%d)", globals->remaining_loop);
186   }
187
188   gras_os_sleep(1.0);           /* FIXME: if the sender quited, receive fail */
189
190   /* 9. Free the allocated resources, and shut GRAS down */
191   gras_socket_close(globals->sock);
192   gras_socket_close(globals->tosuccessor);
193   free(globals);
194   gras_exit();
195
196   return 0;
197 }                               /* end_of_node */