aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gpg.c3
-rw-r--r--src/stat.c160
-rw-r--r--src/triplet.c17
-rw-r--r--src/verify.c18
-rw-r--r--src/wydawca.c12
-rw-r--r--src/wydawca.h1
-rw-r--r--tests/dry_run01.at2
-rw-r--r--tests/upload01.at2
8 files changed, 192 insertions, 23 deletions
diff --git a/src/gpg.c b/src/gpg.c
index 1aafb11..0814b2f 100644
--- a/src/gpg.c
+++ b/src/gpg.c
@@ -121,10 +121,11 @@ static void
121remove_homedir(void) 121remove_homedir(void)
122{ 122{
123 wy_debug(2, (_("removing GNUPG home directory: %s"), temp_homedir)); 123 wy_debug(2, (_("removing GNUPG home directory: %s"), temp_homedir));
124 if (rmdir_r(temp_homedir)) 124 if (rmdir_r(temp_homedir)) {
125 wy_log(LOG_CRIT, _("failed to remove GPG directory %s"), 125 wy_log(LOG_CRIT, _("failed to remove GPG directory %s"),
126 temp_homedir); 126 temp_homedir);
127 } 127 }
128}
128 129
129/* Create a temporary GPG home directory */ 130/* Create a temporary GPG home directory */
130static int 131static int
diff --git a/src/stat.c b/src/stat.c
new file mode 100644
index 0000000..da885f6
--- /dev/null
+++ b/src/stat.c
@@ -0,0 +1,160 @@
1/* wydawca - automatic release submission daemon
2 Copyright (C) 2008-2013, 2017, 2019-2020 Sergey Poznyakoff
3
4 Wydawca is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3 of the License, or (at your
7 option) any later version.
8
9 Wydawca is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with wydawca. If not, see <http://www.gnu.org/licenses/>. */
16
17#include <wydawca.h>
18
19/* Cumulative statistic counters */
20static WY_STAT_COUNTER global_stats[WY_MAX_STAT];
21pthread_mutex_t global_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
22pthread_cond_t global_stats_cond = PTHREAD_COND_INITIALIZER;
23static int stat_stop;
24pthread_t stat_tid;
25
26void
27wydawca_stat_add(int what, size_t n)
28{
29 if (what >= WY_MAX_STAT) abort();
30 pthread_mutex_lock(&global_stats_mutex);
31 global_stats[what] += n;
32 pthread_mutex_unlock(&global_stats_mutex);
33}
34
35void
36wydawca_stat_notify(int final)
37{
38 void *ret;
39 pthread_mutex_lock(&global_stats_mutex);
40 stat_stop = final;
41 pthread_cond_broadcast(&global_stats_cond);
42 pthread_mutex_unlock(&global_stats_mutex);
43 if (final)
44 pthread_join(stat_tid, &ret);
45}
46
47static void
48stat_reset(void)
49{
50 int i;
51
52 for (i = 0; i < WY_MAX_STAT; i++)
53 global_stats[i] = 0;
54}
55
56struct micronent stat_report_schedule;
57
58static void stat_log(void);
59static void stat_reset(void);
60
61void *
62wy_thr_stat(void *ptr)
63{
64 wy_set_cur_thread_name("WY_stat");
65 pthread_mutex_lock(&global_stats_mutex);
66 while (!stat_stop) {
67 struct timespec ts;
68 micron_next_time(&stat_report_schedule, &ts);
69 pthread_cond_timedwait(&global_stats_cond, &global_stats_mutex, &ts);
70 stat_log();
71 notify_stat();
72 stat_reset();
73 }
74 pthread_mutex_unlock(&global_stats_mutex);
75 return NULL;
76}
77
78void
79wydawca_stat_init(void)
80{
81 pthread_create(&stat_tid, NULL, wy_thr_stat, NULL);
82}
83
84static char *stat_name[WY_MAX_STAT] = {
85 N_("errors"),
86 N_("warnings"),
87 N_("bad signatures"),
88 N_("access violation attempts"),
89 N_("complete triplets"),
90 N_("incomplete triplets"),
91 N_("bad triplets"),
92 N_("expired triplets"),
93 N_("triplet successes"),
94 N_("files uploaded"),
95 N_("files archived"),
96 N_("symlinks created"),
97 N_("symlinks removed"),
98 N_("check failures"),
99};
100
101static char *stat_kwname[WY_MAX_STAT] = {
102 "stat:errors",
103 "stat:warnings",
104 "stat:bad_signatures",
105 "stat:access_violations",
106 "stat:complete_triplets",
107 "stat:incomplete_triplets",
108 "stat:bad_triplets",
109 "stat:expired_triplets",
110 "stat:triplet_success",
111 "stat:uploads",
112 "stat:archives",
113 "stat:symlinks",
114 "stat:rmsymlinks",
115 "stat:check_failures"
116};
117
118int
119wy_stat_mask_p(unsigned long mask)
120{
121 int i;
122
123 for (i = 0; i < WY_MAX_STAT; i++)
124 if (global_stats[i] != 0 && (mask && WY_STAT_MASK(i)))
125 return 1;
126 return 0;
127}
128
129int
130wy_stat_expansion(char **ret, char const *name, size_t len)
131{
132 int i;
133
134 for (i = 0; i < WY_MAX_STAT; i++) {
135 if (strlen(stat_kwname[i]) == len
136 && memcmp(stat_kwname[i], name, len) == 0) {
137 size_t size = 0;
138 *ret = NULL;
139 if (grecs_asprintf(ret, &size, "%u", global_stats[i]))
140 return WRDSE_NOSPACE;
141 else
142 return WRDSE_OK;
143 }
144 }
145 return WRDSE_UNDEF;
146}
147
148static void
149stat_log(void)
150{
151 int i;
152
153 if (wy_stat_mask_p(print_stats)) {
154 for (i = 0; i < WY_MAX_STAT; i++)
155 if (print_stats & WY_STAT_MASK(i))
156 wy_log(LOG_INFO, "%s: %u",
157 gettext(stat_name[i]), global_stats[i]);
158 }
159}
160
diff --git a/src/triplet.c b/src/triplet.c
index 138a979..0da254e 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -383,11 +383,13 @@ remove_triplet_unlocked(struct wy_triplet *trp)
383 if (trp->file[i].name) { 383 if (trp->file[i].name) {
384 if (!wy_dry_run) { 384 if (!wy_dry_run) {
385 if (unlinkat(trp->spool->source_fd, trp->file[i].name, 0)) { 385 if (unlinkat(trp->spool->source_fd, trp->file[i].name, 0)) {
386 if (errno != ENOENT) 386 if (errno != ENOENT) {
387 wydawca_stat_incr(WY_STAT_ERRORS);
387 wy_log(LOG_ERR, 388 wy_log(LOG_ERR,
388 _("cannot remove %s/%s: %s"), 389 _("cannot remove %s/%s: %s"),
389 trp->spool->source_dir, 390 trp->spool->source_dir,
390 trp->file[i].name, strerror(errno)); 391 trp->file[i].name, strerror(errno));
392 }
391 } else 393 } else
392 wy_log(LOG_NOTICE, _("removing %s/%s"), 394 wy_log(LOG_NOTICE, _("removing %s/%s"),
393 trp->spool->source_dir, trp->file[i].name); 395 trp->spool->source_dir, trp->file[i].name);
@@ -417,7 +419,8 @@ triplet_commit(struct wy_triplet *trp)
417{ 419{
418 if (spool_open_dictionaries(trp->spool) == 0) { 420 if (spool_open_dictionaries(trp->spool) == 0) {
419 wy_debug(1, (_("processing triplet `%s'"), trp->name)); 421 wy_debug(1, (_("processing triplet `%s'"), trp->name));
420 process_directives(trp); 422 if (process_directives(trp))
423 wydawca_stat_incr(WY_STAT_ERRORS);
421 } 424 }
422} 425}
423 426
@@ -535,6 +538,7 @@ static void wy_ws_error(const char *fmt, ...);
535static inline void 538static inline void
536report_failed_string(char const *str, size_t len) 539report_failed_string(char const *str, size_t len)
537{ 540{
541 wydawca_stat_incr(WY_STAT_ERRORS);
538 if (len > 32) 542 if (len > 32)
539 wy_log(LOG_ERR, _("failed to expand string %16.16s...%16.16s"), 543 wy_log(LOG_ERR, _("failed to expand string %16.16s...%16.16s"),
540 str, str + len - 16); 544 str, str + len - 16);
@@ -1036,6 +1040,7 @@ wy_triplet_get_uploaders(struct wy_triplet *trp)
1036 rc = dictionary_lookup(dict, md, command); 1040 rc = dictionary_lookup(dict, md, command);
1037 free(command); 1041 free(command);
1038 if (rc) { 1042 if (rc) {
1043 wydawca_stat_incr(WY_STAT_ERRORS);
1039 wy_log(LOG_ERR, _("cannot get uploaders for %s"), trp->name); 1044 wy_log(LOG_ERR, _("cannot get uploaders for %s"), trp->name);
1040 dictionary_close(dict, md); 1045 dictionary_close(dict, md);
1041 return NULL; 1046 return NULL;
@@ -1043,6 +1048,7 @@ wy_triplet_get_uploaders(struct wy_triplet *trp)
1043 1048
1044 nrows = dictionary_num_rows(dict); 1049 nrows = dictionary_num_rows(dict);
1045 if (nrows == 0) { 1050 if (nrows == 0) {
1051 wydawca_stat_incr(WY_STAT_ERRORS);
1046 wy_log(LOG_ERR, _("found no uploaders for %s"), trp->name);