/**
  * 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);
     }
 }
Exemple #2
0
 /**
  * Object destructor
  */
 public function __destruct()
 {
     $this->commit();
     // Release "under processing" flag
     LockManager::releaseReadLock($this->_directory);
     if ($this->_closeDirOnExit) {
         $this->_directory->close();
     }
     $this->_directory = null;
     $this->_writer = null;
     $this->_segmentInfos = null;
 }
Exemple #3
0
 /**
  * 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);
 }
Exemple #4
0
 /**
  * Release exclusive optimization lock
  *
  * @param \Zend\Search\Lucene\Storage\Directory\DirectoryInterface $lockDirectory
  */
 public static function releaseOptimizationLock(Directory\DirectoryInterface $lockDirectory)
 {
     $lock = $lockDirectory->getFileObject(self::OPTIMIZATION_LOCK_FILE);
     $lock->unlock();
 }
Exemple #5
0
 /**
  * Write changes if it's necessary.
  *
  * This method must be invoked only from the Writer _updateSegments() method,
  * so index Write lock has to be already obtained.
  *
  * @internal
  * @throws Zend\Search\Lucene\Exception\RuntimeException
  */
 public function writeChanges()
 {
     // Get new generation number
     $latestDelGen = $this->_detectLatestDelGen();
     if (!$this->_deletedDirty) {
         // There was no deletions by current process
         if ($latestDelGen == $this->_delGen) {
             // Delete file hasn't been updated by any concurrent process
             return;
         } elseif ($latestDelGen > $this->_delGen) {
             // Delete file has been updated by some concurrent process
             // Reload deletions file
             $this->_delGen = $latestDelGen;
             $this->_deleted = $this->_loadDelFile();
             return;
         } else {
             throw new RuntimeException('Delete file processing workflow is corrupted for the segment \'' . $this->_name . '\'.');
         }
     }
     if ($latestDelGen > $this->_delGen) {
         // Merge current deletions with latest deletions file
         $this->_delGen = $latestDelGen;
         $latestDelete = $this->_loadDelFile();
         if (extension_loaded('bitset')) {
             $this->_deleted = bitset_union($this->_deleted, $latestDelete);
         } else {
             $this->_deleted += $latestDelete;
         }
     }
     if (extension_loaded('bitset')) {
         $delBytes = $this->_deleted;
         $bitCount = count(bitset_to_array($delBytes));
     } else {
         $byteCount = floor($this->_docCount / 8) + 1;
         $delBytes = str_repeat(chr(0), $byteCount);
         for ($count = 0; $count < $byteCount; $count++) {
             $byte = 0;
             for ($bit = 0; $bit < 8; $bit++) {
                 if (isset($this->_deleted[$count * 8 + $bit])) {
                     $byte |= 1 << $bit;
                 }
             }
             $delBytes[$count] = chr($byte);
         }
         $bitCount = count($this->_deleted);
     }
     if ($this->_delGen == -1) {
         // Set delete file generation number to 1
         $this->_delGen = 1;
     } else {
         // Increase delete file generation number by 1
         $this->_delGen++;
     }
     $delFile = $this->_directory->createFile($this->_name . '_' . base_convert($this->_delGen, 10, 36) . '.del');
     $delFile->writeInt($this->_docCount);
     $delFile->writeInt($bitCount);
     $delFile->writeBytes($delBytes);
     $this->_deletedDirty = false;
 }