don't needlessly redownload contents.xml

This commit is contained in:
David Rose 2009-11-21 20:47:07 +00:00
parent 82f49bb352
commit 09483f7133
9 changed files with 146 additions and 59 deletions

View File

@ -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')

View File

@ -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.

View File

@ -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).

View File

@ -15,6 +15,7 @@
#include "p3dHost.h"
#include "p3dInstanceManager.h"
#include "p3dPackage.h"
#include "mkdir_complete.h"
#include "openssl/md5.h"
#include <algorithm>
@ -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 <host> (or <alt_host>)
// 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 <host> (or <alt_host>)
// 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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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();