namespace Org\Mxchange\CoreFramework\Index\File;
// Import framework stuff
+use Org\Mxchange\CoreFramework\EntryPoint\ApplicationEntryPoint;
use Org\Mxchange\CoreFramework\Factory\Object\ObjectFactory;
use Org\Mxchange\CoreFramework\Filesystem\File\BaseBinaryFile;
+use Org\Mxchange\CoreFramework\Filesystem\File\BinaryFile;
use Org\Mxchange\CoreFramework\Index\BaseIndex;
use Org\Mxchange\CoreFramework\Index\Indexable;
-use Org\Mxchange\CoreFramework\Utils\String\StringUtils;
+use Org\Mxchange\CoreFramework\Utils\Arrays\ArrayUtils;
+use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils;
// Import SPL stuff
use \OutOfBoundsException;
*
* @author Roland Haeder <webmaster@ship-simu.org>
* @version 0.0.0
- * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2021 Core Developer Team
* @license GNU GPL 3.0 or any newer version
* @link http://www.ship-simu.org
*
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
abstract class BaseFileIndex extends BaseIndex implements FileIndexer {
+ /**
+ * Minimum block length
+ */
+ private static $minimumBlockLength = 0;
+
/**
* Protected constructor
*
+ * @param $className Name of class
* @return void
*/
- protected function __construct () {
+ protected function __construct (string $className) {
// Call parent constructor
- parent::__construct(__CLASS__);
+ parent::__construct($className);
}
/**
/* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: CALLED!');
$this->getIteratorInstance()->rewind();
+ // Get header size
+ $headerSize = $this->getIteratorInstance()->getBinaryFileInstance()->getHeaderSize();
+
// Then read it (see constructor for calculation)
- $data = $this->getIteratorInstance()->read($this->getIteratorInstance()->getHeaderSize());
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: headerSize=%d', $headerSize));
+ $data = $this->getIteratorInstance()->getBinaryFileInstance()->read($headerSize);
// Have all requested bytes been read?
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: Read %d bytes (%d wanted).', strlen($data), $this->getIteratorInstance()->getHeaderSize()));
- if (strlen($data) != $this->getIteratorInstance()->getHeaderSize()) {
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: Read %d bytes (%d wanted).', strlen($data), $this->getIteratorInstance()->getBinaryFileInstance()->getHeaderSize()));
+ if (strlen($data) != $this->getIteratorInstance()->getBinaryFileInstance()->getHeaderSize()) {
// Invalid header length
throw new UnexpectedValueException(sprintf('data(%d)=%s is not expected length %d',
strlen($data),
$data,
- $this->getIteratorInstance()->getHeaderSize()
+ $this->getIteratorInstance()->getBinaryFileInstance()->getHeaderSize()
));
} elseif (empty(trim($data, chr(0)))) {
// Empty file header
/* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: File header is empty - EXIT!');
return;
- } elseif (substr($data, -1, 1) != chr(BaseBinaryFile::SEPARATOR_HEADER_ENTRIES)) {
+ } elseif (substr($data, -1, 1) != chr(BinaryFile::SEPARATOR_HEADER_ENTRIES)) {
// Bad last character
throw new UnexpectedValueException(sprintf('data=%s does not end with "%s"',
$data,
- chr(BaseBinaryFile::SEPARATOR_HEADER_ENTRIES)
+ chr(BinaryFile::SEPARATOR_HEADER_ENTRIES)
));
}
$data = substr($data, 0, -1);
// And update seek position
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->updateSeekPosition() ...');
- $this->getIteratorInstance()->updateSeekPosition();
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->binaryFileInstance->updateSeekPosition() ...');
+ $this->getIteratorInstance()->getBinaryFileInstance()->updateSeekPosition();
/*
* Now split it:
* 0 => magic
* 1 => total entries
*/
- $header = explode(chr(BaseBinaryFile::SEPARATOR_HEADER_DATA), $data);
+ $header = explode(chr(BinaryFile::SEPARATOR_HEADER_DATA), $data);
- // Check if the array has only 3 elements
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: header()=%d', count($header)));
+ // Map numeric entries to associative (alpha-numeric) elements
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: Calling ArrayUtils::mapNumericKeysToAssociative(%d) ...', count($header)));
//* PRINTR-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: header(%d)=%s', count($header), print_r($header, true)));
- if (count($header) != 2) {
+ $header = ArrayUtils::mapNumericKeysToAssociative($header, [
+ BinaryFile::HEADER_NAME_MAGIC,
+ BinaryFile::HEADER_NAME_TOTAL_ENTRIES,
+ ]);
+
+ // Check if the array has only 2 elements
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: HEADER_INDEX_ELEMENT_COUNT=%d,header()=%d', BinaryFile::HEADER_INDEX_ELEMENT_COUNT, count($header)));
+ if (count($header) != BinaryFile::HEADER_INDEX_ELEMENT_COUNT) {
// Bad header
- throw new UnexpectedValueException(sprintf('header()=%d is not expected value 2', count($header)));
- } elseif ($header[0] !== Indexable::INDEX_MAGIC) {
+ throw new UnexpectedValueException(sprintf('header()=%d is not expected value %d', count($header), BinaryFile::HEADER_INDEX_ELEMENT_COUNT));
+ } elseif ($header[BinaryFile::HEADER_NAME_MAGIC] !== Indexable::INDEX_MAGIC) {
// Magic must be in first element
- throw new UnexpectedValueException(sprintf('header[0]=%s is not the expected magic (%s)', $header[0], Indexable::INDEX_MAGIC));
- } elseif (strlen($header[1]) != BaseBinaryFile::LENGTH_COUNT) {
+ throw new UnexpectedValueException(sprintf('header[%s]=%s is not the expected magic (%s)', BinaryFile::HEADER_NAME_MAGIC, $header[BinaryFile::HEADER_NAME_MAGIC], Indexable::INDEX_MAGIC));
+ } elseif (strlen($header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES]) != BinaryFile::LENGTH_COUNT) {
// Length of total entries not matching
- throw new UnexpectedValueException(sprintf('header[1](%d)=%s does not have expected length %d', strlen($header[1]), $header[1], BaseBinaryFile::LENGTH_COUNT));
+ throw new UnexpectedValueException(sprintf('header[%s](%d)=%s does not have expected length %d', BinaryFile::HEADER_NAME_TOTAL_ENTRIES, strlen($header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES]), $header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES], BinaryFile::LENGTH_COUNT));
}
// Decode count
- $header[1] = hex2bin($header[1]);
+ $header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES] = hex2bin($header[BinaryFile::HEADER_NAME_TOTAL_ENTRIES]);
// Set it here
- $this->getIteratorInstance()->setHeader($header);
+ $this->getIteratorInstance()->getBinaryFileInstance()->setHeader($header);
// Trace message
/* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: EXIT!');
Indexable::INDEX_MAGIC,
// Separator header data
- chr(BaseBinaryFile::SEPARATOR_HEADER_DATA),
+ chr(BinaryFile::SEPARATOR_HEADER_DATA),
// Total entries
- str_pad(StringUtils::dec2hex($this->getIteratorInstance()->getCounter()), BaseBinaryFile::LENGTH_COUNT, '0', STR_PAD_LEFT),
+ str_pad(StringUtils::dec2hex($this->getIteratorInstance()->getBinaryFileInstance()->getCounter()), BinaryFile::LENGTH_COUNT, '0', STR_PAD_LEFT),
// Separator header<->entries
- chr(BaseBinaryFile::SEPARATOR_HEADER_ENTRIES)
+ chr(BinaryFile::SEPARATOR_HEADER_ENTRIES)
);
// Write it to disk (header is always at seek position 0)
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: Calling this->iteratorInstance->writeAtPosition(0, header=%s) ...', $header));
- $this->getIteratorInstance()->writeAtPosition(0, $header);
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: Calling this->iteratorInstance->binaryFileInstance->writeAtPosition(0, header=%s) ...', $header));
+ $this->getIteratorInstance()->getBinaryFileInstance()->writeAtPosition(0, $header);
// Trace message
/* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: EXIT!');
}
/**
- * Initializes this index
+ * Initializes this file-based index
*
* @param $fileInfoInstance An instance of a SplFileInfo class
* @return void
* @todo Currently the index file is not cached, please implement a memory-handling class and if enough RAM is found, cache the whole index file.
*/
- protected function initIndex (SplFileInfo $fileInfoInstance) {
+ protected function initFileIndex (SplFileInfo $fileInfoInstance) {
// Get a file i/o pointer instance for index file
/* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: fileInfoInstance[%s]=%s - CALLED!', get_class($fileInfoInstance), $fileInfoInstance));
$fileInstance = ObjectFactory::createObjectByConfiguredName('index_file_class', array($fileInfoInstance, $this));
// Calculate header size
$headerSize = (
strlen(Indexable::INDEX_MAGIC) +
- strlen(chr(BaseBinaryFile::SEPARATOR_HEADER_DATA)) +
- BaseBinaryFile::LENGTH_COUNT +
- strlen(chr(BaseBinaryFile::SEPARATOR_HEADER_ENTRIES))
+ strlen(chr(BinaryFile::SEPARATOR_HEADER_DATA)) +
+ BinaryFile::LENGTH_COUNT +
+ strlen(chr(BinaryFile::SEPARATOR_HEADER_ENTRIES))
);
// Set it
/* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: Setting headerSize=%d ...', $headerSize));
- $this->getIteratorInstance()->setHeaderSize($headerSize);
+ $this->getIteratorInstance()->getBinaryFileInstance()->setHeaderSize($headerSize);
// Init counters and gaps array
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->initCountersGapsArray() ...');
- $this->getIteratorInstance()->initCountersGapsArray();
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->binaryFileInstance->initCountersGapsArray() ...');
+ $this->getIteratorInstance()->getBinaryFileInstance()->initCountersGapsArray();
// Default is not created
$created = false;
// Is the file's header initialized?
- if (!$this->getIteratorInstance()->isFileHeaderInitialized()) {
+ if (!$this->getIteratorInstance()->getBinaryFileInstance()->isFileHeaderInitialized()) {
// First pre-allocate a bit
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->preAllocateFile(index) ...');
- $this->getIteratorInstance()->preAllocateFile('index');
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->binaryFileInstance->preAllocateFile(index) ...');
+ $this->getIteratorInstance()->getBinaryFileInstance()->preAllocateFile('index');
// Then write file header
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->createFileHeader() ...');
- $this->getIteratorInstance()->createFileHeader();
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->binaryFileInstance->createFileHeader() ...');
+ $this->getIteratorInstance()->getBinaryFileInstance()->createFileHeader();
// Mark as freshly created
$created = true;
/* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: created=%d', intval($created)));
if (!$created) {
// Analyze file structure
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->analyzeFileStructure() ...');
- $this->getIteratorInstance()->analyzeFileStructure();
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calling this->iteratorInstance->binaryFileInstance->analyzeFileStructure() ...');
+ $this->getIteratorInstance()->getBinaryFileInstance()->analyzeFileStructure();
}
// Trace message
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Calculating ...');
self::$minimumBlockLength = (
// Type
- BaseBinaryFile::LENGTH_TYPE + strlen(chr(BaseBinaryFile::SEPARATOR_TYPE_POSITION)) +
+ BinaryFile::LENGTH_TYPE + strlen(chr(BinaryFile::SEPARATOR_TYPE_POSITION)) +
// Position
- BaseBinaryFile::LENGTH_POSITION + strlen(chr(BaseBinaryFile::SEPARATOR_ENTRIES))
+ BinaryFile::LENGTH_POSITION + strlen(chr(BinaryFile::SEPARATOR_ENTRIES))
);
}
*/
public function getFileSize () {
// Call iterator's method
- return $this->getIteratorInstance()->getFileSize();
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: CALLED!');
+ $fileSize = $this->getIteratorInstance()->getBinaryFileInstance()->getFileSize();
+
+ // Return it
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: fileSize=%d - EXIT!', $fileSize));
+ return $fileSize;
}
/**
throw new InvalidArgumentException(sprintf('length=%d is not valid', $length));
}
- // Partial stub!
- $this->partialStub('length=' . $length);
+ // Debug message
+ /* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(sprintf('[%s:%d]: length=%d,this=%s', __METHOD__, __LINE__, $length, print_r($this, true)));
}
/**
}
// Call iterated object's method
- /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: Calling this->iteratorInstance->writeAtPosition(%d, %s) ...', $seekPosition, $dataStream));
- $status = $this->getIteratorInstance()->writeAtPosition($seekPosition, $dataStream);
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: Calling this->iteratorInstance->binaryFileInstance->writeAtPosition(%d, %s) ...', $seekPosition, $dataStream));
+ $status = $this->getIteratorInstance()->getBinaryFileInstance()->writeAtPosition($seekPosition, $dataStream);
// Return status
/* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-INDEX: status[%s]=%d - EXIT!', gettype($status), $status));
* @return $isLoaded Whether this index has been loaded
*/
public function isIndexLoaded () {
- // Trace message
+ // Is the file gaps-only?
/* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: CALLED!');
+ if ($this->getIteratorInstance()->getBinaryFileInstance()->isFileGapsOnly()) {
+ // Then skip below code as this implies the file has been fully analyzed and "loaded"
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-INDEX: Underlaying file is gaps-only: Returning TRUE ... - EXIT!');
+ return TRUE;
+ }
+
+ // Debug message
/* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(sprintf('[%s:%d]: this=%s', __METHOD__, __LINE__, print_r($this, true)));
}