]> git.mxchange.org Git - core.git/blob - framework/main/classes/index/file_stack/class_FileStackIndex.php
Continued:
[core.git] / framework / main / classes / index / file_stack / class_FileStackIndex.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Index\Stack;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\EntryPoint\ApplicationEntryPoint;
7 use Org\Mxchange\CoreFramework\Index\BaseIndex;
8 use Org\Mxchange\CoreFramework\Index\Indexable;
9 use Org\Mxchange\CoreFramework\Registry\Registerable;
10 use Org\Mxchange\CoreFramework\Stack\File\StackableFile;
11 use Org\Mxchange\CoreFramework\Index\Stack\IndexableStack;
12
13 // Import SPL stuff
14 use \InvalidArgumentException;
15 use \SplFileInfo;
16 use \UnexpectedValueException;
17
18 /**
19  * A FileStack index class
20  *
21  * @author              Roland Haeder <webmaster@ship-simu.org>
22  * @version             0.0.0
23  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
24  * @license             GNU GPL 3.0 or any newer version
25  * @link                http://www.ship-simu.org
26  *
27  * This program is free software: you can redistribute it and/or modify
28  * it under the terms of the GNU General Public License as published by
29  * the Free Software Foundation, either version 3 of the License, or
30  * (at your option) any later version.
31  *
32  * This program is distributed in the hope that it will be useful,
33  * but WITHOUT ANY WARRANTY; without even the implied warranty of
34  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35  * GNU General Public License for more details.
36  *
37  * You should have received a copy of the GNU General Public License
38  * along with this program. If not, see <http://www.gnu.org/licenses/>.
39  */
40 class FileStackIndex extends BaseIndex implements IndexableStack, Registerable {
41         /**
42          * Protected constructor
43          *
44          * @return      void
45          */
46         protected function __construct () {
47                 // Call parent constructor
48                 parent::__construct(__CLASS__);
49         }
50
51         /**
52          * Creates an instance of this Index class and prepares it for usage
53          *
54          * @param       $fileInfoInstance       An instance of a SplFileInfo class
55          * @return      $indexInstance  An instance of this Index class
56          */
57         public final static function createFileStackIndex (SplFileInfo $fileInfoInstance) {
58                 // Get a new instance
59                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: fileInfoInstance[%s]=%s - CALLED!', get_class($fileInfoInstance), $fileInfoInstance));
60                 $indexInstance = new FileStackIndex();
61
62                 // Initialize index
63                 $indexInstance->initIndex($fileInfoInstance);
64
65                 // Return the prepared instance
66                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: indexInstance=%s - EXIT!', $indexInstance->__toString()));
67                 return $indexInstance;
68         }
69
70         /**
71          * Adds given data's hash to an index file
72          *
73          * @param       $groupId        Name of stack to add hash for
74          * @param       $data           Hash and gap position to be added to the index
75          * @return      void
76          * @throws      InvalidArgumentException        If a parameter is not valid
77          * @throws      UnexpectedValueException        If an invalid gap position is being returned
78          */
79         public function addHashedDataToIndex (string $groupId, array $data) {
80                 // Validate parameter
81                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: groupId=%s,data()=%d - CALLED!', $groupId, count($data)));
82                 if (empty($groupId)) {
83                         // Throw IAE
84                         throw new InvalidArgumentException('Parameter "groupId" is empty');
85                 } elseif (count($data) == 0) {
86                         // Throw it again
87                         throw new InvalidArgumentException('Parameter "data" is an empty array');
88                 } elseif (!isset($data[StackableFile::ARRAY_NAME_HASH])) {
89                         // Important array element missing
90                         throw new InvalidArgumentException(sprintf('data[%s] not found', $data[StackableFile::ARRAY_NAME_HASH]));
91                 } elseif (!isset($data[StackableFile::ARRAY_NAME_GAP_POSITION])) {
92                         // Important array element missing
93                         throw new InvalidArgumentException(sprintf('data[%s] not found', $data[StackableFile::ARRAY_NAME_GAP_POSITION]));
94                 } elseif (!isset($data[StackableFile::ARRAY_NAME_DATA_LENGTH])) {
95                         // Important array element missing
96                         throw new InvalidArgumentException(sprintf('data[%s] not found', $data[StackableFile::ARRAY_NAME_DATA_LENGTH]));
97                 }
98
99                 // Raw data been written to the file
100                 $rawData = sprintf('%s%s%s%s%s%s%s',
101                         $groupId,
102                         Indexable::SEPARATOR_GROUP_HASH,
103                         hex2bin($data[StackableFile::ARRAY_NAME_HASH]),
104                         Indexable::SEPARATOR_HASH_GAP_POSITION,
105                         $data[StackableFile::ARRAY_NAME_GAP_POSITION],
106                         Indexable::SEPARATOR_GAP_LENGTH,
107                         $data[StackableFile::ARRAY_NAME_DATA_LENGTH]
108                 );
109
110                 // Search for next free gap
111                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: groupId=%s,hash=%s,rawData()=%d', $groupId, $data[StackableFile::ARRAY_NAME_HASH], strlen($rawData)));
112                 $gapPosition = $this->getIteratorInstance()->searchNextGap(strlen($rawData));
113
114                 // Gap position cannot be smaller or equal than header length
115                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: groupId=%s,hash=%s,gapPosition=%s', $groupId, $data[StackableFile::ARRAY_NAME_HASH], $gapPosition));
116                 if ($gapPosition <= ($this->getIteratorInstance()->getHeaderSize() + 1)) {
117                         // Not valid gap position returned
118                         throw new UnexpectedValueException(sprintf('gapPosition[%s]=%d is smaller or equal headerSize+1=%d', gettype($gapPosition), $gapPosition, ($this->getIteratorInstance()->getHeaderSize() + 1)));
119                 }
120
121                 // Then write the data at that gap
122                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: Calling this->iteratorInstance->writeData(%d,%s) ...', $gapPosition, $rawData));
123                 $this->getIteratorInstance()->writeData($gapPosition, $rawData);
124
125                 // Trace message
126                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: groupId=%s,hash=%s,rawData()=%d - EXIT!', $groupId, $data[StackableFile::ARRAY_NAME_HASH], strlen($rawData)));
127         }
128
129         /**
130          * Searches for next suitable gap the given length of data can fit in
131          * including padding bytes.
132          *
133          * @param       $length                 Length of raw data
134          * @return      $seekPosition   Found next gap's seek position
135          * @throws      InvalidArgumentException        If the parameter is not valid
136          * @todo        Unfinished work
137          */
138         public function searchNextGap (int $length) {
139                 // Validate parameter
140                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: length=%d - CALLED!', $length));
141                 if ($length <= 0) {
142                         // Throw IAE
143                         throw new InvalidArgumentException(sprintf('length=%d is not valid', $length));
144                 }
145
146                 // Partial stub!
147                 $this->partialStub('length=' . $length);
148         }
149
150         /**
151          * Writes at given position by seeking to it.
152          *
153          * @param       $seekPosition   Seek position in file
154          * @param       $dataStream             Data to be written
155          * @return      mixed                   Number of writes bytes or false on error
156          * @throws      InvalidArgumentException        If a parameter is not valid
157          */
158         public function writeAtPosition (int $seekPosition, string $dataStream) {
159                 // Validate parameter
160                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: seekPosition=%d,dataStream(%d)=%s - CALLED!', $seekPosition, strlen($dataStream), $dataStream));
161                 if ($seekPosition < 0) {
162                         // Invalid seek position
163                         throw new InvalidArgumentException(sprintf('seekPosition=%d is not valid.', $seekPosition));
164                 } elseif (empty($dataStream)) {
165                         // Empty dataStream
166                         throw new InvalidArgumentException('Parameter "dataStream" is empty');
167                 }
168
169                 // Call iterated object's method
170                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: Calling this->iteratorInstance->writeAtPosition(%d, %s) ...', $seekPosition, $dataStream));
171                 $status = $this->getIteratorInstance()->writeAtPosition($seekPosition, $dataStream);
172
173                 // Return status
174                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: status[%s]=%d - EXIT!', gettype($status), $status));
175                 return $status;
176         }
177
178         /**
179          * Checks if this index file has been fully and properly loaded.
180          *
181          * @return      $isLoaded       Whether this index file has been loaded
182          */
183         public function isIndexFileLoaded () {
184                 // Trace message
185                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('FILE-STACK-INDEX: CALLED!');
186                 /* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(sprintf('[%s:%d]: this=%s', __METHOD__, __LINE__, print_r($this, true)));
187         }
188
189 }