X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=ood.go;h=717f2ac9fc7097a11c20f901ce583580caa0f8b8;hb=eb14a3333a632b22a4b698ca28fea6e6d11048b8;hp=0552e2016112a46b037976dbfc88f26adf677b2a;hpb=5ca39bfc0b769607db3f84213fc7f16f0c4019fa;p=goredo.git diff --git a/ood.go b/ood.go index 0552e20..717f2ac 100644 --- a/ood.go +++ b/ood.go @@ -22,10 +22,13 @@ package main import ( "errors" "fmt" + "io" "os" "path" "path/filepath" "strings" + + "golang.org/x/sys/unix" ) const ( @@ -33,6 +36,15 @@ const ( DepTypeIfchange = "ifchange" DepTypeAlways = "always" DepTypeStamp = "stamp" + + EnvOODTgtsFd = "REDO_OOD_TGTS_FD" + EnvOODTgtsLockFd = "REDO_OOD_TGTS_LOCK_FD" +) + +var ( + OODTgts map[string]struct{} + FdOODTgts *os.File + FdOODTgtsLock *os.File ) type TgtErr struct { @@ -170,7 +182,7 @@ func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, erro continue } - depOod, err := isOOD(cwd, dep, level+1, seen) + depOod, err := isOODWithTrace(cwd, dep, level+1, seen) if err != nil { return ood, TgtErr{tgtOrig, err} } @@ -186,3 +198,49 @@ Done: trace(CDebug, "ood: %s%s: %v", indent, tgtOrig, ood) return ood, nil } + +func isOODWithTrace( + cwd, tgtOrig string, + level int, + seen map[string]struct{}, +) (bool, error) { + p, err := filepath.Abs(path.Join(cwd, tgtOrig)) + if err != nil { + panic(err) + } + _, ood := OODTgts[p] + if ood { + trace( + CDebug, + "ood: %s%s true, external decision", + strings.Repeat(". ", level), tgtOrig, + ) + goto RecordOODTgt + } + ood, err = isOOD(cwd, tgtOrig, level, seen) + if !ood { + return ood, err + } +RecordOODTgt: + if err = unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_EX); err != nil { + panic(err) + } + if _, err = FdOODTgts.Seek(0, io.SeekEnd); err != nil { + panic(err) + } + if _, err := FdOODTgts.WriteString(p + "\x00"); err != nil { + panic(err) + } + unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_UN) + return true, nil +} + +func oodTgtsClear() { + if err := unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_EX); err != nil { + panic(err) + } + if err := FdOODTgts.Truncate(0); err != nil { + panic(err) + } + unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_UN) +}