root/branches/cu-security-branch/src/apps/karma/comm.c @ 8397

Revision 8397, 15.0 KB (checked in by nlmills, 3 years ago)

initial merge with Orange-Branch. much will be broken

Line 
1/*
2 * (C) 2001 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6
7#include <sys/types.h>
8#include <assert.h>
9#include <unistd.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <gtk/gtk.h>
14#include <time.h>       /* nanosleep() */
15
16#include "karma.h"
17
18#define GUI_COMM_PERF_HISTORY 5
19#undef FAKE_STATS
20#undef FAKE_PERF
21
22/* statistics data structures */
23static const PVFS_util_tab *tab;
24static struct PVFS_mgmt_server_stat *visible_stats = NULL;
25static struct PVFS_mgmt_server_stat *internal_stats = NULL;
26static PVFS_error_details *internal_details = NULL;
27static int visible_stat_ct;
28static int internal_stat_ct;
29
30static PVFS_BMI_addr_t *internal_addrs = NULL;
31static int internal_addr_ct;
32
33static int64_t meta_read_prev = 0;
34static int64_t meta_write_prev = 0;
35
36/* performance data structures */
37static struct PVFS_mgmt_perf_stat **internal_perf;
38static uint32_t *internal_perf_ids;
39static uint64_t *internal_end_time_ms;
40static struct gui_traffic_raw_data *visible_perf = NULL;
41
42GtkListStore *gui_comm_fslist;
43
44static PVFS_credentials creds;
45static PVFS_fs_id cur_fsid = -1;
46
47#ifdef FAKE_STATS
48static struct PVFS_mgmt_server_stat fake_stats[] = {
49    {9, 1048576, 2 * 1048576, 2048, 1024, 102, 4096, 8192, "node0", 3},
50    {9, 524288, 2 * 1048576, 1024, 512, 500, 256, 8192, "node2", 3},
51    {9, 524288, 2 * 1048576, 2048, 512, 102, 512, 1024, "node1", 1},
52    {9, 1048576, 2 * 1048576, 1024, 256, 302, 4096, 8192, "node3", 2},
53    {9, 1048576, 2 * 1048576, 1024, 512, 102, 1024, 8192, "node4", 1}
54};
55static int fake_stat_ct = sizeof(fake_stats) / sizeof(*fake_stats);
56#endif
57
58#ifdef FAKE_PERF
59static struct gui_traffic_raw_data fake_perf[] = {
60    {100 * 1048576, 0, 100, 10, 1020},
61    {120 * 1048576, 0, 100, 10, 1020},
62    {80 * 1048576, 0, 100, 10, 1020},
63    {10, 100 * 1048576, 0, 100, 1020},
64    {100, 130 * 1048576, 10, 1023, 1020},
65    {10 * 1048576, 0, 637, 20, 1020},
66    {140 * 1048576, 0, 1300, 20, 1020},
67    {1 * 1048576, 0, 100, 123, 1020},
68    {10, 64 * 1048576, 0, 2100, 1020},
69    {100, 137 * 1048576, 10, 523, 1020},
70    {100 * 1048576, 0, 100, 10, 1020},
71    {120 * 1048576, 0, 100, 10, 1020},
72    {80 * 1048576, 0, 100, 10, 1020},
73    {10, 100 * 1048576, 0, 100, 1020},
74    {30 * 1048576, 40 * 1048576, 2110, 4023, 1020},
75    {60 * 1048576, 130 * 1048576, 1230, 723, 1020}
76};
77static int fake_perf_ct = sizeof(fake_perf) / sizeof(*fake_perf);
78#endif
79
80/* internal fn prototypes */
81static int gui_comm_stats_collect(
82    void);
83
84/* gui_comm_setup()
85 *
86 * Initializes PVFS2 library and allocates memory for lists of stats from servers.
87 *
88 * Returns 0 on success, -1 on failure (some error initializing).
89 */
90int gui_comm_setup(
91    void)
92{
93    char msgbuf[128];
94    int ret, i, j;
95    PVFS_fs_id default_fsid;
96    struct server_configuration_s *server_config = NULL;
97
98    /* PVFS2 init */
99    tab = PVFS_util_parse_pvfstab(NULL);
100    if (!tab)
101    {
102        return -1;
103    }
104
105    /* create the fslist that we're going to use all over the place */
106    gui_comm_fslist = gtk_list_store_new(4,
107                                         G_TYPE_STRING,
108                                         G_TYPE_STRING,
109                                         G_TYPE_STRING, G_TYPE_INT);
110
111    ret = PVFS_sys_initialize(0);
112    if (ret < 0)
113    {
114        return -1;
115    }
116
117    for (i = 0; i < tab->mntent_count; i++)
118    {
119        ret = PVFS_sys_fs_add(&tab->mntent_array[i]);
120        if (ret < 0)
121        {
122            return (-1);
123        }
124    }
125
126    for (i = 0; i < tab->mntent_count; i++)
127    {
128        GtkTreeIter iter;
129        PVFS_fs_id cur_fs_id;
130
131        gtk_list_store_append(gui_comm_fslist, &iter);
132
133        for (j = strlen(tab->mntent_array[i].the_pvfs_config_server); j > 0;
134             j--)
135        {
136            if (tab->mntent_array[i].the_pvfs_config_server[j] == '/')
137                break;
138        }
139
140        assert(j < 128);
141        strncpy(msgbuf, tab->mntent_array[i].the_pvfs_config_server, j);
142        msgbuf[j] = '\0';
143
144        server_config =
145            PINT_get_server_config_struct(tab->mntent_array[i].fs_id);
146        assert(server_config);
147
148        cur_fs_id =
149            PINT_config_get_fs_id_by_fs_name(server_config,
150                                             tab->mntent_array[i].pvfs_fs_name);
151
152        PINT_put_server_config_struct(server_config);
153        assert(cur_fs_id != PVFS_FS_ID_NULL);
154
155        gtk_list_store_set(gui_comm_fslist,
156                           &iter,
157                           GUI_FSLIST_MNTPT, tab->mntent_array[i].mnt_dir,
158                           GUI_FSLIST_SERVER, msgbuf,
159                           GUI_FSLIST_FSNAME, tab->mntent_array[i].pvfs_fs_name,
160                           GUI_FSLIST_FSID, (gint) cur_fs_id, -1);
161    }
162
163    PVFS_util_gen_credentials(&creds);
164
165    /* print message indicating what file system we are monitoring */
166    snprintf(msgbuf,
167             128,
168             "monitoring %s by default.",
169             tab->mntent_array[0].the_pvfs_config_server);
170    gui_message_new(msgbuf);
171
172    /* prepare config server name for passing to
173     * gui_comm_set_active_fs() - this is the only time that it isn't
174     * quite in the right format.
175     */
176    for (j = strlen(tab->mntent_array[0].the_pvfs_config_server); j > 0; j--)
177    {
178        if (tab->mntent_array[0].the_pvfs_config_server[j] == '/')
179            break;
180    }
181
182    assert(j < 128);
183    strncpy(msgbuf, tab->mntent_array[0].the_pvfs_config_server, j);
184    msgbuf[j] = '\0';
185
186    ret = PVFS_util_get_default_fsid(&default_fsid);
187    /* TODO: what sort of error handling needs to happen here? */
188    if (ret < 0)
189    {
190        return (-1);
191    }
192
193    gui_comm_set_active_fs(msgbuf,
194                           tab->mntent_array[0].pvfs_fs_name, default_fsid);
195
196    return 0;
197}
198
199/* gui_comm_set_active_fsid(contact_server, fsname, fsid)
200 */
201void gui_comm_set_active_fs(
202    char *contact_server,
203    char *fs_name,
204    PVFS_fs_id new_fsid)
205{
206    int i, ret, outcount;
207    char msgbuf[80];
208    struct PVFS_mgmt_perf_stat *bigperfbuf;
209
210#ifdef FAKE_STATS
211    return;
212#else
213    snprintf(msgbuf, 80, "Karma: %s/%s", contact_server, fs_name);
214    gui_set_title(msgbuf);
215
216    if (new_fsid == cur_fsid)
217        return;
218
219    cur_fsid = new_fsid;
220
221    ret = PVFS_mgmt_count_servers(cur_fsid,
222                                  &creds,
223                                  PVFS_MGMT_IO_SERVER | PVFS_MGMT_META_SERVER,
224                                  &outcount);
225    if (ret < 0)
226    {
227        return;
228    }
229
230    assert(outcount > 0);
231
232    /* allocate space for our stats if we need to */
233    if (internal_stats != NULL && internal_stat_ct == outcount)
234        return;
235    else if (internal_stats != NULL)
236    {
237        /* free all our dynamically allocated memory for resizing */
238        free(internal_stats);
239        free(internal_perf[0]);
240        free(internal_perf);
241        free(internal_perf_ids);
242        free(internal_end_time_ms);
243
244        PVFS_error_details_free(internal_details);
245    }
246
247    internal_stats = (struct PVFS_mgmt_server_stat *)
248        malloc(outcount * sizeof(struct PVFS_mgmt_server_stat));
249    internal_stat_ct = outcount;
250
251    internal_details = PVFS_error_details_new(outcount);
252
253    /* save addresses of servers */
254    if (internal_addrs != NULL)
255    {
256        free(internal_addrs);
257    }
258    internal_addrs = (PVFS_BMI_addr_t *)
259        malloc(outcount * sizeof(PVFS_BMI_addr_t));
260    internal_addr_ct = outcount;
261    ret = PVFS_mgmt_get_server_array(cur_fsid,
262                                     &creds,
263                                     PVFS_MGMT_IO_SERVER |
264                                     PVFS_MGMT_META_SERVER, internal_addrs,
265                                     &outcount);
266    if (ret < 0)
267    {
268        PVFS_perror("PVFS_mgmt_get_server_array", ret);
269        return;
270    }
271
272    /* allocate space for performance data */
273    bigperfbuf = (struct PVFS_mgmt_perf_stat *)
274        malloc(GUI_COMM_PERF_HISTORY * outcount *
275               sizeof(struct PVFS_mgmt_perf_stat));
276    internal_perf = (struct PVFS_mgmt_perf_stat **)
277        malloc(outcount * sizeof(struct PVFS_mgmt_perf_stat *));
278
279    for (i = 0; i < outcount; i++)
280    {
281        internal_perf[i] = &bigperfbuf[i * GUI_COMM_PERF_HISTORY];
282    }
283
284    internal_perf_ids = (uint32_t *) malloc(outcount * sizeof(uint32_t));
285    memset(internal_perf_ids, 0, outcount * sizeof(uint32_t));
286    internal_end_time_ms = (uint64_t *) malloc(outcount * sizeof(uint64_t));
287
288#endif
289}
290
291/* gui_comm_stats_retrieve(**svr_stat, *svr_stat_ct)
292 *
293 * Copies latest internal data into visible structures and returns pointers to
294 * visible structures storing server statistics.  These should not be modified
295 * by the caller, but are guaranteed not to be modified between calls to this
296 * function.
297 *
298 * Returns 0 on success, -1 on failure (some error grabbing data).
299 */
300int gui_comm_stats_retrieve(
301    struct PVFS_mgmt_server_stat **svr_stat,
302    int *svr_stat_ct)
303{
304    int ret;
305
306#ifdef FAKE_STATS
307    *svr_stat = fake_stats;
308    *svr_stat_ct = fake_stat_ct;
309    return 0;
310#else
311    /* for now, call gui_comm_stats_collect() to get new data */
312    ret = gui_comm_stats_collect();
313    if (ret != 0)
314        return ret;
315
316    if (visible_stats == NULL)
317    {
318        visible_stats = (struct PVFS_mgmt_server_stat *)
319            malloc(internal_stat_ct * sizeof(struct PVFS_mgmt_server_stat));
320        visible_stat_ct = internal_stat_ct;
321    }
322
323    memcpy(visible_stats,
324           internal_stats,
325           visible_stat_ct * sizeof(struct PVFS_mgmt_server_stat));
326
327    *svr_stat = visible_stats;
328    *svr_stat_ct = visible_stat_ct;
329
330    return 0;
331#endif
332}
333
334/* gui_comm_stats_collect()
335 *
336 * Updates internal stat structures.
337 */
338static int gui_comm_stats_collect(
339    void)
340{
341    int ret;
342    char msgbuf[64];
343    char err_msg[64];
344
345#ifdef FAKE_STATS
346    return 0;
347#else
348    assert(internal_addr_ct == internal_stat_ct);
349
350    ret = PVFS_mgmt_statfs_list(cur_fsid,
351                                &creds,
352                                internal_stats,
353                                internal_addrs,
354                                internal_stat_ct, internal_details, NULL);
355    if (ret == 0)
356        return 0;
357    else if (ret == -PVFS_EDETAIL)
358    {
359        int i;
360
361        for (i = 0; i < internal_details->count_used; i++)
362        {
363            int dummy;
364
365            PVFS_strerror_r(internal_details->error[i].error, err_msg, 64);
366            snprintf(msgbuf,
367                     64,
368                     "Server %s not responding: %s\n",
369                     PVFS_mgmt_map_addr(cur_fsid,
370                                        &creds,
371                                        internal_details->error[i].addr,
372                                        &dummy),
373                     err_msg);
374            gui_message_new(msgbuf);
375        }
376
377        return 0;
378    }
379    else
380    {
381
382        PVFS_strerror_r(ret, err_msg, 64);
383        snprintf(msgbuf,
384                 64,
385                 "Error: PVFS_mgmt_statfs_list(): %s\n",
386                 err_msg);
387        gui_message_new(msgbuf);
388
389        return -1;
390    }
391#endif
392}
393
394/* gui_comm_perf_collect()
395 */
396static int gui_comm_perf_collect(
397    void)
398{
399    int ret;
400    char err_msg[64];
401    char msgbuf[64];
402
403#ifndef FAKE_PERF
404    ret = PVFS_mgmt_perf_mon_list(cur_fsid,
405                                  &creds,
406                                  internal_perf,
407                                  internal_end_time_ms,
408                                  internal_addrs,
409                                  internal_perf_ids,
410                                  internal_addr_ct,
411                                  GUI_COMM_PERF_HISTORY, internal_details,
412                                  NULL);
413    if (ret == 0)
414        return 0;
415    else if (ret == -PVFS_EDETAIL)
416    {
417        int i;
418
419        for (i = 0; i < internal_details->count_used; i++)
420        {
421            int dummy;
422
423            PVFS_strerror_r(internal_details->error[i].error, err_msg, 64);
424            snprintf(msgbuf,
425                     64,
426                     "Server %s not responding: %s\n",
427                     PVFS_mgmt_map_addr(cur_fsid,
428                                        &creds,
429                                        internal_details->error[i].addr,
430                                        &dummy),
431                    err_msg);
432            gui_message_new(msgbuf);
433        }
434
435        return 0;
436    }
437    else
438    {
439        PVFS_strerror_r(ret, err_msg, 64);
440        snprintf(msgbuf,
441                 64,
442                 "Error: PVFS_mgmt_perf_mon_list(): %s\n",
443                 err_msg);
444        gui_message_new(msgbuf);
445
446        return -1;
447    }
448#endif
449
450    return 0;
451}
452
453/* gui_comm_traffic_retrieve()
454 *
455 * Passes back pointer to "raw" traffic data, fills in # of servers.
456 */
457int gui_comm_traffic_retrieve(
458    struct gui_traffic_raw_data **svr_traffic,
459    int *svr_traffic_ct)
460{
461    int ret, svr, idx;
462
463#ifdef FAKE_PERF
464    *svr_traffic = fake_perf;
465    *svr_traffic_ct = fake_perf_ct;
466    return 0;
467#else
468    ret = gui_comm_perf_collect();
469    if (ret != 0)
470        return ret;
471
472    /* initialize visible_perf array if we haven't already */
473    if (visible_perf == NULL)
474    {
475        visible_perf = (struct gui_traffic_raw_data *)
476            malloc(internal_addr_ct * sizeof(struct gui_traffic_raw_data));
477        assert(visible_perf != NULL);
478    }
479    memset(visible_perf,
480           0, internal_addr_ct * sizeof(struct gui_traffic_raw_data));
481
482    /* summarize data and store in visible_perf array */
483    for (svr = 0; svr < internal_addr_ct; svr++)
484    {
485        int valid_start_time = 0;
486        uint64_t start_time_ms = 0;
487
488        struct gui_traffic_raw_data *raw = &visible_perf[svr];
489
490        for (idx = 0; idx < GUI_COMM_PERF_HISTORY; idx++)
491        {
492            if (!internal_perf[svr][idx].valid_flag)
493                continue;
494
495            if (!valid_start_time)
496            {
497                /* Q: should we just assume first entry is good? */
498                valid_start_time = 1;
499                start_time_ms = internal_perf[svr][idx].start_time_ms;
500            }
501
502            raw->data_write_bytes += internal_perf[svr][idx].write;
503            raw->data_read_bytes += internal_perf[svr][idx].read;
504            raw->meta_write_ops = internal_perf[svr][idx].metadata_write;
505            raw->meta_read_ops = internal_perf[svr][idx].metadata_read;
506        }
507
508        if (valid_start_time)
509        {
510            raw->elapsed_time_ms = internal_end_time_ms[svr] - start_time_ms;
511        }
512        else
513        {
514            raw->elapsed_time_ms = 0;
515        }
516
517        /* deal with format in which metadata is returned */
518        if (internal_perf[svr][0].valid_flag)
519        {
520            raw->meta_write_ops -= meta_write_prev;
521            raw->meta_read_ops -= meta_read_prev;
522            meta_write_prev += raw->meta_write_ops;
523            meta_read_prev += raw->meta_read_ops;
524
525            /* simple, if somewhat inaccurate, handling of overflow */
526            if (raw->meta_write_ops < 0)
527                raw->meta_write_ops = 0;
528            if (raw->meta_read_ops < 0)
529                raw->meta_read_ops = 0;
530        }
531    }
532
533    *svr_traffic = visible_perf;
534    *svr_traffic_ct = internal_addr_ct;
535    return 0;
536#endif
537}
538
539/*
540 * Local variables:
541 *  c-indent-level: 4
542 *  c-basic-offset: 4
543 * End:
544 *
545 * vim: ts=8 sts=4 sw=4 expandtab
546 */
Note: See TracBrowser for help on using the browser.