summaryrefslogtreecommitdiff
path: root/trace2
diff options
context:
space:
mode:
authorJosh Steadmon <steadmon@google.com>2019-03-21 21:09:51 (GMT)
committerJunio C Hamano <gitster@pobox.com>2019-03-22 05:27:02 (GMT)
commita4d3a283db5259cc372809da4dc085c3f40aebfb (patch)
tree2f96ae786a221e5ff3bc23abe950c9e119666f91 /trace2
parent041f5ea1cf987a4068ef5f39ba0a09be85952064 (diff)
downloadgit-a4d3a283db5259cc372809da4dc085c3f40aebfb.zip
git-a4d3a283db5259cc372809da4dc085c3f40aebfb.tar.gz
git-a4d3a283db5259cc372809da4dc085c3f40aebfb.tar.bz2
trace2: write to directory targets
When the value of a trace2 environment variable is an absolute path referring to an existing directory, write output to files (one per process) underneath the given directory. Files will be named according to the final component of the trace2 SID, followed by a counter to avoid potential collisions. This makes it more convenient to collect traces for every git invocation by unconditionally setting the relevant trace2 envvar to a constant directory name. Signed-off-by: Josh Steadmon <steadmon@google.com> Reviewed-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'trace2')
-rw-r--r--trace2/tr2_dst.c63
1 files changed, 61 insertions, 2 deletions
diff --git a/trace2/tr2_dst.c b/trace2/tr2_dst.c
index fd490a4..c3d82ca 100644
--- a/trace2/tr2_dst.c
+++ b/trace2/tr2_dst.c
@@ -1,5 +1,6 @@
#include "cache.h"
#include "trace2/tr2_dst.h"
+#include "trace2/tr2_sid.h"
/*
* If a Trace2 target cannot be opened for writing, we should issue a
@@ -12,6 +13,11 @@
*/
#define TR2_ENVVAR_DST_DEBUG "GIT_TR2_DST_DEBUG"
+/*
+ * How many attempts we will make at creating an automatically-named trace file.
+ */
+#define MAX_AUTO_ATTEMPTS 10
+
static int tr2_dst_want_warning(void)
{
static int tr2env_dst_debug = -1;
@@ -36,6 +42,55 @@ void tr2_dst_trace_disable(struct tr2_dst *dst)
dst->need_close = 0;
}
+static int tr2_dst_try_auto_path(struct tr2_dst *dst, const char *tgt_prefix)
+{
+ int fd;
+ const char *last_slash, *sid = tr2_sid_get();
+ struct strbuf path = STRBUF_INIT;
+ size_t base_path_len;
+ unsigned attempt_count;
+
+ last_slash = strrchr(sid, '/');
+ if (last_slash)
+ sid = last_slash + 1;
+
+ strbuf_addstr(&path, tgt_prefix);
+ if (!is_dir_sep(path.buf[path.len - 1]))
+ strbuf_addch(&path, '/');
+ strbuf_addstr(&path, sid);
+ base_path_len = path.len;
+
+ for (attempt_count = 0; attempt_count < MAX_AUTO_ATTEMPTS; attempt_count++) {
+ if (attempt_count > 0) {
+ strbuf_setlen(&path, base_path_len);
+ strbuf_addf(&path, ".%d", attempt_count);
+ }
+
+ fd = open(path.buf, O_WRONLY | O_CREAT | O_EXCL, 0666);
+ if (fd != -1)
+ break;
+ }
+
+ if (fd == -1) {
+ if (tr2_dst_want_warning())
+ warning("trace2: could not open '%.*s' for '%s' tracing: %s",
+ (int) base_path_len, path.buf,
+ dst->env_var_name, strerror(errno));
+
+ tr2_dst_trace_disable(dst);
+ strbuf_release(&path);
+ return 0;
+ }
+
+ strbuf_release(&path);
+
+ dst->fd = fd;
+ dst->need_close = 1;
+ dst->initialized = 1;
+
+ return dst->fd;
+}
+
static int tr2_dst_try_path(struct tr2_dst *dst, const char *tgt_value)
{
int fd = open(tgt_value, O_WRONLY | O_APPEND | O_CREAT, 0666);
@@ -202,8 +257,12 @@ int tr2_dst_get_trace_fd(struct tr2_dst *dst)
return dst->fd;
}
- if (is_absolute_path(tgt_value))
- return tr2_dst_try_path(dst, tgt_value);
+ if (is_absolute_path(tgt_value)) {
+ if (is_directory(tgt_value))
+ return tr2_dst_try_auto_path(dst, tgt_value);
+ else
+ return tr2_dst_try_path(dst, tgt_value);
+ }
#ifndef NO_UNIX_SOCKETS
if (starts_with(tgt_value, PREFIX_AF_UNIX))