Merge branch 'dl/submodule-set-branch'
[git] / trace2 / tr2_sid.c
1 #include "cache.h"
2 #include "trace2/tr2_tbuf.h"
3 #include "trace2/tr2_sid.h"
4
5 #define TR2_ENVVAR_PARENT_SID "GIT_TRACE2_PARENT_SID"
6
7 static struct strbuf tr2sid_buf = STRBUF_INIT;
8 static int tr2sid_nr_git_parents;
9
10 /*
11  * Compute the final component of the SID representing the current process.
12  * This should uniquely identify the process and be a valid filename (to
13  * allow writing trace2 data to per-process files).  It should also be fixed
14  * length for possible use as a database key.
15  *
16  * "<yyyymmdd>T<hhmmss>.<fraction>Z-<host>-<process>"
17  *
18  * where <host> is a 9 character string:
19  *    "H<first_8_chars_of_sha1_of_hostname>"
20  *    "Localhost" when no hostname.
21  *
22  * where <process> is a 9 character string containing the least signifcant
23  * 32 bits in the process-id.
24  *    "P<pid>"
25  * (This is an abribrary choice.  On most systems pid_t is a 32 bit value,
26  * so limit doesn't matter.  On larger systems, a truncated value is fine
27  * for our purposes here.)
28  */
29 static void tr2_sid_append_my_sid_component(void)
30 {
31         const struct git_hash_algo *algo = &hash_algos[GIT_HASH_SHA1];
32         struct tr2_tbuf tb_now;
33         git_hash_ctx ctx;
34         pid_t pid = getpid();
35         unsigned char hash[GIT_MAX_RAWSZ + 1];
36         char hex[GIT_MAX_HEXSZ + 1];
37         char hostname[HOST_NAME_MAX + 1];
38
39         tr2_tbuf_utc_datetime(&tb_now);
40         strbuf_addstr(&tr2sid_buf, tb_now.buf);
41
42         strbuf_addch(&tr2sid_buf, '-');
43         if (xgethostname(hostname, sizeof(hostname)))
44                 strbuf_add(&tr2sid_buf, "Localhost", 9);
45         else {
46                 algo->init_fn(&ctx);
47                 algo->update_fn(&ctx, hostname, strlen(hostname));
48                 algo->final_fn(hash, &ctx);
49                 hash_to_hex_algop_r(hex, hash, algo);
50                 strbuf_addch(&tr2sid_buf, 'H');
51                 strbuf_add(&tr2sid_buf, hex, 8);
52         }
53
54         strbuf_addf(&tr2sid_buf, "-P%08"PRIx32, (uint32_t)pid);
55 }
56
57 /*
58  * Compute a "unique" session id (SID) for the current process.  This allows
59  * all events from this process to have a single label (much like a PID).
60  *
61  * Export this into our environment so that all child processes inherit it.
62  *
63  * If we were started by another git instance, use our parent's SID as a
64  * prefix.  (This lets us track parent/child relationships even if there
65  * is an intermediate shell process.)
66  *
67  * Additionally, count the number of nested git processes.
68  */
69 static void tr2_sid_compute(void)
70 {
71         const char *parent_sid;
72
73         if (tr2sid_buf.len)
74                 return;
75
76         parent_sid = getenv(TR2_ENVVAR_PARENT_SID);
77         if (parent_sid && *parent_sid) {
78                 const char *p;
79                 for (p = parent_sid; *p; p++)
80                         if (*p == '/')
81                                 tr2sid_nr_git_parents++;
82
83                 strbuf_addstr(&tr2sid_buf, parent_sid);
84                 strbuf_addch(&tr2sid_buf, '/');
85                 tr2sid_nr_git_parents++;
86         }
87
88         tr2_sid_append_my_sid_component();
89
90         setenv(TR2_ENVVAR_PARENT_SID, tr2sid_buf.buf, 1);
91 }
92
93 const char *tr2_sid_get(void)
94 {
95         if (!tr2sid_buf.len)
96                 tr2_sid_compute();
97
98         return tr2sid_buf.buf;
99 }
100
101 int tr2_sid_depth(void)
102 {
103         if (!tr2sid_buf.len)
104                 tr2_sid_compute();
105
106         return tr2sid_nr_git_parents;
107 }
108
109 void tr2_sid_release(void)
110 {
111         strbuf_release(&tr2sid_buf);
112 }