X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=ood.go;h=39c265cf787ef253bfdb6193d0bd3e9dcd094557;hb=f0f007ed9bb046289965d2a7e64f215e4a50a441;hp=c455a3b01e22c3221f0b9a5eccc72db6b83996d0;hpb=2fe7eaeac99947f761f4665893c09db31d6b3a4b;p=goredo.git diff --git a/ood.go b/ood.go index c455a3b..39c265c 100644 --- a/ood.go +++ b/ood.go @@ -1,6 +1,6 @@ /* goredo -- djb's redo implementation on pure Go -Copyright (C) 2020-2021 Sergey Matveev +Copyright (C) 2020-2022 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -48,14 +48,14 @@ var ( FdOODTgtsLock *os.File ) -type TgtErr struct { +type TgtError struct { Tgt string Err error } -func (e TgtErr) Unwrap() error { return e.Err } +func (e TgtError) Unwrap() error { return e.Err } -func (e TgtErr) Error() string { +func (e TgtError) Error() string { return fmt.Sprintf("%s: %s", e.Tgt, e.Err) } @@ -107,33 +107,33 @@ func isOODByBuildUUID(cwd, tgtOrig string) bool { func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, error) { indent := strings.Repeat(". ", level) - trace(CDebug, "ood: %s%s checking", indent, tgtOrig) + tracef(CDebug, "ood: %s%s checking", indent, tgtOrig) cwd, tgt := cwdAndTgt(path.Join(cwd, tgtOrig)) depPath := path.Join(cwd, RedoDir, tgt+DepSuffix) fdDep, err := os.Open(depPath) if err != nil { - trace(CDebug, "ood: %s%s -> no dep: %s", indent, tgtOrig, depPath) + tracef(CDebug, "ood: %s%s -> no dep: %s", indent, tgtOrig, depPath) return true, nil } depInfo, err := depRead(fdDep) fdDep.Close() if err != nil { - return true, TgtErr{tgtOrig, err} + return true, TgtError{tgtOrig, err} } if depInfo.build == BuildUUID { - trace(CDebug, "ood: %s%s -> already built", indent, tgtOrig) + tracef(CDebug, "ood: %s%s -> already built", indent, tgtOrig) return false, nil } if _, err := os.Stat(path.Join(cwd, tgt)); err != nil && os.IsNotExist(err) { - trace(CDebug, "ood: %s%s -> non-existent", indent, tgtOrig) + tracef(CDebug, "ood: %s%s -> non-existent", indent, tgtOrig) return true, nil } ood := false for _, dep := range depInfo.ifcreates { if _, err := os.Stat(path.Join(cwd, dep)); err == nil { - trace(CDebug, "ood: %s%s -> %s created", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s created", indent, tgtOrig, dep) ood = true goto Done } @@ -142,80 +142,80 @@ func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, erro for _, m := range depInfo.ifchanges { dep := m["Target"] if dep == "" { - return ood, TgtErr{tgtOrig, errors.New("invalid format of .rec: missing Target")} + return ood, TgtError{tgtOrig, errors.New("invalid format of .rec: missing Target")} } theirInode, err := inodeFromRec(m) if err != nil { - return ood, TgtErr{tgtOrig, fmt.Errorf("invalid format of .rec: %w", err)} + return ood, TgtError{tgtOrig, fmt.Errorf("invalid format of .rec: %w", err)} } theirHsh := m["Hash"] - trace(CDebug, "ood: %s%s -> %s: checking", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: checking", indent, tgtOrig, dep) fd, err := os.Open(path.Join(cwd, dep)) if err != nil { if os.IsNotExist(err) { - trace(CDebug, "ood: %s%s -> %s: not exists", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: not exists", indent, tgtOrig, dep) ood = true goto Done } - return ood, TgtErr{tgtOrig, err} + return ood, TgtError{tgtOrig, err} } defer fd.Close() inode, err := inodeFromFile(fd) if err != nil { - return ood, TgtErr{tgtOrig, err} + return ood, TgtError{tgtOrig, err} } if inode.Size != theirInode.Size { - trace(CDebug, "ood: %s%s -> %s: size differs", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: size differs", indent, tgtOrig, dep) ood = true goto Done } - if InodeTrust && inode.Equals(theirInode) { - trace(CDebug, "ood: %s%s -> %s: same inode", indent, tgtOrig, dep) + if InodeTrust != InodeTrustNone && inode.Equals(theirInode) { + tracef(CDebug, "ood: %s%s -> %s: same inode", indent, tgtOrig, dep) } else { - trace(CDebug, "ood: %s%s -> %s: inode differs", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: inode differs", indent, tgtOrig, dep) hsh, err := fileHash(fd) if err != nil { - return ood, TgtErr{tgtOrig, err} + return ood, TgtError{tgtOrig, err} } if theirHsh != hsh { - trace(CDebug, "ood: %s%s -> %s: hash differs", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: hash differs", indent, tgtOrig, dep) ood = true goto Done } - trace(CDebug, "ood: %s%s -> %s: same hash", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: same hash", indent, tgtOrig, dep) } fd.Close() // optimization not to hold it for long if dep == tgt { - trace(CDebug, "ood: %s%s -> %s: same target", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: same target", indent, tgtOrig, dep) continue } if isSrc(cwd, dep) { - trace(CDebug, "ood: %s%s -> %s: is source", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: is source", indent, tgtOrig, dep) continue } if _, ok := seen[cwdMustRel(cwd, dep)]; ok { - trace(CDebug, "ood: %s%s -> %s: was always built", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: was always built", indent, tgtOrig, dep) continue } depOod, err := isOODWithTrace(cwd, dep, level+1, seen) if err != nil { - return ood, TgtErr{tgtOrig, err} + return ood, TgtError{tgtOrig, err} } if depOod { - trace(CDebug, "ood: %s%s -> %s: ood", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: ood", indent, tgtOrig, dep) ood = true goto Done } - trace(CDebug, "ood: %s%s -> %s: !ood", indent, tgtOrig, dep) + tracef(CDebug, "ood: %s%s -> %s: !ood", indent, tgtOrig, dep) } Done: - trace(CDebug, "ood: %s%s: %v", indent, tgtOrig, ood) + tracef(CDebug, "ood: %s%s: %v", indent, tgtOrig, ood) return ood, nil } @@ -231,14 +231,14 @@ func isOODWithTrace( _, ood := OODTgts[p] if ood { if !isOODByBuildUUID(cwd, tgtOrig) { - trace( + tracef( CDebug, "ood: %s%s -> already built", strings.Repeat(". ", level), tgtOrig, ) return false, nil } - trace( + tracef( CDebug, "ood: %s%s true, external decision", strings.Repeat(". ", level), tgtOrig, @@ -250,7 +250,11 @@ func isOODWithTrace( return ood, err } RecordOODTgt: - if err = unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_EX); err != nil { + flock := unix.Flock_t{ + Type: unix.F_WRLCK, + Whence: io.SeekStart, + } + if err = unix.FcntlFlock(FdOODTgtsLock.Fd(), unix.F_SETLKW, &flock); err != nil { log.Fatalln(err) } if _, err = FdOODTgts.Seek(0, io.SeekEnd); err != nil { @@ -259,16 +263,27 @@ RecordOODTgt: if _, err := FdOODTgts.WriteString(p + "\x00"); err != nil { log.Fatalln(err) } - unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_UN) + flock.Type = unix.F_UNLCK + if err = unix.FcntlFlock(FdOODTgtsLock.Fd(), unix.F_SETLK, &flock); err != nil { + log.Fatalln(err) + } return true, nil } func oodTgtsClear() { - if err := unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_EX); err != nil { + var err error + flock := unix.Flock_t{ + Type: unix.F_WRLCK, + Whence: io.SeekStart, + } + if err = unix.FcntlFlock(FdOODTgtsLock.Fd(), unix.F_SETLKW, &flock); err != nil { + log.Fatalln(err) + } + if err = FdOODTgts.Truncate(0); err != nil { log.Fatalln(err) } - if err := FdOODTgts.Truncate(0); err != nil { + flock.Type = unix.F_UNLCK + if err = unix.FcntlFlock(FdOODTgtsLock.Fd(), unix.F_SETLK, &flock); err != nil { log.Fatalln(err) } - unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_UN) }