]> Cypherpunks.ru repositories - goredo.git/blobdiff - ood.go
Repetitive OOD optimization
[goredo.git] / ood.go
diff --git a/ood.go b/ood.go
index 0552e2016112a46b037976dbfc88f26adf677b2a..cad1ce38f5f23f6beb1124749774a7d4111303ec 100644 (file)
--- a/ood.go
+++ b/ood.go
@@ -26,6 +26,8 @@ import (
        "path"
        "path/filepath"
        "strings"
+
+       "golang.org/x/sys/unix"
 )
 
 const (
@@ -33,6 +35,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 +181,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 +197,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, os.SEEK_END); 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)
+}