X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=framework%2Fmain%2Fclasses%2Fstacker%2Ffile%2Fclass_BaseFileStack.php;h=5513c77759fad82ed0eeacafd84c6871692976e2;hb=196ab0fc031d6987c87e8c5d257c39f664ec9151;hp=faa1b0dc513f7b3463fef1a69c8988be2afba879;hpb=5c227d3d4b639d9e5141bb218c414eb877250cf4;p=core.git diff --git a/framework/main/classes/stacker/file/class_BaseFileStack.php b/framework/main/classes/stacker/file/class_BaseFileStack.php index faa1b0dc..5513c777 100644 --- a/framework/main/classes/stacker/file/class_BaseFileStack.php +++ b/framework/main/classes/stacker/file/class_BaseFileStack.php @@ -1,19 +1,22 @@ . */ -abstract class BaseFileStack extends BaseStacker { +abstract class BaseFileStack extends BaseStacker implements StackableFile { + // Load traits + use IteratorTrait; + // Exception codes const EXCEPTION_BAD_MAGIC = 0xe100; - /** - * Magic for this stack - */ - const STACK_MAGIC = 'STACKv0.1'; - - /** - * Name of array index for gap position - */ - const ARRAY_INDEX_GAP_POSITION = 'gap'; - - /** - * Name of array index for hash - */ - const ARRAY_INDEX_HASH = 'hash'; - - /** - * Name of array index for length of raw data - */ - const ARRAY_INDEX_DATA_LENGTH = 'length'; - - /** - * An instance of an Indexable class - */ - private $indexInstance = NULL; - /** * Protected constructor * @@ -79,25 +60,6 @@ abstract class BaseFileStack extends BaseStacker { parent::__construct($className); } - /** - * Setter for Indexable instance - * - * @param $indexInstance An instance of an Indexable class - * @return void - */ - protected final function setIndexInstance (Indexable $indexInstance) { - $this->indexInstance = $indexInstance; - } - - /** - * Getter for Indexable instance - * - * @return $indexInstance An instance of an Indexable class - */ - public final function getIndexInstance () { - return $this->indexInstance; - } - /** * Reads the file header * @@ -108,7 +70,7 @@ abstract class BaseFileStack extends BaseStacker { */ public function readFileHeader () { // First rewind to beginning as the header sits at the beginning ... - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: CALLED!', __METHOD__, __LINE__)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: CALLED!'); $this->getIteratorInstance()->rewind(); // Then read it (see constructor for calculation) @@ -150,9 +112,6 @@ abstract class BaseFileStack extends BaseStacker { */ $header = explode(chr(BaseBinaryFile::SEPARATOR_HEADER_DATA), $data); - // Set header here - $this->getIteratorInstance()->setHeader($header); - // Check if the array has only 3 elements /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: header(%d)=%s', count($header), print_r($header, true))); if (count($header) != 3) { @@ -161,7 +120,7 @@ abstract class BaseFileStack extends BaseStacker { $data, count($header) )); - } elseif ($header[0] != self::STACK_MAGIC) { + } elseif ($header[0] != StackableFile::STACK_MAGIC) { // Bad magic throw new InvalidMagicException($data, self::EXCEPTION_BAD_MAGIC); } @@ -187,6 +146,9 @@ abstract class BaseFileStack extends BaseStacker { $header[1] = hex2bin($header[1]); $header[2] = hex2bin($header[2]); + // Set header here + $this->getIteratorInstance()->setHeader($header); + // Trace message /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: EXIT!', __METHOD__, __LINE__)); } @@ -198,10 +160,10 @@ abstract class BaseFileStack extends BaseStacker { */ public function flushFileHeader () { // Put all informations together - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: CALLED!', __METHOD__, __LINE__)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: CALLED!'); $header = sprintf('%s%s%s%s%s%s', // Magic - self::STACK_MAGIC, + StackableFile::STACK_MAGIC, // Separator magic<->count chr(BaseBinaryFile::SEPARATOR_HEADER_DATA), @@ -223,7 +185,7 @@ abstract class BaseFileStack extends BaseStacker { $this->getIteratorInstance()->writeData(0, $header, false); // Trace message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: EXIT!', __METHOD__, __LINE__)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: EXIT!'); } /** @@ -232,22 +194,29 @@ abstract class BaseFileStack extends BaseStacker { * @param $fileInfoInstance An instance of a SplFileInfo class * @param $type Type of this stack (e.g. url_source for URL sources) * @return void + * @throws InvalidArgumentException If a parameter is invalid * @todo Currently the stack file is not cached, please implement a memory-handling class and if enough RAM is found, cache the whole stack file. */ protected function initFileStack (SplFileInfo $fileInfoInstance, string $type) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: fileInfoInstance[%s]=%s,type=%s - CALLED!', get_class($fileInfoInstance), $fileInfoInstance, $type)); + if (empty($type)) { + // Invalid parameter + throw new InvalidArgumentException('Parameter "type" is empty'); + } + // Get a stack file instance - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: fileInfoInstance=%s,type=%s - CALLED!', $fileInfoInstance, $type)); - $fileInstance = ObjectFactory::createObjectByConfiguredName('stack_file_class', array($fileInfoInstance, $this)); + $stackInstance = ObjectFactory::createObjectByConfiguredName('stack_file_class', array($fileInfoInstance, $this)); // Get iterator instance - $iteratorInstance = ObjectFactory::createObjectByConfiguredName('file_iterator_class', array($fileInstance)); + $iteratorInstance = ObjectFactory::createObjectByConfiguredName('file_iterator_class', array($stackInstance)); // Set iterator here $this->setIteratorInstance($iteratorInstance); // Calculate header size $this->getIteratorInstance()->setHeaderSize( - strlen(self::STACK_MAGIC) + + strlen(StackableFile::STACK_MAGIC) + strlen(chr(BaseBinaryFile::SEPARATOR_HEADER_DATA)) + BaseBinaryFile::LENGTH_COUNT + strlen(chr(BaseBinaryFile::SEPARATOR_HEADER_DATA)) + @@ -281,6 +250,9 @@ abstract class BaseFileStack extends BaseStacker { // And set it here $this->setIndexInstance($indexInstance); + + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: EXIT!'); } /** @@ -290,12 +262,16 @@ abstract class BaseFileStack extends BaseStacker { * @param $value Value to add to this stacker * @return void * @throws FullStackerException If the stack is full + * @throws InvalidArgumentException If a parameter is not valid * @throws InvalidArgumentException Not all variable types are wanted here */ protected function addValue (string $stackerName, $value) { - // Do some tests - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('stackerName=%s,value[%s]=%s - CALLED!', $stackerName, gettype($value), print_r($value, true))); - if ($this->isStackFull($stackerName)) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: stackerName=%s,value[%s]=%s - CALLED!', $stackerName, gettype($value), print_r($value, true))); + if (empty($stackerName)) { + // No empty stack name + throw new InvalidArgumentException('Parameter "stackerName" is empty'); + } elseif ($this->isStackFull($stackerName)) { // Stacker is full throw new FullStackerException(array($this, $stackerName, $value), self::EXCEPTION_STACKER_IS_FULL); } elseif (is_resource($value) || is_object($value)) { @@ -311,6 +287,9 @@ abstract class BaseFileStack extends BaseStacker { // Add the hash and gap position to the index $this->getIndexInstance()->addHashToIndex($stackerName, $data); + + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: EXIT!'); } /** @@ -318,20 +297,26 @@ abstract class BaseFileStack extends BaseStacker { * * @param $stackerName Name of the stack * @return $value Value of last added value - * @throws EmptyStackerException If the stack is empty + * @throws InvalidArgumentException If a parameter is not valid + * @throws BadMethodCallException If the stack is empty */ protected function getLastValue (string $stackerName) { - // Is the stack not yet initialized or full? - if ($this->isStackEmpty($stackerName)) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: stackerName=%s - CALLED!', $stackerName)); + if (empty($stackerName)) { + // No empty stack name + throw new InvalidArgumentException('Parameter "stackerName" is empty'); + } elseif ($this->isStackEmpty($stackerName)) { // Throw an exception - throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY); - } // END - if + throw new BadMethodCallException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY); + } // Now get the last value /* NOISY-DEBUG: */ $this->partialStub('[' . __METHOD__ . ':' . __LINE__ . '] stackerName=' . $stackerName); $value = NULL; // Return it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: value[]=%s - EXIT!', gettype($value))); return $value; } @@ -340,20 +325,26 @@ abstract class BaseFileStack extends BaseStacker { * * @param $stackerName Name of the stack * @return $value Value of last added value - * @throws EmptyStackerException If the stack is empty + * @throws InvalidArgumentException If a parameter is not valid + * @throws BadMethodCallException If the stack is empty */ protected function getFirstValue (string $stackerName) { - // Is the stack not yet initialized or full? - if ($this->isStackEmpty($stackerName)) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: stackerName=%s - CALLED!', $stackerName)); + if (empty($stackerName)) { + // No empty stack name + throw new InvalidArgumentException('Parameter "stackerName" is empty'); + } elseif ($this->isStackEmpty($stackerName)) { // Throw an exception - throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY); - } // END - if + throw new BadMethodCallException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY); + } // Now get the first value /* NOISY-DEBUG: */ $this->partialStub('[' . __METHOD__ . ':' . __LINE__ . '] stackerName=' . $stackerName); $value = NULL; // Return it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: value[]=%s - EXIT!', gettype($value))); return $value; } @@ -362,14 +353,19 @@ abstract class BaseFileStack extends BaseStacker { * * @param $stackerName Name of the stack * @return $value Value "poped" from array - * @throws EmptyStackerException If the stack is empty + * @throws InvalidArgumentException If a parameter is not valid + * @throws BadMethodCallException If the stack is empty */ protected function popLast (string $stackerName) { - // Is the stack not yet initialized or full? - if ($this->isStackEmpty($stackerName)) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: stackerName=%s - CALLED!', $stackerName)); + if (empty($stackerName)) { + // No empty stack name + throw new InvalidArgumentException('Parameter "stackerName" is empty'); + } elseif ($this->isStackEmpty($stackerName)) { // Throw an exception - throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY); - } // END - if + throw new BadMethodCallException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY); + } // Now, remove the last entry, we don't care about the return value here, see elseif() block above /* NOISY-DEBUG: */ $this->partialStub('[' . __METHOD__ . ':' . __LINE__ . '] stackerName=' . $stackerName); @@ -381,14 +377,19 @@ abstract class BaseFileStack extends BaseStacker { * * @param $stackerName Name of the stack * @return $value Value "shifted" from array - * @throws EmptyStackerException If the named stacker is empty + * @throws InvalidArgumentException If a parameter is not valid + * @throws BadMethodCallException If the named stacker is empty */ protected function popFirst (string $stackerName) { - // Is the stack not yet initialized or full? - if ($this->isStackEmpty($stackerName)) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: stackerName=%s - CALLED!', $stackerName)); + if (empty($stackerName)) { + // No empty stack name + throw new InvalidArgumentException('Parameter "stackerName" is empty'); + } elseif ($this->isStackEmpty($stackerName)) { // Throw an exception - throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY); - } // END - if + throw new BadMethodCallException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY); + } // Now, remove the last entry, we don't care about the return value here, see elseif() block above /* NOISY-DEBUG: */ $this->partialStub('[' . __METHOD__ . ':' . __LINE__ . '] stackerName=' . $stackerName); @@ -400,13 +401,22 @@ abstract class BaseFileStack extends BaseStacker { * * @param $stackerName Name of the stack * @return $isFull Whether the stack is full + * @throws InvalidArgumentException If a parameter is not valid */ protected function isStackFull (string $stackerName) { - // File-based stacks will only run full if the disk space is low. + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: stackerName=%s - CALLED!', $stackerName)); + if (empty($stackerName)) { + // No empty stack name + throw new InvalidArgumentException('Parameter "stackerName" is empty'); + } + // @TODO Please implement this, returning false + /* NOISY-DEBUG: */ $this->partialStub('[' . __METHOD__ . ':' . __LINE__ . '] stackerName=' . $stackerName); $isFull = false; // Return result + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: isFull=%d - EXIT!', intval($isFull))); return $isFull; } @@ -415,13 +425,22 @@ abstract class BaseFileStack extends BaseStacker { * * @param $stackerName Name of the stack * @return $isEmpty Whether the stack is empty - * @throws NoStackerException If given stack is missing + * @throws InvalidArgumentException If a parameter is not valid + * @throws BadMethodCallException If given stack is missing */ public function isStackEmpty (string $stackerName) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: stackerName=%s - CALLED!', $stackerName)); + if (empty($stackerName)) { + // No empty stack name + throw new InvalidArgumentException('Parameter "stackerName" is empty'); + } + // So, is the stack empty? $isEmpty = (($this->getStackCount($stackerName)) == 0); // Return result + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: isEmpty=%d - EXIT!', intval($isEmpty))); return $isEmpty; } @@ -476,7 +495,12 @@ abstract class BaseFileStack extends BaseStacker { */ public function getStackCount (string $stackerName) { // Now, simply return the found count value, this must be up-to-date then! - return $this->getIteratorInstance()->getCounter(); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: stackerName=%s - CALLED!', $stackerName)); + $count = $this->getIteratorInstance()->getCounter(); + + // Return count + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: count=%d - EXIT!', $count)); + return $count; } /** @@ -486,6 +510,7 @@ abstract class BaseFileStack extends BaseStacker { */ public function calculateMinimumBlockLength () { // Calulcate it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: CALLED!'); $length = // Length of entry group BaseBinaryFile::LENGTH_GROUP + strlen(chr(BaseBinaryFile::SEPARATOR_GROUP_HASH)) + @@ -495,6 +520,7 @@ abstract class BaseFileStack extends BaseStacker { strlen(chr(BaseBinaryFile::SEPARATOR_ENTRIES)); // Return it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: length=%d - EXIT!', $length)); return $length; } @@ -609,7 +635,8 @@ abstract class BaseFileStack extends BaseStacker { * @throws UnsupportedOperationException This method is not (and maybe never will be) supported */ public function searchNextGap (int $length) { - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: length=%s', $length)); + // Not supported here + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: length=%d - CALLED!', $length)); throw new UnsupportedOperationException(array($this, __FUNCTION__, $this->getIteratorInstance()->getPointerInstance()), self::EXCEPTION_UNSPPORTED_OPERATION); } @@ -620,7 +647,12 @@ abstract class BaseFileStack extends BaseStacker { */ public function getFileSize () { // Call iterator's method - return $this->getIteratorInstance()->getFileSize(); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: CALLED!'); + $size = $this->getIteratorInstance()->getFileSize(); + + // Return size + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: size=%d - EXIT!', $size)); + return $size; } /** @@ -647,7 +679,15 @@ abstract class BaseFileStack extends BaseStacker { $gapPosition = $this->getIteratorInstance()->searchNextGap(strlen($rawData)); // Gap position cannot be smaller than header length + 1 - assert($gapPosition > $this->getIteratorInstance()->getHeaderSize()); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: gapPosition=%d', $gapPosition)); + if ($gapPosition <= $this->getIteratorInstance()->getHeaderSize()) { + // Improper gap position + throw new UnexpectedValueException(sprintf('gapPosition[%s]=%d is not larger than headerSize=%d', + gettype($gapPosition), + $gapPosition, + $this->getIteratorInstance()->getHeaderSize() + )); + } // Then write the data at that gap /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: groupId=%s,hash=%s,gapPosition=%s', $groupId, $hash, $gapPosition)); @@ -656,9 +696,9 @@ abstract class BaseFileStack extends BaseStacker { // Return gap position, hash and length of raw data /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: groupId=%s,hash=%s,rawData()=%d - EXIT!', $groupId, $hash, strlen($rawData))); return [ - self::ARRAY_INDEX_GAP_POSITION => $gapPosition, - self::ARRAY_INDEX_HASH => $hash, - self::ARRAY_INDEX_DATA_LENGTH => strlen($rawData), + self::ARRAY_NAME_GAP_POSITION => $gapPosition, + self::ARRAY_NAME_HASH => $hash, + self::ARRAY_NAME_DATA_LENGTH => strlen($rawData), ]; }