summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/latency.c
blob: d0039a1f730f4288852d3d1db50ddb4e22dbf874 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
  Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
  This file is part of GlusterFS.

  This file is licensed to you under your choice of the GNU Lesser
  General Public License, version 3 or any later version (LGPLv3 or
  later), or the GNU General Public License, version 2 (GPLv2), in all
  cases as published by the Free Software Foundation.
*/


/*
 * This file contains functions to support dumping of
 * latencies of FOPs broken down by subvolumes.
 */

#include "glusterfs.h"
#include "stack.h"
#include "xlator.h"
#include "common-utils.h"
#include "statedump.h"
#include "libglusterfs-messages.h"

void
gf_update_latency (call_frame_t *frame)
{
        double elapsed;
        struct timespec *begin, *end;

        fop_latency_t *lat;

        begin = &frame->begin;
        end   = &frame->end;

        if (!(begin->tv_sec && end->tv_sec))
                goto out;

        elapsed = (end->tv_sec - begin->tv_sec) * 1e9
                + (end->tv_nsec - begin->tv_nsec);

        /* Can happen mostly at initiator xlator, as STACK_WIND/UNWIND macros
           set it right anyways for those frames */
        if (!frame->op)
                frame->op = frame->root->op;

        lat = &frame->this->stats.interval.latencies[frame->op];

        if (lat->max < elapsed)
                lat->max = elapsed;

        if (lat->min > elapsed)
                lat->min = elapsed;

        lat->total += elapsed;
        lat->count++;
out:
        return;
}


void
gf_proc_dump_latency_info (xlator_t *xl)
{
        char key_prefix[GF_DUMP_MAX_BUF_LEN];
        char key[GF_DUMP_MAX_BUF_LEN];
        int i;

        snprintf (key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.latency", xl->name);
        gf_proc_dump_add_section (key_prefix);

        for (i = 0; i < GF_FOP_MAXVALUE; i++) {
                gf_proc_dump_build_key (key, key_prefix, "%s",
                                        (char *)gf_fop_list[i]);

                fop_latency_t *lat = &xl->stats.interval.latencies[i];

                /* Doesn't make sense to continue if there are no fops
                   came in the given interval */
                if (!lat->count)
                        continue;

                gf_proc_dump_write (key, "%.03f,%"PRId64",%.03f",
                                    (lat->total / lat->count), lat->count,
                                    lat->total);
        }

        memset (xl->stats.interval.latencies, 0,
                sizeof (xl->stats.interval.latencies));

        /* make sure 'min' is set to high value, so it would be
           properly set later */
        for (i = 0; i < GF_FOP_MAXVALUE; i++) {
                xl->stats.interval.latencies[i].min = 0xffffffff;
        }
}


void
gf_latency_toggle (int signum, glusterfs_ctx_t *ctx)
{
        if (ctx) {
                ctx->measure_latency = !ctx->measure_latency;
                gf_msg ("[core]", GF_LOG_INFO, 0,
                        LG_MSG_LATENCY_MEASUREMENT_STATE,
                        "Latency measurement turned %s",
                        ctx->measure_latency ? "on" : "off");
        }
}