]> git.mxchange.org Git - hub.git/blobdiff - application/hub/main/package/assembler/class_PackageAssembler.php
Added noisy debug line
[hub.git] / application / hub / main / package / assembler / class_PackageAssembler.php
index 9e952487b41fe2a604610781294130a023dc1eb5..2aed4c154ba000cc895913ec15fbdcd53b22c9cc 100644 (file)
@@ -5,7 +5,7 @@
  *
  * @author             Roland Haeder <webmaster@ship-simu.org>
  * @version            0.0.0
- * @copyright  Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 Hub Developer Team
+ * @copyright  Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2012 Hub Developer Team
  * @license            GNU GPL 3.0 or any newer version
  * @link               http://www.ship-simu.org
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-class PackageAssembler extends BaseFrameworkSystem implements Assembler, Registerable {
+class PackageAssembler extends BaseHubSystem implements Assembler, Registerable {
+       /**
+        * Pending data
+        */
+       private $pendingData = '';
+
        /**
         * Protected constructor
         *
@@ -36,16 +41,56 @@ class PackageAssembler extends BaseFrameworkSystem implements Assembler, Registe
        /**
         * Creates an instance of this class
         *
-        * @return      $assemblerInstance              An instance of a Fragmentable class
+        * @param       $packageInstance        An instance of a Receivable class
+        * @return      $assemblerInstance      An instance of an Assembler class
         */
-       public static final function createPackageAssembler () {
+       public static final function createPackageAssembler (Receivable $packageInstance) {
                // Get new instance
                $assemblerInstance = new PackageAssembler();
 
+               // Set package instance here
+               $assemblerInstance->setPackageInstance($packageInstance);
+
+               // Create an instance of a raw data input stream
+               $streamInstance = ObjectFactory::createObjectByConfiguredName('node_raw_data_input_stream_class');
+
+               // And set it
+               $assemblerInstance->setInputStreamInstance($streamInstance);
+
                // Return the prepared instance
                return $assemblerInstance;
        }
 
+       /**
+        * Checks whether the input buffer (stacker to be more preceise) is empty.
+        *
+        * @return      $isInputBufferEmpty             Whether the input buffer is empty
+        */
+       private function ifInputBufferIsEmpty () {
+               // Check it
+               $isInputBufferEmpty = $this->getPackageInstance()->getStackerInstance()->isStackEmpty(NetworkPackage::STACKER_NAME_DECODED_HANDLED);
+
+               // Debug message
+               //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-ASSEMBLER: isInputBufferEmpty=' . intval($isInputBufferEmpty));
+
+               // Return it
+               return $isInputBufferEmpty;
+       }
+
+       /**
+        * Checks whether given package content is completed (start/end markers are found)
+        *
+        * @param       $packageContent         An array with two elements: 'raw_data' and 'error_code'
+        * @return      $isCompleted            Whether the given package content is completed
+        */
+       private function isPackageContentCompleted (array $packageContent) {
+               // Check both
+               $isCompleted = $this->ifStartEndMarkersSet($packageContent[BaseRawDataHandler::PACKAGE_RAW_DATA]);
+
+               // Return status
+               return $isCompleted;
+       }
+
        /**
         * Assembles the content from $packageContent. This method does only
         * initialize the whole process by creating a call-back which will then
@@ -56,14 +101,14 @@ class PackageAssembler extends BaseFrameworkSystem implements Assembler, Registe
         * chunks and (maybe) re-request some chunks from the sender, this would
         * take to much time and therefore slow down this node again.
         *
-        * @param       $packageContent         An array with two elements: 'decoded_data' and 'error_code'
+        * @param       $packageContent         An array with two elements: 'raw_data' and 'error_code'
         * @return      void
         * @throws      UnsupportedPackageCodeHandlerException  If the package code handler is not implemented
         */
        public function chunkPackageContent (array $packageContent) {
                // Validate the package content array again
                assert(
-                       (isset($packageContent[BaseRawDataHandler::PACKAGE_DECODED_DATA])) &&
+                       (isset($packageContent[BaseRawDataHandler::PACKAGE_RAW_DATA])) &&
                        (isset($packageContent[BaseRawDataHandler::PACKAGE_ERROR_CODE]))
                );
 
@@ -73,35 +118,97 @@ class PackageAssembler extends BaseFrameworkSystem implements Assembler, Registe
                // Abort if the call-back method is not there
                if (!method_exists($this, $methodName)) {
                        // Throw an exception
-                       throw new UnsupportedPackageCodeHandlerException(array($this, $packageContent, $methodName), BaseListener::EXCEPTION_UNSUPPORTED_PACKAGE_CODE_HANDLER);
+                       throw new UnsupportedPackageCodeHandlerException(array($this, $methodName, $packageContent), BaseListener::EXCEPTION_UNSUPPORTED_PACKAGE_CODE_HANDLER);
                } // END - if
 
                // Call it back
                call_user_func(array($this, $methodName), $packageContent);
        }
 
+       /**************************************************************************
+        *                 Call-back methods for above method                     *
+        **************************************************************************/
+
        /**
-        * Call-back handler to handle unhandled packages
+        * Call-back handler to handle unhandled packages. This method "explodes"
+        * the string with the chunk separator from PackageFragmenter class, does
+        * some low checks on it and feeds it into another queue for verification
+        * and re-request for bad chunks.
         *
-        * @param       $packageContent         An array with two elements: 'decoded_data' and 'error_code'
+        * @param       $packageContent         An array with two elements: 'raw_data' and 'error_code'
         * @return      void
         * @throws      FinalChunkVerificationException         If the final chunk does not start with 'EOP:'
         */
        private function handlePackageByUnhandledPackage (array $packageContent) {
-               /*
-                * "explode" the string from 'decoded_data' with chunk separator to
-                * get an array of chunks. These chunks must then be verified by
-                * their checksums. Also the final chunk must be handled.
-                */
-               $chunks = explode(PackageFragmenter::CHUNK_SEPARATOR, $packageContent[BaseRawDataHandler::PACKAGE_DECODED_DATA]);
-
-               // Validate final chunk
-               if (substr($chunks[count($chunks) - 1], 0, strlen(PackageFragmenter::END_OF_PACKAGE_IDENTIFIER)) != PackageFragmenter::END_OF_PACKAGE_IDENTIFIER) {
-                       // Last chunk is not valid
-                       throw new FinalChunkVerificationException(array($this, $packageContent, $chunks), BaseListener::EXCEPTION_FINAL_CHUNK_VERIFICATION);
-               } // END - if
+               // Debug message
+               /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-ASSEMBLER: packageData[' . BaseRawDataHandler::PACKAGE_RAW_DATA . ']=' . $packageContent[BaseRawDataHandler::PACKAGE_RAW_DATA]);
+
+               // Check for some conditions
+               if ((!$this->ifInputBufferIsEmpty()) || (!$this->isPackageContentCompleted($packageContent))) {
+                       // Last chunk is not valid, so wait for more
+                       $this->pendingData .= $packageContent[BaseRawDataHandler::PACKAGE_RAW_DATA];
+
+                       // Debug message
+                       /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-ASSEMBLER: Partial data received. Waiting for more ... ( ' . strlen($packageContent[BaseRawDataHandler::PACKAGE_RAW_DATA]) . ' bytes)');
+               } else {
+                       // Debug message
+                       //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__)->debugOutput('packageContent=' . print_r($packageContent,true) . ',chunks='.print_r($chunks,true));
+
+                       /*
+                        * "explode" the string from 'raw_data' with chunk separator to
+                        * get an array of chunks. These chunks must then be verified by
+                        * their checksums. Also the final chunk must be handled.
+                        */
+                       $chunks = explode(PackageFragmenter::CHUNK_SEPARATOR, $packageContent[BaseRawDataHandler::PACKAGE_RAW_DATA]);
+
+                       // Now get a chunk handler instance
+                       $handlerInstance = ChunkHandlerFactory::createChunkHandlerInstance();
+
+                       // Add all chunks because the last final chunk is found
+                       $handlerInstance->addAllChunksWithFinal($chunks);
+               }
+       }
+
+       /**
+        * Checks whether the assembler's pending data is empty which means it has
+        * no pending data left for handling ... ;-)
+        *
+        * @return      $ifPendingDataIsEmpty   Whether pending data is empty
+        */
+       public function isPendingDataEmpty () {
+               // A simbple check
+               $ifPendingDataIsEmpty = empty($this->pendingData);
+
+               // Return it
+               return $ifPendingDataIsEmpty;
+       }
+
+       /**
+        * Handles the assembler's pending data
+        *
+        * @return      void
+        */
+       public function handlePendingData () {
+               // Assert on condition
+               assert(!$this->isPendingDataEmpty());
+
+               // Debug output
+               /* NOISY-DEBUG: */ $this->debugOutput('PACKAGE-ASSEMBLER: Going to decode ' . strlen($this->pendingData) . ' Bytes of pending data. pendingData=' . $this->pendingData);
+
+               // Init fake array
+               $packageContent = array(
+                       BaseRawDataHandler::PACKAGE_RAW_DATA   => $this->getInputStreamInstance()->streamData($this->pendingData),
+                       BaseRawDataHandler::PACKAGE_ERROR_CODE => BaseRawDataHandler::SOCKET_ERROR_UNHANDLED
+               );
+
+               // Clear pending data
+               $this->pendingData = '';
+
+               // Debug message
+               /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('PACKAGE-ASSEMBLER: Last block of partial data received. A total of ' . strlen($packageContent[BaseRawDataHandler::PACKAGE_RAW_DATA]) . ' bytes has been received.');
 
-               die('chunks='.print_r($chunks,true));
+               // Call the real handler method
+               $this->handlePackageByUnhandledPackage($packageContent);
        }
 }