1#include "cache.h" 2#include "trace2/tr2_tbuf.h" 3#include "trace2/tr2_sid.h" 4 5#define TR2_ENVVAR_PARENT_SID "GIT_TR2_PARENT_SID" 6 7static struct strbuf tr2sid_buf = STRBUF_INIT; 8static 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 */ 29static 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 */ 69static 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 93const char *tr2_sid_get(void) 94{ 95 if (!tr2sid_buf.len) 96 tr2_sid_compute(); 97 98 return tr2sid_buf.buf; 99} 100 101int tr2_sid_depth(void) 102{ 103 if (!tr2sid_buf.len) 104 tr2_sid_compute(); 105 106 return tr2sid_nr_git_parents; 107} 108 109void tr2_sid_release(void) 110{ 111 strbuf_release(&tr2sid_buf); 112}