trace2 / tr2_sid.con commit Merge branch 'jk/apache-lsan' (7782066)
   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}