config + job: forbid non-verlapping receiver root_fs

refs #136
refs #140
This commit is contained in:
Christian Schwarz
2019-03-20 23:01:24 +01:00
parent 3e71542c78
commit 7756c9a55c
8 changed files with 122 additions and 4 deletions
+43
View File
@@ -2,6 +2,9 @@ package job
import (
"fmt"
"sort"
"strings"
"github.com/pkg/errors"
"github.com/zrepl/zrepl/config"
)
@@ -18,6 +21,22 @@ func JobsFromConfig(c *config.Config) ([]Job, error) {
}
js[i] = j
}
// receiving-side root filesystems must not overlap
{
rfss := make([]string, len(js))
for i, j := range js {
jrfs, ok := j.OwnedDatasetSubtreeRoot()
if !ok {
continue
}
rfss[i] = jrfs.ToString()
}
if err := validateReceivingSidesDoNotOverlap(rfss); err != nil {
return nil, err
}
}
return js, nil
}
@@ -74,3 +93,27 @@ func buildJob(c *config.Global, in config.JobEnum) (j Job, err error) {
return j, nil
}
func validateReceivingSidesDoNotOverlap(receivingRootFSs []string) error {
if len(receivingRootFSs) == 0 {
return nil
}
rfss := make([]string, len(receivingRootFSs))
copy(rfss, receivingRootFSs)
sort.Slice(rfss, func(i, j int) bool {
return strings.Compare(rfss[i], rfss[j]) == -1
})
// idea:
// no path in rfss must be prefix of another
//
// rfss is now lexicographically sorted, which means that
// if i is prefix of j, i < j (in lexicographical order)
// thus,
// if any i is prefix of i+n (n >= 1), there is overlap
for i := 0; i < len(rfss)-1; i++ {
if strings.HasPrefix(rfss[i+1], rfss[i]) {
return fmt.Errorf("receiving jobs with overlapping root filesystems are forbidden")
}
}
return nil
}