NAME
dpb
—
distributed ports builder
SYNOPSIS
dpb |
[-acemqRrsUuvx ] [-A
arch] [-B
chroot] [-b
logfile] [-C
pathlist] [-D
PARAM=value]
[-F m]
[-f m]
[-h hosts]
[-I pathlist]
[-J p]
[-j n]
[-L logdir]
[-l lockdir]
[-M threshold]
[-P pathlist]
[-p parallel]
[-S logfile]
[-X pathlist]
[pathlist ...] |
DESCRIPTION
dpb
is used to build ports on a cluster of
machines, or on a single machine with several cores.
dpb
walks the ports tree to figure out dependencies,
and starts building ports as soon as it can.
dpb
will run with sensible defaults if
used without options. Note, however, that it will produce logs, lock files,
packages, and package installations.
If run as non-root, dpb
will warn. The
preferred way is to run it as root (and preferably under a chroot, see
bulk(8) and
proot(1) for example setups). dpb
will then
change its identity to different users as needed. See
THE SECURITY MODEL OF
DPB for details.
dpb
can be restricted to a subset of the
tree by giving it pathlist ... to build as
parameters.
A pathlist is either a
pkgpath(7) to build, or a filename that contains pkgpaths (one per
line). pathlist parameters can also take the form
filename*scale
in order to multiply the weights of
all pkgpath(7) in a file by a given scale, or
pkgpath=value
, in order to set the weight of a given
pkgpath(7) to a specific value.
dpb
supports ‘hot-fixes’: if
a particular port errors out, it is possible to fix the problem, remove the
corresponding lockfile, and dpb
will pick it up
without needing to be stopped and restarted.
In order to build on a cluster, the ports tree itself should be identical on each machine (shared through NFS or copied at start).
Some directories must be shared:
PACKAGE_REPOSITORY
, DISTDIR
,
and PLIST_REPOSITORY
. The
WRKOBJDIR
and LOCKDIR
should
be local to each machine, and on a high-speed partition.
Also note that dpb
's logs and locks are
managed by the main dpb
process, which runs locally,
and hence those directories do not need to be shared on the cluster.
Some log files ("rolling logs") are kept from one run to the run and stored under ${DISTDIR}/build-stats. On each run, the most recent entries for each pkgpath (see STATS_USED) are used to figure out in which order things should be built. Meanwhile, some more entries are kept around (see STATS_BACKLOG) for potential data analysis over longer periods.
Option -h
file is
used to specify hosts to use, where file may contain
lots of information, but can be as simple as a list of hosts to use, one
host per line (however, it is recommended to also include a
STARTUP script).
Most filenames will go through some control sequence expansions. For instance, the default logdir location can be specified as %p/logs/%a. The following sequences are recognized:
%a
- architecture being used.
%d
- date at start of
dpb
, GMtime, formatted as yyyy-mm-dd@hh:mm:ss. %f
- fetch distfiles location (DISTDIR).
%h
- short hostname running
dpb
. %L
- logdir location.
%p
- portsdir location.
%t
- timestamp (number of seconds since January 1 1970) at start of
dpb
. %$
- Pid of the main
dpb
process .
Options are as follows:
-A
arch- Build packages for given architecture, selecting relevant hosts from the cluster. By default, the current host's architecture will be used.
-a
- Walk the whole tree and builds all packages (default if no pathlist is given).
-B
chroot- chroot to chroot before building. See proot(1) for preparing such an environment.
-b
logfile- Explicitly prime the heuristics module with a previous build log, so that packages that take a long time to build will happen earlier. The rolling log file under %f/build-stats/%a is automatically used.
-C
pathlist- Don't clean port working directories after build. Only use simple pkgpath(7) in the list, as this does not take subpackages and flavors into account.
-c
- Clean port working directory and log before each build.
-D
PARAM=value- Set defined parameter to value. Known parameters are as follows:
- ALWAYS_CLEAN
- Set to 1 if
dpb
should clean work directories even if the port errored out. - BUILD_USER
- Default value for build_user if you want to
specify it on the command line, and want to ensure even the small
"discover PORTSDIR" activity at the beginning of
dpb
is not run as root. - COLOR
- Set to 1 to have the normal display in color.
- CONNECTION_TIMEOUT
- Connection timeout for ssh. Defaults to 10 seconds (but ssh will retry 3 times).
- CONTROL
- Let
dpb
create a unix socket of the given name for external control. Defaults to ‘%L/control-%h-%$’. If no socket is wanted, explicitly set CONTROL to empty. - DISPLAY_TIMEOUT
- Display timeout (in seconds) while waiting for jobs to finish, so that the display is updated even if jobs didn't finish. Defaults to 10 seconds.
- DONT_BUILD_ONCE
- By default,
dpb
will use theBUILD_ONCE
optimization (see bsd.port.mk(5)) if run with-a
: pseudo-flavors that disable subpackages and are not necessary for bootstrap will be disabled, so that the same port is built once, as far as possible. This flag disables that optimization, which might be desirable if you want to build a small subset of packages which would pull in the kitchen sink otherwise. - DONT_CLEAN_LOCKS
- By default,
dpb
will clean old locks from dpb running on the same host that no longer exist, provided they didn't end in error. This is usually the right thing to do after a crash, or after killing dpb abruptly. Sometimes, one may want manual control over which locks to remove. - FETCH_JOBS
- Alternate way to specify the number of fetch jobs.
- FETCH_TIMEOUT
- Timeout (in seconds) after which fetches that don't show any progress will be killed. This can be instead set in DEFAULT or localhost as the ‘fetch_timeout’ property.
- FETCH_CMD
- Override for the default FETCH_CMD coming from ports. This might be useful because fetching isn't chroot'd and is run as ${FETCH_USER}.
- FETCH_USER
- User for all fetch activities if possible (defaults to _pfetch).
- FTP_ONLY
- Don't fetch distfiles/don't build packages that are not allowed for ftp.
- HISTORY_ONLY
- Don't fetch or build anything. Only run
dpb
to figure out old distfiles and update %f/history. - LISTING_EXTRA
- Alternate way to specify
-e
. - LOCKDIR
- Alternate way to specify the locking directory.
- LOGDIR
- Alternate way to specify the logging directory.
- LOG_USER
- User for all log files if possible (defaults to build_user).
- MIRROR
- Applicable to fetch modes. If 0, will only fetch normal
DISTFILES
(default fordpb
-f
). If 1, will also fetch extraSUPDISTFILES
(default fordpb
-F
). - NEVER_CLEAN
- If 1,
dpb
will never clean any work directory after build. - NO_BUILD_STATS
- Disable reading/saving of default build stats under ${DISTDIR}/build-stats/${ARCH}.
- NO_CHECKSUM
- Do not run checksum again for files already fetched.
- NO_CURSOR
- Make the terminal cursor invisible if possible. Avoids flickering on slow graphics cards.
- NO_HISTORY
- Do not update the distfiles history. For instance, if
dpb
is run a second time after a problem during the first run. - NO_QUICK_SCAN
- Disable the quick scan default heuristic, where full bulks will start by scanning the most prominent ports in former builds.
- PORT_USER
- User that can write to the ports tree. Not really used for anything yet.
- RECORD
- Define a file which will save all terminal output. Mostly useful for
presentations, as a way to save
dpb
output and replay it later at a faster rate. Defaults to %L/term-report.log, can be set to nothing to disable. - STARTUP
- Define a start-up script on the command-line, override any host file contents.
- STATS_BACKLOG
- Max number of stats (per individual pkgpath) to save in the rolling log file (defaults to 25).
- STATS_USED
- Clamp number of stats (per individual pkgpath) used for computing build order (defaults to 10).
- STUCK_TIMEOUT
- Timeout (in seconds * speed factor) after which tasks that don't show any progress will be killed. This can be instead set on a per-core basis as the ‘stuck’ property. Note that this will always be divided by the core's speed factor.
- SYSLOG
- Make
dpb
call syslog(3) on every task start/end while creating packages. This does produce lots of messages, it is intended to route the logging on another machine, while tracking down panics and other hangs. - WANTSIZE
- Alternate way to specify
-s
.
-e
- The listing job is extra and won't be given back to the pool when it's finished.
-F
m- Fetch-only mode, for mirroring hosts. Do not build any package but fetch
everything, disregarding
BROKEN
andONLY_FOR_ARCHS
information. Create m localhost jobs for fetching files. -f
m- Create m jobs for fetching files. Those are separate
from the build jobs, since they don't consume cpu, and they run on the
localhost. Defaults to 2. Can be set to 0 to bypass fetching jobs
entirely, and reduce
dpb
memory footprint by a lot. -h
hosts- File with hosts to use for building. One host per line, plus properties,
such as:
espie@aeryn jobs=4 arch=i386
Lines starting with a known variable name such as
STARTUP=path
FETCH_JOBS=5
The special hostname DEFAULT can be used to preset defaults. It should be used at the start of the file.
Use localhost to specify the local machine.
dpb
will special-case it and not use ssh(1) to connect.Properties are as follows:
- always_clean=n
- Set to 0 or 1 on per-host basis. See ALWAYS_CLEAN parameter.
- arch=value
- Architecture of the concerned host. (there should be a startup task to check consistency, but currently this has to be set manually on heterogeneous networks.)
- build_user=user
- Use user for non root jobs if possible (defaults to whoami(1) value).
- chroot=dir
- Chroot to dir before building.
- fetch_timeout=s
- Timeout (in seconds) after which fetches that don't show any progress will be killed. Only makes sense for DEFAULT or localhost.
- jobs=n
- Number of jobs to run on that host, defaults to hw.ncpuonline.
- junk=n
- Junk unused packages each n steps. See
-J
option. - memory=thr
- Build everything below that wrkdir threshold with
USE_MFS
=‘Yes’, assuming the ports tree has been configured so thatWRKOBJDIR_MFS
points to a memory filesystem. thr is the sum, in KBytes, of ports that will be allowed to build in memory.dpb
understands suffixes, such as-M
2G or-M
500M.Note that you should always allow for some margin, as
dpb
makes its decision based on the size information collected during previous builds, so in cases of significant updates, the work directory size will usually grow. - nochecksum=0/1
- Defaults to 1. During the junk stage, run
pkg_delete(1) with the
-q
(no checksum) option. - parallel=p
- Run big ports on several cores. See
-p
option. - parallel2=p
- Run largest ports on many cores. Defaults to the same value as the parallel option, but can be increased for, say, chromium.
- repair=0/1
- Defaults to 1. Run pkg_add(1) with the repair option. This is useful on some bulk machines which tend to crash a lot, leaving /var/db/pkg in a weird state.
- sf=n
- Speed factor. An estimate of that machine's speed with that number of jobs compared to other machines in the same network. Works better with small values, in the range of 1..50. The machine (or machines) with the highest speed factor will get access to all jobs, whereas other machines will be clamped to stuff which does not take too long. Requires previous build information to be effective. Defaults to 1.
- small=s
- Small threshold (in seconds * sf): ports known to build under that
duration are deemed to be small, so
dpb
won't bother calling fine-grained steps for patch/configure/fake. It will go straight to build and package instead. Defaults to 120 seconds. - squiggles=n
- Number of squiggles on this host (see THE SQUIGGLE HEURISTICS below). Defaults to 1 squiggle for hosts with 4 jobs or more, 0.7 for hosts with more than 1 job, 0 for single job hosts.
- stuck=s
- Stuck timeout (in seconds * sf) after which tasks which show no progress will get killed.
- timeout=s
- Defines a specific connection timeout for ssh to that host.
There are no fine-grained options to control ssh(1) options, as those can be specified through virtual host declarations in ssh_config(5).
-I
pathlist- List of pkgpath(7) to install, on the local box. This will also add them to the list of things to build.
-J
p- Override value for the “junk” property. Delete unneeded
installed packages during the build. Each prepare
stage is followed by a show-prepare-results stage.
After every p new dependencies, it will be followed
by a junk stage which uses
pkg_delete(1) with the
-aXI
options to delete automatically installed packages that are currently not needed.dpb
keeps track of list of dependencies on a given host, by storing each dependency list in the lockfile corresponding to the package being built.To avoid a race condition between the depends and junk stages,
dpb
allows only one job on a given host to be in the depends ... junk stages at one time, by using a per-host lock.Defaults to 150. Can be disabled by setting to 0.
Some ports, most notably cmake-based, have an annoying dependency handling bug: they compute their makefile dependencies based on all include files present, not just the ones that are actually enabled. Those ports' build may be broken by a junk phase that removes some unused includes that were added as makefile prerequisites. Those ports should be annotated with DPB_PROPERTIES = nojunk until that bug is fixed: while a port with the ‘nojunk’ property is building, junk will be postponed.
Those ports will be marked with a ‘!’ in the display, to make it more obvious why junk seems to be ineffective.
Note that the ‘nojunk’ property is still active for ports in error, in the belief that trivial fixes can be made that will allow the port build to finish.
-j
n- Number of jobs to run on a single host (defaults to hw.ncpuonline).
-L
logdir- Choose a log directory. (Defaults to %p/logs/%a).
-l
lockdir- Choose a lock directory. (Defaults to %L/locks). Override to keep local, as locks don't really like NFS.
-M
threshold- Build ports below the memory threshold under a memory filesystem, as
configured through
WRKOBJDIR_MFS
(see bsd.port.mk(5)). threshold is the sum, in KBytes, of ports allowed to build there. -m
- Force tty-style reporting.
-P
pathlist- Read list of pkgpath(7) from file.
-p
parallel- Override value for the “parallel” property.
Run big jobs on several cores on the same host, by using MAKE_JOBS=k.
Once such a job has started,
dpb
will not start new jobs on the same host until the big job has stolen enough cores from other finishing jobs.Only big ports which are safe for parallel building (annotated with DPB_PROPERTIES = parallel in their Makefile) will be affected.
It is advisable to set k to an integral fraction of the number of cores available on a given host. parameter can be an integer, or of the form ‘/n’, in which case,
dpb
will set k to a fraction of the total number of jobs on the machine, but never below 2.Defaults to ‘/2’.
-q
- Don't quit while errors/locks are around.
-R
- Rebuild existing packages based on discrepancies between the package
signature and what the port says it should be. Concretely, use to run a
partial bulk build after some library change.
Note that
-R
won't always work, as rebuilding a package when another version is already installed is not supported. Building in a chroot is strongly recommended. -r
- Random build order. Disregard any kind of smart heuristics. Useful to try to find missing build dependencies.
-S
logfile- Read logfile as an initial workdir size log.
-s
- Compute workdir sizes before cleaning up, and stash them in log file
%L/size.log. This will also maintain a rolling log
of build sizes under %f/build-stats/%a-size. In
order to save time,
dpb
will actually not always compute new sizes for known directories, but mostly for new ones, or when the package name changes. -U
- Insist on updating existing packages during dependency solving, even if the new package apparently didn't change.
-u
- Update existing packages during dependency solving. Can be used to run a bulk-build on a machine with installed packages, but might break a bit, since some packages only build on a clean machine right now.
-X
pathlist- Read a list of pkgpath(7) from file, and pass them along in the junk phase: those are packages that should stay on the machine if they've been installed by a dependency. Can be used to avoid endlessly removing/reinstalling the most common packages, e.g., devel/gmake.
-x
- No tty report, only report really important things, like hosts going down and coming back up, build errors, or builds not progressing.
dpb
figures out in which order to build
things on the fly, and constantly displays information relative to what's
currently building. There's a list of what is currently running, one line
per job. Those jobs are ordered in strict chronological order, which means
that long running builds will tend to percolate to the top of the list.
Normal jobs look like this:
www/mozilla-firefox(build) [9452] 41% unchanged for 92 seconds
This contains:
- an optional ‘~’ squiggle marker (see below),
- the pkgpath being built,
- the step currently being run,
- an optional ‘!’ for ports with the ‘nojunk’ property.
- an optional ‘+’ for ports built in memory.
- the pid running that task (note that this is always a pid on the host running dpb: for distributed builds, it will be an ssh(1) to another machine),
- the current size of the log file (displayed as a percentage if previous build statistics are available).
- and a possible notice that things might be stuck when the log file doesn't change for long periods.
And fetch jobs look like this:
<dist-3.0.tgz(#1) [4321] 25%
This contains:
- the file being fetched
- the number of the
MASTER_SITE
being tried - the pid of the ftp(1) process (note that fetch jobs are always local).
- a progress percentage.
This is followed by a host line, containing the name of each host used by dpb. Host names may be tagged with kde3 or kde4. They are followed by a ‘`-'’ for unresponsive hosts, and the pid of the ssh master for distant hosts.
This ends with a summary display:
- I=
- number of built packages that can be installed.
- B=
- number of built packages, not yet known to be installable, because of run depends that still need to be built.
- Q=
- number of packages in the queue, e.g., stuff that can be built now, assuming we have a free slot.
- T=
- number of packages to build, where dependencies are not yet resolved.
- F=
- number of distfiles to fetch, when
-f
is used. - !=
- number of ignored packages. Details in engine.log.
- L=
- list of packages that cannot currently be built because of locks.
- E=
- list of packages in error, that cannot currently be built.
- H=
- list of packages that haven't shown up yet, usually due to nfs, but watch out for revision bumps.
If those three lists are empty, they won't even show up. Packages in errors may be followed by a ‘!’ if they prevent junk from happening.
Note that those numbers refer to pkgpaths known to
dpb
. In general, those numbers will be slightly
higher than the actual number of packages being built, since several paths
may lead to the same package.
dpb
uses some heuristics to try to
maximise the queue as soon as possible. There are also provisions for a
feedback-directed build, where information from previous builds can be used
to try to build long-running jobs first.
Similarly, fetches will use the continue option of ftp(1), since distfiles are checksummed after the fetch anyways.
THE SQUIGGLE HEURISTICS
However, on machines with lots of cores, the basic scheduling
heuristics yields a tail of very small jobs, where
dpb
will mostly wait on
pkg_add(1) to solve dependencies. Starting with
OpenBSD 5.5, a new mechanism (squiggles) was
introduced to counter-balance this effect: big machines devote some of their
cores to ‘squiggles’, jobs that walk the queue in reverse,
thus building smallest ports first. As a result, small ports are built as a
trickle alongside the largest ports, thus offsetting the negative effect of
the exponential queue for a large part.
Note that ‘squiggles’ can be a non-integral value, usually lower than 1, in which case they represent the fraction of cores that should be affected to squiggles, as decided randomly at the start of each build. 0.7 or 0.8 might be a good choice for dual core machines.
DPB PROPERTIES
The
bsd.port.mk(5) variable
DPB_PROPERTIES
may hold several annotations that
only dpb
will look at. These properties are as
follows:
- lonesome
- Large port that stresses the memory limits of the machine, should be built
alone. Prevents
dpb
from scheduling anything else on the same host after it starts building. - noconfigurejunk
- Port that looks for unneeded dependencies during its configure phase (typically, optional tools like doxygen to rebuild documentation). Similar to nojunk but less expensive, since the configure phase is most often limited in scope.
- nojunk
- Port that hardcodes includes in its Makefile mechanisms. Prevents junk from running while port is building.
- parallel
- Port that can be built in parallel, uses
MAKE_JOBS
and several build slots. - parallel2
- Very large port that should be built in parallel, uses
MAKE_JOBS
and lots of build slots. - tag:kde3
- kde3 port that conflicts with kde4 ports. Prevent scheduling ports with tag:kde4 on the same host.
- tag:kde4
- kde4 port that conflicts with kde3 ports. Prevent scheduling ports with tag:kde3 on the same host.
THE SECURITY MODEL OF DPB
When dpb
is run as root, it uses a
privilege drop model instead of the dangerous privilege elevation model of
doas(1). When run as root, by default, _pbuild
is used as the build and log user, and _pfetch is used
as the fetch user.
- Start
dpb
as root. dpb
will drop privileges for every operation except pkg_add(1), pkg_delete(1) and the STARTUP script.- For cluster builds, provide an ssh(1) connection to distant hosts from root as root.
- build_user is used to build stuff locally or
distantly (can be per-host), using:
chroot -u build_user /build_root
(with /build_root = / if there is no actual chroot needed). It must have read access to ${DISTDIR} and ${PORTSDIR}, and write access to ${WRKOBJDIR}, ${PACKAGE_REPOSITORY}, and ${PLIST_REPOSITORY}. It does not require network access. - LOG_USER is used to open all log files. LOG_USER only needs to exist locally. It needs write access to the log directories, including ${DISTDIR}/build-stats. It does not need network access.
- FETCH_USER is used to fetch distfiles and handle corresponding log info. It needs write access to ${DISTDIR}, and network access. Thus, ftp(1) does not happen as root.
- _dpb is used as a fail-safe for any other activities that do not require any rights.
dpb
creates local directories as root, then gives them to the appropriate user.
LOCKS AND ERRORS
dpb
still uses the normal ports tree
mechanism while building, which includes LOCKDIR
.
When starting up dpb
will normally detect stale
locks from old dpb runs, and remove them. If this does not happen, builds
will stay stuck in their initial stage, that is:
show-prepare-results, patch,
build depending on the port. A telltale message
‘Awaiting lock ...’ can be found in the corresponding logfile
paths/pkgpath.log
In addition, when building a package, dpb
produces a lockfile in the locks directory, whose name is deduced from the
basic pkgpath with slashes replaced by dots. This lockfile is filled with
such info as the build start time or the host, or the needed dependencies
for this pkgpath.
The lockfile will also contain the name of a parent pkgpath, for paths that were discovered as dependencies. This is particularly useful for bogus paths, where it would be hard to know where the path came from otherwise.
At the end of a successful build, these lockfiles are removed. The lock will stay around in case of errors. (raw value from wait(2)), and the name of the next task in the build pipeline (with todo=<nothing> in case of failure during clean-up). Normal list of tasks is: depends prepare fetch patch configure build fake package clean.
At the end of each job, dpb
rechecks the
locks directory for existing lockfiles. If some locks have vanished, it will
put the corresponding paths back in the queue and attempt another build.
This eases manual repairs: if a package does not build, the user
can look at the log, go to the port directory, fix the problem, and then
remove the lock. dpb
will pick up the ball and keep
building without interruption.
It is perfectly safe to run several dpb
in
parallel on the same machine. This is not optimal, since each
dpb
ignores the others, and only uses the lock info
to avoid the other's current work, but it can be handy: in an emergency, one
can start a second dpb
to obtain a specific package
right now, in parallel with the original dpb
.
Note that dpb
is very careful not to run
two builds from the same pkgpath at the same time, even on different
machines: in some cases, MULTI_PACKAGES and FLAVOR combinations may lead to
the same package being built simultaneously, and since the package
repository is shared, this can easily lead to trouble.
Handling of shared log files and history is also done very carefully by systematically appending to files or using atomic mv operations.
For obvious reasons, this won't work as well with masters running on distinct machines sharing their logs through NFS.
BUILD CYCLES
There are some various interdependencies in package builds that can be hard to trace in case something goes wrong. Refer to summary.log to fix those specific issues.
AFFINITY
dpb
now maintains a list of
pkgpath-per-host that are currently building in the
affinity directory of its log directory, along with
building-in-memory status.
That information is only wiped out when a given build finishes successfully.
Otherwise dpb
will try to restart that
build on the same host, which can be handy if you interrupt
dpb
while it is building a large port, or if you
remove a lock after fixing a problem.
TAGS FOR EXCLUSIVE BUILDS
Back when we had kde3 and kde4, they couldn't be built simultaneously, and a single host had to be exclusively building kde3 or kde4 ports at a given moment.
Conflicting ports had been annotated with
DPB_PROPERTIES
=tag:kde3,
DPB_PROPERTIES
=tag:kde4
respectively.
More generally, with
DPB_PROPERTIES
=tag:A,
DPB_PROPERTIES
=tag:B,
dpb
will keep track of tags. For instance, if host
X is building ports tagged with
A, then any port with tag B will
be prevented from building on X until the next
junk phase.
This heavily relies on the junk stage to clean-up hosts periodically, and it can even forcibly provoke a junk stage even if junk=0.
This ‘force-junk’ stage is actually implemented as a pseudo path called junk-proxy, which does only junk.
In order for builds to proceed gracefully, machines should start in a clean slate, without any of the problematic ports installed.
As a special-case, failing ports with a tag will not interfere with clean-up, so that hosts do not get locked down to a specific tag. This also means that their dependencies may vanish before human intervention addresses the problem.
This is supposed to be an exceptional hack, helpful while porters figure out how to remove the deadlock.
EXTERNAL CONTROL
By default (see CONTROL),
dpb
will create a Unix socket at
%L/control-%h-%$, only accessible by
LOG_USER, that can accept a few commands, e.g., usable
as nc -U path
Current commands are as follows:
addhost
hostline- Add a new host
addpath
fullpkgpath ...- Add fullpkgpath to scan
bye
- close the socket connection.
dontclean
pkgpath ...- Add new pkgpath to list of paths that should not be cleaned after build
help
- Self explanatory
info
cores- Debug info for cores (to be extended to other data)
rescan
- Force
dpb
to rescan all ignored paths (for various errors, including bogus dependencies) stats
- Show the current stats line
status
fullpkgpath ...- Show the current status of fullpkgpath, whether it's built, installable, ready to build, to build later, along with current dependencies if applicable.
stub
fullpkgpath ...- Stub out fullpkgpath and unlock it if needed.
wipe
fullpkgpath ...- Wipe out an existing lock: clean up the corresponding fullpkgpath on the appropriate host, then remove all lock and affinity info pertaining to the port.
wipehost
hostname ...- Remove all information relevant to a given host from
dpb
, including running jobs, locks, and affinity information.
SHUTTING DOWN GRACEFULLY
dpb
periodically checks for a file named
stop in its log directory. If this file exists, then
it won't start new jobs, and shutdown when the current jobs are finished
unless -q
.
dpb
also checks for files named
stop-<hostname> in its log directory. If such
a file exists, then it won't start new jobs on the corresponding
machine.
FILES
Apart from producing packages, dpb
may
create temporary files as
${FULLDISTDIR}/${DISTFILE}.part.
In fetch mode (-f
and
-F
), dpb
populates
${DISTDIR}/by_cipher/sha256 with links. It also uses
${DISTDIR}/distinfo and
${DISTDIR}/history as a ‘permanent
log’:
- distinfo
- cache of distfiles checksum. Contains all sha256(1) checksums of known files under ${DISTDIR}. Fetching uses this to avoid re-checksumming known files.
- history
- Log of old files under distinfo. After successfully scanning a full ports
tree (
dpb
-a
), the fetch engine knows precisely which files are needed by the build (and their checksums). Anything that is- recorded in distinfo but unneeded
- recorded in distinfo but with the wrong checksum
- not recorded in distinfo, but not needed
ts SHA256 (file) = value
with ts a timestamp from Unix epoch.
When cleaning up old files, with a tool such as clean-old-distfiles(1), it is vital to check both the checksum and the file name: since mirroring stores permanent links under by_cipher, files which are still needed will appear in history under their old checksums, as an indication the link should be removed, but possibly not the file itself.
If ${DISTDIR} ever becomes corrupted,
removing ${DISTDIR}/distinfo will force
dpb
into checking all files again.
All those files belong to the FETCH_USER if it is defined. They should be readable for the build_user.
dpb
also records rolling build statistics
under ${DISTDIR}/build-stats/${ARCH}, and uses them
automatically (see STATS_BACKLOG and
STATS_USED) in the absence of
-b
logfile. That file belongs
to the LOG_USER if it is defined.
If -s
is used, size information for
successful builds will be recorded under
${DISTDIR}/build-stats/${ARCH}-size (by default,
location adjustable with -S
sizelog). This is then reused for the mfs threshold
option. That file also belongs to the LOG_USER if it
is defined.
dpb
also maintains a list of pkgpath
frequencies
${DISTDIR}/build-stats/${ARCH}-dependencies, filled
at end of LISTING if -a
. This list will be
automatically reused when restarting a build: a quick LISTING of the most
important dependencies will happen before the general LISTING, in order to
prime further LISTING steps with most common ports first.
dpb
will also create a large number of log
files under ${PORTSDIR}/logs/${ARCH}, which will
belong to LOG_USER if it is defined:
- affinity/
- Affinity information. One file per full pkgpath, with slash replaced by dots like so: affinity/lang.ghc,-main.
- affinity.log
- On startup
dpb
reads existing affinity information, and records it in that log, together with its pid. This log just exists to verify, along with engine.log, whether correct affinity was heeded. - awaiting-locks.log
- This is purely for gathering performance statistics, about how much lock contention happened around pkg_add(1) and pkg_delete(1) usage. Plotting cumulated time may help in fine-tuning squiggles parameters.
- build.log
- Actual build log. Each line summarizes build of a single pkgpath, as:
‘pkgpath host time logsize (detailed timing)[!]’ where time
is the actual build time in seconds, host is the machine name where this
occurred, logsize is the corresponding log file size, and a ! is appended
in case the build didn't succeed.
The detailed timing info gives a run-down of the build, with clean, fetch, prepare, patch (actually extract+patch), configure, build, fake, package, clean detailed timing info. Note that the actual build time starts at ‘extract’ and finishes at ‘package’.
- built-packages.log
- The actual list of fullpkgname.tgz as they get built.
- cpu-concurrency.log
- Shows the actual concurrency achieved as a result of job starvation / parallel handling. Only gets a new line when the value changes: pid timestamp jobs
- debug.log
- contains various information related to the main engine spinning (RTFS, haven't figured that one yet) along with the more useful warning and die traces that happen when something wrong occurs. Especially useful for the warning messages that tend to be overwritten by subsequent displays. Will also contain error messages pertaining to failure at parsing existing lock files.
- dist/<distfile>.log
- Log of the ftp(1) process(es) that attempted to fetch the distfile.
- control-%h-%$
- Default name for the external control socket.
- dump.log
- A long log file generated at the end of build that yields any information pertinent to ports still in the ‘to build’ and the ‘built’ queues. See also summary.log for an expurged version of same.
- engine.log
- Build engine log. Each line corresponds to a state change for a pkgpath
and starts with the pid of
dpb
, plus a timestamp of the log entry.- ^
- pkgpath temporarily put aside, because a job is running in the same directory.
- !
- pkgpath ignored, either directly, or indirectly because a dependency was ignored. End of the line states reason why ignored.
- A
- affinity mismatch: path considered for build, but not the right host, followed by the affinity information.
- B
- pkgpath built / distfile found.
- C
- forcible clean-up before building a port with a kde tag.
- E
- error in build or fetch.
- F
- distfile queued for download.
- H
- package still not found due to nfs on this run.
- I
- pkgpath can be installed.
- J
- job to build pkgpath started. Also records the host used for the build.
- K
- kde mismatch, no build until host has been cleaned up.
- L
- job did not start, existing lock detected.
- N
- job did not finish. The host may have gone down.
- P
- built package is no longer required for anything.
- Q
- pkgpath queued as buildable whenever a slot is free.
- T
- pkgpath to build / distfile to download.
- V
- pkgpath put back in the buildable queue, after job that was running in the same directory returned.
- W
- only happens when the external control
wipe
command is used: pkgpath will be cleaned up, next log entry will be ‘N’ since the job did not finish and is ready to restart. - X
- only happens when rescanning after an error. The engine temporarily locks paths that are incomplete (detained). These will be kept in a separate list for later examination until the end of the new scan.
- x
- only happens when rescanning after an error. Releases a path for building after the new scan is finished.
- Y
- affinity mismatch, but job will start on the wrong host anyways, as the queue contains no other buildable path.
The engine is no longer run after each package build event because of performance considerations, so the ‘Q’ and ‘I’ changes may be delayed by a few ‘B’.
- equiv.log
- Lists of equivalent pkgpaths for the build, when default flavors and default subpackages have been resolved.
- fetch/bad.log
- List of URLs that did not lead to a correct distfile, either because they were not responding, or because of incorrect checksums.
- fetch/good.log
- List of URLs that fetched correctly, along with timing statistics.
- fetch/manually.log
- List of pkgpaths that require manual intervention, in human-readable form.
- <hostname>.sig.log
- Complete library signature of the host.
- init.<hostname>.log
- Captured output of the initialization job for each host.
- junk.log
- Option
-J
counts the number of dependencies directly added to decide when to runpkg_delete
-a
. This file sums up how many ports were built, and how many ports had dependencies each timedpb
decides to junk. - locks/
- Directory where locks are created. There are three types of locks:
- pkgpath locks for building, where the slash in a pkgpath is replaced with a dot like so: locks/devel.make to flatten the structure.
- distfile locks for fetching, using the distfile name without the path like so: locks/distfile.dist.
- host locks for dependency handling and junking, like so: locks/host:hostname.
- packages/pkgname.log
- one file or symlink per pkgname.
- paths/some/path.log
- one file or symlink per pkgpath.
- performance.log
- Some parts of
dpb
are computationally intensive, such as the engine runs to determine new stuff that can be built, and the actual display reports.Both those activities are rate-limited, so that
dpb
doesn't run its engine at each new package build, and doesn't update its display every time there is a phase change.Lines tagged with ‘ENG’ correspond to the engine; lines tagged with ‘REP’ correspond to the display reports.
Lines ending with a dash ‘-’ correspond to new activity that didn't trigger a computation.
Other lines will feature a plus ‘+’ for normal runs, or an exclamation point ‘’! for forced runs, followed by two numbers: the next timestamp at which we'll be allowed to run, and a measure of how much time it took to run this pass.
That information is mostly relevant while
dpb
is building lots of small packages very quickly. - signature.log
- Discrepancies between hosts that prevent them from starting up.
- size.log
- Size of work directory at the end of each build, built only with
-s
. - stats.log
- Simple log of the B=... line summaries. Mostly useful for making plots and tweaking performance.
- stop
- Not a logfile at all, but a file created by the user to stop
dpb
creating new jobs. - stop-<hostname>
- Not a logfile at all, but created by the user to stop hostname creating new jobs.
- summary.log
- A summary file generated at end of build that lists packages not built or
not installable, along with a reason for it. This summarizes packages not
built because of existing locks, because of errors, but also because they
depend on something that was not built.
In that last case, summary.log contains a chain of dependencies leading to the problematic package, or in case of build cycles, stopping at the first loop.
- term-report.log
- Saves all terminal output, so that it can be replayed at hi speed with dpb-replay(1).
- vars.log
- Logs the directories that were walked in the ports tree for dependency information, including the path to a dependency that triggered this particular step.
DIAGNOSTICS
- Waiting for hosts to finish STARTUP...
- Displayed on the console while
dpb
is setting up hosts, getting essential data from the ports tree, running a STARTUP script, collecting base library signatures. - stuck on <lockfilename>
- Display on the console when
dpb
detects a "frozen" port has happened outside ofdpb
's purview, namely because the ports tree itself has that specific port locked withoutdpb
's knowledge. See bsd.port.mk(5), portlock(1). - (Junk lock obtained for <host> at <time>)
- (Junk lock released for <host> at <time>)
- Printed in a paths/pkgpath.log file when
attempting to get a ‘junk lock’. On a given host, all
dependency operations are serialized. The dependency computation itself is
handled by the main
dpb
process, which needs to know exactly which dependencies are used at a given point, so that junk can clean up the host correctly. In particular, junk will not clean up dependencies already scheduled for installation. Ports that do not obtain the lock on first try are put to sleep. - Received IO
- Printed in a paths/pkgpath.log file when woken up before trying attempting to obtain a junk lock again...
- Woken up <fullpkgpath>
- Printed in a paths/pkgpath.log when waking another task by sending it SIGIO, so that it may attempt to obtain the junk lock again.
- (Junk lock failure for <host> at <time>)
- All ports sleeping for a junk lock are woken at the same time, so only one of them will obtain the lock, and the others will fail and be put to sleep again.
- Short-cut: depends already handled by <fullpkgpath>
- Printed in a paths/pkgpath.log when a port wakes
up after others that ran
pkg_add(1). As
dpb
maintains dependencies for a given host globally, it coalesces depends lists together. - Don't run junk because nojunk in <fullpkgpath>
- Printed in a paths/pkgpath.log while evaluating
whether to run junk. Normally,
junk happens at regular intervals, but ports marked
‘nojunk’ will delay that.
dpb
still keeps track of attempted junks. - Still tainted: <bool>
- A host may have a tag (kde3/kde4) that prevents building differently tagged ports. This will be cleansed by junk eventually. This prints in path/pkgpath.log to indicate whether this particular junk will keep the host tainted with a tag or not.
- Forced junk, retainting: <tag>
- Printed at end of prepare-results, when an eventual junk was run even though some ports still hold a tag.
- Can't run junk because of lock on <fullpkgpath>
- junk can't happen because fullpkgpath is locked and is marked ‘nojunk’.
- Avoided depends for <dependencies>
- As dependencies are handled globally per-host, some ports can avoid pkg_add(1) altogether because another port already installed the correct dependencies.
- SPINNING ON MAIN
- Printed in debug.log, this is an actual bug: the
engine said it can build, there are cores available, but
dpb
can't start a new build job. - SPINNING ON FETCH
- Printed in debug.log, this is an actual bug: the
engine said it can fetch, there are fetching cores available, but
dpb
can't start a new fetch job. - KILLED: <job> stuck at <somewhere>
- Printed in path/pkgpath.log when a port exceeds its timeout.
- !: <path> tried and didn't get it
- Printed in engine.log Scanning the port didn't give us useful information. See vars.log for gory details.
BUGS AND LIMITATIONS
dpb
performs best with lots of paths to
build. When just used to build a few ports, there's a high risk of
starvation as there are bottlenecks in parts of the tree.
Fetch jobs don't deal with checksum changes yet: if a fetch fails
because of a wrong checksum, if you update the distinfo file and remove the
lock, dpb
won't pick it up.
Note that dpb
does not manage installed
packages in any intelligent way, it will just call
pkg_add(1) during its depend stage to install its dependencies. With
-u
, it will call pkg_add -r. With
-U
, it will call pkg_add -r -D installed, but there
is nothing else going on. This is especially true when using
-R
, ensure the machine is clean of possibly older
packages first, or run dpb
with
-U
.
In particular -R
and
-J
together may lead to strange issues.
On heterogeneous networks, calibration of build info and choice of speed factors is not perfect, and somewhat a dark art. Using distinct speed factors on a build log that comes from a single machine works fine, but using the build info coming from several machines does not work all that well.
dpb
should check
/usr/include and
/usr/X11R6/include for consistency, but it
doesn't.
When a host fails consistency check, there is not yet a way to
re-add it after fixing the problem. You have to stop
dpb
, cleanup and restart.
The default limits in login.conf are too small for bulk builds on any kind of parallel machines. Bump number of processes, file descriptors, and memory.
Even though dpb
tries really hard to check
heterogeneous networks for sanity (checking shared libraries and .la files),
it is still dependent on the user to make sure all the hosts build ports the
same way.
Make sure your NFS setup is consistent. The ports dir itself should be exported or synchronized. Distfiles, the package repository, and the plist repository should be exported, but WRKOBJDIR should not be on NFS unless you have absolutely no choice, or if you exhibit deep masochistic tendencies. Pay particular attention to discrepancies in /etc/mk.conf.
Also, dpb
connects to external hosts
through ssh(1), relying on
ssh_config(5) for any special cases.
When fetching distfiles, dpb
may freeze
and spin in a tight loop while the last distfiles are being fetched. This is
definitely a bug, which has been around for quite some time, which is a bit
difficult to reproduce, and hasn't been fixed yet. So if
dpb
stops updating its display right around the end
of fetch, you've hit the bug. Just kill dpb
and
restart it.
SEE ALSO
clean-old-distfiles(1), dpb-replay(1), proot(1), pkgpath(7), bulk(8)
HISTORY
The original dpb
command was written by
Nikolay Sturm. This version is a complete rewrite from scratch using all the
stuff we learnt over the years to make it better.
AUTHORS
Marc Espie <espie@openbsd.org>