Mike Goslin 25 лет назад
Родитель
Сommit
45fe04bff1

+ 332 - 0
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 <event.h>
+#include <pt_Event.h>
+#include <throw_event.h>
+#include <eventParameter.h>
+#include <filename.h>
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////
+// 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;
+}

+ 52 - 0
panda/src/downloader/asyncDecompressor.h

@@ -0,0 +1,52 @@
+// Filename: decompressor.h
+// Created by:  mike (09Jan97)
+//
+////////////////////////////////////////////////////////////////////
+//
+#ifndef ASYNCDECOMPRESSOR_H
+#define ASYNCDECOMPRESSOR_H
+//
+////////////////////////////////////////////////////////////////////
+// Includes
+////////////////////////////////////////////////////////////////////
+#include <pandabase.h>
+#include <filename.h>
+#include <tokenBoard.h>
+#include <buffer.h>
+#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<DecompressorToken> DecompressorTokenBoard;
+  DecompressorTokenBoard *_token_board;
+
+  PT(Buffer) _buffer;
+  int _half_buffer_length;
+  Filename _temp_file_name;
+};
+
+#endif

+ 251 - 0
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 <event.h>
+#include <pt_Event.h>
+#include <throw_event.h>
+#include <eventParameter.h>
+#include <filename.h>
+
+////////////////////////////////////////////////////////////////////
+// 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;
+}

+ 46 - 0
panda/src/downloader/asyncExtractor.h

@@ -0,0 +1,46 @@
+// Filename: extractor.h
+// Created by:  mike (09Jan97)
+//
+////////////////////////////////////////////////////////////////////
+//
+#ifndef ASYNCEXTRACTOR_H
+#define ASYNCEXTRACTOR_H
+//
+////////////////////////////////////////////////////////////////////
+// Includes
+////////////////////////////////////////////////////////////////////
+#include <pandabase.h>
+#include <filename.h>
+#include <tokenBoard.h>
+#include <buffer.h>
+#include <multifile.h>
+#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<ExtractorToken> ExtractorTokenBoard;
+  ExtractorTokenBoard *_token_board;
+
+  PT(Buffer) _buffer;
+};
+
+#endif

+ 56 - 211
panda/src/downloader/decompressor.cxx

@@ -11,10 +11,6 @@
 #include "decompressor.h"
 #include "decompressor.h"
 #include "config_downloader.h"
 #include "config_downloader.h"
 
 
-#include <event.h>
-#include <pt_Event.h>
-#include <throw_event.h>
-#include <eventParameter.h>
 #include <filename.h>
 #include <filename.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
@@ -22,32 +18,13 @@
 // Defines
 // 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
 //     Function: Decompressor::Constructor
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 Decompressor::
 Decompressor::
-Decompressor(void) : AsyncUtility() {
+Decompressor(void) {
   PT(Buffer) buffer = new Buffer(decompressor_buffer_size);
   PT(Buffer) buffer = new Buffer(decompressor_buffer_size);
   init(buffer);
   init(buffer);
 }
 }
@@ -58,7 +35,7 @@ Decompressor(void) : AsyncUtility() {
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 Decompressor::
 Decompressor::
-Decompressor(PT(Buffer) buffer) : AsyncUtility() {
+Decompressor(PT(Buffer) buffer) {
   init(buffer);
   init(buffer);
 }
 }
 
 
@@ -70,8 +47,6 @@ Decompressor(PT(Buffer) buffer) : AsyncUtility() {
 void Decompressor::
 void Decompressor::
 init(PT(Buffer) buffer) {
 init(PT(Buffer) buffer) {
   nassertv(!buffer.is_null());
   nassertv(!buffer.is_null());
-  _frequency = decompressor_frequency;
-  _token_board = new DecompressorTokenBoard;
   _half_buffer_length = buffer->get_length()/2; 
   _half_buffer_length = buffer->get_length()/2; 
   _buffer = buffer;
   _buffer = buffer;
   char *temp_name = tempnam(NULL, "dc");
   char *temp_name = tempnam(NULL, "dc");
@@ -87,19 +62,16 @@ init(PT(Buffer) buffer) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 Decompressor::
 Decompressor::
 ~Decompressor(void) {
 ~Decompressor(void) {
-  destroy_thread();
-
-  delete _token_board;
   _temp_file_name.unlink();
   _temp_file_name.unlink();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Decompressor::request_decompress
+//     Function: Decompressor::initiate 
 //       Access: Public
 //       Access: Public
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int Decompressor::
 int Decompressor::
-request_decompress(const Filename &source_file, const string &event_name) {
+initiate(Filename &source_file) {
   Filename dest_file = source_file;
   Filename dest_file = source_file;
   string extension = source_file.get_extension();
   string extension = source_file.get_extension();
   if (extension == "pz")
   if (extension == "pz")
@@ -110,169 +82,41 @@ request_decompress(const Filename &source_file, const string &event_name) {
         << "Decompressor::request_decompress() - Unknown file extension: ."
         << "Decompressor::request_decompress() - Unknown file extension: ."
         << extension << endl; 
         << 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
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int Decompressor::
 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
   // 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()
     downloader_cat.error()
       << "Decompressor::decompress() - Error opening source file: " 
       << "Decompressor::decompress() - Error opening source file: " 
-      << source_file << endl;
+      << _source_file << endl;
     return false;
     return false;
   } 
   } 
 
 
   // Determine source file length
   // 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()
     downloader_cat.warning()
       << "Decompressor::decompress() - Zero length file: "
       << "Decompressor::decompress() - Zero length file: "
       << source_file << endl;
       << source_file << endl;
     return true;
     return true;
   }
   }
-  read_stream.seekg(0, ios::beg);
+  _read_stream.seekg(0, ios::beg);
 
 
   // Open destination file 
   // Open destination file 
-  ofstream write_stream;
   dest_file.set_binary();
   dest_file.set_binary();
-  if (!dest_file.open_write(write_stream)) {
+  if (!dest_file.open_write(_write_stream)) {
     downloader_cat.error()
     downloader_cat.error()
       << "Decompressor::decompress() - Error opening dest file: " 
       << "Decompressor::decompress() - Error opening dest file: " 
       << source_file << endl;
       << 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,
   // Read from the source file into the first half of the buffer,
   // decompress into the second half of the buffer, write the second
   // decompress into the second half of the buffer, write the second
   // half of the buffer to disk, and repeat.
   // 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);
+  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,
+  while (avail_in > 0) {
+    int ret = _decompressor.decompress_to_stream(next_in, avail_in,
 			next_out, avail_out, dest_buffer, 
 			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 &&
+			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)
 	  avail_out == dest_buffer_length)
-	handled_all_input = true;
-    }
-
-    nap();
-
+      _read_stream.close();
+      _write_stream.close();
+      _source_file.unlink();
+      return DS_success;
   }
   }
 
 
-  read_stream.close();
-  write_stream.close();
-
-  source_file.unlink();
-
-  return true;
+  return DS_ok;
 }
 }

+ 23 - 16
panda/src/downloader/decompressor.h

@@ -11,42 +11,49 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 #include <pandabase.h>
 #include <pandabase.h>
 #include <filename.h>
 #include <filename.h>
-#include <tokenBoard.h>
 #include <buffer.h>
 #include <buffer.h>
+#include <pointerTo.h>
 #include "zcompressor.h"
 #include "zcompressor.h"
-#include "asyncUtility.h"
-
-class DecompressorToken;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : Decompressor 
 //       Class : Decompressor 
 // Description :
 // Description :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDAEXPRESS Decompressor : public AsyncUtility {
+class EXPCL_PANDAEXPRESS Decompressor {
 PUBLISHED:
 PUBLISHED:
+  enum DecompressStatus {
+    DS_ok = 2,
+    DS_success = 1,
+    DS_error = -1,
+    DS_error_write = -2,
+    DS_error_zlib = -3,
+  };
+
   Decompressor(void);
   Decompressor(void);
   Decompressor(PT(Buffer) buffer);
   Decompressor(PT(Buffer) buffer);
   virtual ~Decompressor(void);
   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:
 private:
   void init(PT(Buffer) buffer);
   void init(PT(Buffer) buffer);
-  virtual bool process_request(void);
-
-  typedef TokenBoard<DecompressorToken> DecompressorTokenBoard;
-  DecompressorTokenBoard *_token_board;
 
 
   PT(Buffer) _buffer;
   PT(Buffer) _buffer;
   int _half_buffer_length;
   int _half_buffer_length;
   Filename _temp_file_name;
   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
 #endif