*** empty log message ***

This commit is contained in:
Mike Goslin 2000-12-11 22:41:54 +00:00
parent 11d75a93ad
commit fc8e976192
5 changed files with 129 additions and 53 deletions

View File

@ -11,21 +11,22 @@
Configure(config_downloader); Configure(config_downloader);
NotifyCategoryDef(downloader, ""); NotifyCategoryDef(downloader, "");
// How often we write to disk is determined by this ratio which is
// relative to the downloader-byte-rate (e.g. if disk-write-ratio is 4,
// we will write every 4 seconds if the frequency is 0.2)
const int downloader_disk_write_frequency =
config_downloader.GetInt("downloader-disk-write-frequency", 4);
// We'd like this to be about 1 second worth of download assuming a // We'd like this to be about 1 second worth of download assuming a
// 28.8Kb connection (28.8Kb / 8 = 3600 bytes per second). // 28.8Kb connection (28.8Kb / 8 = 3600 bytes per second).
const int downloader_buffer_size = const int downloader_byte_rate =
config_downloader.GetInt("downloader-buffer-size", 3600); config_downloader.GetInt("downloader-byte-rate", 3600);
// Frequency of download chunk requests in seconds (or fractions of) // Frequency of download chunk requests in seconds (or fractions of)
// (Estimated 200 msec round-trip to server). // (Estimated 200 msec round-trip to server).
const float downloader_frequency = const float downloader_frequency =
config_downloader.GetFloat("downloader-frequency", 0.2); config_downloader.GetFloat("downloader-frequency", 0.2);
// Estimated available bandwidth (assume a 28.8Kb connection, so again
// we have 3600 bytes per second).
const float downloader_bandwidth =
config_downloader.GetFloat("downloader-bandwidth", 3600.0);
const int downloader_timeout = const int downloader_timeout =
config_downloader.GetInt("downloader-timeout", 15); config_downloader.GetInt("downloader-timeout", 15);

View File

@ -11,9 +11,9 @@
NotifyCategoryDecl(downloader, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS); NotifyCategoryDecl(downloader, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
extern const int downloader_buffer_size; extern const int downloader_disk_write_frequency;
extern const int downloader_byte_rate;
extern const float downloader_frequency; extern const float downloader_frequency;
extern const float downloader_bandwidth;
extern const int downloader_timeout; extern const int downloader_timeout;
extern const int downloader_timeout_retries; extern const int downloader_timeout_retries;

View File

@ -6,27 +6,27 @@
#include "config_downloader.h" #include "config_downloader.h"
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Downloader::set_bandwidth // Function: Downloader::set_byte_rate
// Access: Public // Access: Public
// Description: Note: modem speeds are reported in bits, so you // Description: Note: modem speeds are reported in bits, so you
// need to convert! // need to convert!
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void Downloader:: INLINE void Downloader::
set_bandwidth(float bytes) { set_byte_rate(float bytes) {
#ifdef HAVE_IPC #ifdef HAVE_IPC
mutex_lock lock(_bandwidth_frequency_lock); mutex_lock lock(_bandwidth_frequency_lock);
#endif #endif
_bandwidth = bytes; _byte_rate = bytes;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Downloader::get_bandwidth // Function: Downloader::get_byte_rate
// Access: Public // Access: Public
// Description: Returns bandwidth in bytes. // Description: Returns byte rate in bytes.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE float Downloader:: INLINE float Downloader::
get_bandwidth(void) const { get_byte_rate(void) const {
return _bandwidth; return _byte_rate;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -50,14 +50,17 @@ is_download_enabled(void) const {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Downloader::change_buffer_size // Function: Downloader::set_disk_write_frequency
// Access: Public // Access: Public
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool Downloader:: INLINE bool Downloader::
change_buffer_size(int size) { set_disk_write_frequency(int frequency) {
nassertr(frequency > 0, false);
_disk_write_frequency = frequency;
int size = _disk_write_frequency * (_byte_rate * _frequency);
if (size == _buffer_size) if (size == _buffer_size)
return true; return false;
nassertr(size > 0, false); nassertr(size > 0, false);
#ifdef HAVE_IPC #ifdef HAVE_IPC
_buffer_lock.lock(); _buffer_lock.lock();
@ -68,3 +71,23 @@ change_buffer_size(int size) {
#endif #endif
return true; return true;
} }
////////////////////////////////////////////////////////////////////
// Function: Downloader::get_disk_write_frequency
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE int Downloader::
get_disk_write_frequency(void) const {
return _disk_write_frequency;
}
////////////////////////////////////////////////////////////////////
// Function: Downloader::get_last_attempt_stalled
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool Downloader::
get_last_attempt_stalled(void) const {
return _last_attempt_stalled;
}

View File

@ -57,12 +57,13 @@ public:
INLINE DownloaderToken(uint id, const string &file_name, INLINE DownloaderToken(uint id, const string &file_name,
const Filename &file_dest, const string &event_name, const Filename &file_dest, const string &event_name,
int first_byte, int last_byte, int total_bytes, int first_byte, int last_byte, int total_bytes,
bool partial_content) : _id(id), _first_byte(first_byte), bool partial_content, bool sync) : _id(id), _first_byte(first_byte),
_last_byte(last_byte), _total_bytes(total_bytes) { _last_byte(last_byte), _total_bytes(total_bytes) {
_file_name = file_name; _file_name = file_name;
_event_name = event_name; _event_name = event_name;
_file_dest = file_dest; _file_dest = file_dest;
_partial_content = partial_content; _partial_content = partial_content;
_sync = sync;
} }
uint _id; uint _id;
string _file_name; string _file_name;
@ -72,6 +73,7 @@ public:
int _last_byte; int _last_byte;
int _total_bytes; int _total_bytes;
bool _partial_content; bool _partial_content;
bool _sync;
}; };
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -81,10 +83,10 @@ public:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
Downloader:: Downloader::
Downloader(void) : AsyncUtility() { Downloader(void) : AsyncUtility() {
PT(Buffer) buffer = new Buffer(downloader_buffer_size); init();
init(buffer);
} }
#if 0
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Downloader::Constructor // Function: Downloader::Constructor
// Access: Public // Access: Public
@ -94,6 +96,7 @@ Downloader::
Downloader(PT(Buffer) buffer) : AsyncUtility() { Downloader(PT(Buffer) buffer) : AsyncUtility() {
init(buffer); init(buffer);
} }
#endif
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Downloader::init // Function: Downloader::init
@ -101,18 +104,23 @@ Downloader(PT(Buffer) buffer) : AsyncUtility() {
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void Downloader:: void Downloader::
init(PT(Buffer) buffer) { init(void) {
nassertv(!buffer.is_null()); _disk_write_frequency = downloader_disk_write_frequency;
_byte_rate = downloader_byte_rate;
_frequency = downloader_frequency; _frequency = downloader_frequency;
_bandwidth = downloader_bandwidth; nassertv(_frequency > 0);
if (_frequency == 0)
_buffer_size = _disk_write_frequency * _byte_rate;
else
_buffer_size = _disk_write_frequency * (_byte_rate * _frequency);
_buffer = new Buffer(_buffer_size);
_new_buffer_size = 0;
_connected = false; _connected = false;
_token_board = new DownloaderTokenBoard; _token_board = new DownloaderTokenBoard;
_buffer = buffer;
_download_enabled = true; _download_enabled = true;
_last_attempt_stalled = true;
// We need to flush after every write in case we're interrupted // We need to flush after every write in case we're interrupted
_dest_stream.setf(ios::unitbuf, 0); _dest_stream.setf(ios::unitbuf, 0);
_buffer_size = _buffer->get_length();
_new_buffer_size = 0;
#if defined(WIN32) #if defined(WIN32)
WSAData mydata; WSAData mydata;
@ -227,6 +235,30 @@ disconnect_from_server(void) {
_connected = false; _connected = false;
} }
////////////////////////////////////////////////////////////////////
// Function: Downloader::request_sync_download
// Access: Public
// Description: Requests the synchronous download of a complete file.
////////////////////////////////////////////////////////////////////
int Downloader::
request_sync_download(const string &file_name, const Filename &file_dest,
const string &event_name) {
return request_download(file_name, file_dest, event_name, true);
}
////////////////////////////////////////////////////////////////////
// Function: Downloader::request_sync_download
// Access: Public
// Description: Requests the synchronous download of a complete file.
////////////////////////////////////////////////////////////////////
int Downloader::
request_sync_download(const string &file_name, const Filename &file_dest,
const string &event_name, int first_byte,
int last_byte, int total_bytes, bool partial_content) {
return request_download(file_name, file_dest, event_name, first_byte,
last_byte, total_bytes, partial_content, true);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Downloader::request_download // Function: Downloader::request_download
// Access: Public // Access: Public
@ -234,9 +266,9 @@ disconnect_from_server(void) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int Downloader:: int Downloader::
request_download(const string &file_name, const Filename &file_dest, request_download(const string &file_name, const Filename &file_dest,
const string &event_name) { const string &event_name, bool sync) {
return request_download(file_name, file_dest, event_name, 0, 0, 0, return request_download(file_name, file_dest, event_name, 0, 0, 0,
false); false, sync);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -258,7 +290,7 @@ int Downloader::
request_download(const string &file_name, const Filename &file_dest, request_download(const string &file_name, const Filename &file_dest,
const string &event_name, int first_byte, const string &event_name, int first_byte,
int last_byte, int total_bytes, int last_byte, int total_bytes,
bool partial_content) { bool partial_content, bool sync) {
nassertr(first_byte <= last_byte && last_byte <= total_bytes, 0); nassertr(first_byte <= last_byte && last_byte <= total_bytes, 0);
@ -291,7 +323,7 @@ request_download(const string &file_name, const Filename &file_dest,
tok = new DownloaderToken(_next_token++, file_name, file_dest, tok = new DownloaderToken(_next_token++, file_name, file_dest,
event_name, first_byte, last_byte, total_bytes, event_name, first_byte, last_byte, total_bytes,
partial_content); partial_content, sync);
_token_board->_waiting.insert(tok); _token_board->_waiting.insert(tok);
#ifdef HAVE_IPC #ifdef HAVE_IPC
@ -314,7 +346,7 @@ request_download(const string &file_name, const Filename &file_dest,
tok = new DownloaderToken(_next_token++, file_name, file_dest, tok = new DownloaderToken(_next_token++, file_name, file_dest,
event_name, first_byte, last_byte, total_bytes, event_name, first_byte, last_byte, total_bytes,
partial_content); partial_content, sync);
_token_board->_waiting.insert(tok); _token_board->_waiting.insert(tok);
process_request(); process_request();
} }
@ -342,7 +374,7 @@ process_request() {
PT(DownloaderToken) tok = _token_board->_waiting.extract(); PT(DownloaderToken) tok = _token_board->_waiting.extract();
int ret = download(tok->_file_name, tok->_file_dest, tok->_event_name, int ret = download(tok->_file_name, tok->_file_dest, tok->_event_name,
tok->_first_byte, tok->_last_byte, tok->_total_bytes, tok->_first_byte, tok->_last_byte, tok->_total_bytes,
tok->_partial_content, tok->_id); tok->_partial_content, tok->_sync, tok->_id);
if (ret == D_success) { if (ret == D_success) {
_token_board->_done.insert(tok); _token_board->_done.insert(tok);
@ -420,8 +452,9 @@ safe_send(int socket, const char *data, int length, long timeout) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int Downloader:: int Downloader::
safe_receive(int socket, DownloadStatus &status, int length, safe_receive(int socket, DownloadStatus &status, int length,
long timeout, int &bytes) { long timeout, int &bytes, bool &stalled) {
bytes = 0; bytes = 0;
stalled = true;
if (length == 0) { if (length == 0) {
downloader_cat.error() downloader_cat.error()
<< "Downloader::safe_receive() - requested 0 length receive!" << endl; << "Downloader::safe_receive() - requested 0 length receive!" << endl;
@ -454,6 +487,8 @@ safe_receive(int socket, DownloadStatus &status, int length,
bytes += ret; bytes += ret;
status._next_in += ret; status._next_in += ret;
status._bytes_in_buffer += ret; status._bytes_in_buffer += ret;
if (bytes == length)
stalled = false;
} else if (ret == 0) { } else if (ret == 0) {
if (downloader_cat.is_debug()) if (downloader_cat.is_debug())
downloader_cat.debug() downloader_cat.debug()
@ -475,7 +510,8 @@ safe_receive(int socket, DownloadStatus &status, int length,
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int Downloader:: int Downloader::
attempt_read(int length, DownloadStatus &status, int &bytes_read) { attempt_read(int length, DownloadStatus &status, int &bytes_read,
bool &stalled) {
bytes_read = 0; bytes_read = 0;
for (int i = 0; i < downloader_timeout_retries; i++) { for (int i = 0; i < downloader_timeout_retries; i++) {
@ -494,7 +530,7 @@ attempt_read(int length, DownloadStatus &status, int &bytes_read) {
// Make the request for length bytes // Make the request for length bytes
int bytes; int bytes;
int ans = safe_receive(_socket, status, length, int ans = safe_receive(_socket, status, length,
(long)downloader_timeout, bytes); (long)downloader_timeout, bytes, stalled);
bytes_read += bytes; bytes_read += bytes;
switch (ans) { switch (ans) {
@ -528,7 +564,7 @@ attempt_read(int length, DownloadStatus &status, int &bytes_read) {
int Downloader:: int Downloader::
download(const string &file_name, Filename file_dest, download(const string &file_name, Filename file_dest,
const string &event_name, int first_byte, int last_byte, const string &event_name, int first_byte, int last_byte,
int total_bytes, bool partial_content, uint id) { int total_bytes, bool partial_content, bool sync, uint id) {
if (_download_enabled == false) { if (_download_enabled == false) {
if (downloader_cat.is_debug()) if (downloader_cat.is_debug())
@ -611,16 +647,21 @@ download(const string &file_name, Filename file_dest,
_bandwidth_frequency_lock.lock(); _bandwidth_frequency_lock.lock();
#endif #endif
// read_size is the length of the buffer requested via safe_receive() // read_size is the length of the buffer requested via safe_receive()
int read_size = (int)_bandwidth; int read_size;
if (_frequency > 0) nassertr(_frequency > 0, D_error);
read_size = (int)(_bandwidth * _frequency); if (sync == true || _frequency == 0)
read_size = (int)_byte_rate;
else
read_size = (int)(_byte_rate * _frequency);
#ifdef HAVE_IPC #ifdef HAVE_IPC
_bandwidth_frequency_lock.unlock(); _bandwidth_frequency_lock.unlock();
#endif #endif
// Attempt to read // Attempt to read
int bytes_read; int bytes_read;
int ret = attempt_read(read_size, status, bytes_read); bool stalled;
int ret = attempt_read(read_size, status, bytes_read, stalled);
_last_attempt_stalled = stalled;
if (bytes_read > 0) if (bytes_read > 0)
got_any_data = true; got_any_data = true;

View File

@ -33,24 +33,32 @@ class DownloaderToken;
class EXPCL_PANDAEXPRESS Downloader : public AsyncUtility { class EXPCL_PANDAEXPRESS Downloader : public AsyncUtility {
PUBLISHED: PUBLISHED:
Downloader(void); Downloader(void);
Downloader(PT(Buffer) buffer); //Downloader(PT(Buffer) buffer);
virtual ~Downloader(void); virtual ~Downloader(void);
bool connect_to_server(const string &name, uint port=80); bool connect_to_server(const string &name, uint port=80);
void disconnect_from_server(void); void disconnect_from_server(void);
int request_download(const string &file_name, const Filename &file_dest, int request_sync_download(const string &file_name, const Filename &file_dest,
const string &event_name); const string &event_name);
int request_download(const string &file_name, const Filename &file_dest, int request_sync_download(const string &file_name, const Filename &file_dest,
const string &event_name, int first_byte, const string &event_name, int first_byte,
int last_byte, int total_bytes, int last_byte, int total_bytes,
bool partial_content = true); bool partial_content = true);
int request_download(const string &file_name, const Filename &file_dest,
const string &event_name, bool sync = false);
int request_download(const string &file_name, const Filename &file_dest,
const string &event_name, int first_byte,
int last_byte, int total_bytes,
bool partial_content = true, bool sync = false);
INLINE void set_bandwidth(float bytes); INLINE void set_byte_rate(float bytes);
INLINE float get_bandwidth(void) const; INLINE float get_byte_rate(void) const;
INLINE bool set_disk_write_frequency(int frequency);
INLINE int get_disk_write_frequency(void) const;
INLINE void enable_download(bool val); INLINE void enable_download(bool val);
INLINE bool is_download_enabled(void) const; INLINE bool is_download_enabled(void) const;
INLINE bool change_buffer_size(int size); INLINE bool get_last_attempt_stalled(void) const;
private: private:
class DownloadStatus { class DownloadStatus {
@ -79,20 +87,21 @@ private:
char *_buffer; char *_buffer;
}; };
void init(PT(Buffer) buffer); void init();
int download(const string &file_name, Filename file_dest, int download(const string &file_name, Filename file_dest,
const string &event_name, int first_byte, const string &event_name, int first_byte,
int last_byte, int total_bytes, bool partial_content, int last_byte, int total_bytes, bool partial_content,
uint id); bool sync, uint id);
virtual bool process_request(void); virtual bool process_request(void);
bool parse_header(DownloadStatus &status); bool parse_header(DownloadStatus &status);
bool write_to_disk(DownloadStatus &status); bool write_to_disk(DownloadStatus &status);
bool connect_to_server(void); bool connect_to_server(void);
int safe_send(int socket, const char *data, int length, long timeout); int safe_send(int socket, const char *data, int length, long timeout);
int safe_receive(int socket, DownloadStatus &status, int length, int safe_receive(int socket, DownloadStatus &status, int length,
long timeout, int &bytes); long timeout, int &bytes, bool &stalled);
bool parse_http_response(const string &resp); bool parse_http_response(const string &resp);
int attempt_read(int length, DownloadStatus &status, int &bytes_read); int attempt_read(int length, DownloadStatus &status, int &bytes_read,
bool &stalled);
typedef TokenBoard<DownloaderToken> DownloaderTokenBoard; typedef TokenBoard<DownloaderToken> DownloaderTokenBoard;
DownloaderTokenBoard *_token_board; DownloaderTokenBoard *_token_board;
@ -106,11 +115,13 @@ private:
int _socket; int _socket;
PT(Buffer) _buffer; PT(Buffer) _buffer;
float _bandwidth; int _disk_write_frequency;
float _byte_rate;
bool _download_enabled; bool _download_enabled;
ofstream _dest_stream; ofstream _dest_stream;
int _new_buffer_size; int _new_buffer_size;
int _buffer_size; int _buffer_size;
bool _last_attempt_stalled;
string _server_name; string _server_name;
struct sockaddr_in _sin; struct sockaddr_in _sin;