/** * Generate compound index file */ protected function _generateCFS() { $cfsFile = $this->_directory->createFile($this->_name . '.cfs'); $cfsFile->writeVInt(count($this->_files)); $dataOffsetPointers = array(); foreach ($this->_files as $fileName) { $dataOffsetPointers[$fileName] = $cfsFile->tell(); $cfsFile->writeLong(0); // write dummy data $cfsFile->writeString($fileName); } foreach ($this->_files as $fileName) { // Get actual data offset $dataOffset = $cfsFile->tell(); // Seek to the data offset pointer $cfsFile->seek($dataOffsetPointers[$fileName]); // Write actual data offset value $cfsFile->writeLong($dataOffset); // Seek back to the end of file $cfsFile->seek($dataOffset); $dataFile = $this->_directory->getFileObject($fileName); $byteCount = $this->_directory->fileLength($fileName); while ($byteCount > 0) { $data = $dataFile->readBytes(min($byteCount, 131072)); $byteCount -= strlen($data); $cfsFile->writeBytes($data); } $this->_directory->deleteFile($fileName); } }
/** * Opens the index. * * IndexReader constructor needs Directory as a parameter. It should be * a string with a path to the index folder or a Directory object. * * @param \ZendSearch\Lucene\Storage\Directory\Filesystem|string $directory * @throws \ZendSearch\Lucene\Exception\InvalidArgumentException * @throws \ZendSearch\Lucene\Exception\RuntimeException */ public function __construct($directory = null, $create = false) { if ($directory === null) { throw new InvalidArgumentException('No index directory specified'); } if (is_string($directory)) { $this->_directory = new Directory\Filesystem($directory); $this->_closeDirOnExit = true; } else { $this->_directory = $directory; $this->_closeDirOnExit = false; } $this->_segmentInfos = array(); // Mark index as "under processing" to prevent other processes from premature index cleaning LockManager::obtainReadLock($this->_directory); $this->_generation = self::getActualGeneration($this->_directory); if ($create) { try { LockManager::obtainWriteLock($this->_directory); } catch (\Exception $e) { LockManager::releaseReadLock($this->_directory); if (strpos($e->getMessage(), 'Can\'t obtain exclusive index lock') === false) { throw new RuntimeException($e->getMessage(), $e->getCode(), $e); } else { throw new RuntimeException('Can\'t create index. It\'s under processing now', 0, $e); } } if ($this->_generation == -1) { // Directory doesn't contain existing index, start from 1 $this->_generation = 1; $nameCounter = 0; } else { // Directory contains existing index $segmentsFile = $this->_directory->getFileObject(self::getSegmentFileName($this->_generation)); $segmentsFile->seek(12); // 12 = 4 (int, file format marker) + 8 (long, index version) $nameCounter = $segmentsFile->readInt(); $this->_generation++; } Index\Writer::createIndex($this->_directory, $this->_generation, $nameCounter); LockManager::releaseWriteLock($this->_directory); } if ($this->_generation == -1) { throw new RuntimeException('Index doesn\'t exists in the specified directory.'); } elseif ($this->_generation == 0) { $this->_readPre21SegmentsFile(); } else { $this->_readSegmentsFile(); } }
/** * Get name for new segment * * @return string */ private function _newSegmentName() { Lucene\LockManager::obtainWriteLock($this->_directory); $generation = Lucene\Index::getActualGeneration($this->_directory); $segmentsFile = $this->_directory->getFileObject(Lucene\Index::getSegmentFileName($generation), false); $segmentsFile->seek(12); // 12 = 4 (int, file format marker) + 8 (long, index version) $segmentNameCounter = $segmentsFile->readInt(); $segmentsFile->seek(12); // 12 = 4 (int, file format marker) + 8 (long, index version) $segmentsFile->writeInt($segmentNameCounter + 1); // Flash output to guarantee that wrong value will not be loaded between unlock and // return (which calls $segmentsFile destructor) $segmentsFile->flush(); Lucene\LockManager::releaseWriteLock($this->_directory); return '_' . base_convert($segmentNameCounter, 10, 36); }
/** * Release exclusive optimization lock * * @param \ZendSearch\Lucene\Storage\Directory $lockDirectory */ public static function releaseOptimizationLock(Directory $lockDirectory) { $lock = $lockDirectory->getFileObject(self::OPTIMIZATION_LOCK_FILE); $lock->unlock(); }
/** * Load terms dictionary index * * @throws \ZendSearch\Lucene\Exception\ExceptionInterface */ private function _loadDictionaryIndex() { // Check, if index is already serialized if ($this->_directory->fileExists($this->_name . '.sti')) { // Load serialized dictionary index data $stiFile = $this->_directory->getFileObject($this->_name . '.sti'); $stiFileData = $stiFile->readBytes($this->_directory->fileLength($this->_name . '.sti')); // Load dictionary index data if (($unserializedData = @unserialize($stiFileData)) !== false) { list($this->_termDictionary, $this->_termDictionaryInfos) = $unserializedData; return; } } // Load data from .tii file and generate .sti file // Prefetch dictionary index data $tiiFile = $this->openCompoundFile('.tii'); $tiiFileData = $tiiFile->readBytes($this->compoundFileLength('.tii')); // Load dictionary index data list($this->_termDictionary, $this->_termDictionaryInfos) = DictionaryLoader::load($tiiFileData); $stiFileData = serialize(array($this->_termDictionary, $this->_termDictionaryInfos)); $stiFile = $this->_directory->createFile($this->_name . '.sti'); $stiFile->writeBytes($stiFileData); }