diff --git a/panda/src/downloader/downloadDb.cxx b/panda/src/downloader/downloadDb.cxx index ae346885a2..209321d3a7 100644 --- a/panda/src/downloader/downloadDb.cxx +++ b/panda/src/downloader/downloadDb.cxx @@ -779,6 +779,15 @@ bool DownloadDb::Db:: write(ofstream &write_stream) { write_header(write_stream); + // Declare these outside the loop so we do not keep creating + // and deleting them + PN_int32 phase; + PN_int32 version; + PN_int32 size; + PN_int32 status; + PN_int32 num_files; + PN_int32 name_length; + PN_int32 header_length; // Iterate over the multifiles writing them to the stream vector::const_iterator i = _mfile_records.begin(); @@ -786,15 +795,14 @@ write(ofstream &write_stream) { _datagram.clear(); // Cache some properties so we do not have to keep asking for them - PN_int32 phase = (*i)->_phase; - PN_int32 version = (*i)->_version; - PN_int32 size = (*i)->_size; - PN_int32 status = (*i)->_status; - PN_int32 num_files = (*i)->get_num_files(); - PN_int32 name_length = (*i)->_name.length(); + phase = (*i)->_phase; + version = (*i)->_version; + size = (*i)->_size; + status = (*i)->_status; + num_files = (*i)->get_num_files(); + name_length = (*i)->_name.length(); // Compute the length of this datagram - PN_int32 header_length; header_length = sizeof(header_length) + // Size of this header length sizeof(name_length) + // Size of the size of the name string @@ -1012,11 +1020,15 @@ get_version(const string &name, HashVal hash) { void DownloadDb:: write_version_map(ofstream &write_stream) { _master_datagram.clear(); + VersionMap::iterator vmi; vectorHash::iterator i; + string name; + HashVal hash; + _master_datagram.add_int32(_versions.size()); for (vmi = _versions.begin(); vmi != _versions.end(); ++vmi) { - string name = (*vmi).first; + name = (*vmi).first; downloader_cat.spam() << "DownloadDb::write_version_map() - writing file: " << name << " of length: " << name.length() << endl; @@ -1025,7 +1037,7 @@ write_version_map(ofstream &write_stream) { _master_datagram.add_int32((*vmi).second.size()); for (i = (*vmi).second.begin(); i != (*vmi).second.end(); ++i) { // *i will point to a HashVal - HashVal hash = *i; + hash = *i; // Write out each uint separately _master_datagram.add_uint32(hash.get_value(0)); _master_datagram.add_uint32(hash.get_value(1)); diff --git a/panda/src/downloader/downloader.cxx b/panda/src/downloader/downloader.cxx index 9aa6fb6e66..9c0f75fc04 100644 --- a/panda/src/downloader/downloader.cxx +++ b/panda/src/downloader/downloader.cxx @@ -115,6 +115,8 @@ init(void) { _last_attempt_stalled = true; // We need to flush after every write in case we're interrupted _dest_stream.setf(ios::unitbuf, 0); + _last_attempt_stalled = false; + _current_attempt_stalled = false; #if defined(WIN32) WSAData mydata; @@ -376,6 +378,13 @@ process_request() { _token_board->_done.insert(tok); return_event->add_parameter(EventParameter(DS_success)); + // Throw a "done" event now. + if (!tok->_event_name.empty()) { + PT_Event done = new Event(tok->_event_name); + done->add_parameter(EventParameter((int)tok->_id)); + throw_event(done); + } + if (downloader_cat.is_debug()) { downloader_cat.debug() << "Downloader::process_request() - downloading complete for " @@ -440,9 +449,8 @@ safe_send(int socket, const char *data, int length, long timeout) { //////////////////////////////////////////////////////////////////// int Downloader:: safe_receive(int socket, DownloadStatus &status, int length, - long timeout, int &bytes, bool &stalled) { + long timeout, int &bytes) { bytes = 0; - stalled = true; if (length == 0) { downloader_cat.error() << "Downloader::safe_receive() - requested 0 length receive!" << endl; @@ -475,8 +483,12 @@ safe_receive(int socket, DownloadStatus &status, int length, bytes += ret; status._next_in += ret; status._bytes_in_buffer += ret; - if (bytes == length) - stalled = false; + if (bytes < length) { + if (downloader_cat.is_debug()) + downloader_cat.debug() + << "Downloader::safe_receive() - Download stalled" << endl; + _current_attempt_stalled = true; + } } else if (ret == 0) { if (downloader_cat.is_debug()) downloader_cat.debug() @@ -498,8 +510,7 @@ safe_receive(int socket, DownloadStatus &status, int length, // Description: //////////////////////////////////////////////////////////////////// int Downloader:: -attempt_read(int length, DownloadStatus &status, int &bytes_read, - bool &stalled) { +attempt_read(int length, DownloadStatus &status, int &bytes_read) { bytes_read = 0; for (int i = 0; i < downloader_timeout_retries; i++) { @@ -518,7 +529,7 @@ attempt_read(int length, DownloadStatus &status, int &bytes_read, // Make the request for length bytes int bytes; int ans = safe_receive(_socket, status, length, - (long)downloader_timeout, bytes, stalled); + (long)downloader_timeout, bytes); bytes_read += bytes; switch (ans) { @@ -627,10 +638,11 @@ download(const string &file_name, Filename file_dest, DownloadStatus status(_buffer->_buffer, event_name, first_byte, last_byte, total_bytes, partial_content, id); bool got_any_data = false; - + // Loop at the requested frequency until the download completes for (;;) { bool resize_buffer = false; + // Ensure that these don't change while we're computing read_size #ifdef HAVE_IPC _buffer_lock.lock(); @@ -655,6 +667,10 @@ download(const string &file_name, Filename file_dest, if (resize_buffer == true) { // Flush the write buffer before resizing it if (status._bytes_in_buffer > 0) { + if (downloader_cat.is_debug()) + downloader_cat.debug() + << "Downloader::download() - Flushing buffer" << endl; + if (write_to_disk(status) == false) { downloader_cat.error() << "Downloader::download() - failed to flush buffer during " @@ -671,7 +687,14 @@ download(const string &file_name, Filename file_dest, << "Downloader::download() - resizing disk buffer to: " << _disk_buffer_size << endl; _buffer.clear(); + downloader_cat.debug() + << "Downloader::download() - buffer cleared" << endl; _buffer = new Buffer(_disk_buffer_size); + // Update the status with the new buffer + status._buffer = _buffer->_buffer; + status.reset(); + downloader_cat.debug() + << "Downloader::download() - new buffer created" << endl; } #ifdef HAVE_IPC @@ -680,9 +703,16 @@ download(const string &file_name, Filename file_dest, // Attempt to read int bytes_read; - bool stalled; - int ret = attempt_read(_read_size, status, bytes_read, stalled); - _last_attempt_stalled = stalled; + + int ret = attempt_read(_read_size, status, bytes_read); + if (downloader_cat.is_debug()) + downloader_cat.debug() + << "Downloader::download() - stalled status: " << _current_attempt_stalled + << endl; + + _last_attempt_stalled = _current_attempt_stalled; + _current_attempt_stalled = false; + if (bytes_read > 0) got_any_data = true; diff --git a/panda/src/downloader/downloader.h b/panda/src/downloader/downloader.h index 7bdb5f217f..fa1a44f308 100644 --- a/panda/src/downloader/downloader.h +++ b/panda/src/downloader/downloader.h @@ -88,8 +88,6 @@ private: int _total_bytes; bool _partial_content; uint _id; - - private: char *_buffer; }; @@ -104,10 +102,9 @@ private: bool connect_to_server(void); int safe_send(int socket, const char *data, int length, long timeout); int safe_receive(int socket, DownloadStatus &status, int length, - long timeout, int &bytes, bool &stalled); + long timeout, int &bytes); bool parse_http_response(const string &resp); - int attempt_read(int length, DownloadStatus &status, int &bytes_read, - bool &stalled); + int attempt_read(int length, DownloadStatus &status, int &bytes_read); typedef TokenBoard DownloaderTokenBoard; DownloaderTokenBoard *_token_board; @@ -129,6 +126,7 @@ private: ofstream _dest_stream; int _disk_buffer_size; bool _last_attempt_stalled; + bool _current_attempt_stalled; string _server_name; struct sockaddr_in _sin;