Commit graph

246 commits

Author SHA1 Message Date
Avery Pennarun
10afd9000f Add some conditionals around some high-bandwidth debug statements.
When you have lots of unmodified dependencies, building these printout
strings (which aren't even printed unless you're using -d) ends up taking
something like 5% of the runtime.
2010-12-10 00:50:53 -08:00
Avery Pennarun
6e6e453908 Some speedups for doing redo-ifchange on a large number of static files.
Fix some wastage revealed by the (almost useless, sigh) python profiler.
2010-12-10 00:50:53 -08:00
Avery Pennarun
b5c02e410e state.py: reorder things so sqlite never does fdatasync().
It was briefly synchronous at data creation time, adding a few ms to
redo startup.
2010-12-10 00:50:53 -08:00
Avery Pennarun
e446d4dd04 builder.py: don't import the 'random' module unless we need it.
Initializing the random number generator involves some pointless reading
from /dev/urandom.
2010-12-10 00:50:53 -08:00
Avery Pennarun
e1a0fc9c12 state.File.is_checked() was being too paranoid.
It wasn't allowing us to short circuit a dependency if that dependency had
been built previously, but that was already being checked (more correctly)
in dirty_deps().
2010-12-10 00:50:52 -08:00
Avery Pennarun
94cecc240b Don't abort if 'insert into Files' gives an IntegrityError.
It can happen occasionally if some other parallel redo adds the same file at
the same time.
2010-12-10 00:50:52 -08:00
Avery Pennarun
3ef2bd7300 Don't check as often whether the .redo directory exists.
Just check it once after running a subprocess: that's the only way it ought
to be able to disappear (ie. in a 'make clean' setup).
2010-12-10 00:50:52 -08:00
Avery Pennarun
29d6c9a746 Don't db.commit() so frequently.
Just commit when we're about to do something blocking.  sqlite goes a lot
faster with bigger transactions.  This change does show a small percentage
speedup in tests, but not as much as I'd like.
2010-12-10 00:50:52 -08:00
Avery Pennarun
fb79851530 Calculate dependencies with fewer sqlite queries. 2010-12-10 00:50:52 -08:00
Avery Pennarun
c339359f04 Schema cleanup. 2010-12-10 00:50:52 -08:00
Avery Pennarun
b86a32d33d flush-cache.sh: for speed, disable sqlite's synchronous mode. 2010-12-10 00:50:52 -08:00
Avery Pennarun
f4535be0cd Fix a deadlock.
We were holding a database open with a read lock while a child redo might
need to open it with a write lock.
2010-12-10 00:50:52 -08:00
Avery Pennarun
9e36106642 sqlite3: configure the timeout explicitly.
In flush-cache.sh, we have to do this, because the sqlite3 command-line tool
sets it to zero.  Inevitably during parallel testing, it'll end up
contending for a lock, and we really want it to wait a bit.

In state.py, it's not as important since the default is nonzero.  But
python-sqlite3's default of 5 seconds makes me a little too nervous; I can
imagine a disk write waiting for more than 5 seconds sometime.  So let's use
60 instead.
2010-12-10 00:50:52 -08:00
Avery Pennarun
a62bd50d44 Switch state.py to use sqlite3 instead of filesystem-based stamps.
It passes all tests when run serialized, but still gives weird errors
(OperationalError: database is locked) when run with -j5.  sqlite3 shouldn't
be barfing just because the database is locked, since the default timeout is
5 seconds, and it's dying *way* faster than that.
2010-12-10 00:50:52 -08:00
Avery Pennarun
8dad223225 flush-cache: run it as a separate program, not using 'source'
That way it doesn't clutter up 'redo -x' as much.
2010-12-10 00:50:52 -08:00
Avery Pennarun
43b74f3220 builder._nice(): show the right filename in the case of chdir().
This only affects cosmetics, not actual behaviour, which is why the unit
tests didn't catch it.
2010-12-10 00:49:30 -08:00
Avery Pennarun
51bbdc6c5a If we can't find a .do file for a target, mark it as not is_generated.
This allows files to transition from generated to not-generated if the .do
file is ever removed (ie. the user is changing things and the file is now a
source file, not a target).
2010-12-06 03:12:53 -08:00
Avery Pennarun
0979a6e666 t/passfailtest.do: just return exit codes, don't print messages.
The exit code numbers are useful enough, and the messages are the sort of
thing that might turn into lies eventually.
2010-12-06 03:12:02 -08:00
Avery Pennarun
b3a14a28c4 When -x or -v is given, print the sh command we're executing. 2010-12-06 02:47:24 -08:00
Avery Pennarun
4669903887 The mtime of a directory is kind of useless, so don't use it. 2010-12-05 03:58:20 -08:00
Avery Pennarun
66187e879e Slightly improve the "if target already existed" rule to ignore directories.
So if you have a default.do, it might be used to build mydir, even if mydir
already existed when we started.

This might be useful if you have a mydir.setup.do and a mydir.do; mydir.do
depends on mydir.setup.do, but mydir.setup.do creates mydir, it just doesn't
*finish* with mydir.  Still, my the time mydir.do runs, mydir already
exists, and redo would get confused.

I think directories are fundamentally special in this way, because it makes
sense to "create" a directory even if that directory isn't "done" at this
phase.
2010-12-04 05:42:07 -08:00
Avery Pennarun
66e7c0db5e toplevel all.do: 'redo t' no longer works.
It's too bad, but it's actually more readable to force people to say
'redo t/all' if they really mean it.  So just fix the help message.
2010-11-27 23:17:41 -08:00
Avery Pennarun
8953260d28 deps/test1.do: fix an == vs. =
In sh's [] command, you should use =, not ==.  I got away with this because
bash accepts ==, but that's non-portable.
2010-11-27 21:48:43 -08:00
Avery Pennarun
a5855641f8 This tests the chdir-related bug from the previous commit. 2010-11-25 06:37:24 -08:00
Avery Pennarun
c29de89051 Fix more trouble with .do scripts that cd to other directories.
The interaction of REDO_STARTDIR, REDO_PWD, and getcwd() are pretty
complicated.  In this case, we accidentally assumed that the current
instance of redo was running with getcwd() == REDO_STARTDIR+REDO_PWD, and so
the new target was REDO_STARTDIR+REDO_PWD+t, but this isn't the case if the
current .do script did chdir().

The correct answer is REDO_STARTDIR+getcwd()+t.
2010-11-25 06:37:24 -08:00
Avery Pennarun
f3413c0f7c doublestatic: fix dependencies if two files depend on one non-generated file.
If a and b both depend on c, and c is a static (non-generated) file that has
changed since the last successful build of a and b, we would try to redo
a, but would forget to redo b.  Now it does both.
2010-11-24 04:52:30 -08:00
Avery Pennarun
9fc5ae1b56 Optimization: don't getcwd() so often.
We never chdir() except just as we exec a subprocess, so it's okay to cache
this value.  This makes strace output look cleaner, and speeds things up a
little bit when checking a large number of dependencies.

Relatedly, take a debug2() message and put it in an additional if, so that
we don't have to do so much work to calculate it when we're just going to
throw it away anyhow.
2010-11-24 03:45:38 -08:00
Avery Pennarun
0ec15eeb09 If a target's .do file disappears, don't forget to stamp it.
If a file previously was generated but now isn't (ie. its .do file
disappears), we would never re-stamp that target, and so all its
dependencies would rebuild continually.
2010-11-24 03:44:37 -08:00
Avery Pennarun
60f5446733 Correctly handle dependencies for "cd somewhere; redo-ifchange somefile"
We would build 'somefile' correctly the first time, but we wouldn't
attach the dependency on somefile to the right $TARGET, so our target would
not auto-rebuild in the future based on somefile.
2010-11-24 03:06:33 -08:00
Avery Pennarun
984ad747f8 Remove special case for "dirname" -> "dirname/all"
It actually decreases readability of the .do files - by not making it
explicit when you're going into a subdir.

Plus it adds ambiguity: what if there's a dirname.do *and* a dirname/all?
We could resolve the ambiguity if we wanted, but that adds more code, while
taking out this special case makes *less* code and improves readability.
I think it's the right way to go.
2010-11-24 02:48:27 -08:00
Avery Pennarun
282bb0488e If the created target is a directory, it's okay for the .do to create it.
Normally, creating the target $1 yourself is bad; create $3 instead.  But if
$1 is a directory, we'll allow it.  That way 'redo subdir' can call
subdir.do, and subdir.do can both create the directory *and* run a bunch of
sub-.do files on it.
2010-11-24 02:30:54 -08:00
Avery Pennarun
83dd52c209 Targets created from stdout should be rw-, not rwx.
I had forgotten to pass the create mode to open().  Oops!
2010-11-24 02:26:15 -08:00
Avery Pennarun
190dd657d8 It's okay if a file is marked as generated and doesn't have a .do.
If we don't know how to rebuild the file, but it already exists, that's
pretty harmless.  Just consider it a successful rebuild.
2010-11-24 02:18:19 -08:00
Avery Pennarun
77eacf1423 Fix some missing 'clean.do' rules. 2010-11-23 01:12:46 -08:00
Avery Pennarun
ac36c5bbb1 t/deps/dirtest: test correct dependency checking for targets named 'dirname'
We had a bug (fixed in the previous commit) where doing 'redo-ifchange
dirname' (which runs dirname/all.do) would not create the stamp correctly,
so that it would always show up as dirty.

It's a little bit complicated to simulate, but this does it.
2010-11-23 01:08:32 -08:00
Avery Pennarun
cd853fccfb test.do would run all its subtasks even though it used 'redo-ifchange'.
The behaviour is what we wanted, but it shouldn't have worked.  So fix the
bug in redo-ifchange, then change test.do to use 'redo' instead so it
continues to do what we want, only for the right reason.

(The bug is that 'redo-ifchange dirname', which runs dirname/all.do, didn't
result in stamps getting checked correctly.)
2010-11-23 01:08:32 -08:00
Avery Pennarun
3fcd677428 Add t/deps/basic, to test basic autodependency behaviour.
Unfortunately it failed before the previous patch, so that's why this test
is needed :(

The test is a little ugly, because the bug I'm testing for didn't happen
except if you ran 'redo' two times in a row, not two times inside the same
redo session.  That's because dependency caching inside the one session
prevents the accidental rebuild.
2010-11-22 22:53:40 -08:00
Avery Pennarun
f337df463d state.stamp() can't imply state.built().
...because we deliberately stamp non-generated files as well, and that
doesn't need to imply that we rebuilt them just now.  In fact, we know for a
fact that we *didn't* rebuild them just now, but we still need to record the
timestamp for later.
2010-11-22 22:53:40 -08:00
Avery Pennarun
6d767e2a65 user-friendliness sanity checks: catch common mistakes regarding $1/$2/$3.
.do files should never modify $1, and should write to *either* $3 or stdout,
but not both.  If they write to both, it's probably because they forgot to
redirect stdout to stderr, a very easy mistake to make but a hard one to
detect.

Now redo detects it for you and prints an informative message.
2010-11-22 04:43:33 -08:00
Avery Pennarun
dce0076554 Print a useful message and exit when the .redo directory disappears. 2010-11-22 04:04:45 -08:00
Avery Pennarun
2dbd47100d state.py: reduce race condition between Lock.trylock() and unlock().
If 'redo clean' deletes the lockfile after trylock() succeeds but before
unlock(), then unlock() won't be able to open the pipe in order to release
readers, and any waiters might end up waiting forever.

We can't open the fifo for write until there's at least one reader, so let's
open a reader *just* to let us open a writer.  Then we'll leave them open
until the later unlock(), which can just close them both.
2010-11-22 04:04:45 -08:00
Avery Pennarun
dd937d6102 redo-if{change,create}: print a useful message if REDO isn't set.
Again, I forgot to make vars.py not crash if the variables aren't set, so we
can print a useful error message.  But this time I have the right solution:
vars.py will do the checking for itself, and abort with a nice message.
2010-11-22 02:45:00 -08:00
Avery Pennarun
501b534308 Add a new --debug-pids option.
This makes the helpers.* log functions prepend getpid() to each line, so you
can see which pid did what.
2010-11-22 01:50:46 -08:00
Avery Pennarun
135d1c161a builder.py: set FD_CLOEXEC flag on $3 when running a .do file.
Otherwise it could be inherited by other jwack jobs started from the same
parent process, resulting in some very-hard-to-debug race conditions, let me
tell you.
2010-11-22 01:48:02 -08:00
Avery Pennarun
8d0eba9c44 builder.py: use os.exec() instead of subprocess.call().
This avoids a second fork altogether, which apparently doesn't matter all
that much (5.3s -> 5.15s).  However, simply not importing the subprocess
module reduces us further to 4.6s.

And 'ps axf' now looks prettier because we have fewer stupid intermediate
processes.
2010-11-22 00:15:29 -08:00
Avery Pennarun
dcc2edba0c builder.py: further refactoring to run more stuff in the parent process
instead of inside the fork.

Still doesn't seem to affect runtime.  Good.

One nice side effect is jwack.py no longer needs to know anything about our
locks.
2010-11-22 00:04:15 -08:00
Avery Pennarun
3209316856 builder.py: now the only exported function is main().
We can also avoid forking altogether if should_build() returns false.  This
doesn't seem to result in any noticeable speedup, but it's cleaner at least.
2010-11-21 23:36:29 -08:00
Avery Pennarun
547dbe550f builder.py: remove the build() wrapper function and BuildError.
The only thing we want to do on a build error is return a nonzero exit code,
so let's just do that, simplifying the code a bit.
2010-11-21 23:06:31 -08:00
Avery Pennarun
7aa7c41e38 builder,jwack: slight cleanup to token passing.
In rare cases, one process could end up holding onto more than one token.
2010-11-21 22:46:20 -08:00
Avery Pennarun
9b800ca29f redo-ifchange.py: don't forget to release jwack tokens on exit.
This only really matters if it exited abnormally... but it still matters.
2010-11-21 21:15:24 -08:00