Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * Zend Framework
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to version 1.0 of the Zend Framework
8
 * license, that is bundled with this package in the file LICENSE, and
9
 * is available through the world-wide-web at the following URL:
10
 * http://www.zend.com/license/framework/1_0.txt. If you did not receive
11
 * a copy of the Zend Framework license and are unable to obtain it
12
 * through the world-wide-web, please send a note to license@zend.com
13
 * so we can mail you a copy immediately.
14
 *
15
 * @package    Zend_Search_Lucene
16
 * @subpackage Index
17
 * @copyright  Copyright (c) 2005-2006 Zend Technologies USA Inc. (http://www.zend.com)
18
 * @license    http://www.zend.com/license/framework/1_0.txt Zend Framework License version 1.0
19
 */
20
 
21
 
22
/** Zend_Search_Lucene_Index_SegmentWriter */
23
require_once 'Zend/Search/Lucene/Index/SegmentWriter.php';
24
 
25
/** Zend_Search_Lucene_Index_SegmentInfo */
26
require_once 'Zend/Search/Lucene/Index/SegmentInfo.php';
27
 
28
 
29
/**
30
 * @package    Zend_Search_Lucene
31
 * @subpackage Index
32
 * @copyright  Copyright (c) 2005-2006 Zend Technologies USA Inc. (http://www.zend.com)
33
 * @license    http://www.zend.com/license/framework/1_0.txt Zend Framework License version 1.0
34
 */
35
class Zend_Search_Lucene_Index_Writer
36
{
37
    /**
38
     * @todo Implement segment merger
39
     * @todo Implement mergeFactor, minMergeDocs, maxMergeDocs usage.
40
     * @todo Implement Analyzer substitution
41
     * @todo Implement Zend_Search_Lucene_Storage_DirectoryRAM and Zend_Search_Lucene_Storage_FileRAM to use it for
42
     *       temporary index files
43
     * @todo Directory lock processing
44
     */
45
 
46
    /**
47
     * File system adapter.
48
     *
49
     * @var Zend_Search_Lucene_Storage_Directory
50
     */
51
    private $_directory = null;
52
 
53
 
54
    /**
55
     * Index version
56
     * Counts how often the index has been changed by adding or deleting docs
57
     *
58
     * @var integer
59
     */
60
    private $_version;
61
 
62
    /**
63
     * Segment name counter.
64
     * Used to name new segments .
65
     *
66
     * @var integer
67
     */
68
    private $_segmentNameCounter;
69
 
70
    /**
71
     * Number of the segments in the index
72
     *
73
     * @var inteher
74
     */
75
    private $_segments;
76
 
77
    /**
78
     * Determines how often segment indices
79
     * are merged by addDocument().
80
     *
81
     * @var integer
82
     */
83
    public $mergeFactor;
84
 
85
    /**
86
     * Determines the minimal number of documents required before
87
     * the buffered in-memory documents are merging and a new Segment
88
     * is created.
89
     *
90
     * @var integer
91
     */
92
    public $minMergeDocs;
93
 
94
    /**
95
     * Determines the largest number of documents ever merged by addDocument().
96
     *
97
     * @var integer
98
     */
99
    public $maxMergeDocs;
100
 
101
    /**
102
     * List of the segments, created by index writer
103
     * Array of Zend_Search_Lucene_Index_SegmentInfo objects
104
     *
105
     * @var array
106
     */
107
    private $_newSegments;
108
 
109
    /**
110
     * Current segment to add documents
111
     *
112
     * @var Zend_Search_Lucene_Index_SegmentWriter
113
     */
114
    private $_currentSegment;
115
 
116
    /**
117
     * Opens the index for writing
118
     *
119
     * IndexWriter constructor needs Directory as a parameter. It should be
120
     * a string with a path to the index folder or a Directory object.
121
     * Second constructor parameter create is optional - true to create the
122
     * index or overwrite the existing one.
123
     *
124
     * @param Zend_Search_Lucene_Storage_Directory $directory
125
     * @param boolean $create
126
     */
127
    public function __construct(Zend_Search_Lucene_Storage_Directory $directory, $create = false)
128
    {
129
        $this->_directory = $directory;
130
 
131
        if ($create) {
132
            foreach ($this->_directory->fileList() as $file) {
133
                if ($file == 'deletable' ||
134
                    $file == 'segments'  ||
135
                    substr($file, strlen($file)-4) == '.cfs') {
136
                        $this->_directory->deleteFile($file);
137
                    }
138
            }
139
            $segmentsFile = $this->_directory->createFile('segments');
140
            $segmentsFile->writeInt((int)0xFFFFFFFF);
141
            // write version
142
            $segmentsFile->writeLong(0);
143
            // write name counter
144
            $segmentsFile->writeInt(0);
145
            // write segment counter
146
            $segmentsFile->writeInt(0);
147
 
148
            $deletableFile = $this->_directory->createFile('deletable');
149
            // write counter
150
            $deletableFile->writeInt(0);
151
 
152
            $this->_version            = 0;
153
            $this->_segmentNameCounter = 0;
154
            $this->_segments           = 0;
155
        } else {
156
            $segmentsFile = $this->_directory->getFileObject('segments');
157
            $format = $segmentsFile->readInt();
158
            if ($format != (int)0xFFFFFFFF) {
159
                throw new Zend_Search_Lucene_Exception('Wrong segments file format');
160
            }
161
 
162
            // read version
163
            $this->_version            = $segmentsFile->readLong();
164
            // read counter
165
            $this->_segmentNameCounter = $segmentsFile->readInt();
166
            // read segment counter
167
            $this->_segments           = $segmentsFile->readInt();
168
        }
169
 
170
        $this->_newSegments = array();
171
        $this->_currentSegment = null;
172
    }
173
 
174
    /**
175
     * Adds a document to this index.
176
     *
177
     * @param Zend_Search_Lucene_Document $document
178
     */
179
    public function addDocument(Zend_Search_Lucene_Document $document)
180
    {
181
        if ($this->_currentSegment === null) {
182
            $this->_currentSegment =
183
                new Zend_Search_Lucene_Index_SegmentWriter($this->_directory, $this->_newSegmentName());
184
        }
185
        $this->_currentSegment->addDocument($document);
186
        $this->_version++;
187
    }
188
 
189
 
190
 
191
    /**
192
     * Update segments file by adding current segment to a list
193
     * @todo !!!!!Finish the implementation
194
     *
195
     * @throws Zend_Search_Lucene_Exception
196
     */
197
    private function _updateSegments()
198
    {
199
        $segmentsFile   = $this->_directory->getFileObject('segments');
200
        $newSegmentFile = $this->_directory->createFile('segments.new');
201
 
202
        $newSegmentFile->writeInt((int)0xFFFFFFFF);
203
        $newSegmentFile->writeLong($this->_version);
204
        $newSegmentFile->writeInt($this->_segmentNameCounter);
205
        $newSegmentFile->writeInt($this->_segments + count($this->_newSegments));
206
 
207
        $segmentsFile->seek(20);
208
        $newSegmentFile->writeBytes($segmentsFile->readBytes($this->_directory->fileLength('segments') - 20));
209
 
210
        foreach ($this->_newSegments as $segmentName => $segmentInfo) {
211
            $newSegmentFile->writeString($segmentName);
212
            $newSegmentFile->writeInt($segmentInfo->count());
213
        }
214
 
215
        $this->_directory->renameFile('segments.new', 'segments');
216
    }
217
 
218
 
219
    /**
220
     * Commit current changes
221
     * returns array of new segments
222
     *
223
     * @return array
224
     */
225
    public function commit()
226
    {
227
        if ($this->_currentSegment !== null) {
228
            $newSegment = $this->_currentSegment->close();
229
            if ($newSegment !== null) {
230
                $this->_newSegments[$newSegment->getName()] = $newSegment;
231
            }
232
            $this->_currentSegment = null;
233
        }
234
 
235
        if (count($this->_newSegments) != 0) {
236
            $this->_updateSegments();
237
        }
238
 
239
        $result = $this->_newSegments;
240
        $this->_newSegments = array();
241
 
242
        return $result;
243
    }
244
 
245
 
246
    /**
247
     * Merges the provided indexes into this index.
248
     *
249
     * @param array $readers
250
     * @return void
251
     */
252
    public function addIndexes($readers)
253
    {
254
        /**
255
         * @todo implementation
256
         */
257
    }
258
 
259
 
260
    /**
261
     * Returns the number of documents currently in this index.
262
     *
263
     * @return integer
264
     */
265
    public function docCount($readers)
266
    {
267
        /**
268
         * @todo implementation
269
         */
270
    }
271
 
272
 
273
    /**
274
     * Flushes all changes to an index and closes all associated files.
275
     *
276
     */
277
    public function close()
278
    {
279
        /**
280
         * @todo implementation
281
         */
282
    }
283
 
284
 
285
    /**
286
     * Merges all segments together into a single segment, optimizing
287
     * an index for search.
288
     *
289
     * return void
290
     */
291
    public function optimize()
292
    {
293
        /**
294
         * @todo implementation
295
         */
296
    }
297
 
298
    /**
299
     * Get name for new segment
300
     *
301
     * @return string
302
     */
303
    private function _newSegmentName()
304
    {
305
        return '_' . base_convert($this->_segmentNameCounter++, 10, 36);
306
    }
307
 
308
}