/** * Update segments file by adding current segment to a list * @todo !!!!!Finish the implementation * * @throws Zend_Search_Lucene_Exception */ private function _updateSegments() { $segmentsFile = $this->_directory->getFileObject('segments'); $newSegmentFile = $this->_directory->createFile('segments.new'); $newSegmentFile->writeInt((int) 0xffffffff); $newSegmentFile->writeLong($this->_version); $newSegmentFile->writeInt($this->_segmentNameCounter); $newSegmentFile->writeInt($this->_segments + count($this->_newSegments)); $segmentsFile->seek(20); $newSegmentFile->writeBytes($segmentsFile->readBytes($this->_directory->fileLength('segments') - 20)); foreach ($this->_newSegments as $segmentName => $segmentInfo) { $newSegmentFile->writeString($segmentName); $newSegmentFile->writeInt($segmentInfo->count()); } $this->_directory->renameFile('segments.new', 'segments'); }
/** * Update segments file by adding current segment to a list * * @throws Zend_Search_Lucene_Exception */ private function _updateSegments() { // Get an exclusive index lock // Wait, until all parallel searchers or indexers won't stop // and stop all next searchers, while we are updating segments file $lock = $this->_directory->getFileObject('index.lock'); if (!$lock->lock(LOCK_EX)) { throw new Zend_Search_Lucene_Exception('Can\'t obtain exclusive index lock'); } // Do not share file handlers to get file updates from other sessions. $segmentsFile = $this->_directory->getFileObject('segments', false); $newSegmentFile = $this->_directory->createFile('segments.new', false); // Write format marker $newSegmentFile->writeInt((int) 0xffffffff); // Write index version $segmentsFile->seek(4, SEEK_CUR); $version = $segmentsFile->readLong() + $this->_versionUpdate; $this->_versionUpdate = 0; $newSegmentFile->writeLong($version); // Write segment name counter $newSegmentFile->writeInt($segmentsFile->readInt()); // Get number of segments offset $numOfSegmentsOffset = $newSegmentFile->tell(); // Write number of segemnts $segmentsCount = $segmentsFile->readInt(); $newSegmentFile->writeInt(0); // Write dummy data (segment counter) $segments = array(); for ($count = 0; $count < $segmentsCount; $count++) { $segName = $segmentsFile->readString(); $segSize = $segmentsFile->readInt(); if (!in_array($segName, $this->_segmentsToDelete)) { $newSegmentFile->writeString($segName); $newSegmentFile->writeInt($segSize); $segments[$segName] = $segSize; } } $segmentsFile->close(); $segmentsCount = count($segments) + count($this->_newSegments); // Remove segments, not listed in $segments (deleted) // Load segments, not listed in $this->_segmentInfos foreach ($this->_segmentInfos as $segId => $segInfo) { if (isset($segments[$segInfo->getName()])) { // Segment is already included into $this->_segmentInfos unset($segments[$segInfo->getName()]); } else { // remove deleted segment from a list unset($this->_segmentInfos[$segId]); } } // $segments contains a list of segments to load // do it later foreach ($this->_newSegments as $segName => $segmentInfo) { $newSegmentFile->writeString($segName); $newSegmentFile->writeInt($segmentInfo->count()); $this->_segmentInfos[] = $segmentInfo; } $this->_newSegments = array(); $newSegmentFile->seek($numOfSegmentsOffset); $newSegmentFile->writeInt($segmentsCount); // Update segments count $newSegmentFile->close(); $this->_directory->renameFile('segments.new', 'segments'); // Segments file update is finished // Switch back to shared lock mode $lock->lock(LOCK_SH); $fileList = $this->_directory->fileList(); foreach ($this->_segmentsToDelete as $nameToDelete) { foreach (self::$_indexExtensions as $ext) { if ($this->_directory->fileExists($nameToDelete . $ext)) { $this->_directory->deleteFile($nameToDelete . $ext); } } foreach ($fileList as $file) { if (substr($file, 0, strlen($nameToDelete) + 2) == $nameToDelete . '.f' && ctype_digit(substr($file, strlen($nameToDelete) + 2))) { $this->_directory->deleteFile($file); } } } $this->_segmentsToDelete = array(); // Load segments, created by other process foreach ($segments as $segName => $segSize) { // Load new segments $this->_segmentInfos[] = new Zend_Search_Lucene_Index_SegmentInfo($segName, $segSize, $this->_directory); } }
/** * Update segments file by adding current segment to a list * * @todo !!!! locks should be processed to prevent concurrent access errors * * @throws Zend_Search_Lucene_Exception */ private function _updateSegments() { $segmentsFile = $this->_directory->getFileObject('segments'); $newSegmentFile = $this->_directory->createFile('segments.new'); // Write format marker $newSegmentFile->writeInt((int) 0xffffffff); // Write index version $segmentsFile->seek(4, SEEK_CUR); $version = $segmentsFile->readLong() + $this->_versionUpdate; $this->_versionUpdate = 0; $newSegmentFile->writeLong($version); // Write segment name counter $newSegmentFile->writeInt($segmentsFile->readInt()); // Write number of segemnts $segments = $segmentsFile->readInt(); $newSegmentFile->writeInt($segments + count($this->_newSegments) - count($this->_segmentsToDelete)); for ($count = 0; $count < $segments; $count++) { $segName = $segmentsFile->readString(); $segSize = $segmentsFile->readInt(); if (!array_key_exists($segName, $this->_segmentsToDelete)) { $newSegmentFile->writeString($segName); $newSegmentFile->writeInt($segSize); } } foreach ($this->_newSegments as $segmentName => $segmentInfo) { $newSegmentFile->writeString($segmentName); $newSegmentFile->writeInt($segmentInfo->count()); $this->_segmentInfos[] = $segmentInfo; } $this->_newSegments = array(); $fileList = $this->_directory->fileList(); foreach ($this->_segmentsToDelete as $nameToDelete) { foreach ($this->_segmentInfos as $segId => $segInfo) { if ($segInfo->getName() == $nameToDelete) { unset($this->_segmentInfos[$segId]); } } foreach (self::$_indexExtensions as $ext) { if ($this->_directory->fileExists($nameToDelete . $ext)) { $this->_directory->deleteFile($nameToDelete . $ext); } } foreach ($fileList as $file) { if (substr($file, 0, strlen($nameToDelete) + 2) == $nameToDelete . '.f' && ctype_digit(substr($file, strlen($nameToDelete) + 2))) { $this->_directory->deleteFile($file); } } } $this->_segmentsToDelete = array(); $this->_directory->renameFile('segments.new', 'segments'); }