Passed
Branch master (b37043)
by Timo
11:18
created

Apache_Solr_Service_Balancer::removeReadService()   D

Complexity

Conditions 9
Paths 9

Size

Total Lines 26
Code Lines 17

Duplication

Lines 26
Ratio 100 %

Importance

Changes 0
Metric Value
cc 9
eloc 17
nc 9
nop 1
dl 26
loc 26
rs 4.909
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright (c) 2007-2011, Servigistics, Inc.
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 *  - Redistributions of source code must retain the above copyright notice,
10
 *    this list of conditions and the following disclaimer.
11
 *  - Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *  - Neither the name of Servigistics, Inc. nor the names of
15
 *    its contributors may be used to endorse or promote products derived from
16
 *    this software without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
 * POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * @copyright Copyright 2007-2011 Servigistics, Inc. (http://servigistics.com)
31
 * @license http://solr-php-client.googlecode.com/svn/trunk/COPYING New BSD
32
 * @version $Id$
33
 *
34
 * @package Apache
35
 * @subpackage Solr
36
 * @author Donovan Jimenez <[email protected]>, Dan Wolfe
37
 */
38
39
// See Issue #1 (http://code.google.com/p/solr-php-client/issues/detail?id=1)
40
// Doesn't follow typical include path conventions, but is more convenient for users
41
require_once(dirname(dirname(__FILE__)) . '/Service.php');
42
43
require_once(dirname(dirname(__FILE__)) . '/NoServiceAvailableException.php');
44
45
/**
46
 * Reference Implementation for using multiple Solr services in a distribution. Functionality
47
 * includes:
48
 *    routing of read / write operations
49
 *    failover (on selection) for multiple read servers
50
 */
51
class Apache_Solr_Service_Balancer
52
{
53
    /**
54
     * SVN Revision meta data for this class
55
     */
56
    const SVN_REVISION = '$Revision$';
57
58
    /**
59
     * SVN ID meta data for this class
60
     */
61
    const SVN_ID = '$Id$';
62
63
    protected $_createDocuments = true;
64
65
    protected $_readableServices = array();
66
    protected $_writeableServices = array();
67
68
    protected $_currentReadService = null;
69
    protected $_currentWriteService = null;
70
71
    protected $_readPingTimeout = 2;
72
    protected $_writePingTimeout = 4;
73
74
    // Configuration for server selection backoff intervals
75
    protected $_useBackoff = false;        // Set to true to use more resillient write server selection
76
    protected $_backoffLimit = 600;        // 10 minute default maximum
77
    protected $_backoffEscalation = 2.0;    // Rate at which to increase backoff period
78
    protected $_defaultBackoff = 2.0;        // Default backoff interval
79
80
    /**
81
     * Constructor. Takes arrays of read and write service instances or descriptions
82
     *
83
     * @param array $readableServices
84
     * @param array $writeableServices
85
     */
86
    public function __construct(
87
        $readableServices = array(),
88
        $writeableServices = array()
89
    ) {
90
        //setup readable services
91
        foreach ($readableServices as $service) {
92
            $this->addReadService($service);
93
        }
94
95
        //setup writeable services
96
        foreach ($writeableServices as $service) {
97
            $this->addWriteService($service);
98
        }
99
    }
100
101
    /**
102
     * Adds a service instance or service descriptor (if it is already
103
     * not added)
104
     *
105
     * @param mixed $service
106
     *
107
     * @throws Apache_Solr_InvalidArgumentException If service descriptor is not valid
108
     */
109
    public function addReadService($service)
110
    {
111
        if ($service instanceof Apache_Solr_Service) {
112
            $id = $this->_getServiceId($service->getHost(), $service->getPort(),
113
                $service->getPath());
114
115
            $this->_readableServices[$id] = $service;
116
        } else {
117
            if (is_array($service)) {
118
                if (isset($service['host']) && isset($service['port']) && isset($service['path'])) {
119
                    $id = $this->_getServiceId((string)$service['host'],
120
                        (int)$service['port'], (string)$service['path']);
121
122
                    $this->_readableServices[$id] = $service;
123
                } else {
124
                    throw new Apache_Solr_InvalidArgumentException('A Readable Service description array does not have all required elements of host, port, and path');
125
                }
126
            }
127
        }
128
    }
129
130
    /**
131
     * Generates a service ID
132
     *
133
     * @param string $host
134
     * @param integer $port
135
     * @param string $path
136
     * @return string
137
     */
138
    protected function _getServiceId($host, $port, $path)
139
    {
140
        return $host . ':' . $port . $path;
141
    }
142
143
    /**
144
     * Adds a service instance or service descriptor (if it is already
145
     * not added)
146
     *
147
     * @param mixed $service
148
     *
149
     * @throws Apache_Solr_InvalidArgumentException If service descriptor is not valid
150
     */
151
    public function addWriteService($service)
152
    {
153
        if ($service instanceof Apache_Solr_Service) {
154
            $id = $this->_getServiceId($service->getHost(), $service->getPort(),
155
                $service->getPath());
156
157
            $this->_writeableServices[$id] = $service;
158
        } else {
159
            if (is_array($service)) {
160
                if (isset($service['host']) && isset($service['port']) && isset($service['path'])) {
161
                    $id = $this->_getServiceId((string)$service['host'],
162
                        (int)$service['port'], (string)$service['path']);
163
164
                    $this->_writeableServices[$id] = $service;
165
                } else {
166
                    throw new Apache_Solr_InvalidArgumentException('A Writeable Service description array does not have all required elements of host, port, and path');
167
                }
168
            }
169
        }
170
    }
171
172
    /**
173
     * Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
174
     *
175
     * NOTE: inside a phrase fewer characters need escaped, use {@link Apache_Solr_Service::escapePhrase()} instead
176
     *
177
     * @param string $value
178
     * @return string
179
     */
180
    public static function escape($value)
181
    {
182
        return Apache_Solr_Service::escape($value);
183
    }
184
185
    /**
186
     * Escape a value meant to be contained in a phrase for special query characters
187
     *
188
     * @param string $value
189
     * @return string
190
     */
191
    public static function escapePhrase($value)
192
    {
193
        return Apache_Solr_Service::escapePhrase($value);
194
    }
195
196
    /**
197
     * Convenience function for creating phrase syntax from a value
198
     *
199
     * @param string $value
200
     * @return string
201
     */
202
    public static function phrase($value)
203
    {
204
        return Apache_Solr_Service::phrase($value);
205
    }
206
207
    public function setReadPingTimeout($timeout)
208
    {
209
        $this->_readPingTimeout = $timeout;
210
    }
211
212
    public function setWritePingTimeout($timeout)
213
    {
214
        $this->_writePingTimeout = $timeout;
215
    }
216
217
    public function setUseBackoff($enable)
218
    {
219
        $this->_useBackoff = $enable;
220
    }
221
222
    /**
223
     * Get the current state of teh create documents flag.
224
     *
225
     * @return boolean
226
     */
227
    public function getCreateDocuments()
228
    {
229
        return $this->_createDocuments;
230
    }
231
232
    /**
233
     * Set the create documents flag. This determines whether {@link Apache_Solr_Response} objects will
234
     * parse the response and create {@link Apache_Solr_Document} instances in place.
235
     *
236
     * @param boolean $createDocuments
237
     */
238
    public function setCreateDocuments($createDocuments)
239
    {
240
        $this->_createDocuments = (bool)$createDocuments;
241
242
        // set on current read service
243
        if ($this->_currentReadService) {
244
            $service = $this->_selectReadService();
245
            $service->setCreateDocuments($createDocuments);
246
        }
247
    }
248
249
    /**
250
     * Iterate through available read services and select the first with a ping
251
     * that satisfies configured timeout restrictions (or the default)
252
     *
253
     * @return Apache_Solr_Service
254
     *
255
     * @throws Apache_Solr_NoServiceAvailableException If there are no read services that meet requirements
256
     */
257
    protected function _selectReadService($forceSelect = false)
258
    {
259
        if (!$this->_currentReadService || !isset($this->_readableServices[$this->_currentReadService]) || $forceSelect) {
260
            if ($this->_currentReadService && isset($this->_readableServices[$this->_currentReadService]) && $forceSelect) {
261
                // we probably had a communication error, ping the current read service, remove it if it times out
262
                if ($this->_readableServices[$this->_currentReadService]->ping($this->_readPingTimeout) === false) {
263
                    $this->removeReadService($this->_currentReadService);
264
                }
265
            }
266
267
            if (count($this->_readableServices)) {
268
                // select one of the read services at random
269
                $ids = array_keys($this->_readableServices);
270
271
                $id = $ids[rand(0, count($ids) - 1)];
272
                $service = $this->_readableServices[$id];
273
274
                if (is_array($service)) {
275
                    //convert the array definition to a client object
276
                    $service = new Apache_Solr_Service($service['host'],
277
                        $service['port'], $service['path']);
278
                    $this->_readableServices[$id] = $service;
279
                }
280
281
                $service->setCreateDocuments($this->_createDocuments);
282
                $this->_currentReadService = $id;
283
            } else {
284
                throw new Apache_Solr_NoServiceAvailableException('No read services were available');
285
            }
286
        }
287
288
        return $this->_readableServices[$this->_currentReadService];
289
    }
290
291
    /**
292
     * Removes a service instance or descriptor from the available services
293
     *
294
     * @param mixed $service
295
     *
296
     * @throws Apache_Solr_InvalidArgumentException If service descriptor is not valid
297
     */
298
    public function removeReadService($service)
299
    {
300
        $id = '';
301
302
        if ($service instanceof Apache_Solr_Service) {
303
            $id = $this->_getServiceId($service->getHost(), $service->getPort(),
304
                $service->getPath());
305
        } else {
306
            if (is_array($service)) {
307
                if (isset($service['host']) && isset($service['port']) && isset($service['path'])) {
308
                    $id = $this->_getServiceId((string)$service['host'],
309
                        (int)$service['port'], (string)$service['path']);
310
                } else {
311
                    throw new Apache_Solr_InvalidArgumentException('A Readable Service description array does not have all required elements of host, port, and path');
312
                }
313
            } else {
314
                if (is_string($service)) {
315
                    $id = $service;
316
                }
317
            }
318
        }
319
320
        if ($id && isset($this->_readableServices[$id])) {
321
            unset($this->_readableServices[$id]);
322
        }
323
    }
324
325
    /**
326
     * Raw Add Method. Takes a raw post body and sends it to the update service.  Post body
327
     * should be a complete and well formed "add" xml document.
328
     *
329
     * @param string $rawPost
330
     * @return Apache_Solr_Response
331
     *
332
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
333
     */
334
    public function add($rawPost)
335
    {
336
        $service = $this->_selectWriteService();
337
338
        do {
339
            try {
340
                return $service->add($rawPost);
341
            } catch (Apache_Solr_HttpTransportException $e) {
342
                if ($e->getCode() != 0) {
343
                    //IF NOT COMMUNICATION ERROR
344
345
                    throw $e;
346
                }
347
            }
348
349
            $service = $this->_selectWriteService(true);
350
        } while ($service);
351
352
        return false;
353
    }
354
355
    /**
356
     * Iterate through available write services and select the first with a ping
357
     * that satisfies configured timeout restrictions (or the default)
358
     *
359
     * @return Apache_Solr_Service
360
     *
361
     * @throws Apache_Solr_NoServiceAvailableException If there are no write services that meet requirements
362
     */
363
    protected function _selectWriteService($forceSelect = false)
364
    {
365
        if ($this->_useBackoff) {
366
            return $this->_selectWriteServiceSafe($forceSelect);
367
        }
368
369
        if (!$this->_currentWriteService || !isset($this->_writeableServices[$this->_currentWriteService]) || $forceSelect) {
370
            if ($this->_currentWriteService && isset($this->_writeableServices[$this->_currentWriteService]) && $forceSelect) {
371
                // we probably had a communication error, ping the current read service, remove it if it times out
372
                if ($this->_writeableServices[$this->_currentWriteService]->ping($this->_writePingTimeout) === false) {
373
                    $this->removeWriteService($this->_currentWriteService);
374
                }
375
            }
376
377
            if (count($this->_writeableServices)) {
378
                // select one of the read services at random
379
                $ids = array_keys($this->_writeableServices);
380
381
                $id = $ids[rand(0, count($ids) - 1)];
382
                $service = $this->_writeableServices[$id];
383
384
                if (is_array($service)) {
385
                    //convert the array definition to a client object
386
                    $service = new Apache_Solr_Service($service['host'],
387
                        $service['port'], $service['path']);
388
                    $this->_writeableServices[$id] = $service;
389
                }
390
391
                $this->_currentWriteService = $id;
392
            } else {
393
                throw new Apache_Solr_NoServiceAvailableException('No write services were available');
394
            }
395
        }
396
397
        return $this->_writeableServices[$this->_currentWriteService];
398
    }
399
400
    /**
401
     * Iterate through available write services and select the first with a ping
402
     * that satisfies configured timeout restrictions (or the default).  The
403
     * timeout period will increase until a connection is made or the limit is
404
     * reached.   This will allow for increased reliability with heavily loaded
405
     * server(s).
406
     *
407
     * @return Apache_Solr_Service
408
     *
409
     * @throws Apache_Solr_NoServiceAvailableException If there are no write services that meet requirements
410
     */
411
412
    protected function _selectWriteServiceSafe($forceSelect = false)
413
    {
414
        if (!$this->_currentWriteService || !isset($this->_writeableServices[$this->_currentWriteService]) || $forceSelect) {
415
            if (count($this->_writeableServices)) {
416
                $backoff = $this->_defaultBackoff;
417
418
                do {
419
                    // select one of the read services at random
420
                    $ids = array_keys($this->_writeableServices);
421
422
                    $id = $ids[rand(0, count($ids) - 1)];
423
                    $service = $this->_writeableServices[$id];
424
425
                    if (is_array($service)) {
426
                        //convert the array definition to a client object
427
                        $service = new Apache_Solr_Service($service['host'],
428
                            $service['port'], $service['path']);
429
                        $this->_writeableServices[$id] = $service;
430
                    }
431
432
                    $this->_currentWriteService = $id;
433
434
                    $backoff *= $this->_backoffEscalation;
435
436
                    if ($backoff > $this->_backoffLimit) {
437
                        throw new Apache_Solr_NoServiceAvailableException('No write services were available.  All timeouts exceeded.');
438
                    }
439
                } while ($this->_writeableServices[$this->_currentWriteService]->ping($backoff) === false);
440
            } else {
441
                throw new Apache_Solr_NoServiceAvailableException('No write services were available');
442
            }
443
        }
444
445
        return $this->_writeableServices[$this->_currentWriteService];
446
    }
447
448
    /**
449
     * Removes a service instance or descriptor from the available services
450
     *
451
     * @param mixed $service
452
     *
453
     * @throws Apache_Solr_InvalidArgumentException If service descriptor is not valid
454
     */
455
    public function removeWriteService($service)
456
    {
457
        $id = '';
458
459
        if ($service instanceof Apache_Solr_Service) {
460
            $id = $this->_getServiceId($service->getHost(), $service->getPort(),
461
                $service->getPath());
462
        } else {
463
            if (is_array($service)) {
464
                if (isset($service['host']) && isset($service['port']) && isset($service['path'])) {
465
                    $id = $this->_getServiceId((string)$service['host'],
466
                        (int)$service['port'], (string)$service['path']);
467
                } else {
468
                    throw new Apache_Solr_InvalidArgumentException('A Readable Service description array does not have all required elements of host, port, and path');
469
                }
470
            } else {
471
                if (is_string($service)) {
472
                    $id = $service;
473
                }
474
            }
475
        }
476
477
        if ($id && isset($this->_writeableServices[$id])) {
478
            unset($this->_writeableServices[$id]);
479
        }
480
    }
481
482
    /**
483
     * Add a Solr Document to the index
484
     *
485
     * @param Apache_Solr_Document $document
486
     * @param boolean $allowDups
487
     * @param boolean $overwritePending
488
     * @param boolean $overwriteCommitted
489
     * @return Apache_Solr_Response
490
     *
491
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
492
     */
493
    public function addDocument(
494
        Apache_Solr_Document $document,
495
        $allowDups = false,
496
        $overwritePending = true,
497
        $overwriteCommitted = true
498
    ) {
499
        $service = $this->_selectWriteService();
500
501
        do {
502
            try {
503
                return $service->addDocument($document, $allowDups,
504
                    $overwritePending, $overwriteCommitted);
505
            } catch (Apache_Solr_HttpTransportException $e) {
506
                if ($e->getCode() != 0) {
507
                    //IF NOT COMMUNICATION ERROR
508
509
                    throw $e;
510
                }
511
            }
512
513
            $service = $this->_selectWriteService(true);
514
        } while ($service);
515
516
        return false;
517
    }
518
519
    /**
520
     * Add an array of Solr Documents to the index all at once
521
     *
522
     * @param array $documents Should be an array of Apache_Solr_Document instances
523
     * @param boolean $allowDups
524
     * @param boolean $overwritePending
525
     * @param boolean $overwriteCommitted
526
     * @return Apache_Solr_Response
527
     *
528
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
529
     */
530
    public function addDocuments(
531
        $documents,
532
        $allowDups = false,
533
        $overwritePending = true,
534
        $overwriteCommitted = true
535
    ) {
536
        $service = $this->_selectWriteService();
537
538
        do {
539
            try {
540
                return $service->addDocuments($documents, $allowDups,
541
                    $overwritePending, $overwriteCommitted);
542
            } catch (Apache_Solr_HttpTransportException $e) {
543
                if ($e->getCode() != 0) {
544
                    //IF NOT COMMUNICATION ERROR
545
546
                    throw $e;
547
                }
548
            }
549
550
            $service = $this->_selectWriteService(true);
551
        } while ($service);
552
553
        return false;
554
    }
555
556
    /**
557
     * Send a commit command.  Will be synchronous unless both wait parameters are set
558
     * to false.
559
     *
560
     * @param boolean $optimize
561
     * @param boolean $waitFlush Not used, will be removed with EXT:solr version 4.0
562
     * @param boolean $waitSearcher
563
     * @param integer $timeout
564
     * @return Apache_Solr_Response
565
     *
566
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
567
     */
568
    public function commit(
569
        $optimize = true,
570
        $waitFlush = true,
571
        $waitSearcher = true,
572
        $timeout = 3600
573
    ) {
574
        $service = $this->_selectWriteService();
575
576
        do {
577
            try {
578
                return $service->commit($optimize, $waitFlush, $waitSearcher,
579
                    $timeout);
580
            } catch (Apache_Solr_HttpTransportException $e) {
581
                if ($e->getCode() != 0) {
582
                    //IF NOT COMMUNICATION ERROR
583
584
                    throw $e;
585
                }
586
            }
587
588
            $service = $this->_selectWriteService(true);
589
        } while ($service);
590
591
        return false;
592
    }
593
594
    /**
595
     * Raw Delete Method. Takes a raw post body and sends it to the update service. Body should be
596
     * a complete and well formed "delete" xml document
597
     *
598
     * @param string $rawPost
599
     * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
600
     * @return Apache_Solr_Response
601
     *
602
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
603
     */
604
    public function delete($rawPost, $timeout = 3600)
605
    {
606
        $service = $this->_selectWriteService();
607
608
        do {
609
            try {
610
                return $service->delete($rawPost, $timeout);
611
            } catch (Apache_Solr_HttpTransportException $e) {
612
                if ($e->getCode() != 0) {
613
                    //IF NOT COMMUNICATION ERROR
614
615
                    throw $e;
616
                }
617
            }
618
619
            $service = $this->_selectWriteService(true);
620
        } while ($service);
621
622
        return false;
623
    }
624
625
    /**
626
     * Create a delete document based on document ID
627
     *
628
     * @param string $id
629
     * @param boolean $fromPending
630
     * @param boolean $fromCommitted
631
     * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
632
     * @return Apache_Solr_Response
633
     *
634
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
635
     */
636
    public function deleteById(
637
        $id,
638
        $fromPending = true,
639
        $fromCommitted = true,
640
        $timeout = 3600
641
    ) {
642
        $service = $this->_selectWriteService();
643
644
        do {
645
            try {
646
                return $service->deleteById($id, $fromPending, $fromCommitted,
647
                    $timeout);
648
            } catch (Apache_Solr_HttpTransportException $e) {
649
                if ($e->getCode() != 0) {
650
                    //IF NOT COMMUNICATION ERROR
651
652
                    throw $e;
653
                }
654
            }
655
656
            $service = $this->_selectWriteService(true);
657
        } while ($service);
658
659
        return false;
660
    }
661
662
    /**
663
     * Create and post a delete document based on multiple document IDs.
664
     *
665
     * @param array $ids Expected to be utf-8 encoded strings
666
     * @param boolean $fromPending
667
     * @param boolean $fromCommitted
668
     * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
669
     * @return Apache_Solr_Response
670
     *
671
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
672
     */
673
    public function deleteByMultipleIds(
674
        $ids,
675
        $fromPending = true,
676
        $fromCommitted = true,
677
        $timeout = 3600
678
    ) {
679
        $service = $this->_selectWriteService();
680
681
        do {
682
            try {
683
                return $service->deleteByMultipleId($ids, $fromPending,
684
                    $fromCommitted, $timeout);
685
            } catch (Apache_Solr_HttpTransportException $e) {
686
                if ($e->getCode() != 0) {
687
                    //IF NOT COMMUNICATION ERROR
688
689
                    throw $e;
690
                }
691
            }
692
693
            $service = $this->_selectWriteService(true);
694
        } while ($service);
695
696
        return false;
697
    }
698
699
    /**
700
     * Create a delete document based on a query and submit it
701
     *
702
     * @param string $rawQuery
703
     * @param boolean $fromPending
704
     * @param boolean $fromCommitted
705
     * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
706
     * @return Apache_Solr_Response
707
     *
708
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
709
     */
710
    public function deleteByQuery(
711
        $rawQuery,
712
        $fromPending = true,
713
        $fromCommitted = true,
714
        $timeout = 3600
715
    ) {
716
        $service = $this->_selectWriteService();
717
718
        do {
719
            try {
720
                return $service->deleteByQuery($rawQuery, $fromPending,
721
                    $fromCommitted, $timeout);
722
            } catch (Apache_Solr_HttpTransportException $e) {
723
                if ($e->getCode() != 0) {
724
                    //IF NOT COMMUNICATION ERROR
725
726
                    throw $e;
727
                }
728
            }
729
730
            $service = $this->_selectWriteService(true);
731
        } while ($service);
732
733
        return false;
734
    }
735
736
    /**
737
     * Use Solr Cell to extract document contents. See {@link http://wiki.apache.org/solr/ExtractingRequestHandler} for information on how
738
     * to use Solr Cell and what parameters are available.
739
     *
740
     * NOTE: when passing an Apache_Solr_Document instance, field names and boosts will automatically be prepended by "literal." and "boost."
741
     * as appropriate. Any keys from the $params array will NOT be treated this way. Any mappings from the document will overwrite key / value
742
     * pairs in the params array if they have the same name (e.g. you pass a "literal.id" key and value in your $params array but you also
743
     * pass in a document isntance with an "id" field" - the document's value(s) will take precedence).
744
     *
745
     * @param string $file Path to file to extract data from
746
     * @param array $params optional array of key value pairs that will be sent with the post (see Solr Cell documentation)
747
     * @param Apache_Solr_Document $document optional document that will be used to generate post parameters (literal.* and boost.* params)
748
     * @param string $mimetype optional mimetype specification (for the file being extracted)
749
     *
750
     * @return Apache_Solr_Response
751
     *
752
     * @throws Apache_Solr_InvalidArgumentException if $file, $params, or $document are invalid.
753
     */
754
    public function extract(
755
        $file,
756
        $params = array(),
757
        $document = null,
758
        $mimetype = 'application/octet-stream'
759
    ) {
760
        $service = $this->_selectWriteService();
761
762
        do {
763
            try {
764
                return $service->extract($file, $params, $document, $mimetype);
765
            } catch (Apache_Solr_HttpTransportException $e) {
766
                if ($e->getCode() != 0) {
767
                    //IF NOT COMMUNICATION ERROR
768
769
                    throw $e;
770
                }
771
            }
772
773
            $service = $this->_selectWriteService(true);
774
        } while ($service);
775
776
        return false;
777
    }
778
779
    /**
780
     * Use Solr Cell to extract document contents. See {@link http://wiki.apache.org/solr/ExtractingRequestHandler} for information on how
781
     * to use Solr Cell and what parameters are available.
782
     *
783
     * NOTE: when passing an Apache_Solr_Document instance, field names and boosts will automatically be prepended by "literal." and "boost."
784
     * as appropriate. Any keys from the $params array will NOT be treated this way. Any mappings from the document will overwrite key / value
785
     * pairs in the params array if they have the same name (e.g. you pass a "literal.id" key and value in your $params array but you also
786
     * pass in a document isntance with an "id" field" - the document's value(s) will take precedence).
787
     *
788
     * @param string $data Data that will be passed to Solr Cell
789
     * @param array $params optional array of key value pairs that will be sent with the post (see Solr Cell documentation)
790
     * @param Apache_Solr_Document $document optional document that will be used to generate post parameters (literal.* and boost.* params)
791
     * @param string $mimetype optional mimetype specification (for the file being extracted)
792
     *
793
     * @return Apache_Solr_Response
794
     *
795
     * @throws Apache_Solr_InvalidArgumentException if $file, $params, or $document are invalid.
796
     *
797
     * @todo Should be using multipart/form-data to post parameter values, but I could not get my implementation to work. Needs revisisted.
798
     */
799
    public function extractFromString(
800
        $data,
801
        $params = array(),
802
        $document = null,
803
        $mimetype = 'application/octet-stream'
804
    ) {
805
        $service = $this->_selectWriteService();
806
807
        do {
808
            try {
809
                return $service->extractFromString($data, $params, $document,
810
                    $mimetype);
811
            } catch (Apache_Solr_HttpTransportException $e) {
812
                if ($e->getCode() != 0) {
813
                    //IF NOT COMMUNICATION ERROR
814
815
                    throw $e;
816
                }
817
            }
818
819
            $service = $this->_selectWriteService(true);
820
        } while ($service);
821
822
        return false;
823
    }
824
825
    /**
826
     * Send an optimize command.  Will be synchronous unless both wait parameters are set
827
     * to false.
828
     *
829
     * @param boolean $waitFlush Not used, will be removed with EXT:solr version 4.0
830
     * @param boolean $waitSearcher
831
     * @param integer $timeout Maximum expected duration of the optimize operation on the server (otherwise, will throw a communication exception)
832
     * @return Apache_Solr_Response
833
     *
834
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
835
     */
836
    public function optimize(
837
        $waitFlush = true,
838
        $waitSearcher = true,
839
        $timeout = 3600
840
    ) {
841
        $service = $this->_selectWriteService();
842
843
        do {
844
            try {
845
                return $service->optimize($waitFlush, $waitSearcher, $timeout);
846
            } catch (Apache_Solr_HttpTransportException $e) {
847
                if ($e->getCode() != 0) {
848
                    //IF NOT COMMUNICATION ERROR
849
850
                    throw $e;
851
                }
852
            }
853
854
            $service = $this->_selectWriteService(true);
855
        } while ($service);
856
857
        return false;
858
    }
859
860
    /**
861
     * Simple Search interface
862
     *
863
     * @param string $query The raw query string
864
     * @param int $offset The starting offset for result documents
865
     * @param int $limit The maximum number of result documents to return
866
     * @param array $params key / value pairs for query parameters, use arrays for multivalued parameters
867
     * @param string $method The HTTP method (Apache_Solr_Service::METHOD_GET or Apache_Solr_Service::METHOD::POST)
868
     * @return Apache_Solr_Response
869
     *
870
     * @throws Apache_Solr_HttpTransportException If an error occurs during the service call
871
     */
872
    public function search(
873
        $query,
874
        $offset = 0,
875
        $limit = 10,
876
        $params = array(),
877
        $method = Apache_Solr_Service::METHOD_GET
878
    ) {
879
        $service = $this->_selectReadService();
880
881
        do {
882
            try {
883
                return $service->search($query, $offset, $limit, $params,
884
                    $method);
885
            } catch (Apache_Solr_HttpTransportException $e) {
886
                if ($e->getCode() != 0) {
887
                    //IF NOT COMMUNICATION ERROR
888
889
                    throw $e;
890
                }
891
            }
892
893
            $service = $this->_selectReadService(true);
894
        } while ($service);
895
896
        return false;
897
    }
898
}
899