b97b97533e25f48833630ac1e73d95a9e9749907
[oweals/gnunet.git] / src / ats-tests / perf_ats_logging.c
1 /*
2  This file is part of GNUnet.
3  (C) 2010-2013 Christian Grothoff (and other contributing authors)
4
5  GNUnet is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published
7  by the Free Software Foundation; either version 3, or (at your
8  option) any later version.
9
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  General Public License for more details.
14
15  You should have received a copy of the GNU General Public License
16  along with GNUnet; see the file COPYING.  If not, write to the
17  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  Boston, MA 02111-1307, USA.
19  */
20 /**
21  * @file ats/perf_ats_logging.c
22  * @brief ats benchmark: logging for performance tests
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "perf_ats.h"
29
30 #define LOGGING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
31
32 static GNUNET_SCHEDULER_TaskIdentifier log_task;
33
34 static struct BenchmarkPeer *peers;
35 static int num_peers;
36 static char *name;
37
38 struct LoggingTimestep
39 {
40   struct GNUNET_TIME_Absolute timestamp;
41
42   struct LoggingTimestep *next;
43   struct LoggingTimestep *prev;
44 };
45
46 struct LoggingPeer
47 {
48   struct BenchmarkPeer *peer;
49
50   struct GNUNET_TIME_Absolute start;
51
52   struct LoggingTimestep *head;
53   struct LoggingTimestep *tail;
54 };
55
56 /**
57  * Log structure of length num_peers
58  */
59 static struct LoggingPeer *lp;
60
61
62 static void
63 write_to_file ()
64 {
65   struct GNUNET_DISK_FileHandle *f;
66   char * filename;
67   char *data;
68   struct LoggingTimestep *cur;
69   int c_m;
70
71   GNUNET_asprintf (&filename, "%llu_%s.data", GNUNET_TIME_absolute_get().abs_value_us,name);
72
73   f = GNUNET_DISK_file_open (filename,
74       GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
75       GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
76   if (NULL == f)
77   {
78     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open log file `%s'\n", filename);
79     GNUNET_free (filename);
80     return;
81   }
82
83   for (c_m = 0; c_m < num_peers; c_m++)
84   {
85     for (cur = lp[c_m].head; NULL != cur; cur = cur->next)
86     {
87       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
88           "Master [%u]: timestamp %llu \n", lp[c_m].peer->no, cur->timestamp);
89
90       GNUNET_asprintf (&data, "%llu;\n", cur->timestamp);
91
92       if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data)))
93         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", filename);
94       GNUNET_free (data);
95
96     }
97   }
98
99   if (GNUNET_SYSERR == GNUNET_DISK_file_close(f))
100   {
101     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n", filename);
102     GNUNET_free (filename);
103     return;
104   }
105
106   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data file successfully written to log file `%s'\n", filename);
107   GNUNET_free (filename);
108 }
109
110 static void
111 collect_log_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
112 {
113   int c_m;
114   int c_s;
115   struct LoggingTimestep *lt;
116   struct BenchmarkPartner *p;
117
118   log_task = GNUNET_SCHEDULER_NO_TASK;
119
120   for (c_m = 0; c_m < num_peers; c_m++)
121   {
122     lt = GNUNET_malloc (sizeof (struct LoggingTimestep));
123     GNUNET_CONTAINER_DLL_insert_tail(lp[c_m].head, lp[c_m].tail, lt);
124     lt->timestamp = GNUNET_TIME_absolute_get();
125
126     for (c_s = 0; c_s < lp[c_m].peer->num_partners; c_s++)
127     {
128       p = &peers[c_m].partners[c_s];
129
130       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
131           "Master [%u]: slave [%u]\n",
132           lp->peer->no, p->dest->no);
133     }
134   }
135
136   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
137     return;
138
139   log_task = GNUNET_SCHEDULER_add_delayed (LOGGING_FREQUENCY,
140       &collect_log_task, NULL);
141 }
142
143
144 void
145 perf_logging_stop ()
146 {
147   int c_m;
148   struct GNUNET_SCHEDULER_TaskContext tc;
149   struct LoggingTimestep *cur;
150
151   if (GNUNET_SCHEDULER_NO_TASK != log_task)
152     GNUNET_SCHEDULER_cancel (log_task);
153   log_task = GNUNET_SCHEDULER_NO_TASK;
154   tc.reason = GNUNET_SCHEDULER_REASON_SHUTDOWN;
155   collect_log_task (NULL, &tc);
156
157   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
158       _("Stop logging\n"));
159
160   write_to_file ();
161
162   for (c_m = 0; c_m < num_peers; c_m++)
163   {
164     while (NULL != (cur = lp[c_m].head))
165     {
166       GNUNET_CONTAINER_DLL_remove (lp[c_m].head, lp[c_m].tail, cur);
167       GNUNET_free (cur);
168     }
169   }
170
171   GNUNET_free (lp);
172 }
173
174 void
175 perf_logging_start (char * testname, struct BenchmarkPeer *masters, int num_masters)
176 {
177   int c_m;
178   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
179       _("Start logging `%s'\n"), testname);
180
181   peers = masters;
182   num_peers = num_masters;
183   name = testname;
184
185   lp = GNUNET_malloc (num_masters * sizeof (struct LoggingPeer));
186
187   for (c_m = 0; c_m < num_masters; c_m ++)
188   {
189     lp[c_m].peer = &masters[c_m];
190     lp[c_m].start = GNUNET_TIME_absolute_get();
191   }
192
193   /* Schedule logging task */
194   log_task = GNUNET_SCHEDULER_add_now (&collect_log_task, NULL);
195 }
196 /* end of file perf_ats_logging.c */
197