* Register GC roots properly.
This commit is contained in:
		| @@ -19,6 +19,9 @@ void printHelp() | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static Path gcRootsDir; | ||||||
|  |  | ||||||
|  |  | ||||||
| Expr evalAttr(EvalState & state, Expr e) | Expr evalAttr(EvalState & state, Expr e) | ||||||
| { | { | ||||||
|     return e ? evalExpr(state, e) : e; |     return e ? evalExpr(state, e) : e; | ||||||
| @@ -97,12 +100,12 @@ static void findJobsWrapped(EvalState & state, XMLWriter & doc, | |||||||
|          |          | ||||||
|         if (getDerivation(state, e, drv)) { |         if (getDerivation(state, e, drv)) { | ||||||
|             XMLAttrs xmlAttrs; |             XMLAttrs xmlAttrs; | ||||||
|             Path outPath, drvPath; |             Path drvPath; | ||||||
|  |  | ||||||
|             xmlAttrs["jobName"] = attrPath; |             xmlAttrs["jobName"] = attrPath; | ||||||
|             xmlAttrs["nixName"] = drv.name; |             xmlAttrs["nixName"] = drv.name; | ||||||
|             xmlAttrs["system"] = drv.system; |             xmlAttrs["system"] = drv.system; | ||||||
|             xmlAttrs["drvPath"] = drv.queryDrvPath(state); |             xmlAttrs["drvPath"] = drvPath = drv.queryDrvPath(state); | ||||||
|             xmlAttrs["outPath"] = drv.queryOutPath(state); |             xmlAttrs["outPath"] = drv.queryOutPath(state); | ||||||
|             xmlAttrs["description"] = drv.queryMetaInfo(state, "description"); |             xmlAttrs["description"] = drv.queryMetaInfo(state, "description"); | ||||||
|             xmlAttrs["longDescription"] = drv.queryMetaInfo(state, "longDescription"); |             xmlAttrs["longDescription"] = drv.queryMetaInfo(state, "longDescription"); | ||||||
| @@ -110,6 +113,12 @@ static void findJobsWrapped(EvalState & state, XMLWriter & doc, | |||||||
|             xmlAttrs["homepage"] = drv.queryMetaInfo(state, "homepage"); |             xmlAttrs["homepage"] = drv.queryMetaInfo(state, "homepage"); | ||||||
|             xmlAttrs["schedulingPriority"] = drv.queryMetaInfo(state, "schedulingPriority"); |             xmlAttrs["schedulingPriority"] = drv.queryMetaInfo(state, "schedulingPriority"); | ||||||
|          |          | ||||||
|  |             /* Register the derivation as a GC root.  !!! This | ||||||
|  |                registers roots for jobs that we may have already | ||||||
|  |                done. */ | ||||||
|  |             Path root = gcRootsDir + "/" + baseNameOf(drvPath); | ||||||
|  |             if (!pathExists(root)) addPermRoot(drvPath, root, false); | ||||||
|  |              | ||||||
|             XMLOpenElement _(doc, "job", xmlAttrs); |             XMLOpenElement _(doc, "job", xmlAttrs); | ||||||
|             showArgsUsed(doc, argsUsed); |             showArgsUsed(doc, argsUsed); | ||||||
|         } |         } | ||||||
| @@ -170,6 +179,10 @@ void run(Strings args) | |||||||
|                     ? (ATermList) autoArgs.get(toATerm(name)) |                     ? (ATermList) autoArgs.get(toATerm(name)) | ||||||
|                     : ATempty, e)); |                     : ATempty, e)); | ||||||
|         } |         } | ||||||
|  |         else if (arg == "--gc-roots-dir") { | ||||||
|  |             if (i == args.end()) throw UsageError("missing argument"); | ||||||
|  |             gcRootsDir = *i++; | ||||||
|  |         } | ||||||
|         else if (arg[0] == '-') |         else if (arg[0] == '-') | ||||||
|             throw UsageError(format("unknown flag `%1%'") % arg); |             throw UsageError(format("unknown flag `%1%'") % arg); | ||||||
|         else |         else | ||||||
| @@ -178,6 +191,8 @@ void run(Strings args) | |||||||
|  |  | ||||||
|     if (releaseExpr == "") throw UsageError("no expression specified"); |     if (releaseExpr == "") throw UsageError("no expression specified"); | ||||||
|      |      | ||||||
|  |     if (gcRootsDir == "") throw UsageError("--gc-roots-dir not specified"); | ||||||
|  |      | ||||||
|     store = openStore(); |     store = openStore(); | ||||||
|  |  | ||||||
|     Expr e = parseExprFromFile(state, releaseExpr); |     Expr e = parseExprFromFile(state, releaseExpr); | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ our @ISA = qw(Exporter); | |||||||
| our @EXPORT = qw( | our @EXPORT = qw( | ||||||
|     isValidPath queryPathInfo |     isValidPath queryPathInfo | ||||||
|     getHydraPath getHydraDBPath openHydraDB |     getHydraPath getHydraDBPath openHydraDB | ||||||
|     registerRoot getGCRootsDir |     registerRoot getGCRootsDir gcRootFor | ||||||
|     getPrimaryBuildsForReleaseSet getRelease getLatestSuccessfulRelease ); |     getPrimaryBuildsForReleaseSet getRelease getLatestSuccessfulRelease ); | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -80,22 +80,26 @@ sub openHydraDB { | |||||||
|  |  | ||||||
| sub getGCRootsDir { | sub getGCRootsDir { | ||||||
|     die unless defined $ENV{LOGNAME}; |     die unless defined $ENV{LOGNAME}; | ||||||
|     return "/nix/var/nix/gcroots/per-user/$ENV{LOGNAME}/hydra-roots"; |     my $dir = "/nix/var/nix/gcroots/per-user/$ENV{LOGNAME}/hydra-roots"; | ||||||
|  |     mkpath $dir if !-e $dir; | ||||||
|  |     return $dir; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | sub gcRootFor { | ||||||
|  |     my ($path) = @_; | ||||||
|  |     return getGCRootsDir . basename $path; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| sub registerRoot { | sub registerRoot { | ||||||
|     my ($path) = @_; |     my ($path) = @_; | ||||||
|  |  | ||||||
|     my $gcRootsDir = getGCRootsDir; |  | ||||||
|      |      | ||||||
|     mkpath($gcRootsDir) if !-e $gcRootsDir; |     my $link = gcRootFor $path; | ||||||
|  |      | ||||||
|     my $link = "$gcRootsDir/" . basename $path; |  | ||||||
|          |  | ||||||
|     if (!-l $link) { |     if (!-l $link) { | ||||||
|         symlink($path, $link) |         symlink($path, $link) | ||||||
|             or die "cannot create symlink in $gcRootsDir to $path"; |             or die "cannot create GC root `$link' to `$path'"; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -28,8 +28,6 @@ sub doBuild { | |||||||
|     my $failedDepBuild; |     my $failedDepBuild; | ||||||
|     my $failedDepStepNr; |     my $failedDepStepNr; | ||||||
|      |      | ||||||
|     registerRoot $outPath; |  | ||||||
|      |  | ||||||
|     if (!isValidPath($outPath)) { |     if (!isValidPath($outPath)) { | ||||||
|         $isCachedBuild = 0; |         $isCachedBuild = 0; | ||||||
|  |  | ||||||
| @@ -75,7 +73,8 @@ sub doBuild { | |||||||
|         # to get notifications about specific build steps, the |         # to get notifications about specific build steps, the | ||||||
|         # associated log files, etc. |         # associated log files, etc. | ||||||
|         my $cmd = "nix-store --max-silent-time 1800 --keep-going --no-build-output " . |         my $cmd = "nix-store --max-silent-time 1800 --keep-going --no-build-output " . | ||||||
|             "--log-type flat --print-build-trace --realise $drvPath 2>&1"; |             "--log-type flat --print-build-trace --realise $drvPath " . | ||||||
|  |             "--add-root " . gcRootFor $outPath . " 2>&1"; | ||||||
|  |  | ||||||
|         my $buildStepNr = 1; |         my $buildStepNr = 1; | ||||||
|          |          | ||||||
|   | |||||||
| @@ -267,9 +267,6 @@ sub checkJob { | |||||||
|                 , sha256hash => $input->{sha256hash} |                 , sha256hash => $input->{sha256hash} | ||||||
|                 }); |                 }); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         # !!! this should really by done by nix-instantiate to prevent a GC race. |  | ||||||
|         registerRoot $drvPath; |  | ||||||
|     }); |     }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -330,9 +327,12 @@ sub checkJobSet { | |||||||
|     $nixExprPath .= "/" . $jobset->nixexprpath; |     $nixExprPath .= "/" . $jobset->nixexprpath; | ||||||
|  |  | ||||||
|     (my $res, my $jobsXml, my $stderr) = captureStdoutStderr( |     (my $res, my $jobsXml, my $stderr) = captureStdoutStderr( | ||||||
|         "hydra_eval_jobs", $nixExprPath, inputsToArgs($inputInfo)); |         "hydra_eval_jobs", $nixExprPath, "--gc-roots-dir", getGCRootsDir, | ||||||
|  |         inputsToArgs($inputInfo)); | ||||||
|     die "cannot evaluate the Nix expression containing the jobs:\n$stderr" unless $res; |     die "cannot evaluate the Nix expression containing the jobs:\n$stderr" unless $res; | ||||||
|  |  | ||||||
|  |     print STDERR "$stderr"; | ||||||
|  |  | ||||||
|     my $jobs = XMLin($jobsXml, |     my $jobs = XMLin($jobsXml, | ||||||
|                      ForceArray => ['error', 'job', 'arg'], |                      ForceArray => ['error', 'job', 'arg'], | ||||||
|                      KeyAttr => [], |                      KeyAttr => [], | ||||||
|   | |||||||
| @@ -83,14 +83,14 @@ my @buildsToKeep = $db->resultset('Builds')->search({finished => 1, keep => 1}, | |||||||
| keepBuild $_ foreach @buildsToKeep; | keepBuild $_ foreach @buildsToKeep; | ||||||
|  |  | ||||||
|  |  | ||||||
| # For scheduled builds, we register the derivation and the output as a GC root. | # For scheduled builds, we register the derivation as a GC root. | ||||||
| print STDERR "*** looking for scheduled builds\n"; | print STDERR "*** looking for scheduled builds\n"; | ||||||
| foreach my $build ($db->resultset('Builds')->search({finished => 0}, {join => 'schedulingInfo'})) { | foreach my $build ($db->resultset('Builds')->search({finished => 0}, {join => 'schedulingInfo'})) { | ||||||
|     if (isValidPath($build->drvpath)) { |     if (isValidPath($build->drvpath)) { | ||||||
|         print STDERR "keeping scheduled build ", $build->id, " (", |         print STDERR "keeping scheduled build ", $build->id, " (", | ||||||
|             strftime("%Y-%m-%d %H:%M:%S", localtime($build->timestamp)), ")\n"; |             strftime("%Y-%m-%d %H:%M:%S", localtime($build->timestamp)), ")\n"; | ||||||
|         registerRoot $build->drvpath; |         registerRoot $build->drvpath; | ||||||
|         registerRoot $build->outpath; |         registerRoot $build->outpath if -e $build->outpath; | ||||||
|     } else { |     } else { | ||||||
|         print STDERR "warning: derivation ", $build->drvpath, " has disappeared\n"; |         print STDERR "warning: derivation ", $build->drvpath, " has disappeared\n"; | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user