guarantee proper ordering of download phases

This commit is contained in:
David Rose 2009-12-19 03:38:03 +00:00
parent 74264f850f
commit 6eba1cf08a
2 changed files with 53 additions and 56 deletions

View File

@ -39,6 +39,7 @@ from direct.stdpy import file
from direct.task.TaskManagerGlobal import taskMgr
from direct.showbase.MessengerGlobal import messenger
from direct.showbase import AppRunnerGlobal
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.p3d.HostInfo import HostInfo
# These imports are read by the C++ wrapper in p3dPythonRun.cxx.
@ -63,6 +64,8 @@ class AppRunner(DirectObject):
It does not usually exist while running Python directly, but you
can use dummyAppRunner() to create one at startup for testing or
development purposes. """
notify = directNotify.newCategory("AppRunner")
def __init__(self):
DirectObject.__init__(self)
@ -171,7 +174,7 @@ class AppRunner(DirectObject):
if args[1] == 'notify':
# Quietly ignore notifies.
return
print "Ignoring request: %s" % (args,)
self.notify.info("Ignoring request: %s" % (args,))
self.requestFunc = defaultRequestFunc
# This will be filled in with the default WindowProperties for
@ -245,8 +248,8 @@ class AppRunner(DirectObject):
# All right, get the package info now.
package = host.getPackage(packageName, version)
if not package:
print "Package %s %s not known on %s" % (
packageName, version, hostUrl)
self.notify.warning("Package %s %s not known on %s" % (
packageName, version, hostUrl))
return False
return self.__rInstallPackage(package, [])
@ -266,7 +269,7 @@ class AppRunner(DirectObject):
if host.downloadContentsFile(self.http):
p2 = host.getPackage(packageName, version)
if not p2:
print "Couldn't find %s %s on %s" % (packageName, version, host.hostUrl)
self.notify.warning("Couldn't find %s %s on %s" % (packageName, version, host.hostUrl))
else:
if p2 not in nested:
self.__rInstallPackage(p2, nested)
@ -279,8 +282,8 @@ class AppRunner(DirectObject):
if not package.installPackage(self):
return False
print "Package %s %s installed." % (
package.packageName, package.packageVersion)
self.notify.info("Package %s %s installed." % (
package.packageName, package.packageVersion))
return True
def getHostWithAlt(self, hostUrl):
@ -353,13 +356,13 @@ class AppRunner(DirectObject):
if self.superMirrorUrl:
# Use the "super mirror" first.
url = PandaModules.URLSpec(self.superMirrorUrl + fileSpec.filename)
print "Freshening %s" % (url)
self.notify.info("Freshening %s" % (url))
doc = self.http.getDocument(url)
if not doc or not doc.isValid():
# Failing the super mirror, contact the actual host.
url = PandaModules.URLSpec(host.hostUrlPrefix + fileSpec.filename)
print "Freshening %s" % (url)
self.notify.info("Freshening %s" % (url))
doc = self.http.getDocument(url)
if not doc.isValid():
return False
@ -379,7 +382,7 @@ class AppRunner(DirectObject):
if not fileSpec.fullVerify(pathname = localPathname):
# No good after download.
print "%s is still no good after downloading." % (url)
self.notify.info("%s is still no good after downloading." % (url))
return False
return True

View File

@ -4,6 +4,7 @@ from direct.showbase.MessengerGlobal import messenger
from direct.task.TaskManagerGlobal import taskMgr
from direct.p3d.PackageInfo import PackageInfo
from pandac.PandaModules import TPLow
from direct.directnotify.DirectNotifyGlobal import directNotify
class PackageInstaller(DirectObject):
@ -27,6 +28,8 @@ class PackageInstaller(DirectObject):
.. packageFinished() may therefore overlap.
"""
notify = directNotify.newCategory("PackageInstaller")
globalLock = Lock()
nextUniqueId = 1
@ -101,8 +104,8 @@ class PackageInstaller(DirectObject):
# All right, get the package info now.
package = self.host.getPackage(self.packageName, self.version)
if not package:
print "Package %s %s not known on %s" % (
self.packageName, self.version, self.host.hostUrl)
self.notify.warning("Package %s %s not known on %s" % (
self.packageName, self.version, self.host.hostUrl))
return False
self.package = package
@ -126,8 +129,8 @@ class PackageInstaller(DirectObject):
# All right, get the package info now.
package = self.host.getPackage(self.packageName, self.version)
if not package:
print "Package %s %s not known on %s" % (
self.packageName, self.version, self.host.hostUrl)
self.notify.warning("Package %s %s not known on %s" % (
self.packageName, self.version, self.host.hostUrl))
return False
self.package = package
@ -251,30 +254,15 @@ class PackageInstaller(DirectObject):
return
self.packages.append(pp)
if not pp.checkDescFile():
# Still need to download the desc file.
self.needsDescFile.append(pp)
if not self.descFileTask:
self.descFileTask = taskMgr.add(
self.__getDescFileTask, 'getDescFile',
taskChain = self.taskChain)
else:
# The desc file is ready, which means so are the requirements.
for packageName, version, host in pp.package.requires:
pp2 = self.PendingPackage(packageName, version, host)
self.__internalAddPackage(pp2)
# Now that we've added the required packages, add the
# package itself.
if not pp.package.hasPackage:
# The desc file is good, but the package itself needs
# to be downloaded.
self.needsDownload.append(pp)
else:
# The package is already fully downloaded.
self.earlyDone.append(pp)
# We always add the package to needsDescFile, even if we
# already have its desc file; this guarantees that packages
# are downloaded in the order they are added.
self.needsDescFile.append(pp)
if not self.descFileTask:
self.descFileTask = taskMgr.add(
self.__getDescFileTask, 'getDescFile',
taskChain = self.taskChain)
def donePackages(self):
""" After calling addPackage() for each package to be
@ -314,27 +302,31 @@ class PackageInstaller(DirectObject):
is called; at the time of this callback, the total download
size is known, and we can sensibly report progress through the
whole. """
pass
self.notify.info("downloadStarted")
def packageStarted(self, package):
""" This callback is made for each package between
downloadStarted() and downloadFinished() to indicate the start
of a new package. """
pass
self.notify.debug("packageStarted: %s" % (package.packageName))
def packageProgress(self, package, progress):
""" This callback is made repeatedly between packageStarted()
and packageFinished() to update the current progress on the
indicated package only. The progress value ranges from 0
(beginning) to 1 (complete). """
pass
self.notify.debug("packageProgress: %s %s" % (package.packageName, progress))
def downloadProgress(self, overallProgress):
""" This callback is made repeatedly between downloadStarted()
and downloadFinished() to update the current progress through
all packages. The progress value ranges from 0 (beginning) to
1 (complete). """
pass
self.notify.debug("downloadProgress: %s" % (overallProgress))
def packageFinished(self, package, success):
""" This callback is made for each package between
@ -346,7 +338,8 @@ class PackageInstaller(DirectObject):
already downloaded), this callback will be made immediately,
*without* a corresponding call to packageStarted(), and may
even be made before downloadStarted(). """
pass
self.notify.info("packageFinished: %s %s" % (package.packageName, success))
def downloadFinished(self, success):
""" This callback is made when all of the packages have been
@ -356,7 +349,8 @@ class PackageInstaller(DirectObject):
If there were no packages that required downloading, this
callback will be made immediately, *without* a corresponding
call to downloadStarted(). """
pass
self.notify.info("downloadFinished: %s" % (success))
def __prepareToStart(self):
""" This is called internally when transitioning from S_ready
@ -401,14 +395,14 @@ class PackageInstaller(DirectObject):
def __packageStarted(self, pp):
""" This method is called when a single package is beginning
to download. """
print "Downloading package %s" % (pp.packageName)
self.__callDownloadStarted()
self.__callPackageStarted(pp)
def __packageDone(self, pp):
""" This method is called when a single package has been
downloaded and installed, or has failed. """
print "Downloaded %s: %s" % (pp.packageName, pp.success)
self.__callPackageFinished(pp, pp.success)
pp.notified = True
@ -507,16 +501,15 @@ class PackageInstaller(DirectObject):
self.packageLock.release()
# Now serve this one package.
if not pp.getDescFile(self.appRunner.http):
self.__donePackage(pp, False)
return task.cont
if not pp.checkDescFile():
if not pp.getDescFile(self.appRunner.http):
self.__donePackage(pp, False)
return task.cont
if pp.package.hasPackage:
# This package is already downloaded.
self.__donePackage(pp, True)
return task.cont
# This package is now ready to be downloaded.
# This package is now ready to be downloaded. We always add
# it to needsDownload, even if it's already downloaded, to
# guarantee ordering of packages.
self.packageLock.acquire()
try:
# Also add any packages required by this one.
@ -552,9 +545,10 @@ class PackageInstaller(DirectObject):
messenger.send('PackageInstaller-%s-packageStarted' % self.uniqueId,
[pp], taskChain = 'default')
if not pp.package.downloadPackage(self.appRunner.http):
self.__donePackage(pp, False)
return task.cont
if not pp.package.hasPackage:
if not pp.package.downloadPackage(self.appRunner.http):
self.__donePackage(pp, False)
return task.cont
# Successfully downloaded and installed.
self.__donePackage(pp, True)