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
remove_homedir(void)
{
wy_debug(2, (_("removing GNUPG home directory: %s"), temp_homedir));
- if (rmdir_r(temp_homedir))
+ if (rmdir_r(temp_homedir)) {
wy_log(LOG_CRIT, _("failed to remove GPG directory %s"),
temp_homedir);
}
+}
/* Create a temporary GPG home directory */
static 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 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2008-2013, 2017, 2019-2020 Sergey Poznyakoff
+
+ Wydawca is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ Wydawca is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with wydawca. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <wydawca.h>
+
+/* Cumulative statistic counters */
+static WY_STAT_COUNTER global_stats[WY_MAX_STAT];
+pthread_mutex_t global_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t global_stats_cond = PTHREAD_COND_INITIALIZER;
+static int stat_stop;
+pthread_t stat_tid;
+
+void
+wydawca_stat_add(int what, size_t n)
+{
+ if (what >= WY_MAX_STAT) abort();
+ pthread_mutex_lock(&global_stats_mutex);
+ global_stats[what] += n;
+ pthread_mutex_unlock(&global_stats_mutex);
+}
+
+void
+wydawca_stat_notify(int final)
+{
+ void *ret;
+ pthread_mutex_lock(&global_stats_mutex);
+ stat_stop = final;
+ pthread_cond_broadcast(&global_stats_cond);
+ pthread_mutex_unlock(&global_stats_mutex);
+ if (final)
+ pthread_join(stat_tid, &ret);
+}
+
+static void
+stat_reset(void)
+{
+ int i;
+
+ for (i = 0; i < WY_MAX_STAT; i++)
+ global_stats[i] = 0;
+}
+
+struct micronent stat_report_schedule;
+
+static void stat_log(void);
+static void stat_reset(void);
+
+void *
+wy_thr_stat(void *ptr)
+{
+ wy_set_cur_thread_name("WY_stat");
+ pthread_mutex_lock(&global_stats_mutex);
+ while (!stat_stop) {
+ struct timespec ts;
+ micron_next_time(&stat_report_schedule, &ts);
+ pthread_cond_timedwait(&global_stats_cond, &global_stats_mutex, &ts);
+ stat_log();
+ notify_stat();
+ stat_reset();
+ }
+ pthread_mutex_unlock(&global_stats_mutex);
+ return NULL;
+}
+
+void
+wydawca_stat_init(void)
+{
+ pthread_create(&stat_tid, NULL, wy_thr_stat, NULL);
+}
+
+static char *stat_name[WY_MAX_STAT] = {
+ N_("errors"),
+ N_("warnings"),
+ N_("bad signatures"),
+ N_("access violation attempts"),
+ N_("complete triplets"),
+ N_("incomplete triplets"),
+ N_("bad triplets"),
+ N_("expired triplets"),
+ N_("triplet successes"),
+ N_("files uploaded"),
+ N_("files archived"),
+ N_("symlinks created"),
+ N_("symlinks removed"),
+ N_("check failures"),
+};
+
+static char *stat_kwname[WY_MAX_STAT] = {
+ "stat:errors",
+ "stat:warnings",
+ "stat:bad_signatures",
+ "stat:access_violations",
+ "stat:complete_triplets",
+ "stat:incomplete_triplets",
+ "stat:bad_triplets",
+ "stat:expired_triplets",
+ "stat:triplet_success",
+ "stat:uploads",
+ "stat:archives",
+ "stat:symlinks",
+ "stat:rmsymlinks",
+ "stat:check_failures"
+};
+
+int
+wy_stat_mask_p(unsigned long mask)
+{
+ int i;
+
+ for (i = 0; i < WY_MAX_STAT; i++)
+ if (global_stats[i] != 0 && (mask && WY_STAT_MASK(i)))
+ return 1;
+ return 0;
+}
+
+int
+wy_stat_expansion(char **ret, char const *name, size_t len)
+{
+ int i;
+
+ for (i = 0; i < WY_MAX_STAT; i++) {
+ if (strlen(stat_kwname[i]) == len
+ && memcmp(stat_kwname[i], name, len) == 0) {
+ size_t size = 0;
+ *ret = NULL;
+ if (grecs_asprintf(ret, &size, "%u", global_stats[i]))
+ return WRDSE_NOSPACE;
+ else
+ return WRDSE_OK;
+ }
+ }
+ return WRDSE_UNDEF;
+}
+
+static void
+stat_log(void)
+{
+ int i;
+
+ if (wy_stat_mask_p(print_stats)) {
+ for (i = 0; i < WY_MAX_STAT; i++)
+ if (print_stats & WY_STAT_MASK(i))
+ wy_log(LOG_INFO, "%s: %u",
+ gettext(stat_name[i]), global_stats[i]);
+ }
+}
+
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)
if (trp->file[i].name) {
if (!wy_dry_run) {
if (unlinkat(trp->spool->source_fd, trp->file[i].name, 0)) {
- if (errno != ENOENT)
+ if (errno != ENOENT) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR,
_("cannot remove %s/%s: %s"),
trp->spool->source_dir,
trp->file[i].name, strerror(errno));
+ }
} else
wy_log(LOG_NOTICE, _("removing %s/%s"),
trp->spool->source_dir, trp->file[i].name);
@@ -417,7 +419,8 @@ triplet_commit(struct wy_triplet *trp)
{
if (spool_open_dictionaries(trp->spool) == 0) {
wy_debug(1, (_("processing triplet `%s'"), trp->name));
- process_directives(trp);
+ if (process_directives(trp))
+ wydawca_stat_incr(WY_STAT_ERRORS);
}
}
@@ -535,6 +538,7 @@ static void wy_ws_error(const char *fmt, ...);
static inline void
report_failed_string(char const *str, size_t len)
{
+ wydawca_stat_incr(WY_STAT_ERRORS);
if (len > 32)
wy_log(LOG_ERR, _("failed to expand string %16.16s...%16.16s"),
str, str + len - 16);
@@ -1036,6 +1040,7 @@ wy_triplet_get_uploaders(struct wy_triplet *trp)
rc = dictionary_lookup(dict, md, command);
free(command);
if (rc) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR, _("cannot get uploaders for %s"), trp->name);
dictionary_close(dict, md);
return NULL;
@@ -1043,6 +1048,7 @@ wy_triplet_get_uploaders(struct wy_triplet *trp)
nrows = dictionary_num_rows(dict);
if (nrows == 0) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR, _("found no uploaders for %s"), trp->name);
dictionary_close(dict, md);
return NULL;
@@ -1050,6 +1056,7 @@ wy_triplet_get_uploaders(struct wy_triplet *trp)
ncols = dictionary_num_cols(dict);
if (ncols < 4) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR,
_("project-uploader dictionary error: "
"too few columns (%lu)"), (unsigned long) ncols);
@@ -1084,6 +1091,7 @@ wy_triplet_get_uploaders(struct wy_triplet *trp)
}
if (!info.name || !info.realname || !info.gpg_key || !info.email) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR,
_("project-uploader dictionary error: "
"malformed row %lu"), (unsigned long) i);
@@ -1104,6 +1112,7 @@ wy_triplet_get_uploaders(struct wy_triplet *trp)
dictionary_close(dict, md);
if (!head) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR, _("no valid uploaders found for %s"), trp->name);
return NULL;
}
@@ -1138,6 +1147,7 @@ wy_triplet_get_admins(struct wy_triplet *trp)
dict = spool->dictionary[project_owner_dict];
if (dict->type == dictionary_none) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR,
_("%s: dictionary %s not configured (spool %s)"),
trp->name, "project_owner_dict", spool->tag);
@@ -1146,6 +1156,7 @@ wy_triplet_get_admins(struct wy_triplet *trp)
md = dictionary_open(dict);
if (!md) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR,
_("%s: failed to open dictionary %s (spool %s)"),
trp->name, "project_owner_dict", spool->tag);
@@ -1157,6 +1168,7 @@ wy_triplet_get_admins(struct wy_triplet *trp)
rc = dictionary_lookup(dict, md, command);
free(command);
if (rc) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR,
_("%s: cannot obtain recipient emails"), trp->name);
dictionary_close(dict, md);
@@ -1167,6 +1179,7 @@ wy_triplet_get_admins(struct wy_triplet *trp)
ncols = dictionary_num_cols(dict);
if (nrows == 0) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
wy_log(LOG_ERR,
_("%s: cannot obtain recipient emails"), trp->name);
return NULL;
diff --git a/src/verify.c b/src/verify.c
index 39626f3..c3b1845 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -133,6 +133,7 @@ fill_project_name(struct wy_triplet *trp)
trp->blurb = blurb;
if (directive_parse(trp)) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
free(blurb);
trp->blurb = NULL;
return 1;
@@ -189,13 +190,18 @@ real_verify_directive_file(struct wy_triplet *trp)
if (!wy_triplet_get_uploaders(trp))
return DIRECTIVE_BAD;
- if (verify_directive_signature(trp)) {
- /*FIXME: Update stats */
+ switch (verify_directive_signature(trp)) {
+ case 0:
+ wy_debug(1, (_("%s: directive file signature OK"), trp->name));
+ break;
+ case 1:
wy_log(LOG_ERR, _("invalid signature for %s"),
trp->name ? trp->name : "[unknown]");
return DIRECTIVE_BAD;
- } else
- wy_debug(1, (_("%s: directive file signature OK"), trp->name));
+ case -1:
+ wydawca_stat_incr(WY_STAT_ERRORS);
+ return DIRECTIVE_BAD;
+ }
if (wy_debug_level > 1) {
int i;
@@ -203,8 +209,10 @@ real_verify_directive_file(struct wy_triplet *trp)
wy_log(LOG_DEBUG, "directive[%d] = %s", i, trp->directive[i]);
}
- if (verify_directive_format(trp))
+ if (verify_directive_format(trp)) {
+ wydawca_stat_incr(WY_STAT_ERRORS);
return DIRECTIVE_BAD;
+ }
return DIRECTIVE_GOOD;
}
diff --git a/src/wydawca.c b/src/wydawca.c
index 635a158..525e538 100644
--- a/src/wydawca.c
+++ b/src/wydawca.c
@@ -138,18 +138,6 @@ static void (*log_printer) (int prio, const char *fmt, va_list ap) =
void
wy_vlog(int prio, char const *fmt, va_list ap)
{
- switch (prio) {
- case LOG_EMERG:
- case LOG_ALERT:
- case LOG_CRIT:
- case LOG_ERR:
- wydawca_stat_incr(WY_STAT_ERRORS);
- break;
-
- case LOG_WARNING:
- wydawca_stat_incr(WY_STAT_WARNINGS);
- }
-
log_printer(prio, fmt, ap);
}
diff --git a/src/wydawca.h b/src/wydawca.h
index fabd461..cb29ebc 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -365,7 +365,6 @@ extern size_t spool_count;
typedef unsigned WY_STAT_COUNTER;
-void wydawca_stat_log(void);
void wydawca_stat_init(void);
void wydawca_stat_notify(int final);
void wydawca_stat_add(int what, size_t n);
diff --git a/tests/dry_run01.at b/tests/dry_run01.at
index 387a9da..ff7294b 100644
--- a/tests/dry_run01.at
+++ b/tests/dry_run01.at
@@ -63,7 +63,7 @@ sed -e 's/incomplete triplets: 1/incomplete triplets: 0/' err >&2
[wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) started
wydawca: [[ERR]] No public key
wydawca: [[ERR]] invalid signature for conversion-1.1.tar
-wydawca: [[INFO]] errors: 2
+wydawca: [[INFO]] errors: 0
wydawca: [[INFO]] warnings: 0
wydawca: [[INFO]] bad signatures: 1
wydawca: [[INFO]] access violation attempts: 1
diff --git a/tests/upload01.at b/tests/upload01.at
index 279599e..be25c25 100644
--- a/tests/upload01.at
+++ b/tests/upload01.at
@@ -71,7 +71,7 @@ upload dir
[wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) started
wydawca: [[ERR]] No public key
wydawca: [[ERR]] invalid signature for conversion-1.1.tar
-wydawca: [[INFO]] errors: 2
+wydawca: [[INFO]] errors: 0
wydawca: [[INFO]] warnings: 0
wydawca: [[INFO]] bad signatures: 1
wydawca: [[INFO]] access violation attempts: 1

Return to:

Send suggestions and report system problems to the System administrator.