/*
- * Copyright (C) 2008-2011 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2008-2011 Andre Noll <maan@tuebingen.mpg.de>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
#include "gcc-compat.h"
#include "cmdline.h"
#include "log.h"
-#include "string.h"
-#include "error.h"
-#include "fd.h"
+#include "str.h"
+#include "err.h"
+#include "file.h"
#include "exec.h"
#include "daemon.h"
-#include "signal.h"
+#include "sig.h"
#include "df.h"
-#include "time.h"
+#include "tv.h"
#include "snap.h"
#include "ipc.h"
static struct snapshot *find_oldest_removable_snapshot(struct snapshot_list *sl)
{
- int i;
- struct snapshot *s;
+ int i, num_complete;
+ struct snapshot *s, *ref = NULL;
+
+ num_complete = num_complete_snapshots(sl);
+ if (num_complete <= conf.min_complete_arg)
+ return NULL;
FOR_EACH_SNAPSHOT(s, i, sl) {
if (snapshot_is_being_created(s))
continue;
- if (is_reference_snapshot(s))
+ if (is_reference_snapshot(s)) { /* avoid this one */
+ ref = s;
continue;
+ }
DSS_INFO_LOG(("oldest removable snapshot: %s\n", s->name));
return s;
}
- return NULL;
+ assert(ref);
+ DSS_WARNING_LOG(("removing reference snapshot %s\n", ref->name));
+ return ref;
}
static int rename_incomplete_snapshot(int64_t start)
{
char *old_name;
int ret;
+ int64_t now;
+ /*
+ * We don't want the dss_rename() below to fail with EEXIST because the
+ * last complete snapshot was created (and completed) in the same
+ * second as this one.
+ */
+ while ((now = get_current_time()) == start)
+ sleep(1);
free(path_to_last_complete_snapshot);
- ret = complete_name(start, get_current_time(),
- &path_to_last_complete_snapshot);
+ ret = complete_name(start, now, &path_to_last_complete_snapshot);
if (ret < 0)
return ret;
old_name = incomplete_name(start);
return -E_INVALID_NUMBER;
}
DSS_DEBUG_LOG(("unit interval: %i day(s)\n", conf.unit_interval_arg));
- if (conf.num_intervals_arg <= 0) {
- DSS_ERROR_LOG(("bad number of intervals %i\n", conf.num_intervals_arg));
+ if (conf.num_intervals_arg <= 0 || conf.num_intervals_arg > 30) {
+ DSS_ERROR_LOG(("bad number of intervals: %i\n",
+ conf.num_intervals_arg));
return -E_INVALID_NUMBER;
}
DSS_DEBUG_LOG(("number of intervals: %i\n", conf.num_intervals_arg));
return change_to_dest_dir();
}
+static void kill_children(void)
+{
+ restart_create_process();
+ dss_kill(create_pid, SIGTERM, NULL);
+ dss_kill(remove_pid, SIGTERM, NULL);
+}
+
static int handle_signal(void)
{
int sig, ret = next_signal();
switch (sig) {
case SIGINT:
case SIGTERM:
- restart_create_process();
- dss_kill(create_pid, SIGTERM, NULL);
- dss_kill(remove_pid, SIGTERM, NULL);
+ kill_children();
ret = -E_SIGNAL;
break;
case SIGHUP:
*argv = dss_malloc((15 + conf.rsync_option_given) * sizeof(char *));
(*argv)[i++] = dss_strdup("rsync");
- (*argv)[i++] = dss_strdup("-aq");
+ (*argv)[i++] = dss_strdup("-a");
(*argv)[i++] = dss_strdup("--delete");
for (j = 0; j < conf.rsync_option_given; j++)
(*argv)[i++] = dss_strdup(conf.rsync_option_arg[j]);
ret = select_loop();
if (ret >= 0) /* impossible */
ret = -E_BUG;
+ kill_children();
exit_hook(ret);
return ret;
}
if (s->flags & SS_COMPLETE)
d = (s->completion_time - s->creation_time) / 60;
dss_msg("%u\t%s\t%3" PRId64 ":%02" PRId64 "\n", s->interval, s->name, d/60, d%60);
- };
+ }
free_snapshot_list(&sl);
return 1;
}
if (ret < 0)
goto out;
ret = call_command_handler();
+ signal_shutdown();
out:
if (ret < 0)
DSS_EMERG_LOG(("%s\n", dss_strerror(-ret)));