mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
guarantee proper ordering of download phases
This commit is contained in:
parent
74264f850f
commit
6eba1cf08a
@ -39,6 +39,7 @@ from direct.stdpy import file
|
|||||||
from direct.task.TaskManagerGlobal import taskMgr
|
from direct.task.TaskManagerGlobal import taskMgr
|
||||||
from direct.showbase.MessengerGlobal import messenger
|
from direct.showbase.MessengerGlobal import messenger
|
||||||
from direct.showbase import AppRunnerGlobal
|
from direct.showbase import AppRunnerGlobal
|
||||||
|
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||||
from direct.p3d.HostInfo import HostInfo
|
from direct.p3d.HostInfo import HostInfo
|
||||||
|
|
||||||
# These imports are read by the C++ wrapper in p3dPythonRun.cxx.
|
# 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
|
It does not usually exist while running Python directly, but you
|
||||||
can use dummyAppRunner() to create one at startup for testing or
|
can use dummyAppRunner() to create one at startup for testing or
|
||||||
development purposes. """
|
development purposes. """
|
||||||
|
|
||||||
|
notify = directNotify.newCategory("AppRunner")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
DirectObject.__init__(self)
|
DirectObject.__init__(self)
|
||||||
@ -171,7 +174,7 @@ class AppRunner(DirectObject):
|
|||||||
if args[1] == 'notify':
|
if args[1] == 'notify':
|
||||||
# Quietly ignore notifies.
|
# Quietly ignore notifies.
|
||||||
return
|
return
|
||||||
print "Ignoring request: %s" % (args,)
|
self.notify.info("Ignoring request: %s" % (args,))
|
||||||
self.requestFunc = defaultRequestFunc
|
self.requestFunc = defaultRequestFunc
|
||||||
|
|
||||||
# This will be filled in with the default WindowProperties for
|
# This will be filled in with the default WindowProperties for
|
||||||
@ -245,8 +248,8 @@ class AppRunner(DirectObject):
|
|||||||
# All right, get the package info now.
|
# All right, get the package info now.
|
||||||
package = host.getPackage(packageName, version)
|
package = host.getPackage(packageName, version)
|
||||||
if not package:
|
if not package:
|
||||||
print "Package %s %s not known on %s" % (
|
self.notify.warning("Package %s %s not known on %s" % (
|
||||||
packageName, version, hostUrl)
|
packageName, version, hostUrl))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return self.__rInstallPackage(package, [])
|
return self.__rInstallPackage(package, [])
|
||||||
@ -266,7 +269,7 @@ class AppRunner(DirectObject):
|
|||||||
if host.downloadContentsFile(self.http):
|
if host.downloadContentsFile(self.http):
|
||||||
p2 = host.getPackage(packageName, version)
|
p2 = host.getPackage(packageName, version)
|
||||||
if not p2:
|
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:
|
else:
|
||||||
if p2 not in nested:
|
if p2 not in nested:
|
||||||
self.__rInstallPackage(p2, nested)
|
self.__rInstallPackage(p2, nested)
|
||||||
@ -279,8 +282,8 @@ class AppRunner(DirectObject):
|
|||||||
if not package.installPackage(self):
|
if not package.installPackage(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print "Package %s %s installed." % (
|
self.notify.info("Package %s %s installed." % (
|
||||||
package.packageName, package.packageVersion)
|
package.packageName, package.packageVersion))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getHostWithAlt(self, hostUrl):
|
def getHostWithAlt(self, hostUrl):
|
||||||
@ -353,13 +356,13 @@ class AppRunner(DirectObject):
|
|||||||
if self.superMirrorUrl:
|
if self.superMirrorUrl:
|
||||||
# Use the "super mirror" first.
|
# Use the "super mirror" first.
|
||||||
url = PandaModules.URLSpec(self.superMirrorUrl + fileSpec.filename)
|
url = PandaModules.URLSpec(self.superMirrorUrl + fileSpec.filename)
|
||||||
print "Freshening %s" % (url)
|
self.notify.info("Freshening %s" % (url))
|
||||||
doc = self.http.getDocument(url)
|
doc = self.http.getDocument(url)
|
||||||
|
|
||||||
if not doc or not doc.isValid():
|
if not doc or not doc.isValid():
|
||||||
# Failing the super mirror, contact the actual host.
|
# Failing the super mirror, contact the actual host.
|
||||||
url = PandaModules.URLSpec(host.hostUrlPrefix + fileSpec.filename)
|
url = PandaModules.URLSpec(host.hostUrlPrefix + fileSpec.filename)
|
||||||
print "Freshening %s" % (url)
|
self.notify.info("Freshening %s" % (url))
|
||||||
doc = self.http.getDocument(url)
|
doc = self.http.getDocument(url)
|
||||||
if not doc.isValid():
|
if not doc.isValid():
|
||||||
return False
|
return False
|
||||||
@ -379,7 +382,7 @@ class AppRunner(DirectObject):
|
|||||||
|
|
||||||
if not fileSpec.fullVerify(pathname = localPathname):
|
if not fileSpec.fullVerify(pathname = localPathname):
|
||||||
# No good after download.
|
# 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 False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -4,6 +4,7 @@ from direct.showbase.MessengerGlobal import messenger
|
|||||||
from direct.task.TaskManagerGlobal import taskMgr
|
from direct.task.TaskManagerGlobal import taskMgr
|
||||||
from direct.p3d.PackageInfo import PackageInfo
|
from direct.p3d.PackageInfo import PackageInfo
|
||||||
from pandac.PandaModules import TPLow
|
from pandac.PandaModules import TPLow
|
||||||
|
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||||
|
|
||||||
class PackageInstaller(DirectObject):
|
class PackageInstaller(DirectObject):
|
||||||
|
|
||||||
@ -27,6 +28,8 @@ class PackageInstaller(DirectObject):
|
|||||||
.. packageFinished() may therefore overlap.
|
.. packageFinished() may therefore overlap.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
notify = directNotify.newCategory("PackageInstaller")
|
||||||
|
|
||||||
globalLock = Lock()
|
globalLock = Lock()
|
||||||
nextUniqueId = 1
|
nextUniqueId = 1
|
||||||
|
|
||||||
@ -101,8 +104,8 @@ class PackageInstaller(DirectObject):
|
|||||||
# All right, get the package info now.
|
# All right, get the package info now.
|
||||||
package = self.host.getPackage(self.packageName, self.version)
|
package = self.host.getPackage(self.packageName, self.version)
|
||||||
if not package:
|
if not package:
|
||||||
print "Package %s %s not known on %s" % (
|
self.notify.warning("Package %s %s not known on %s" % (
|
||||||
self.packageName, self.version, self.host.hostUrl)
|
self.packageName, self.version, self.host.hostUrl))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.package = package
|
self.package = package
|
||||||
@ -126,8 +129,8 @@ class PackageInstaller(DirectObject):
|
|||||||
# All right, get the package info now.
|
# All right, get the package info now.
|
||||||
package = self.host.getPackage(self.packageName, self.version)
|
package = self.host.getPackage(self.packageName, self.version)
|
||||||
if not package:
|
if not package:
|
||||||
print "Package %s %s not known on %s" % (
|
self.notify.warning("Package %s %s not known on %s" % (
|
||||||
self.packageName, self.version, self.host.hostUrl)
|
self.packageName, self.version, self.host.hostUrl))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.package = package
|
self.package = package
|
||||||
@ -251,30 +254,15 @@ class PackageInstaller(DirectObject):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.packages.append(pp)
|
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:
|
# We always add the package to needsDescFile, even if we
|
||||||
# The desc file is ready, which means so are the requirements.
|
# already have its desc file; this guarantees that packages
|
||||||
for packageName, version, host in pp.package.requires:
|
# are downloaded in the order they are added.
|
||||||
pp2 = self.PendingPackage(packageName, version, host)
|
self.needsDescFile.append(pp)
|
||||||
self.__internalAddPackage(pp2)
|
if not self.descFileTask:
|
||||||
|
self.descFileTask = taskMgr.add(
|
||||||
# Now that we've added the required packages, add the
|
self.__getDescFileTask, 'getDescFile',
|
||||||
# package itself.
|
taskChain = self.taskChain)
|
||||||
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)
|
|
||||||
|
|
||||||
def donePackages(self):
|
def donePackages(self):
|
||||||
""" After calling addPackage() for each package to be
|
""" 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
|
is called; at the time of this callback, the total download
|
||||||
size is known, and we can sensibly report progress through the
|
size is known, and we can sensibly report progress through the
|
||||||
whole. """
|
whole. """
|
||||||
pass
|
|
||||||
|
self.notify.info("downloadStarted")
|
||||||
|
|
||||||
def packageStarted(self, package):
|
def packageStarted(self, package):
|
||||||
""" This callback is made for each package between
|
""" This callback is made for each package between
|
||||||
downloadStarted() and downloadFinished() to indicate the start
|
downloadStarted() and downloadFinished() to indicate the start
|
||||||
of a new package. """
|
of a new package. """
|
||||||
pass
|
|
||||||
|
self.notify.debug("packageStarted: %s" % (package.packageName))
|
||||||
|
|
||||||
def packageProgress(self, package, progress):
|
def packageProgress(self, package, progress):
|
||||||
""" This callback is made repeatedly between packageStarted()
|
""" This callback is made repeatedly between packageStarted()
|
||||||
and packageFinished() to update the current progress on the
|
and packageFinished() to update the current progress on the
|
||||||
indicated package only. The progress value ranges from 0
|
indicated package only. The progress value ranges from 0
|
||||||
(beginning) to 1 (complete). """
|
(beginning) to 1 (complete). """
|
||||||
pass
|
|
||||||
|
self.notify.debug("packageProgress: %s %s" % (package.packageName, progress))
|
||||||
|
|
||||||
def downloadProgress(self, overallProgress):
|
def downloadProgress(self, overallProgress):
|
||||||
""" This callback is made repeatedly between downloadStarted()
|
""" This callback is made repeatedly between downloadStarted()
|
||||||
and downloadFinished() to update the current progress through
|
and downloadFinished() to update the current progress through
|
||||||
all packages. The progress value ranges from 0 (beginning) to
|
all packages. The progress value ranges from 0 (beginning) to
|
||||||
1 (complete). """
|
1 (complete). """
|
||||||
pass
|
|
||||||
|
self.notify.debug("downloadProgress: %s" % (overallProgress))
|
||||||
|
|
||||||
def packageFinished(self, package, success):
|
def packageFinished(self, package, success):
|
||||||
""" This callback is made for each package between
|
""" This callback is made for each package between
|
||||||
@ -346,7 +338,8 @@ class PackageInstaller(DirectObject):
|
|||||||
already downloaded), this callback will be made immediately,
|
already downloaded), this callback will be made immediately,
|
||||||
*without* a corresponding call to packageStarted(), and may
|
*without* a corresponding call to packageStarted(), and may
|
||||||
even be made before downloadStarted(). """
|
even be made before downloadStarted(). """
|
||||||
pass
|
|
||||||
|
self.notify.info("packageFinished: %s %s" % (package.packageName, success))
|
||||||
|
|
||||||
def downloadFinished(self, success):
|
def downloadFinished(self, success):
|
||||||
""" This callback is made when all of the packages have been
|
""" 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
|
If there were no packages that required downloading, this
|
||||||
callback will be made immediately, *without* a corresponding
|
callback will be made immediately, *without* a corresponding
|
||||||
call to downloadStarted(). """
|
call to downloadStarted(). """
|
||||||
pass
|
|
||||||
|
self.notify.info("downloadFinished: %s" % (success))
|
||||||
|
|
||||||
def __prepareToStart(self):
|
def __prepareToStart(self):
|
||||||
""" This is called internally when transitioning from S_ready
|
""" This is called internally when transitioning from S_ready
|
||||||
@ -401,14 +395,14 @@ class PackageInstaller(DirectObject):
|
|||||||
def __packageStarted(self, pp):
|
def __packageStarted(self, pp):
|
||||||
""" This method is called when a single package is beginning
|
""" This method is called when a single package is beginning
|
||||||
to download. """
|
to download. """
|
||||||
print "Downloading package %s" % (pp.packageName)
|
|
||||||
self.__callDownloadStarted()
|
self.__callDownloadStarted()
|
||||||
self.__callPackageStarted(pp)
|
self.__callPackageStarted(pp)
|
||||||
|
|
||||||
def __packageDone(self, pp):
|
def __packageDone(self, pp):
|
||||||
""" This method is called when a single package has been
|
""" This method is called when a single package has been
|
||||||
downloaded and installed, or has failed. """
|
downloaded and installed, or has failed. """
|
||||||
print "Downloaded %s: %s" % (pp.packageName, pp.success)
|
|
||||||
self.__callPackageFinished(pp, pp.success)
|
self.__callPackageFinished(pp, pp.success)
|
||||||
pp.notified = True
|
pp.notified = True
|
||||||
|
|
||||||
@ -507,16 +501,15 @@ class PackageInstaller(DirectObject):
|
|||||||
self.packageLock.release()
|
self.packageLock.release()
|
||||||
|
|
||||||
# Now serve this one package.
|
# Now serve this one package.
|
||||||
if not pp.getDescFile(self.appRunner.http):
|
if not pp.checkDescFile():
|
||||||
self.__donePackage(pp, False)
|
if not pp.getDescFile(self.appRunner.http):
|
||||||
return task.cont
|
self.__donePackage(pp, False)
|
||||||
|
return task.cont
|
||||||
|
|
||||||
if pp.package.hasPackage:
|
# This package is now ready to be downloaded. We always add
|
||||||
# This package is already downloaded.
|
# it to needsDownload, even if it's already downloaded, to
|
||||||
self.__donePackage(pp, True)
|
# guarantee ordering of packages.
|
||||||
return task.cont
|
|
||||||
|
|
||||||
# This package is now ready to be downloaded.
|
|
||||||
self.packageLock.acquire()
|
self.packageLock.acquire()
|
||||||
try:
|
try:
|
||||||
# Also add any packages required by this one.
|
# Also add any packages required by this one.
|
||||||
@ -552,9 +545,10 @@ class PackageInstaller(DirectObject):
|
|||||||
messenger.send('PackageInstaller-%s-packageStarted' % self.uniqueId,
|
messenger.send('PackageInstaller-%s-packageStarted' % self.uniqueId,
|
||||||
[pp], taskChain = 'default')
|
[pp], taskChain = 'default')
|
||||||
|
|
||||||
if not pp.package.downloadPackage(self.appRunner.http):
|
if not pp.package.hasPackage:
|
||||||
self.__donePackage(pp, False)
|
if not pp.package.downloadPackage(self.appRunner.http):
|
||||||
return task.cont
|
self.__donePackage(pp, False)
|
||||||
|
return task.cont
|
||||||
|
|
||||||
# Successfully downloaded and installed.
|
# Successfully downloaded and installed.
|
||||||
self.__donePackage(pp, True)
|
self.__donePackage(pp, True)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user