-
Notifications
You must be signed in to change notification settings - Fork 0
/
tr2_sid.c
112 lines (95 loc) · 2.9 KB
/
tr2_sid.c
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
109
110
111
112
#include "cache.h"
#include "trace2/tr2_tbuf.h"
#include "trace2/tr2_sid.h"
#define TR2_ENVVAR_PARENT_SID "GIT_TRACE2_PARENT_SID"
static struct strbuf tr2sid_buf = STRBUF_INIT;
static int tr2sid_nr_git_parents;
/*
* Compute the final component of the SID representing the current process.
* This should uniquely identify the process and be a valid filename (to
* allow writing trace2 data to per-process files). It should also be fixed
* length for possible use as a database key.
*
* "<yyyymmdd>T<hhmmss>.<fraction>Z-<host>-<process>"
*
* where <host> is a 9 character string:
* "H<first_8_chars_of_sha1_of_hostname>"
* "Localhost" when no hostname.
*
* where <process> is a 9 character string containing the least significant
* 32 bits in the process-id.
* "P<pid>"
* (This is an abribrary choice. On most systems pid_t is a 32 bit value,
* so limit doesn't matter. On larger systems, a truncated value is fine
* for our purposes here.)
*/
static void tr2_sid_append_my_sid_component(void)
{
const struct git_hash_algo *algo = &hash_algos[GIT_HASH_SHA1];
struct tr2_tbuf tb_now;
git_hash_ctx ctx;
pid_t pid = getpid();
unsigned char hash[GIT_MAX_RAWSZ + 1];
char hex[GIT_MAX_HEXSZ + 1];
char hostname[HOST_NAME_MAX + 1];
tr2_tbuf_utc_datetime(&tb_now);
strbuf_addstr(&tr2sid_buf, tb_now.buf);
strbuf_addch(&tr2sid_buf, '-');
if (xgethostname(hostname, sizeof(hostname)))
strbuf_add(&tr2sid_buf, "Localhost", 9);
else {
algo->init_fn(&ctx);
algo->update_fn(&ctx, hostname, strlen(hostname));
algo->final_fn(hash, &ctx);
hash_to_hex_algop_r(hex, hash, algo);
strbuf_addch(&tr2sid_buf, 'H');
strbuf_add(&tr2sid_buf, hex, 8);
}
strbuf_addf(&tr2sid_buf, "-P%08"PRIx32, (uint32_t)pid);
}
/*
* Compute a "unique" session id (SID) for the current process. This allows
* all events from this process to have a single label (much like a PID).
*
* Export this into our environment so that all child processes inherit it.
*
* If we were started by another git instance, use our parent's SID as a
* prefix. (This lets us track parent/child relationships even if there
* is an intermediate shell process.)
*
* Additionally, count the number of nested git processes.
*/
static void tr2_sid_compute(void)
{
const char *parent_sid;
if (tr2sid_buf.len)
return;
parent_sid = getenv(TR2_ENVVAR_PARENT_SID);
if (parent_sid && *parent_sid) {
const char *p;
for (p = parent_sid; *p; p++)
if (*p == '/')
tr2sid_nr_git_parents++;
strbuf_addstr(&tr2sid_buf, parent_sid);
strbuf_addch(&tr2sid_buf, '/');
tr2sid_nr_git_parents++;
}
tr2_sid_append_my_sid_component();
setenv(TR2_ENVVAR_PARENT_SID, tr2sid_buf.buf, 1);
}
const char *tr2_sid_get(void)
{
if (!tr2sid_buf.len)
tr2_sid_compute();
return tr2sid_buf.buf;
}
int tr2_sid_depth(void)
{
if (!tr2sid_buf.len)
tr2_sid_compute();
return tr2sid_nr_git_parents;
}
void tr2_sid_release(void)
{
strbuf_release(&tr2sid_buf);
}