diff --git a/panda/src/downloader/asyncDecompressor.cxx b/panda/src/downloader/asyncDecompressor.cxx new file mode 100644 index 0000000000..06e65f9aae --- /dev/null +++ b/panda/src/downloader/asyncDecompressor.cxx @@ -0,0 +1,332 @@ +// Filename: decompressor.cxx +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// + +// This file is compiled only if we have zlib installed. + +//////////////////////////////////////////////////////////////////// +// Includes +//////////////////////////////////////////////////////////////////// +#include "asyncDecompressor.h" +#include "config_downloader.h" + +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////// +// Defines +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Class : DecompressorToken +// Description : Holds a request for the decompressor. +//////////////////////////////////////////////////////////////////// +class DecompressorToken : public ReferenceCount { +public: + INLINE DecompressorToken(uint id, const Filename &source_file, + const Filename &dest_file, const string &event_name) { + _id = id; + _source_file = source_file; + _dest_file = dest_file; + _event_name = event_name; + } + int _id; + Filename _source_file; + Filename _dest_file; + string _event_name; +}; + +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +Decompressor:: +Decompressor(void) : AsyncUtility() { + PT(Buffer) buffer = new Buffer(decompressor_buffer_size); + init(buffer); +} + +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +Decompressor:: +Decompressor(PT(Buffer) buffer) : AsyncUtility() { + init(buffer); +} + +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::Constructor +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +void Decompressor:: +init(PT(Buffer) buffer) { + nassertv(!buffer.is_null()); + _frequency = decompressor_frequency; + _token_board = new DecompressorTokenBoard; + _half_buffer_length = buffer->get_length()/2; + _buffer = buffer; + char *temp_name = tempnam(NULL, "dc"); + _temp_file_name = temp_name; + _temp_file_name.set_binary(); + delete temp_name; +} + +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +Decompressor:: +~Decompressor(void) { + destroy_thread(); + + delete _token_board; + _temp_file_name.unlink(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::request_decompress +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +int Decompressor:: +request_decompress(const Filename &source_file, const string &event_name) { + Filename dest_file = source_file; + string extension = source_file.get_extension(); + if (extension == "pz") + dest_file = source_file.get_fullpath_wo_extension(); + else { + if (downloader_cat.is_debug()) + downloader_cat.debug() + << "Decompressor::request_decompress() - Unknown file extension: ." + << extension << endl; + } + return request_decompress(source_file, dest_file, event_name); +} + +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::request_decompress +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +int Decompressor:: +request_decompress(const Filename &source_file, const Filename &dest_file, + const string &event_name) { + + PT(DecompressorToken) tok; + if (_threads_enabled) { + + // Make sure we actually are threaded + if (!_threaded) { + downloader_cat.info() + << "Decompressor::request_decompress() - create_thread() was " + << "never called! Calling it now..." << endl; + create_thread(); + } + + // We need to grab the lock in order to signal the condition variable +#ifdef HAVE_IPC + _lock.lock(); +#endif + + if (_token_board->_waiting.is_full()) { + downloader_cat.error() + << "Downloader::request_download() - Too many pending requests\n"; + return 0; + } + + if (downloader_cat.is_debug()) { + downloader_cat.debug() + << "Decompress requested for file: " << source_file << endl; + } + + tok = new DecompressorToken(_next_token++, source_file, dest_file, + event_name); + _token_board->_waiting.insert(tok); + +#ifdef HAVE_IPC + _request_cond->signal(); + _lock.unlock(); +#endif + + } else { + // If we're not running asynchronously, process the load request + // directly now. + if (_token_board->_waiting.is_full()) { + downloader_cat.error() + << "Downloader::request_download() - Too many pending requests\n"; + return 0; + } + if (downloader_cat.is_debug()) { + downloader_cat.debug() + << "Decompress requested for file: " << source_file << endl; + } + + tok = new DecompressorToken(_next_token++, source_file, dest_file, + event_name); + _token_board->_waiting.insert(tok); + process_request(); + } + + return tok->_id; +} + +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::process_request +// Access: Private +// Description: Serves any requests on the token board, moving them +// to the done queue. +//////////////////////////////////////////////////////////////////// +bool Decompressor:: +process_request() { + if (_shutdown) { + if (downloader_cat.is_debug()) + downloader_cat.debug() + << "Decompressor shutting down...\n"; + return false; + } + + // If there is actually a request token - process it + while (!_token_board->_waiting.is_empty()) { + PT(DecompressorToken) tok = _token_board->_waiting.extract(); + if (decompress(tok->_source_file, tok->_dest_file)) { + _token_board->_done.insert(tok); + + // 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() + << "Decompressor::process_request() - decompress complete for " + << tok->_source_file << "\n"; + } + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::decompress +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +bool Decompressor:: +decompress(Filename &source_file) { + Filename dest_file = source_file; + string extension = source_file.get_extension(); + if (extension == "pz") + dest_file = source_file.get_fullpath_wo_extension(); + else { + if (downloader_cat.is_debug()) + downloader_cat.debug() + << "Decompressor::request_decompress() - Unknown file extension: ." + << extension << endl; + return false; + } + return decompress(source_file, dest_file); +} + +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::decompress +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +bool Decompressor:: +decompress(Filename &source_file, Filename &dest_file) { + + // Open source file + ifstream read_stream; + source_file.set_binary(); + if (!source_file.open_read(read_stream)) { + downloader_cat.error() + << "Decompressor::decompress() - Error opening source file: " + << source_file << endl; + return false; + } + + // Determine source file length + read_stream.seekg(0, ios::end); + int source_file_length = read_stream.tellg(); + if (source_file_length == 0) { + downloader_cat.warning() + << "Decompressor::decompress() - Zero length file: " + << source_file << endl; + return true; + } + read_stream.seekg(0, ios::beg); + + // Open destination file + ofstream write_stream; + dest_file.set_binary(); + if (!dest_file.open_write(write_stream)) { + downloader_cat.error() + << "Decompressor::decompress() - Error opening dest file: " + << source_file << endl; + return false; + } + + // Read from the source file into the first half of the buffer, + // decompress into the second half of the buffer, write the second + // half of the buffer to disk, and repeat. + int total_bytes_read = 0; + bool read_all_input = false; + bool handled_all_input = false; + int source_buffer_length; + ZDecompressor decompressor; + while (handled_all_input == false) { + + // See if there is anything left in the source file + if (read_all_input == false) { + read_stream.read(_buffer->_buffer, _half_buffer_length); + source_buffer_length = read_stream.gcount(); + total_bytes_read += source_buffer_length; + if (read_stream.eof()) { + nassertr(total_bytes_read == source_file_length, false); + read_all_input = true; + } + } + + char *next_in = _buffer->_buffer; + int avail_in = source_buffer_length; + char *dest_buffer = _buffer->_buffer + source_buffer_length; + char *next_out = dest_buffer; + int dest_buffer_length = _buffer->get_length() - source_buffer_length; + int avail_out = dest_buffer_length; + nassertr(avail_out > 0 && avail_in > 0, false); + + while (avail_in > 0) { + int ret = decompressor.decompress_to_stream(next_in, avail_in, + next_out, avail_out, dest_buffer, + dest_buffer_length, write_stream); + if (ret == ZCompressorBase::S_error) + return false; + if ((int)decompressor.get_total_in() == source_file_length && + avail_out == dest_buffer_length) + handled_all_input = true; + } + + nap(); + + } + + read_stream.close(); + write_stream.close(); + + source_file.unlink(); + + return true; +} diff --git a/panda/src/downloader/asyncDecompressor.h b/panda/src/downloader/asyncDecompressor.h new file mode 100644 index 0000000000..b20a62b39f --- /dev/null +++ b/panda/src/downloader/asyncDecompressor.h @@ -0,0 +1,52 @@ +// Filename: decompressor.h +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// +// +#ifndef ASYNCDECOMPRESSOR_H +#define ASYNCDECOMPRESSOR_H +// +//////////////////////////////////////////////////////////////////// +// Includes +//////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include "zcompressor.h" +#include "asyncUtility.h" + +class DecompressorToken; + +//////////////////////////////////////////////////////////////////// +// Class : Decompressor +// Description : +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDAEXPRESS Decompressor : public AsyncUtility { +PUBLISHED: + Decompressor(void); + Decompressor(PT(Buffer) buffer); + virtual ~Decompressor(void); + + int request_decompress(const Filename &source_file, + const string &event_name); + int request_decompress(const Filename &source_file, + const Filename &dest_file, + const string &event_name); + + bool decompress(Filename &source_file); + bool decompress(Filename &source_file, Filename &dest_file); + +private: + void init(PT(Buffer) buffer); + virtual bool process_request(void); + + typedef TokenBoard DecompressorTokenBoard; + DecompressorTokenBoard *_token_board; + + PT(Buffer) _buffer; + int _half_buffer_length; + Filename _temp_file_name; +}; + +#endif diff --git a/panda/src/downloader/asyncExtractor.cxx b/panda/src/downloader/asyncExtractor.cxx new file mode 100644 index 0000000000..95a03ad764 --- /dev/null +++ b/panda/src/downloader/asyncExtractor.cxx @@ -0,0 +1,251 @@ +// Filename: extractor.cxx +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// +// +//////////////////////////////////////////////////////////////////// +// Includes +//////////////////////////////////////////////////////////////////// +#include "asyncExtractor.h" +#include "config_downloader.h" + +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////// +// Defines +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Class : ExtractorToken +// Description : Holds a request for the extractor. +//////////////////////////////////////////////////////////////////// +class ExtractorToken : public ReferenceCount { +public: + INLINE ExtractorToken(uint id, const Filename &source_file, + const string &event_name, + const Filename &rel_path) { + _id = id; + _source_file = source_file; + _event_name = event_name; + _rel_path = rel_path; + } + int _id; + Filename _source_file; + string _event_name; + Filename _rel_path; +}; + +//////////////////////////////////////////////////////////////////// +// Function: Extractor::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +Extractor:: +Extractor(void) : AsyncUtility() { + PT(Buffer) buffer = new Buffer(extractor_buffer_size); + init(buffer); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extractor::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +Extractor:: +Extractor(PT(Buffer) buffer) : AsyncUtility() { + init(buffer); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extractor::Constructor +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +void Extractor:: +init(PT(Buffer) buffer) { + nassertv(!buffer.is_null()); + _frequency = extractor_frequency; + _token_board = new ExtractorTokenBoard; + _buffer = buffer; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extractor::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +Extractor:: +~Extractor(void) { + destroy_thread(); + + delete _token_board; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extractor::request_extract +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +int Extractor:: +request_extract(const Filename &source_file, const string &event_name, + const Filename &rel_path) { + + PT(ExtractorToken) tok; + if (_threads_enabled) { + + // Make sure we actually are threaded + if (!_threaded) { + downloader_cat.info() + << "Extractor::request_extract() - create_thread() was " + << "never called! Calling it now..." << endl; + create_thread(); + } + + // We need to grab the lock in order to signal the condition variable +#ifdef HAVE_IPC + _lock.lock(); +#endif + + if (_token_board->_waiting.is_full()) { + downloader_cat.error() + << "Extractor::request_extract() - Too many pending requests\n"; + return 0; + } + + if (downloader_cat.is_debug()) { + downloader_cat.debug() + << "Extract requested for file: " << source_file << endl; + } + + tok = new ExtractorToken(_next_token++, source_file, event_name, + rel_path); + _token_board->_waiting.insert(tok); + +#ifdef HAVE_IPC + _request_cond->signal(); + _lock.unlock(); +#endif + + } else { + // If we're not running asynchronously, process the load request + // directly now. + if (_token_board->_waiting.is_full()) { + downloader_cat.error() + << "Extractor::request_extract() - Too many pending requests\n"; + return 0; + } + if (downloader_cat.is_debug()) { + downloader_cat.debug() + << "Extract requested for file: " << source_file << endl; + } + + tok = new ExtractorToken(_next_token++, source_file, event_name, + rel_path); + _token_board->_waiting.insert(tok); + process_request(); + } + + return tok->_id; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extractor::process_request +// Access: Private +// Description: Serves any requests on the token board, moving them +// to the done queue. +//////////////////////////////////////////////////////////////////// +bool Extractor:: +process_request() { + if (_shutdown) { + if (downloader_cat.is_debug()) + downloader_cat.debug() + << "Extractor shutting down...\n"; + return false; + } + + // If there is actually a request token - process it + while (!_token_board->_waiting.is_empty()) { + PT(ExtractorToken) tok = _token_board->_waiting.extract(); + if (extract(tok->_source_file, tok->_rel_path)) { + _token_board->_done.insert(tok); + + // 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() + << "Extractor::process_request() - extract complete for " + << tok->_source_file << "\n"; + } + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extractor::extract +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +bool Extractor:: +extract(Filename &source_file, const Filename &rel_path) { + + // Open source file + ifstream read_stream; + source_file.set_binary(); + if (!source_file.open_read(read_stream)) { + downloader_cat.error() + << "Extractor::extract() - Error opening source file: " + << source_file << endl; + return false; + } + + // Determine source file length + read_stream.seekg(0, ios::end); + int source_file_length = read_stream.tellg(); + read_stream.seekg(0, ios::beg); + + // Read the multifile header + Multifile mfile; + + // Read from the source file and write to the appropriate extracted file + int total_bytes_read = 0; + bool read_all_input = false; + bool handled_all_input = false; + int source_buffer_length; + while (handled_all_input == false) { + + // See if there is anything left in the source file + if (read_all_input == false) { + read_stream.read(_buffer->_buffer, _buffer->get_length()); + source_buffer_length = read_stream.gcount(); + total_bytes_read += source_buffer_length; + if (read_stream.eof()) { + nassertr(total_bytes_read == source_file_length, false); + read_all_input = true; + } + } + + // Write to the out file + char *start = _buffer->_buffer; + int size = source_buffer_length; + if (mfile.write_extract(start, size, rel_path) == true) + handled_all_input = true; + + nap(); + } + + read_stream.close(); + source_file.unlink(); + + return true; +} diff --git a/panda/src/downloader/asyncExtractor.h b/panda/src/downloader/asyncExtractor.h new file mode 100644 index 0000000000..5f630115e0 --- /dev/null +++ b/panda/src/downloader/asyncExtractor.h @@ -0,0 +1,46 @@ +// Filename: extractor.h +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// +// +#ifndef ASYNCEXTRACTOR_H +#define ASYNCEXTRACTOR_H +// +//////////////////////////////////////////////////////////////////// +// Includes +//////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include "asyncUtility.h" + +class ExtractorToken; + +//////////////////////////////////////////////////////////////////// +// Class : Extractor +// Description : +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDAEXPRESS Extractor : public AsyncUtility { +PUBLISHED: + Extractor(void); + Extractor(PT(Buffer) buffer); + virtual ~Extractor(void); + + int request_extract(const Filename &source_file, + const string &event_name, const Filename &rel_path = ""); + + bool extract(Filename &source_file, const Filename &rel_path); + +private: + void init(PT(Buffer) buffer); + virtual bool process_request(void); + + typedef TokenBoard ExtractorTokenBoard; + ExtractorTokenBoard *_token_board; + + PT(Buffer) _buffer; +}; + +#endif diff --git a/panda/src/downloader/decompressor.cxx b/panda/src/downloader/decompressor.cxx index be65a173d6..657abced73 100644 --- a/panda/src/downloader/decompressor.cxx +++ b/panda/src/downloader/decompressor.cxx @@ -11,10 +11,6 @@ #include "decompressor.h" #include "config_downloader.h" -#include -#include -#include -#include #include #include @@ -22,32 +18,13 @@ // Defines //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Class : DecompressorToken -// Description : Holds a request for the decompressor. -//////////////////////////////////////////////////////////////////// -class DecompressorToken : public ReferenceCount { -public: - INLINE DecompressorToken(uint id, const Filename &source_file, - const Filename &dest_file, const string &event_name) { - _id = id; - _source_file = source_file; - _dest_file = dest_file; - _event_name = event_name; - } - int _id; - Filename _source_file; - Filename _dest_file; - string _event_name; -}; - //////////////////////////////////////////////////////////////////// // Function: Decompressor::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// Decompressor:: -Decompressor(void) : AsyncUtility() { +Decompressor(void) { PT(Buffer) buffer = new Buffer(decompressor_buffer_size); init(buffer); } @@ -58,7 +35,7 @@ Decompressor(void) : AsyncUtility() { // Description: //////////////////////////////////////////////////////////////////// Decompressor:: -Decompressor(PT(Buffer) buffer) : AsyncUtility() { +Decompressor(PT(Buffer) buffer) { init(buffer); } @@ -70,8 +47,6 @@ Decompressor(PT(Buffer) buffer) : AsyncUtility() { void Decompressor:: init(PT(Buffer) buffer) { nassertv(!buffer.is_null()); - _frequency = decompressor_frequency; - _token_board = new DecompressorTokenBoard; _half_buffer_length = buffer->get_length()/2; _buffer = buffer; char *temp_name = tempnam(NULL, "dc"); @@ -87,19 +62,16 @@ init(PT(Buffer) buffer) { //////////////////////////////////////////////////////////////////// Decompressor:: ~Decompressor(void) { - destroy_thread(); - - delete _token_board; _temp_file_name.unlink(); } //////////////////////////////////////////////////////////////////// -// Function: Decompressor::request_decompress +// Function: Decompressor::initiate // Access: Public // Description: //////////////////////////////////////////////////////////////////// int Decompressor:: -request_decompress(const Filename &source_file, const string &event_name) { +initiate(Filename &source_file) { Filename dest_file = source_file; string extension = source_file.get_extension(); if (extension == "pz") @@ -110,169 +82,41 @@ request_decompress(const Filename &source_file, const string &event_name) { << "Decompressor::request_decompress() - Unknown file extension: ." << extension << endl; } - return request_decompress(source_file, dest_file, event_name); + return initiate(source_file, dest_file); } //////////////////////////////////////////////////////////////////// -// Function: Decompressor::request_decompress +// Function: Decompressor::initiate // Access: Public // Description: //////////////////////////////////////////////////////////////////// int Decompressor:: -request_decompress(const Filename &source_file, const Filename &dest_file, - const string &event_name) { - - PT(DecompressorToken) tok; - if (_threads_enabled) { - - // Make sure we actually are threaded - if (!_threaded) { - downloader_cat.info() - << "Decompressor::request_decompress() - create_thread() was " - << "never called! Calling it now..." << endl; - create_thread(); - } - - // We need to grab the lock in order to signal the condition variable -#ifdef HAVE_IPC - _lock.lock(); -#endif - - if (_token_board->_waiting.is_full()) { - downloader_cat.error() - << "Downloader::request_download() - Too many pending requests\n"; - return 0; - } - - if (downloader_cat.is_debug()) { - downloader_cat.debug() - << "Decompress requested for file: " << source_file << endl; - } - - tok = new DecompressorToken(_next_token++, source_file, dest_file, - event_name); - _token_board->_waiting.insert(tok); - -#ifdef HAVE_IPC - _request_cond->signal(); - _lock.unlock(); -#endif - - } else { - // If we're not running asynchronously, process the load request - // directly now. - if (_token_board->_waiting.is_full()) { - downloader_cat.error() - << "Downloader::request_download() - Too many pending requests\n"; - return 0; - } - if (downloader_cat.is_debug()) { - downloader_cat.debug() - << "Decompress requested for file: " << source_file << endl; - } - - tok = new DecompressorToken(_next_token++, source_file, dest_file, - event_name); - _token_board->_waiting.insert(tok); - process_request(); - } - - return tok->_id; -} - -//////////////////////////////////////////////////////////////////// -// Function: Decompressor::process_request -// Access: Private -// Description: Serves any requests on the token board, moving them -// to the done queue. -//////////////////////////////////////////////////////////////////// -bool Decompressor:: -process_request() { - if (_shutdown) { - if (downloader_cat.is_debug()) - downloader_cat.debug() - << "Decompressor shutting down...\n"; - return false; - } - - // If there is actually a request token - process it - while (!_token_board->_waiting.is_empty()) { - PT(DecompressorToken) tok = _token_board->_waiting.extract(); - if (decompress(tok->_source_file, tok->_dest_file)) { - _token_board->_done.insert(tok); - - // 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() - << "Decompressor::process_request() - decompress complete for " - << tok->_source_file << "\n"; - } - } - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: Decompressor::decompress -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -bool Decompressor:: -decompress(Filename &source_file) { - Filename dest_file = source_file; - string extension = source_file.get_extension(); - if (extension == "pz") - dest_file = source_file.get_fullpath_wo_extension(); - else { - if (downloader_cat.is_debug()) - downloader_cat.debug() - << "Decompressor::request_decompress() - Unknown file extension: ." - << extension << endl; - return false; - } - return decompress(source_file, dest_file); -} - -//////////////////////////////////////////////////////////////////// -// Function: Decompressor::decompress -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -bool Decompressor:: -decompress(Filename &source_file, Filename &dest_file) { +initiate(Filename &source_file, Filename &dest_file) { // Open source file - ifstream read_stream; - source_file.set_binary(); - if (!source_file.open_read(read_stream)) { + _source_file = source_file; + _source_file.set_binary(); + if (!_source_file.open_read(_read_stream)) { downloader_cat.error() << "Decompressor::decompress() - Error opening source file: " - << source_file << endl; + << _source_file << endl; return false; } // Determine source file length - read_stream.seekg(0, ios::end); - int source_file_length = read_stream.tellg(); - if (source_file_length == 0) { + _read_stream.seekg(0, ios::end); + _source_file_length = _read_stream.tellg(); + if (_source_file_length == 0) { downloader_cat.warning() << "Decompressor::decompress() - Zero length file: " << source_file << endl; return true; } - read_stream.seekg(0, ios::beg); + _read_stream.seekg(0, ios::beg); // Open destination file - ofstream write_stream; dest_file.set_binary(); - if (!dest_file.open_write(write_stream)) { + if (!dest_file.open_write(_write_stream)) { downloader_cat.error() << "Decompressor::decompress() - Error opening dest file: " << source_file << endl; @@ -282,51 +126,52 @@ decompress(Filename &source_file, Filename &dest_file) { // Read from the source file into the first half of the buffer, // decompress into the second half of the buffer, write the second // half of the buffer to disk, and repeat. - int total_bytes_read = 0; - bool read_all_input = false; - bool handled_all_input = false; - int source_buffer_length; - ZDecompressor decompressor; - while (handled_all_input == false) { + _total_bytes_read = 0; + _read_all_input = false; + _source_buffer_length; + return 1; +} - // See if there is anything left in the source file - if (read_all_input == false) { - read_stream.read(_buffer->_buffer, _half_buffer_length); - source_buffer_length = read_stream.gcount(); - total_bytes_read += source_buffer_length; - if (read_stream.eof()) { - nassertr(total_bytes_read == source_file_length, false); - read_all_input = true; - } +//////////////////////////////////////////////////////////////////// +// Function: Decompressor::run +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +int Decompressor:: +run(void) { + + // See if there is anything left in the source file + if (_read_all_input == false) { + _read_stream.read(_buffer->_buffer, _half_buffer_length); + _source_buffer_length = _read_stream.gcount(); + _total_bytes_read += _source_buffer_length; + if (_read_stream.eof()) { + nassertr(_total_bytes_read == _source_file_length, false); + _read_all_input = true; } - - char *next_in = _buffer->_buffer; - int avail_in = source_buffer_length; - char *dest_buffer = _buffer->_buffer + source_buffer_length; - char *next_out = dest_buffer; - int dest_buffer_length = _buffer->get_length() - source_buffer_length; - int avail_out = dest_buffer_length; - nassertr(avail_out > 0 && avail_in > 0, false); - - while (avail_in > 0) { - int ret = decompressor.decompress_to_stream(next_in, avail_in, - next_out, avail_out, dest_buffer, - dest_buffer_length, write_stream); - if (ret == ZCompressorBase::S_error) - return false; - if ((int)decompressor.get_total_in() == source_file_length && - avail_out == dest_buffer_length) - handled_all_input = true; - } - - nap(); - } - read_stream.close(); - write_stream.close(); + char *next_in = _buffer->_buffer; + int avail_in = _source_buffer_length; + char *dest_buffer = _buffer->_buffer + _source_buffer_length; + char *next_out = dest_buffer; + int dest_buffer_length = _buffer->get_length() - _source_buffer_length; + int avail_out = dest_buffer_length; + nassertr(avail_out > 0 && avail_in > 0, false); - source_file.unlink(); + while (avail_in > 0) { + int ret = _decompressor.decompress_to_stream(next_in, avail_in, + next_out, avail_out, dest_buffer, + dest_buffer_length, _write_stream); + if (ret == ZCompressorBase::S_error) + return DS_error_zlib; + if ((int)_decompressor.get_total_in() == _source_file_length && + avail_out == dest_buffer_length) + _read_stream.close(); + _write_stream.close(); + _source_file.unlink(); + return DS_success; + } - return true; + return DS_ok; } diff --git a/panda/src/downloader/decompressor.h b/panda/src/downloader/decompressor.h index 5fa0f06f31..44ab123305 100644 --- a/panda/src/downloader/decompressor.h +++ b/panda/src/downloader/decompressor.h @@ -11,42 +11,49 @@ //////////////////////////////////////////////////////////////////// #include #include -#include #include +#include #include "zcompressor.h" -#include "asyncUtility.h" - -class DecompressorToken; //////////////////////////////////////////////////////////////////// // Class : Decompressor // Description : //////////////////////////////////////////////////////////////////// -class EXPCL_PANDAEXPRESS Decompressor : public AsyncUtility { +class EXPCL_PANDAEXPRESS Decompressor { PUBLISHED: + enum DecompressStatus { + DS_ok = 2, + DS_success = 1, + DS_error = -1, + DS_error_write = -2, + DS_error_zlib = -3, + }; + Decompressor(void); Decompressor(PT(Buffer) buffer); virtual ~Decompressor(void); - int request_decompress(const Filename &source_file, - const string &event_name); - int request_decompress(const Filename &source_file, - const Filename &dest_file, - const string &event_name); + int initiate(Filename &source_file); + int initiate(Filename &source_file, Filename &dest_file); - bool decompress(Filename &source_file); - bool decompress(Filename &source_file, Filename &dest_file); + int run(void); private: void init(PT(Buffer) buffer); - virtual bool process_request(void); - - typedef TokenBoard DecompressorTokenBoard; - DecompressorTokenBoard *_token_board; PT(Buffer) _buffer; int _half_buffer_length; Filename _temp_file_name; + + Filename _source_file; + ifstream _read_stream; + ofstream _write_stream; + int _source_file_length; + int _total_bytes_read; + bool _read_all_input; + bool _handled_all_input; + int _source_buffer_length; + ZDecompressor _decompressor; }; #endif