Source for file Balancer.php

Documentation is available at Balancer.php

  1. <?php
  2. /**
  3.  * @copyright Copyright 2007 Conduit Internet Technologies, Inc. (http://conduit-it.com)
  4.  * @license Apache Licence, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
  5.  *
  6.  *  Licensed under the Apache License, Version 2.0 (the "License");
  7.  *  you may not use this file except in compliance with the License.
  8.  *  You may obtain a copy of the License at
  9.  *
  10.  *      http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  *  Unless required by applicable law or agreed to in writing, software
  13.  *  distributed under the License is distributed on an "AS IS" BASIS,
  14.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  *  See the License for the specific language governing permissions and
  16.  *  limitations under the License.
  17.  *
  18.  * @package Apache
  19.  * @subpackage Solr
  20.  * @author Donovan Jimenez <djimenez@conduit-it.com>
  21.  */
  22.  
  23. require_once('Apache/Solr/Service.php');
  24.  
  25. /**
  26.  * Reference Implementation for using multiple Solr services in a distribution. Functionality
  27.  * includes:
  28.  *     routing of read / write operations
  29.  *     failover (on selection) for multiple read servers
  30.  */
  31. {
  32.     protected $_readableServices = array();
  33.     protected $_writeableServices = array();
  34.  
  35.     protected $_currentReadService = null;
  36.     protected $_currentWriteService = null;
  37.  
  38.     protected $_readPingTimeout = 0.01;
  39.     protected $_writePingTimeout = 1;
  40.  
  41.     /**
  42.      * Constructor. Takes arrays of read and write service instances or descriptions
  43.      *
  44.      * @param array $readableServices 
  45.      * @param array $writeableServices 
  46.      */
  47.     public function __construct($readableServices array()$writeableServices array())
  48.     {
  49.         //setup readable services
  50.         foreach ($readableServices as $service)
  51.         {
  52.             $this->addReadService($service);
  53.         }
  54.  
  55.         //setup writeable services
  56.         foreach ($writeableServices as $service)
  57.         {
  58.             $this->addWriteService($service);
  59.         }
  60.     }
  61.  
  62.     public function setReadPingTimeout($timeout)
  63.     {
  64.         $this->_readPingTimeout = $timeout;
  65.     }
  66.  
  67.     public function setWritePingTimetou($timeout)
  68.     {
  69.         $this->_writePingTimeout = $timeout;
  70.     }
  71.  
  72.     /**
  73.      * Generates a service ID
  74.      *
  75.      * @param string $host 
  76.      * @param integer $port 
  77.      * @param string $path 
  78.      * @return string 
  79.      */
  80.     private function _getServiceId($host$port$path)
  81.     {
  82.         return $host ':' $port $path;
  83.     }
  84.  
  85.     /**
  86.      * Adds a service instance or service descriptor (if it is already
  87.      * not added)
  88.      *
  89.      * @param mixed $service 
  90.      *
  91.      * @throws Exception If service descriptor is not valid
  92.      */
  93.     public function addReadService($service)
  94.     {
  95.         if ($service instanceof Apache_Solr_Service)
  96.         {
  97.             $id $this->_getServiceId($service->getHost()$service->getPort()$service->getPath());
  98.  
  99.             $this->_readableServices[$id$service;
  100.         }
  101.         else if (is_array($service))
  102.         {
  103.             if (isset($service['host']&& isset($service['port']&& isset($service['path']))
  104.             {
  105.                 $id $this->_getServiceId((string)$service['host'](int)$service['port'](string)$service['path']);
  106.  
  107.                 $this->_readableServices[$id$service;
  108.             }
  109.             else
  110.             {
  111.                 throw new Exception('A Readable Service description array does not have all required elements of host, port, and path');
  112.             }
  113.         }
  114.     }
  115.  
  116.     /**
  117.      * Removes a service instance or descriptor from the available services
  118.      *
  119.      * @param mixed $service 
  120.      *
  121.      * @throws Exception If service descriptor is not valid
  122.      */
  123.     public function removeReadService($service)
  124.     {
  125.         $id '';
  126.  
  127.         if ($service instanceof Apache_Solr_Service)
  128.         {
  129.             $id $this->_getServiceId($service->getHost()$service->getPort()$service->getPath());
  130.         }
  131.         else if (is_array($service))
  132.         {
  133.             if (isset($service['host']&& isset($service['port']&& isset($service['path']))
  134.             {
  135.                 $id $this->_getServiceId((string)$service['host'](int)$service['port'](string)$service['path']);
  136.             }
  137.             else
  138.             {
  139.                 throw new Exception('A Readable Service description array does not have all required elements of host, port, and path');
  140.             }
  141.         }
  142.  
  143.         if ($id)
  144.         {
  145.             unset($this->_readableServices[$id]);
  146.         }
  147.     }
  148.  
  149.     /**
  150.      * Adds a service instance or service descriptor (if it is already
  151.      * not added)
  152.      *
  153.      * @param mixed $service 
  154.      *
  155.      * @throws Exception If service descriptor is not valid
  156.      */
  157.     public function addWriteService($service)
  158.     {
  159.         if ($service instanceof Apache_Solr_Service)
  160.         {
  161.             $id $this->_getServiceId($service->getHost()$service->getPort()$service->getPath());
  162.  
  163.             $this->_writeableServices[$id$service;
  164.         }
  165.         else if (is_array($service))
  166.         {
  167.             if (isset($service['host']&& isset($service['port']&& isset($service['path']))
  168.             {
  169.                 $id $this->_getServiceId((string)$service['host'](int)$service['port'](string)$service['path']);
  170.  
  171.                 $this->_writeableServices[$id$service;
  172.             }
  173.             else
  174.             {
  175.                 throw new Exception('A Writeable Service description array does not have all required elements of host, port, and path');
  176.             }
  177.         }
  178.     }
  179.  
  180.     /**
  181.      * Removes a service instance or descriptor from the available services
  182.      *
  183.      * @param mixed $service 
  184.      *
  185.      * @throws Exception If service descriptor is not valid
  186.      */
  187.     public function removeWriteService($service)
  188.     {
  189.         $id '';
  190.  
  191.         if ($service instanceof Apache_Solr_Service)
  192.         {
  193.             $id $this->_getServiceId($service->getHost()$service->getPort()$service->getPath());
  194.         }
  195.         else if (is_array($service))
  196.         {
  197.             if (isset($service['host']&& isset($service['port']&& isset($service['path']))
  198.             {
  199.                 $id $this->_getServiceId((string)$service['host'](int)$service['port'](string)$service['path']);
  200.             }
  201.             else
  202.             {
  203.                 throw new Exception('A Readable Service description array does not have all required elements of host, port, and path');
  204.             }
  205.         }
  206.  
  207.         if ($id)
  208.         {
  209.             unset($this->_writeableServices[$id]);
  210.         }
  211.     }
  212.  
  213.     /**
  214.      * Iterate through available read services and select the first with a ping
  215.      * that satisfies configured timeout restrictions (or the default)
  216.      *
  217.      * @return Apache_Solr_Service 
  218.      *
  219.      * @throws Exception If there are no read services that meet requirements
  220.      */
  221.     private function _selectReadService()
  222.     {
  223.         if (!$this->_currentReadService || !isset($this->_readableServices[$this->_currentReadService]))
  224.         {
  225.             foreach ($this->_readableServices as $id => $service)
  226.             {
  227.                 if (is_array($service))
  228.                 {
  229.                     //convert the array definition to a client object
  230.                     $service new Apache_Solr_Service($service['host']$service['port']$service['path']);
  231.                     $this->_readableServices[$id$service;
  232.                 }
  233.  
  234.                 //check the service (make sure it pings quickly)
  235.                 if ($service->ping($this->_readPingTimeout!== false)
  236.                 {
  237.                     $this->_currentReadService = $id;
  238.                     return $this->_readableServices[$this->_currentReadService];
  239.                 }
  240.             }
  241.  
  242.             throw new Exception('No read services were available');
  243.         }
  244.  
  245.         return $this->_readableServices[$this->_currentReadService];
  246.     }
  247.  
  248.     /**
  249.      * Iterate through available write services and select the first with a ping
  250.      * that satisfies configured timeout restrictions (or the default)
  251.      *
  252.      * @return Apache_Solr_Service 
  253.      *
  254.      * @throws Exception If there are no write services that meet requirements
  255.      */
  256.     private function _selectWriteService()
  257.     {
  258.         if (!$this->_currentWriteService || !isset($this->_writeableServices[$this->_currentWriteService]))
  259.         {
  260.             foreach ($this->_writeableServices as $id => $service)
  261.             {
  262.                 if (is_array($service))
  263.                 {
  264.                     //convert the array definition to a client object
  265.                     $service new Apache_Solr_Service($service['host']$service['port']$service['path']);
  266.                     $this->_writeableServices[$id$service;
  267.                 }
  268.  
  269.                 //check the service
  270.                 if ($service->ping($this->_writePingTimeout!== false)
  271.                 {
  272.                     $this->_currentWriteService = $id;
  273.                     return $this->_writeableServices[$this->_currentWriteService];
  274.                 }
  275.             }
  276.  
  277.             throw new Exception('No write services were available');
  278.         }
  279.  
  280.         return $this->_writeableServices[$this->_currentWriteService];
  281.     }
  282.  
  283.     /**
  284.      * Raw Add Method. Takes a raw post body and sends it to the update service.  Post body
  285.      * should be a complete and well formed "add" xml document.
  286.      *
  287.      * @param string $rawPost 
  288.      * @return Apache_Solr_Response 
  289.      *
  290.      * @throws Exception If an error occurs during the service call
  291.      */
  292.     public function add($rawPost)
  293.     {
  294.         $service $this->_selectWriteService();
  295.  
  296.         return $service->add($rawPost);
  297.     }
  298.  
  299.     /**
  300.      * Add a Solr Document to the index
  301.      *
  302.      * @param Apache_Solr_Document $document 
  303.      * @param boolean $allowDups 
  304.      * @param boolean $overwritePending 
  305.      * @param boolean $overwriteCommitted 
  306.      * @return Apache_Solr_Response 
  307.      *
  308.      * @throws Exception If an error occurs during the service call
  309.      */
  310.     public function addDocument(Apache_Solr_Document $document$allowDups false$overwritePending true$overwriteCommitted true)
  311.     {
  312.         $service $this->_selectWriteService();
  313.  
  314.         return $service->addDocument($document$allowDups$overwritePending$overwriteCommitted);
  315.     }
  316.  
  317.     /**
  318.      * Add an array of Solr Documents to the index all at once
  319.      *
  320.      * @param array $documents Should be an array of Apache_Solr_Document instances
  321.      * @param boolean $allowDups 
  322.      * @param boolean $overwritePending 
  323.      * @param boolean $overwriteCommitted 
  324.      * @return Apache_Solr_Response 
  325.      *
  326.      * @throws Exception If an error occurs during the service call
  327.      */
  328.     public function addDocuments($documents$allowDups false$overwritePending true$overwriteCommitted true)
  329.     {
  330.         $service $this->_selectWriteService();
  331.  
  332.         return $service->addDocuments($documents$allowDups$overwritePending$overwriteCommitted);
  333.     }
  334.  
  335.     /**
  336.      * Send a commit command.  Will be synchronous unless both wait parameters are set
  337.      * to false.
  338.      *
  339.      * @param boolean $waitFlush 
  340.      * @param boolean $waitSearcher 
  341.      * @return Apache_Solr_Response 
  342.      *
  343.      * @throws Exception If an error occurs during the service call
  344.      */
  345.     public function commit($waitFlush true$waitSearcher true)
  346.     {
  347.         $service $this->_selectWriteService();
  348.  
  349.         return $service->commit($waitFlush$waitSearcher);
  350.     }
  351.  
  352.     /**
  353.      * Raw Delete Method. Takes a raw post body and sends it to the update service. Body should be
  354.      * a complete and well formed "delete" xml document
  355.      *
  356.      * @param string $rawPost 
  357.      * @return Apache_Solr_Response 
  358.      *
  359.      * @throws Exception If an error occurs during the service call
  360.      */
  361.     public function delete($rawPost)
  362.     {
  363.         $service $this->_selectWriteService();
  364.  
  365.         return $service->delete($rawPost);
  366.     }
  367.  
  368.     /**
  369.      * Create a delete document based on document ID
  370.      *
  371.      * @param string $id 
  372.      * @param boolean $fromPending 
  373.      * @param boolean $fromCommitted 
  374.      * @return Apache_Solr_Response 
  375.      *
  376.      * @throws Exception If an error occurs during the service call
  377.      */
  378.     public function deleteById($id$fromPending true$fromCommitted true)
  379.     {
  380.         $service $this->_selectWriteService();
  381.  
  382.         return $service->deleteById($id$fromPending$fromCommitted);
  383.     }
  384.  
  385.     /**
  386.      * Create a delete document based on a query and submit it
  387.      *
  388.      * @param string $rawQuery 
  389.      * @param boolean $fromPending 
  390.      * @param boolean $fromCommitted 
  391.      * @return Apache_Solr_Response 
  392.      *
  393.      * @throws Exception If an error occurs during the service call
  394.      */
  395.     public function deleteByQuery($rawQuery$fromPending true$fromCommitted true)
  396.     {
  397.         $service $this->_selectWriteService();
  398.  
  399.         return $service->deleteByQuery($rawQuery$fromPending$fromCommitted);
  400.     }
  401.  
  402.     /**
  403.      * Send an optimize command.  Will be synchronous unless both wait parameters are set
  404.      * to false.
  405.      *
  406.      * @param boolean $waitFlush 
  407.      * @param boolean $waitSearcher 
  408.      * @return Apache_Solr_Response 
  409.      *
  410.      * @throws Exception If an error occurs during the service call
  411.      */
  412.     public function optimize($waitFlush true$waitSearcher true)
  413.     {
  414.         $service $this->_selectWriteService();
  415.  
  416.         return $service->optimize($waitFlush$waitSearcher);
  417.     }
  418.  
  419.     /**
  420.      * Simple Search interface
  421.      *
  422.      * @param string $query The raw query string
  423.      * @param int $offset The starting offset for result documents
  424.      * @param int $limit The maximum number of result documents to return
  425.      * @param array $params key / value pairs for query parameters, use arrays for multivalued parameters
  426.      * @return Apache_Solr_Response 
  427.      *
  428.      * @throws Exception If an error occurs during the service call
  429.      */
  430.     public function search($query$offset 0$limit 10$params array())
  431.     {
  432.         $service $this->_selectReadService();
  433.  
  434.         return $service->search($query$offset$limit$params);
  435.     }
  436. }

Documentation generated on Tue, 02 Oct 2007 12:55:37 -0400 by phpDocumentor 1.4.0