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

Revision 7941, 15.1 KB (checked in by nlmills, 4 years ago)

merged in changes from summer at LANL

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