Subject: Re: Simultaneous builds
To: David Maxwell <david@fundy.net>
From: Alistair Crooks <agc@pkgsrc.org>
List: tech-pkg
Date: 01/15/2002 15:35:00
--5vNYLRcllDrimb99
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Fri, Jan 11, 2002 at 11:31:11AM -0400, David Maxwell wrote:
>
> Is that 'doesn't do too well on NFS' with multiple clients, or with
> multiple connections from one client? (or both?)
>
> I guess multiple machines of the same ARCH using the same pkgsrc tree
> wasn't something I was concerned about. Intuitively, I would have
> expected shlock to work okay with NFS from a single client though.
Yes, shlock does work fine from a single client. But it needs a
single coherent PID space to do its job effectively, so that
precludes multiple clients using the same ${WRKDIR}s.
Anyway, help is at hand.
You may have noticed that I made some modifications to bsd.pkg.mk
to append the first component of the hostname to a WRKDIR, if
OBJHOSTNAME is defined in /etc/mk.conf. I've also committed a
package for the shlock utility, which can be used on Operating
Systems which don't have it as standard (and here I've guessed
at Solaris and Linux - unfortunately I can't connect to the
Darwin host right now to check).
Together with the attached diffs, you should be able to use
the PKGSRC_LOCKTYPE= "sleep" or "once" (in /etc/mk.conf), and
also the PKGSRC_SLEEPSECS definition if you're using "sleep"
waits.
With the attached diffs applied, and PKGSRC_LOCKTYPE set to "sleep"
in /etc/mk.conf, I get the following output in one window:
[14:23:45] agc@fs0 ...pkgsrc/devel/cvs 185 > make
=> Checksum OK for cvs-1.11.tar.gz.
=> Checksum OK for cvs-1.11-v6-20020111.diff.gz.
work.fs0 -> /usr/obj/pkgsrc/devel/cvs/work.fs0
=> Lock acquired on behalf of process 22189
===> extract-message [cvs-1.11nb2] ===> Extracting for cvs-1.11nb2
=> Lock released on behalf of process 22189
=> Lock acquired on behalf of process 22189
===> patch-message [cvs-1.11nb2] ===> Patching for cvs-1.11nb2
===> do-patch [cvs-1.11nb2] ===> Applying distribution patches for cvs-1.11nb2
===> do-patch [cvs-1.11nb2] ===> Applying distribution patch cvs-1.11-v6-20020111.diff.gz
Hmm... Looks like a new-style context diff to me...
The text leading up to this was:
...
and a simultaneous make in another window gives...
[14:09:10] agc@fs0 ...pkgsrc/devel/cvs 130 > make
=> Checksum OK for cvs-1.11.tar.gz.
=> Checksum OK for cvs-1.11-v6-20020111.diff.gz.
=> Lock is held by pid 22189
=> Lock is held by pid 22189
^C[14:23:56] agc@fs0 ...pkgsrc/devel/cvs 131 >
The reason I posted these here is that I've had to move the creation
of the ${WRKDIR} out of the do-extract target, and I would like
others to check that I haven't borked anything.
If I get positive feedback, I'll apply these diffs to the main
tree.
Thanks,
Alistair
--5vNYLRcllDrimb99
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=locking-diffs
Index: bsd.pkg.defaults.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/bsd.pkg.defaults.mk,v
retrieving revision 1.32
diff -u -r1.32 bsd.pkg.defaults.mk
--- bsd.pkg.defaults.mk 2002/01/11 14:41:42 1.32
+++ bsd.pkg.defaults.mk 2002/01/15 14:23:55
@@ -31,6 +31,24 @@
# Possible: defined, not defined
# Default: not defined
+PKGSRC_LOCKTYPE?= none
+# The type of locking which will be done if competing processes attempt to
+# do work on one package directory simultaneously.
+# + Locking requires that OBJHOSTNAME is set.
+# + Locking may require the pkgsrc/pkgtools/shlock package to be installed
+# on certain OS types.
+# + Sleep locking means that the process will sleep for ${PKGSRC_SLEEPSECS}
+# seconds, then try to acquire the lock, and sleeping again if it's not
+# available.
+# + Once locking will try once to acquire the lock, and then fail.
+# Possible: none, sleep, once
+# Default: none
+
+PKGSRC_SLEEPSECS?= 5
+# The number of seconds to wait when PKGSRC_LOCKTYPE is sleep
+# Possible: a positive integer
+# Default: 5
+
#USETBL=
# Run raw manual pages through tbl(1) before piping through troff(1)
# when formatting manual pages.
Index: bsd.pkg.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/bsd.pkg.mk,v
retrieving revision 1.903
diff -u -r1.903 bsd.pkg.mk
--- bsd.pkg.mk 2002/01/15 09:02:09 1.903
+++ bsd.pkg.mk 2002/01/15 14:24:00
@@ -911,6 +911,20 @@
@${FALSE}
.endif
+.if (${PKGSRC_LOCKTYPE} == "sleep" || ${PKGSRC_LOCKTYPE} == "once") && !defined(OBJHOSTNAME)
+.BEGIN:
+ @${ECHO_MSG} 'PKGSRC_LOCKTYPE needs OBJHOSTNAME defined.'
+ @${FALSE}
+.endif
+
+.if (${PKGSRC_LOCKTYPE} == "sleep" || ${PKGSRC_LOCKTYPE} == "once") && !exists(${SHLOCK})
+.BEGIN:
+ @${ECHO_MSG} 'The ${SHLOCK} utility does not exist, and is necessary for locking.'
+ @${ECHO_MSG} 'Please go to the ${.CURDIR}/../../pkgtools/shlock directory, and type'
+ @${ECHO_MSG} 'make install'
+ @${FALSE}
+.endif
+
PKGREPOSITORYSUBDIR?= All
PKGREPOSITORY?= ${PACKAGES}/${PKGREPOSITORYSUBDIR}
PKGFILE?= ${PKGREPOSITORY}/${PKGNAME}${PKG_SUFX}
@@ -1383,6 +1397,31 @@
. endif
.endif
+# pkgsrc coarse-grained locking definitions and targets
+.if ${PKGSRC_LOCKTYPE} == "none"
+_ACQUIRE_LOCK= ${_PKG_SILENT}${_PKG_DEBUG}${DO_NADA}
+_RELEASE_LOCK= ${_PKG_SILENT}${_PKG_DEBUG}${DO_NADA}
+.else
+LOCKFILE= ${WRKDIR}/.lockfile
+
+_ACQUIRE_LOCK= \
+ ${_PKG_SILENT}${_PKG_DEBUG} \
+ ppid=`${PS} -p $$$$ -o ppid | ${AWK} 'NR == 2 { print $$0 }'`; \
+ while ${TRUE}; do \
+ ${SHLOCK} -f ${LOCKFILE} -p $$ppid && break; \
+ ${ECHO} "=> Lock is held by pid `cat ${LOCKFILE}`"; \
+ case "${PKGSRC_LOCKTYPE}" in \
+ once) exit 1 ;; \
+ sleep) sleep ${PKGSRC_SLEEPSECS} ;; \
+ esac \
+ done; \
+ ${ECHO_MSG} "=> Lock acquired on behalf of process $$ppid"
+
+_RELEASE_LOCK= \
+ ${_PKG_SILENT}${_PKG_DEBUG} \
+ ${ECHO_MSG} "=> Lock released on behalf of process `${CAT} ${LOCKFILE}`"; \
+ ${RM} ${LOCKFILE}
+.endif # PKGSRC_LOCKTYPE
# Extract
@@ -1450,19 +1489,30 @@
. endif
.endfor
-.if !target(do-extract)
-do-extract:
-. ifndef KEEP_WRKDIR
+${WRKDIR}:
+.if !defined(KEEP_WRKDIR)
+. if ${PKGSRC_LOCKTYPE} == "sleep" || ${PKGSRC_LOCKTYPE} == "once"
+. if !exists(${LOCKFILE})
${_PKG_SILENT}${_PKG_DEBUG}${RM} -rf ${WRKDIR}
+. endif
. endif
+.endif
${_PKG_SILENT}${_PKG_DEBUG}${MKDIR} ${WRKDIR}
-. ifdef WRKOBJDIR
+.ifdef WRKOBJDIR
+. if ${PKGSRC_LOCKTYPE} == "sleep" || ${PKGSRC_LOCKTYPE} == "once"
+. if !exists(${LOCKFILE})
${_PKG_SILENT}${_PKG_DEBUG} \
- ${RM} -f ${WRKDIR_BASENAME} || ${TRUE}; \
+ ${RM} -f ${WRKDIR_BASENAME} || ${TRUE}
+. endif
+. endif
+ ${_PKG_SILENT}${_PKG_DEBUG} \
if ${LN} -s ${WRKDIR} ${WRKDIR_BASENAME} 2>/dev/null; then \
${ECHO} "${WRKDIR_BASENAME} -> ${WRKDIR}"; \
fi
-. endif # WRKOBJDIR
+.endif # WRKOBJDIR
+
+.if !target(do-extract)
+do-extract: ${WRKDIR}
. if defined(EXTRACT_CMD) && !empty(EXTRACT_CMD)
${_PKG_SILENT}${_PKG_DEBUG} \
for file in "" ${EXTRACT_ONLY}; do \
@@ -1820,7 +1870,7 @@
if [ X"$$found" != X"" ]; then \
${ECHO} "$$found" >> ${WRKDIR}/.CONFLICTS; \
fi
-. endfor
+. endfor
${_PKG_SILENT}${_PKG_DEBUG} \
if [ -s ${WRKDIR}/.CONFLICTS ]; then \
found=`${SED} -e s'|${PKG_DBDIR}/||g' ${WRKDIR}/.CONFLICTS | tr '\012' ' '`; \
@@ -2140,6 +2190,23 @@
. endif # libc.sylib
.endif
+acquire-extract-lock:
+ ${_ACQUIRE_LOCK}
+acquire-patch-lock:
+ ${_ACQUIRE_LOCK}
+acquire-configure-lock:
+ ${_ACQUIRE_LOCK}
+acquire-build-lock:
+ ${_ACQUIRE_LOCK}
+
+release-extract-lock:
+ ${_RELEASE_LOCK}
+release-patch-lock:
+ ${_RELEASE_LOCK}
+release-configure-lock:
+ ${_RELEASE_LOCK}
+release-build-lock:
+ ${_RELEASE_LOCK}
################################################################
# Skeleton targets start here
@@ -2156,19 +2223,19 @@
.endif
.if !target(extract)
-extract: checksum ${EXTRACT_COOKIE}
+extract: checksum ${WRKDIR} acquire-extract-lock ${EXTRACT_COOKIE} release-extract-lock
.endif
.if !target(patch)
-patch: extract ${PATCH_COOKIE}
+patch: extract acquire-patch-lock ${PATCH_COOKIE} release-patch-lock
.endif
.if !target(configure)
-configure: patch ${CONFIGURE_COOKIE}
+configure: patch acquire-configure-lock ${CONFIGURE_COOKIE} release-configure-lock
.endif
.if !target(build)
-build: configure ${BUILD_COOKIE}
+build: configure acquire-build-lock ${BUILD_COOKIE} release-build-lock
.endif
.if !target(install)
Index: defs.Darwin.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/defs.Darwin.mk,v
retrieving revision 1.16
diff -u -r1.16 defs.Darwin.mk
--- defs.Darwin.mk 2001/12/27 21:27:07 1.16
+++ defs.Darwin.mk 2002/01/15 14:24:00
@@ -36,11 +36,13 @@
PATCH?= /usr/bin/patch
PAX?= /bin/pax
PKGLOCALEDIR?= share
+PS?= /bin/ps
RM?= /bin/rm
RMDIR?= /bin/rmdir
SED?= /usr/bin/sed
SETENV?= /usr/bin/env
SH?= /bin/sh
+SHLOCK= /usr/bin/shlock
SORT?= /usr/bin/sort
SU?= /usr/bin/su
TAIL?= /usr/bin/tail
Index: defs.Linux.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/defs.Linux.mk,v
retrieving revision 1.21
diff -u -r1.21 defs.Linux.mk
--- defs.Linux.mk 2001/12/19 10:29:11 1.21
+++ defs.Linux.mk 2002/01/15 14:24:01
@@ -36,11 +36,13 @@
PATCH?= /usr/bin/patch
PAX?= ${ZOULARISBASE}/bin/pax
PKGLOCALEDIR?= share
+PS?= /bin/ps
RM?= /bin/rm
RMDIR?= /bin/rmdir
SED?= /bin/sed
SETENV?= /usr/bin/env
SH?= /bin/sh
+SHLOCK= ${LOCALBASE}/bin/shlock
.if exists(/bin/sort)
SORT?= /bin/sort
.else
Index: defs.NetBSD.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/defs.NetBSD.mk,v
retrieving revision 1.19
diff -u -r1.19 defs.NetBSD.mk
--- defs.NetBSD.mk 2001/12/19 10:29:11 1.19
+++ defs.NetBSD.mk 2002/01/15 14:24:01
@@ -36,11 +36,13 @@
PATCH?= /usr/bin/patch
PAX?= /bin/pax
PKGLOCALEDIR?= share
+PS?= /bin/ps
RM?= /bin/rm
RMDIR?= /bin/rmdir
SED?= /usr/bin/sed
SETENV?= /usr/bin/env
SH?= /bin/sh
+SHLOCK= /usr/bin/shlock
SORT?= /usr/bin/sort
SU?= /usr/bin/su
TAIL?= /usr/bin/tail
Index: defs.SunOS.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/defs.SunOS.mk,v
retrieving revision 1.19
diff -u -r1.19 defs.SunOS.mk
--- defs.SunOS.mk 2001/12/19 10:29:11 1.19
+++ defs.SunOS.mk 2002/01/15 14:24:01
@@ -47,11 +47,13 @@
.endif
PAX?= /bin/pax
PKGLOCALEDIR?= lib
+PS?= /bin/ps
RM?= /usr/bin/rm
RMDIR?= /usr/bin/rmdir
SED?= /usr/xpg4/bin/sed
SETENV?= /usr/bin/env
SH?= /bin/ksh
+SHLOCK= ${LOCALBASE}/bin/shlock
SORT?= /usr/bin/sort
SU?= /usr/bin/su
TAIL?= /usr/xpg4/bin/tail
--5vNYLRcllDrimb99--