8
*/
9
#define MAX_AUTO_ATTEMPTS 10
10
11
+/*
12
+ * Sentinel file used to detect when we should discard new traces to avoid
13
+ * writing too many trace files to a directory.
14
+ */
15
+#define DISCARD_SENTINEL_NAME "git-trace2-discard"
16
+
17
+/*
18
+ * When set to zero, disables directory file count checks. Otherwise, controls
19
+ * how many files we can write to a directory before entering discard mode.
20
+ * This can be overridden via the TR2_SYSENV_MAX_FILES setting.
21
+ */
22
+static int tr2env_max_files = 0;
23
+
24
static int tr2_dst_want_warning(void)
25
{
26
static int tr2env_dst_debug = -1;
45
dst->need_close = 0;
46
}
47
48
+/*
49
+ * Check to make sure we're not overloading the target directory with too many
50
+ * files. First get the threshold (if present) from the config or envvar. If
51
+ * it's zero or unset, disable this check. Next check for the presence of a
52
+ * sentinel file, then check file count. If we are overloaded, create the
53
+ * sentinel file if it doesn't already exist.
54
+ *
55
+ * We expect that some trace processing system is gradually collecting files
56
+ * from the target directory; after it removes the sentinel file we'll start
57
+ * writing traces again.
58
+ */
59
+static int tr2_dst_too_many_files(const char *tgt_prefix)
60
+{
61
+ int file_count = 0, max_files = 0, ret = 0;
62
+ const char *max_files_var;
63
+ DIR *dirp;
64
+ struct strbuf path = STRBUF_INIT, sentinel_path = STRBUF_INIT;
65
+ struct stat statbuf;
66
+
67
+ /* Get the config or envvar and decide if we should continue this check */
68
+ max_files_var = tr2_sysenv_get(TR2_SYSENV_MAX_FILES);
69
+ if (max_files_var && *max_files_var && ((max_files = atoi(max_files_var)) >= 0))
70
+ tr2env_max_files = max_files;
71
+
72
+ if (!tr2env_max_files) {
73
+ ret = 0;
74
+ goto cleanup;
75
+ }
76
+
77
+ strbuf_addstr(&path, tgt_prefix);
78
+ if (!is_dir_sep(path.buf[path.len - 1])) {
79
+ strbuf_addch(&path, '/');
80
+ }
81
+
82
+ /* check sentinel */
83
+ strbuf_addbuf(&sentinel_path, &path);
84
+ strbuf_addstr(&sentinel_path, DISCARD_SENTINEL_NAME);
85
+ if (!stat(sentinel_path.buf, &statbuf)) {
86
+ ret = 1;
87
+ goto cleanup;
88
+ }
89
+
90
+ /* check file count */
91
+ dirp = opendir(path.buf);
92
+ while (file_count < tr2env_max_files && dirp && readdir(dirp))
93
+ file_count++;
94
+ if (dirp)
95
+ closedir(dirp);
96
+
97
+ if (file_count >= tr2env_max_files) {
98
+ creat(sentinel_path.buf, 0666);
99
+ ret = 1;
100
+ goto cleanup;
101
+ }
102
+
103
+cleanup:
104
+ strbuf_release(&path);
105
+ strbuf_release(&sentinel_path);
106
+ return ret;
107
+}
108
+
109
static int tr2_dst_try_auto_path(struct tr2_dst *dst, const char *tgt_prefix)
110
{
111
int fd;
124
strbuf_addstr(&path, sid);
125
base_path_len = path.len;
126
127
+ if (tr2_dst_too_many_files(tgt_prefix)) {
128
+ strbuf_release(&path);
129
+ if (tr2_dst_want_warning())
130
+ warning("trace2: not opening %s trace file due to too "
131
+ "many files in target directory %s",
132
+ tr2_sysenv_display_name(dst->sysenv_var),
133
+ tgt_prefix);
134
+ return 0;
135
+ }
136
+
137
for (attempt_count = 0; attempt_count < MAX_AUTO_ATTEMPTS; attempt_count++) {
138
if (attempt_count > 0) {
139
strbuf_setlen(&path, base_path_len);