From 09483f7133a509528a9e4a76861a66a614d2d287 Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 21 Nov 2009 20:47:07 +0000 Subject: [PATCH] don't needlessly redownload contents.xml --- direct/src/p3d/AppRunner.py | 13 ++-- direct/src/p3d/HostInfo.py | 25 +++++-- direct/src/p3d/coreapi.pdef | 3 + direct/src/plugin/p3dHost.cxx | 111 ++++++++++++++++++----------- direct/src/plugin/p3dHost.h | 3 +- direct/src/plugin/p3dInstance.cxx | 35 +++++++++ direct/src/plugin/p3dInstance.h | 1 + direct/src/plugin/p3dPackage.cxx | 6 +- direct/src/plugin/p3dPythonRun.cxx | 8 ++- 9 files changed, 146 insertions(+), 59 deletions(-) diff --git a/direct/src/p3d/AppRunner.py b/direct/src/p3d/AppRunner.py index 41f7cbbd00..28c36bc89a 100644 --- a/direct/src/p3d/AppRunner.py +++ b/direct/src/p3d/AppRunner.py @@ -521,17 +521,20 @@ class AppRunner(DirectObject): # The "super mirror" URL, generally used only by panda3d.exe. self.superMirrorUrl = superMirrorUrl - def addPackageInfo(self, name, platform, version, hostUrl): + def addPackageInfo(self, name, platform, version, hostUrl, hostDir = None): """ Called by the browser for each one of the "required" packages that were preloaded before starting the application. If for some reason the package isn't already downloaded, this will download it on the spot. Raises OSError on failure. """ host = self.getHost(hostUrl) + if hostDir and not host.hostDir: + host.hostDir = hostDir - if not host.downloadContentsFile(self.http): - message = "Host %s cannot be downloaded, cannot preload %s." % (hostUrl, name) - raise OSError, message + if not host.readContentsFile(): + if not host.downloadContentsFile(self.http): + message = "Host %s cannot be downloaded, cannot preload %s." % (hostUrl, name) + raise OSError, message if not platform: platform = None @@ -894,6 +897,8 @@ def dummyAppRunner(tokens = [], argv = None): if platform.startswith('win'): rootDir = Filename(Filename.getUserAppdataDirectory(), 'Panda3D') + elif platform.startswith('osx'): + rootDir = Filename(Filename.getHomeDirectory(), 'Library/Caches/Panda3D') else: rootDir = Filename(Filename.getHomeDirectory(), '.panda3d') diff --git a/direct/src/p3d/HostInfo.py b/direct/src/p3d/HostInfo.py index fb1ae398df..e0e349dbe5 100644 --- a/direct/src/p3d/HostInfo.py +++ b/direct/src/p3d/HostInfo.py @@ -164,17 +164,31 @@ class HostInfo: return False - def readContentsFile(self, tempFilename): + def readContentsFile(self, tempFilename = None): """ Reads the contents.xml file for this particular host, once it has been downloaded into the indicated temporary file. Returns true on success, false if the contents file is not - already on disk or is unreadable. On success, copies the file - into the standard location if it's not there already. """ + already on disk or is unreadable. - assert not self.hasContentsFile + If tempFilename is specified, it is the filename read, and it + is copied the file into the standard location if it's not + there already. If tempFilename is not specified, the standard + filename is read if it is known. """ + + if self.hasContentsFile: + # No need to read it again. + return True if not hasattr(PandaModules, 'TiXmlDocument'): return False + + if not tempFilename: + if not self.hostDir: + # If the filename is not specified, we can infer it + # only if we already know our hostDir. + return False + + tempFilename = Filename(self.hostDir, 'contents.xml') doc = PandaModules.TiXmlDocument(tempFilename.toOsSpecific()) if not doc.LoadFile(): @@ -256,8 +270,7 @@ class HostInfo: self.descriptiveName = descriptiveName hostDirBasename = xhost.Attribute('host_dir') - if hostDirBasename and not self.hostDir: - self.__determineHostDir(hostDirBasename) + self.__determineHostDir(hostDirBasename) # Get the "download" URL, which is the source from which we # download everything other than the contents.xml file. diff --git a/direct/src/p3d/coreapi.pdef b/direct/src/p3d/coreapi.pdef index 9468439742..4e8f05d302 100644 --- a/direct/src/p3d/coreapi.pdef +++ b/direct/src/p3d/coreapi.pdef @@ -19,6 +19,9 @@ from pandac.PandaModules import getModelPath, Filename, ConfigVariableFilename # Also see panda3d.pdef. +packager.setHost('file:///Users/drose/p3dstage', + descriptiveName = 'local odysseus', hostDir = 'odysseus') + class coreapi(solo): # The special "coreapi" package. As a "solo", this is just a # single .dll (or dylib, or whatever). diff --git a/direct/src/plugin/p3dHost.cxx b/direct/src/plugin/p3dHost.cxx index 759b195556..8d0ee70495 100644 --- a/direct/src/plugin/p3dHost.cxx +++ b/direct/src/plugin/p3dHost.cxx @@ -15,6 +15,7 @@ #include "p3dHost.h" #include "p3dInstanceManager.h" #include "p3dPackage.h" +#include "mkdir_complete.h" #include "openssl/md5.h" #include @@ -97,6 +98,25 @@ get_alt_host(const string &alt_host) { return this; } +//////////////////////////////////////////////////////////////////// +// Function: P3DHost::read_contents_file +// Access: Public +// Description: Reads the contents.xml file in the standard +// filename, if possible. +// +// Returns true on success, false on failure. +//////////////////////////////////////////////////////////////////// +bool P3DHost:: +read_contents_file() { + if (_host_dir.empty()) { + // If we haven't got a host_dir yet, we can't read the contents. + return false; + } + + string standard_filename = _host_dir + "/contents.xml"; + return read_contents_file(standard_filename); +} + //////////////////////////////////////////////////////////////////// // Function: P3DHost::read_contents_file // Access: Public @@ -163,16 +183,63 @@ read_contents_file(const string &contents_filename) { determine_host_dir(""); } assert(!_host_dir.empty()); + mkdir_complete(_host_dir, nout); string standard_filename = _host_dir + "/contents.xml"; if (standardize_filename(standard_filename) != standardize_filename(contents_filename)) { - copy_file(contents_filename, standard_filename); + if (!copy_file(contents_filename, standard_filename)) { + nout << "Couldn't copy to " << standard_filename << "\n"; + } } return true; } +//////////////////////////////////////////////////////////////////// +// Function: P3DHost::read_xhost +// Access: Public +// Description: Reads the host data from the (or ) +// entry in the contents.xml file, or from a +// p3d_info.xml file. +//////////////////////////////////////////////////////////////////// +void P3DHost:: +read_xhost(TiXmlElement *xhost) { + const char *descriptive_name = xhost->Attribute("descriptive_name"); + if (descriptive_name != NULL && _descriptive_name.empty()) { + _descriptive_name = descriptive_name; + } + + const char *host_dir_basename = xhost->Attribute("host_dir"); + if (host_dir_basename == NULL) { + host_dir_basename = ""; + } + determine_host_dir(host_dir_basename); + + // Get the "download" URL, which is the source from which we + // download everything other than the contents.xml file. + const char *download_url = xhost->Attribute("download_url"); + if (download_url != NULL) { + _download_url_prefix = download_url; + } + if (!_download_url_prefix.empty()) { + if (_download_url_prefix[_download_url_prefix.size() - 1] != '/') { + _download_url_prefix += "/"; + } + } else { + _download_url_prefix = _host_url_prefix; + } + + TiXmlElement *xmirror = xhost->FirstChildElement("mirror"); + while (xmirror != NULL) { + const char *url = xmirror->Attribute("url"); + if (url != NULL) { + add_mirror(url); + } + xmirror = xmirror->NextSiblingElement("mirror"); + } +} + //////////////////////////////////////////////////////////////////// // Function: P3DHost::get_package // Access: Public @@ -455,48 +522,6 @@ determine_host_dir(const string &host_dir_basename) { } } -//////////////////////////////////////////////////////////////////// -// Function: P3DHost::read_xhost -// Access: Private -// Description: Reads the host data from the (or ) -// entry in the contents.xml file. -//////////////////////////////////////////////////////////////////// -void P3DHost:: -read_xhost(TiXmlElement *xhost) { - const char *descriptive_name = xhost->Attribute("descriptive_name"); - if (descriptive_name != NULL && _descriptive_name.empty()) { - _descriptive_name = descriptive_name; - } - - const char *host_dir_basename = xhost->Attribute("host_dir"); - if (host_dir_basename != NULL && _host_dir.empty()) { - determine_host_dir(host_dir_basename); - } - - // Get the "download" URL, which is the source from which we - // download everything other than the contents.xml file. - const char *download_url = xhost->Attribute("download_url"); - if (download_url != NULL) { - _download_url_prefix = download_url; - } - if (!_download_url_prefix.empty()) { - if (_download_url_prefix[_download_url_prefix.size() - 1] != '/') { - _download_url_prefix += "/"; - } - } else { - _download_url_prefix = _host_url_prefix; - } - - TiXmlElement *xmirror = xhost->FirstChildElement("mirror"); - while (xmirror != NULL) { - const char *url = xmirror->Attribute("url"); - if (url != NULL) { - add_mirror(url); - } - xmirror = xmirror->NextSiblingElement("mirror"); - } -} - //////////////////////////////////////////////////////////////////// // Function: P3DHost::standardize_filename diff --git a/direct/src/plugin/p3dHost.h b/direct/src/plugin/p3dHost.h index d8c465a00a..0227fea891 100644 --- a/direct/src/plugin/p3dHost.h +++ b/direct/src/plugin/p3dHost.h @@ -46,7 +46,9 @@ public: inline int get_contents_seq() const; inline bool check_contents_hash(const string &pathname) const; + bool read_contents_file(); bool read_contents_file(const string &contents_filename); + void read_xhost(TiXmlElement *xhost); P3DPackage *get_package(const string &package_name, const string &package_version, @@ -64,7 +66,6 @@ public: private: void determine_host_dir(const string &host_dir_basename); - void read_xhost(TiXmlElement *xhost); static string standardize_filename(const string &filename); static bool copy_file(const string &from_filename, const string &to_filename); diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index db0aadd5c3..4b7bc87e8b 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -912,6 +912,12 @@ add_package(const string &name, const string &version, P3DHost *host) { host = inst_mgr->get_host(alt_host_url); alt_host.clear(); } + + if (!host->has_contents_file()) { + // Since we haven't downloaded this host's contents.xml file yet, + // get its additional host information. + get_host_info(host); + } P3DPackage *package = host->get_package(name, version, alt_host); add_package(package); @@ -1822,6 +1828,35 @@ find_alt_host_url(const string &host_url, const string &alt_host) { return string(); } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstance::get_host_info +// Access: Private +// Description: Looks in the p3d_info.xml file for the auxiliary host +// information for the selected host. Some of this +// information is helpful to have before the host has +// read its own contents.xml file (particularly the +// host_dir specification). +//////////////////////////////////////////////////////////////////// +void P3DInstance:: +get_host_info(P3DHost *host) { + // We should only call this function if we haven't already read the + // host's more-authoritative contents.xml file. + assert(!host->has_contents_file()); + + TiXmlElement *xhost = _xpackage->FirstChildElement("host"); + while (xhost != NULL) { + const char *url = xhost->Attribute("url"); + if (url != NULL && host->get_host_url() == url) { + // Found the entry for this particular host. + host->read_xhost(xhost); + return; + } + xhost = xhost->NextSiblingElement("host"); + } + + // Didn't find an entry for this host; oh well. +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstance::send_browser_script_object // Access: Private diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index b88985905d..e0f37f3667 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -169,6 +169,7 @@ private: void mark_p3d_trusted(); void scan_app_desc_file(TiXmlDocument *doc); string find_alt_host_url(const string &host_url, const string &alt_host); + void get_host_info(P3DHost *host); void send_browser_script_object(); P3D_request *make_p3d_request(TiXmlElement *xrequest); diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx index 2430b5cf9f..a2ad12084c 100755 --- a/direct/src/plugin/p3dPackage.cxx +++ b/direct/src/plugin/p3dPackage.cxx @@ -225,6 +225,7 @@ make_xml() { xpackage->SetAttribute("version", _package_version); } xpackage->SetAttribute("host", _host->get_host_url()); + xpackage->SetAttribute("host_dir", _host->get_host_dir()); return xpackage; } @@ -268,14 +269,12 @@ begin_info_download() { //////////////////////////////////////////////////////////////////// void P3DPackage:: download_contents_file() { - /* P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); if (!_host->has_contents_file() && !inst_mgr->get_verify_contents()) { // If we're allowed to read a contents file without checking the // server first, try it now. _host->read_contents_file(); } - */ if (_host->has_contents_file()) { // We've already got a contents.xml file; go straight to the @@ -310,7 +309,8 @@ contents_file_download_finished(bool success) { // Maybe we can read an already-downloaded contents.xml file. string standard_filename = _host->get_host_dir() + "/contents.xml"; - if (!_host->read_contents_file(standard_filename)) { + if (_host->get_host_dir().empty() || + !_host->read_contents_file(standard_filename)) { // Couldn't even read that. Fail. report_done(false); delete _temp_contents_file; diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index 0334456cea..ca60eea257 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -1224,6 +1224,7 @@ add_package_info(P3DCInstance *inst, TiXmlElement *xpackage) { const char *platform = xpackage->Attribute("platform"); const char *version = xpackage->Attribute("version"); const char *host = xpackage->Attribute("host"); + const char *host_dir = xpackage->Attribute("host_dir"); if (name == NULL || host == NULL) { return; } @@ -1233,10 +1234,13 @@ add_package_info(P3DCInstance *inst, TiXmlElement *xpackage) { if (platform == NULL) { platform = ""; } + if (host_dir == NULL) { + host_dir = ""; + } PyObject *result = PyObject_CallMethod - (_runner, (char *)"addPackageInfo", (char *)"ssss", - name, platform, version, host); + (_runner, (char *)"addPackageInfo", (char *)"sssss", + name, platform, version, host, host_dir); if (result == NULL) { PyErr_Print();