Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
70e7673bfbb8e8efb79ee82a4e78ad93d1e4a243
[simgrid.git] / examples / msg / app-chainsend / peer.c
1 /* Copyright (c) 2012-2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "peer.h"
8
9 XBT_LOG_NEW_DEFAULT_CATEGORY(msg_peer, "Messages specific for the peer");
10
11 void peer_init_chain(peer_t peer, message_t msg)
12 {
13   peer->prev = msg->prev_hostname;
14   peer->next = msg->next_hostname;
15   peer->total_pieces = msg->num_pieces;
16   peer->init = 1;
17 }
18
19 static void peer_forward_msg(peer_t peer, message_t msg)
20 {
21   msg_task_t task = task_message_data_new(NULL, msg->data_length);
22   msg_comm_t comm = NULL;
23   XBT_DEBUG("Sending (isend) from %s into mailbox %s", peer->me, peer->next);
24   comm = MSG_task_isend(task, peer->next);
25   queue_pending_connection(comm, peer->pending_sends);
26 }
27
28 int peer_execute_task(peer_t peer, msg_task_t task)
29 {
30   int done = 0;
31   message_t msg = MSG_task_get_data(task);
32   
33   XBT_DEBUG("Peer %s got message of type %d\n", peer->me, msg->type);
34   if (msg->type == MESSAGE_BUILD_CHAIN)
35     peer_init_chain(peer, msg);
36   if (msg->type == MESSAGE_SEND_DATA){
37     xbt_assert(peer->init, "peer_execute_task() failed: got msg_type %d before initialization", msg->type);
38     if (peer->next != NULL)
39       peer_forward_msg(peer, msg);
40     peer->pieces++;
41     peer->bytes += msg->data_length;
42     if (peer->pieces >= peer->total_pieces) {
43       XBT_DEBUG("%d pieces receieved", peer->pieces);
44       done = 1;
45     }
46   }
47
48   MSG_task_execute(task);
49
50   return done;
51 }
52
53 msg_error_t peer_wait_for_message(peer_t peer)
54 {
55   msg_error_t status;
56   msg_comm_t comm = NULL;
57   msg_task_t task = NULL;
58   int done = 0;
59
60   while (done == 0) {
61     comm = MSG_task_irecv(&task, peer->me);
62     queue_pending_connection(comm, peer->pending_recvs);
63     int idx = MSG_comm_waitany(peer->pending_recvs);
64     if (idx != -1) {
65       comm = xbt_dynar_get_as(peer->pending_recvs, idx, msg_comm_t);
66       status = MSG_comm_get_status(comm);
67       XBT_DEBUG("peer_wait_for_message: error code = %d", status);
68       xbt_assert(status == MSG_OK, "peer_wait_for_message() failed");
69
70       task = MSG_comm_get_task(comm);
71       MSG_comm_destroy(comm);
72       xbt_dynar_cursor_rm(peer->pending_recvs, (unsigned int*)&idx);
73       done = peer_execute_task(peer, task);
74
75       task_message_delete(task);
76       task = NULL;
77     }
78     process_pending_connections(peer->pending_sends);
79   }
80
81   return status;
82 }
83
84 void peer_init(peer_t p, int argc, char *argv[])
85 {
86   p->init = 0;
87   p->prev = NULL;
88   p->next = NULL;
89   p->pieces = 0;
90   p->bytes = 0;
91   p->pending_recvs = xbt_dynar_new(sizeof(msg_comm_t), NULL);
92   p->pending_sends = xbt_dynar_new(sizeof(msg_comm_t), NULL);
93   /* Set mailbox name: use host number from argv or hostname if no argument given */
94   if (argc > 1) {
95     p->me = bprintf("host%s", argv[1]);
96   } else {
97     p->me = xbt_strdup(MSG_host_get_name(MSG_host_self()));
98   }
99 }
100
101 void peer_shutdown(peer_t p)
102 {
103   unsigned int size = xbt_dynar_length(p->pending_sends);
104   unsigned int idx;
105   msg_comm_t *comms = xbt_new(msg_comm_t, size);
106
107   for (idx = 0; idx < size; idx++) {
108     comms[idx] = xbt_dynar_get_as(p->pending_sends, idx, msg_comm_t);
109   }
110
111   XBT_DEBUG("Waiting for sends to finish before shutdown...");
112   MSG_comm_waitall(comms, size, PEER_SHUTDOWN_DEADLINE);
113
114   for (idx = 0; idx < size; idx++) {
115     MSG_comm_destroy(comms[idx]);
116   }
117
118   xbt_free(comms);
119 }
120
121 void peer_delete(peer_t p)
122 {
123   xbt_dynar_free(&p->pending_recvs);
124   xbt_dynar_free(&p->pending_sends);
125   xbt_free(p->me);
126   xbt_free(p->prev);
127   xbt_free(p->next);
128
129   xbt_free(p);
130 }
131
132 void peer_print_stats(peer_t p, float elapsed_time)
133 {
134   XBT_INFO("### %f %llu bytes (Avg %f MB/s); copy finished (simulated).", elapsed_time, p->bytes, p->bytes / 1024.0 / 1024.0 / elapsed_time); 
135 }
136
137 /** Peer function  */
138 int peer(int argc, char *argv[])
139 {
140   peer_t p = xbt_new(s_peer_t, 1);
141   msg_error_t status;
142
143   XBT_DEBUG("peer");
144
145   peer_init(p, argc, argv);
146   float start_time = MSG_get_clock();
147   status = peer_wait_for_message(p);
148   peer_shutdown(p);
149   float end_time = MSG_get_clock();
150   peer_print_stats(p, end_time - start_time);
151   peer_delete(p);
152
153   return status;
154 }