*/
const SEPARATOR_HASH_NAME = 0x05;
+ /**
+ * Length of name
+ */
+ const COUNT_NAME = 10;
+
+ /**
+ * Length of count
+ */
+ const COUNT_LENGTH = 20;
+
+ /**
+ * Length of position
+ */
+ const COUNT_POSITION = 20;
+
+ /**
+ * Counter for total entries
+ */
+ private $totalEntries = 0;
+
+ /**
+ * Current seek position
+ */
+ private $seekPosition = 0;
+
/**
* Protected constructor
*
parent::__construct($className);
}
+ /**
+ * Getter for total entries
+ *
+ * @return $totalEntries Total entries in this stack
+ */
+ private function getCounter () {
+ // Get it
+ return $this->totalEntries;
+ }
+
+ /**
+ * Increment counter
+ *
+ * @return void
+ */
+ private function incrementCounter () {
+ // Get it
+ $this->totalEntries++;
+ }
+
+ /**
+ * Getter for seek position
+ *
+ * @return $seekPosition Current seek position (stored here in object)
+ */
+ private function getSeekPosition () {
+ // Get it
+ return $this->seekPosition;
+ }
+
+ /**
+ * Setter for seek position
+ *
+ * @param $seekPosition Current seek position (stored here in object)
+ * @return void
+ */
+ private function setSeekPosition ($seekPosition) {
+ // And set it
+ $this->seekPosition = $seekPosition;
+ }
+
+ /**
+ * Updates seekPosition attribute from file to avoid to much access on file.
+ *
+ * @return void
+ */
+ private function updateSeekPosition () {
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
+
+ // Get key (= seek position)
+ $seekPosition = $this->getIteratorInstance()->key();
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] Setting seekPosition=%s', __METHOD__, __LINE__, $seekPosition));
+
+ // And set it here
+ $this->setSeekPosition($seekPosition);
+
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__));
+ }
+
/**
* Checks whether the file header is initialized
*
* @return $isInitialized Whether the file header is initialized
*/
private function isFileHeaderInitialized () {
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
// Default is not initialized
$isInitialized = FALSE;
// Is the file initialized?
if ($this->isFileInitialized()) {
// Some bytes has been written, so rewind to start of it.
- $this->getIteratorInstance()->rewind();
+ $rewindStatus = $this->getIteratorInstance()->rewind();
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] rewindStatus=%s', __METHOD__, __LINE__, $rewindStatus));
+
+ // Is the rewind() call successfull?
+ if ($rewindStatus != 1) {
+ // Something bad happened
+ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] Could not rewind().', __METHOD__, __LINE__));
+ } // END - if
// Read file header
$this->readFileHeader();
} // END - if
// Return result
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] isInitialized=%d - EXIT!', __METHOD__, __LINE__, intval($isInitialized)));
return $isInitialized;
}
* @return $isInitialized Whether the file's size is zero
*/
private function isFileInitialized () {
- // Default is not initialized
- $isInitialized = FALSE;
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
// Get it from iterator which holds the pointer instance. If FALSE is returned
$fileSize = $this->getIteratorInstance()->size();
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] fileSize=%s', __METHOD__, __LINE__, $fileSize));
/*
* The returned file size should not be FALSE or NULL as this means
assert(is_int($fileSize));
// Is more than 0 returned?
- if ($fileSize > 0) {
- // So is the header written?
- $isInitialized = $this->getIteratorInstance()->isHeaderInitialized();
- } // END - if
+ $isInitialized = ($fileSize > 0);
// Return result
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] isInitialized=%d - EXIT!', __METHOD__, __LINE__, intval($isInitialized)));
return $isInitialized;
}
+ /**
+ * Creates the file-stack's header
+ *
+ * @return void
+ */
+ private function createFileHeader () {
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
+ // The file's header should not be initialized here
+ assert(!$this->isFileHeaderInitialized());
+
+ // Flush file header
+ $this->flushFileHeader();
+
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!!', __METHOD__, __LINE__));
+ }
+
+ /**
+ * Flushes the file header
+ *
+ * @return void
+ */
+ private function flushFileHeader () {
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
+
+ // Put all informations together
+ $header = sprintf('%s%s%s%s%s',
+ // Magic
+ self::STACK_MAGIC,
+
+ // Separator magic<->count
+ chr(self::SEPARATOR_MAGIC_COUNT),
+
+ // Total entries (will be zero) and pad it to 20 chars
+ str_pad($this->dec2hex($this->getCounter()), self::COUNT_LENGTH, '0', STR_PAD_LEFT),
+
+ // Position (will be zero)
+ str_pad($this->dec2hex(0, 2), self::COUNT_POSITION, '0', STR_PAD_LEFT),
+
+ // Separator position<->entries
+ chr(self::SEPARATOR_SEEK_POS_ENTRIES)
+ );
+
+ // Write it to disk (header is always at seek position 0)
+ $this->getIteratorInstance()->writeAtPosition(0, $header);
+
+ // Update seek position
+ $this->updateSeekPosition();
+
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__));
+ }
+
+ /**
+ * Pre-allocates file (if enabled) with some space for later faster write access.
+ *
+ * @return void
+ */
+ private function preAllocateFile () {
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
+
+ // Is it enabled?
+ if ($this->getConfigInstance()->getConfigEntry('file_stack_pre_allocate_enabled') != 'Y') {
+ // Not enabled
+ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] Not pre-allocating stack file.', __METHOD__, __LINE__));
+
+ // Don't continue here.
+ return;
+ } // END - if
+
+ // Message to user
+ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] Pre-allocating stack file ...', __METHOD__, __LINE__));
+
+ /*
+ * Calculate minimum length for one entry:
+ * minimum length = hash length + separator + name + minimum entry size = ?? + 1 + 10 + 1 = ??
+ */
+ $minLengthEntry = self::getHashLength() + strlen(self::SEPARATOR_HASH_NAME) + self::COUNT_NAME + 1;
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] minLengthEntry=%s', __METHOD__, __LINE__, $minLengthEntry));
+
+ // Calulcate seek position
+ $seekPosition = $minLengthEntry * $this->getConfigInstance()->getConfigEntry('file_stack_pre_allocate_count');
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] seekPosition=%s', __METHOD__, __LINE__, $seekPosition));
+
+ // Now seek to the position
+ $this->getIteratorInstance()->seek($seekPosition);
+
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__));
+ }
+
/**
* Initializes this file-based stack.
*
} else {
// No, then create it (which may pre-allocate the stack)
$this->createFileHeader();
+
+ // And pre-allocate a bit
+ $this->preAllocateFile();
}
}