]> git.tuebingen.mpg.de Git - dss.git/commitdiff
Merge branch 'master' into next
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 13 Oct 2019 04:05:17 +0000 (06:05 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 13 Oct 2019 04:05:17 +0000 (06:05 +0200)
* master:
  Simplify split_args().

.gitignore
Makefile
dss.c
dss.suite
dss.svg [new file with mode: 0644]
err.h
index.html.in
mklogo [deleted file]
snap.c

index 1bb2a256e58d29073cf553ece92b355f5bf2ef7b..4aafb488c3fc2f1196e67b58c20b7998684a5126 100644 (file)
@@ -5,5 +5,4 @@ dss.lsg.*
 dss
 dss.1
 dss.1.html
-dss.png
 index.html
index 2d0a6bb64e6a4094081b6efc9779fcfc1156a153..ef00f50cffdec1fdf36b24f8fa0f4b5f0adb8035 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -38,9 +38,6 @@ dss: $(dss_objects)
 %.o: %.c Makefile
        $(CC) -c $(DSS_CPPFLAGS) $(CPPFLAGS) $(DSS_CFLAGS) $(CFLAGS) $<
 
-dss.png: mklogo
-       ./mklogo > $@
-
 %.lsg.h: %.suite
        lopsubgen --gen-h=$@ < $<
 %.lsg.c: %.suite
@@ -52,7 +49,7 @@ dss.png: mklogo
        groff -m man -Thtml -P -l -P -r $< | sed -e '1,/^<body>/d; /^<\/body>/,$$d' > $@
 
 clean:
-       rm -f *.o dss dss.1 dss.1.html Makefile.deps *.png *~ index.html dss.lsg.h dss.lsg.c
+       rm -f *.o dss dss.1 dss.1.html Makefile.deps *~ index.html dss.lsg.h dss.lsg.c
 
 ifneq ($(findstring strip, $(MAKECMDGOALS)),)
        strip_option := -s
diff --git a/dss.c b/dss.c
index 217dfafd25c55741e564c0feb13c1ccfbad317d0..1354aa757128d1ec6069290f7c8303991e6eeb5c 100644 (file)
--- a/dss.c
+++ b/dss.c
@@ -651,6 +651,7 @@ static struct snapshot *find_oldest_removable_snapshot(struct snapshot_list *sl)
        int i, num_complete;
        struct snapshot *s, *ref = NULL;
 
+       DSS_DEBUG_LOG(("picking snapshot with earliest creation time\n"));
        num_complete = num_complete_snapshots(sl);
        if (num_complete <= OPT_UINT32_VAL(DSS, MIN_COMPLETE))
                return NULL;
@@ -661,7 +662,6 @@ static struct snapshot *find_oldest_removable_snapshot(struct snapshot_list *sl)
                        ref = s;
                        continue;
                }
-               DSS_INFO_LOG(("oldest removable snapshot: %s\n", s->name));
                return s;
        }
        assert(ref);
@@ -669,6 +669,50 @@ static struct snapshot *find_oldest_removable_snapshot(struct snapshot_list *sl)
        return ref;
 }
 
+/* returns NULL <==> *reason is set to NULL */
+static struct snapshot *find_removable_snapshot(struct snapshot_list *sl,
+               bool try_hard, char **reason)
+{
+       struct snapshot *victim;
+
+       /*
+        * Don't remove anything if there is free space and we have fewer
+        * snapshots than configured, plus one. This way there is always one
+        * snapshot that can be recycled.
+        */
+       if (!try_hard && sl->num_snapshots <=
+                       1 << OPT_UINT32_VAL(DSS, NUM_INTERVALS))
+               goto nope;
+       victim = find_orphaned_snapshot(sl);
+       if (victim) {
+               *reason = make_message("orphaned");
+               return victim;
+       }
+       victim = find_outdated_snapshot(sl);
+       if (victim) {
+               *reason = make_message("outdated");
+               return victim;
+       }
+       if (!OPT_GIVEN(DSS, KEEP_REDUNDANT)) {
+               victim = find_redundant_snapshot(sl);
+               if (victim) {
+                       *reason = make_message("redundant");
+                       return victim;
+               }
+       }
+       if (!try_hard)
+               goto nope;
+       DSS_WARNING_LOG(("nothing obvious to remove\n"));
+       victim = find_oldest_removable_snapshot(sl);
+       if (victim) {
+               *reason = make_message("oldest");
+               return victim;
+       }
+nope:
+       *reason = NULL;
+       return NULL;
+}
+
 static int rename_incomplete_snapshot(int64_t start)
 {
        char *old_name;
@@ -701,7 +745,7 @@ static int try_to_free_disk_space(void)
        struct snapshot_list sl;
        struct snapshot *victim;
        struct timeval now;
-       const char *why;
+       char *why;
        int low_disk_space;
 
        ret = disk_space_low(NULL);
@@ -712,55 +756,25 @@ static int try_to_free_disk_space(void)
        if (tv_diff(&next_removal_check, &now, NULL) > 0)
                return 0;
        if (!low_disk_space) {
-               if (OPT_GIVEN(DSS, KEEP_REDUNDANT))
-                       return 0;
                if (snapshot_creation_status != HS_READY)
                        return 0;
                if (next_snapshot_is_due())
                        return 0;
        }
-       /*
-        * Idle and --keep_redundant not given, or low disk space. Look at
-        * existing snapshots.
-        */
+       /* Idle or low disk space, look at existing snapshots. */
        dss_get_snapshot_list(&sl);
-       ret = 0;
-       /*
-        * Don't remove anything if there is free space and we have fewer
-        * snapshots than configured, plus one. This way there is always one
-        * snapshot that can be recycled.
-        */
-       if (!low_disk_space && sl.num_snapshots <=
-                       1 << OPT_UINT32_VAL(DSS, NUM_INTERVALS))
-               goto out;
-       why = "outdated";
-       victim = find_outdated_snapshot(&sl);
-       if (victim)
-               goto remove;
-       why = "redundant";
-       victim = find_redundant_snapshot(&sl);
-       if (victim)
-               goto remove;
-       why = "orphaned";
-       victim = find_orphaned_snapshot(&sl);
+       victim = find_removable_snapshot(&sl, low_disk_space, &why);
+       if (victim) {
+               pre_remove_hook(victim, why);
+               free(why);
+       }
+       free_snapshot_list(&sl);
        if (victim)
-               goto remove;
-       /* try harder only if disk space is low */
+               return 1;
        if (!low_disk_space)
-               goto out;
-       DSS_WARNING_LOG(("disk space low and nothing obvious to remove\n"));
-       why = "oldest";
-       victim = find_oldest_removable_snapshot(&sl);
-       if (victim)
-               goto remove;
+               return 0;
        DSS_CRIT_LOG(("uhuhu: disk space low and nothing to remove\n"));
-       ret = -ERRNO_TO_DSS_ERROR(ENOSPC);
-       goto out;
-remove:
-       pre_remove_hook(victim, why);
-out:
-       free_snapshot_list(&sl);
-       return ret;
+       return -ERRNO_TO_DSS_ERROR(ENOSPC);
 }
 
 static void post_create_hook(void)
@@ -1645,55 +1659,55 @@ static int com_prune(void)
        struct snapshot_list sl;
        struct snapshot *victim;
        struct disk_space ds;
-       const char *why;
+       char *why;
+       bool try_hard;
 
        lock_dss_or_die();
-       ret = get_disk_space(".", &ds);
-       if (ret < 0)
-               return ret;
-       log_disk_space(&ds);
+       switch (OPT_UINT32_VAL(PRUNE, DISK_SPACE)) {
+       case FDS_LOW: try_hard = true; break;
+       case FDS_HIGH: try_hard = false; break;
+       default:
+               ret = get_disk_space(".", &ds);
+               if (ret < 0)
+                       return ret;
+               log_disk_space(&ds);
+               try_hard = disk_space_low(&ds);
+       }
        dss_get_snapshot_list(&sl);
-       why = "outdated";
-       victim = find_outdated_snapshot(&sl);
-       if (victim)
-               goto rm;
-       why = "redundant";
-       victim = find_redundant_snapshot(&sl);
-       if (victim)
-               goto rm;
-       ret = 0;
-       goto out;
-rm:
+       victim = find_removable_snapshot(&sl, try_hard, &why);
+       if (!victim) {
+               dss_msg("nothing to prune\n");
+               ret = 0;
+               goto free_sl;
+       }
        if (OPT_GIVEN(DSS, DRY_RUN)) {
-               dss_msg("%s snapshot %s (interval = %i)\n",
+               dss_msg("picking %s snapshot %s (interval = %i)\n",
                        why, victim->name, victim->interval);
                ret = 0;
-               goto out;
+               goto free_why;
        }
        pre_remove_hook(victim, why);
        if (snapshot_removal_status == HS_PRE_RUNNING) {
                ret = wait_for_remove_process();
                if (ret < 0)
-                       goto out;
+                       goto free_why;
+               ret = -E_HOOK_FAILED;
                if (snapshot_removal_status != HS_PRE_SUCCESS)
-                       goto out;
+                       goto free_why;
        }
        ret = exec_rm();
        if (ret < 0)
-               goto out;
+               goto free_why;
        ret = wait_for_remove_process();
        if (ret < 0)
-               goto out;
-       if (snapshot_removal_status != HS_SUCCESS)
-               goto out;
+               goto free_why;
+       assert(snapshot_removal_status == HS_SUCCESS);
        post_remove_hook();
-       if (snapshot_removal_status != HS_POST_RUNNING)
-               goto out;
+       assert(snapshot_removal_status == HS_POST_RUNNING);
        ret = wait_for_remove_process();
-       if (ret < 0)
-               goto out;
-       ret = 1;
-out:
+free_why:
+       free(why);
+free_sl:
        free_snapshot_list(&sl);
        return ret;
 }
index 16c7e58542eff8750c8437dcea137f347a435950..f9cf8af5993345452fddc7b3d9790d0d7e6d7a13 100644 (file)
--- a/dss.suite
+++ b/dss.suite
@@ -450,19 +450,38 @@ caption = Subcommands
                snapshots.
        [/description]
 [subcommand prune]
-       purpose = remove redundant and outdated snapshots
+       purpose = remove snapshots
        [description]
-               A snapshot is considered outdated if its interval number is greater or
-               equal than the specified number of unit intervals. See --unit-interval
-               and --num-intervals above.
-
-               A snapshot is said to be redundant if the interval it belongs to
-               contains more than the configured number of snapshots.
-
-               The prune command gets rid of both outdated and redundant snapshots. At
-               most one snapshot is removed per invocation. If --dry-run is given, the
-               subcommand only prints the snapshot that would be removed.
+               A snapshot is said to be (a) outdated if its interval number is greater
+               or equal than the specified number of unit intervals, (b) redundant if
+               the interval it belongs to contains more than the configured number of
+               snapshots, and (c) orphaned if it is incomplete and not being created
+               or deleted. All other snapshots are called regular.
+
+               Unless --dry-run is given, which just prints the snapshot that would be
+               removed, this subcommand gets rid of non-regular snapshots.  At most
+               one snapshot is removed per invocation. If no such snapshot exists
+               and disk space is low, the subcommand also removes regular snapshots,
+               always picking the oldest one.
+
+               The subcommand fails if there is another dss "run" process.
        [/description]
+       [option disk-space]
+               summary = act as if free disk space was high/low
+               arg_info = required_arg
+               arg_type = string
+               typestr = mode
+               values = {
+                       FDS_CHECK = "check",
+                       FDS_HIGH = "high",
+                       FDS_LOW = "low"
+               }
+               default_val = check
+               [help]
+                       By default, free disk space is checked and even regular snapshots
+                       become candidates for removal if disk space is low. This option
+                       overrides the result of the check.
+               [/help]
 [subcommand ls]
        purpose = print the list of all snapshots
        [description]
diff --git a/dss.svg b/dss.svg
new file mode 100644 (file)
index 0000000..fb69bd7
--- /dev/null
+++ b/dss.svg
@@ -0,0 +1,65 @@
+<svg
+       xmlns="http://www.w3.org/2000/svg"
+       xmlns:xlink="http://www.w3.org/1999/xlink"
+       width="154"
+       height="100"
+>
+       <defs>
+               <rect id="rect"
+                       stroke-width="0"
+                       x="0"
+                       y="0"
+                       width="37"
+                       height="94"
+               />
+       </defs>
+       <defs>
+               <circle id="circle"
+                       stroke-width="1"
+                       stroke="black"
+                       fill="#a22"
+                       cx="0"
+                       cy="0"
+                       r="4"
+               />
+       </defs>
+       <marker
+               id="arrow"
+               stroke="white"
+               fill="white"
+               viewBox="0 0 10 10" refX="5" refY="5"
+               markerWidth="4" markerHeight="4"
+               orient="auto-start-reverse">
+               <path d="M 0 0 L 10 5 L 0 10 z" />
+       </marker>
+       <use fill="#bbf" xlink:href="#rect" transform="translate(0, 0)"/>
+       <use fill="#99f" xlink:href="#rect" transform="translate(36, 0)"/>
+       <use fill="#44f" xlink:href="#rect" transform="translate(72, 0)"/>
+       <use fill="#11f" xlink:href="#rect" transform="translate(108, 0)"/>
+
+       <text x="47" y="40" stroke="white" fill="white" font-size="25">DSS</text>
+
+       <line
+               x1="7" y1="50" x2="127" y2="50" stroke-width="3"
+               stroke="white"
+               marker-end="url(#arrow)"
+       />
+       <use xlink:href="#circle" x="18" y="77"/>
+
+       <use xlink:href="#circle" x="48" y="77"/>
+       <use xlink:href="#circle" x="60" y="77"/>
+
+       <use xlink:href="#circle" x="77" y="77"/>
+       <use xlink:href="#circle" x="86" y="77"/>
+       <use xlink:href="#circle" x="95" y="77"/>
+       <use xlink:href="#circle" x="104" y="77"/>
+
+       <use xlink:href="#circle" x="113" y="70"/>
+       <use xlink:href="#circle" x="122" y="70"/>
+       <use xlink:href="#circle" x="131" y="70"/>
+       <use xlink:href="#circle" x="140" y="70"/>
+       <use xlink:href="#circle" x="114" y="85"/>
+       <use xlink:href="#circle" x="122" y="85"/>
+       <use xlink:href="#circle" x="130" y="85"/>
+       <use xlink:href="#circle" x="138" y="85"/>
+</svg>
diff --git a/err.h b/err.h
index 9505dfcc99f718ce1f8fe540401446e1dff82e8e..bd22554dd90d8ee2e282ff3c8c24b2fd56b7d5cd 100644 (file)
--- a/err.h
+++ b/err.h
@@ -44,6 +44,7 @@ static inline char *dss_strerror(int num)
        DSS_ERROR(INVALID_NUMBER, "invalid number"), \
        DSS_ERROR(STRFTIME, "strftime() failed"), \
        DSS_ERROR(LOCALTIME, "localtime() failed"), \
+       DSS_ERROR(HOOK_FAILED, "hook failure"), \
        DSS_ERROR(MOUNTPOINT, "destination directory is no mountpoint"), \
        DSS_ERROR(NULL_OPEN, "can not open /dev/null"), \
        DSS_ERROR(DUP_PIPE, "exec error: can not create pipe"), \
index 42606cabd91b2e80a41a3c959ac4b683a53f5753..b505761997987f74dfe6a9d2fe73046e21a0e868 100644 (file)
@@ -12,7 +12,7 @@
        <table>
                <tr>
                        <td>
-                               <IMG SRC="dss.png" alt="dss">
+                               <img src="dss.svg" alt="dss">
                        </td>
                        <td>
                                <h1>The dyadic snapshot scheduler</h1>
diff --git a/mklogo b/mklogo
deleted file mode 100755 (executable)
index d4705ba..0000000
--- a/mklogo
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-
-# Script for Image Magick that writes the dss logo in png format
-# to stdout.
-
-set -u
-
-width=320
-height=110
-border=5
-radius1=4
-radius2=5
-circle_y=90
-arrow_y=70
-text_x=128
-text_y=55
-pointsize=36
-
-declare -a circle arrow rectangle text
-
-make_circles()
-{
-       local inner='stroke black fill red circle'
-       local outer='stroke black fill black circle'
-       local num=1
-       local idx=0
-       local y=$circle_y
-       local step x0 i j idx num
-
-       for ((i = 0; i < 4; i++)); do
-               step=$(((width / 4 + num) / (num + 1)))
-               x0=$((border + width / 4 * i))
-               for ((j = 1; j <= $num; j++)); do
-                       x=$((x0 + j * $step))
-                       circle[$idx]='-draw'; let idx++
-                       circle[$idx]="$outer $x,$y,$((x + radius2)),$y"; let idx++
-                       circle[$idx]='-draw'; let idx++
-                       circle[$idx]="$inner $x,$y,$((x + radius1)),$y"; let idx++
-               done
-               num=$((num * 2))
-       done
-       #echo "${circle[@]}"; exit 0
-}
-
-make_arrow()
-{
-       local arrow_head='l -15,-5  +5,+5  -5,+5  +15,-5 z'
-       local idx=0
-       local x0 x1 y
-
-       arrow[$idx]='-draw'; let idx++
-       x0=$((3 * border)); x1=$((width - 2 * border))
-       y=$arrow_y
-       arrow[$idx]="stroke white line $x0,$y $x1,$y"; let idx++
-       arrow[$idx]='-draw'; let idx++
-       x0=$((width - 2 * border))
-       arrow[$idx]="stroke white fill white path 'M $x0,$y $arrow_head'"
-       #echo "${arrow[@]}"; exit 0
-}
-
-make_rectangles()
-{
-       local idx=0
-       local x x0 x1 y y0 y1 i red_green color
-
-       rectangle[$idx]='-draw'; let idx++
-       x=$((width + 2 * border))
-       y=$((height + 2 * border))
-       rectangle[$idx]="stroke yellow fill yellow rectangle 0,0 $x,$y"; let idx++
-       for ((i = 0; i < 4; i++)); do
-               rectangle[$idx]='-draw'; let idx++
-               red_green="$(printf '%02x' $(((3 - i) * 60)))"
-               color="#${red_green}${red_green}ff"
-               x0=$((border + i * width / 4)); x1=$((x0 + width / 4 - 1))
-               y0=$border; y1=$((y0 + height))
-               rectangle[$idx]="stroke $color fill $color rectangle $x0,$y0 $x1,$y1"
-               let idx++
-       done
-       #echo "${rectangle[@]}"; exit 0
-}
-
-make_text()
-{
-       text=(-pointsize $pointsize -draw \
-               "fill white text $text_x,$text_y DSS")
-       #echo "${text[@]}"; exit 0
-}
-
-make_rectangles
-make_arrow
-make_circles
-make_text
-
-convert -size $((width + 2 * border))x$((height + 2 * border)) \
-       -background none xc: \
-       "${rectangle[@]}" \
-       "${arrow[@]}" \
-       "${circle[@]}" \
-       "${text[@]}" \
-       png:-
diff --git a/snap.c b/snap.c
index 8de76d459da1a8844a452fa576d706014b229be9..da95c1f342dc09bcc01d1eef58a075dd721472ef 100644 (file)
--- a/snap.c
+++ b/snap.c
@@ -146,7 +146,7 @@ static int compare_snapshots(const void *a, const void *b)
        return NUM_COMPARE(s2->creation_time, s1->creation_time);
 }
 
-
+/* The returned snapshot list is sorted by creation time. */
 void get_snapshot_list(struct snapshot_list *sl, int unit_interval,
                int num_intervals)
 {