Logo AND Algorithmique Numérique Distribuée

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