Index: CHANGELOG.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/apachesolr/CHANGELOG.txt,v
retrieving revision 1.1.2.112.2.41
diff -u -p -r1.1.2.112.2.41 CHANGELOG.txt
--- CHANGELOG.txt 22 Jan 2010 19:30:11 -0000 1.1.2.112.2.41
+++ CHANGELOG.txt 27 Jan 2010 11:34:44 -0000
@@ -5,6 +5,7 @@ Apache Solr Search Integration x.x-x.x,
Apache Solr Search Integration 5.x-2.x, 2010-xx-xx
------------------------------
+#267831 by claudiu.cristea: Load balancer implementation.
Apache Solr Search Integration 5.x-2.0-rc2, 2010-01-22
------------------------------
Index: Drupal_Apache_Solr_Service.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/apachesolr/Drupal_Apache_Solr_Service.php,v
retrieving revision 1.1.2.20.4.7
diff -u -p -r1.1.2.20.4.7 Drupal_Apache_Solr_Service.php
--- Drupal_Apache_Solr_Service.php 22 Jan 2010 17:26:38 -0000 1.1.2.20.4.7
+++ Drupal_Apache_Solr_Service.php 27 Jan 2010 11:34:44 -0000
@@ -33,7 +33,8 @@ class Drupal_Apache_Solr_Service extends
* @return
* (float) seconds taken to ping the server, FALSE if timeout occurs.
*/
- public function ping($timeout = 2) {
+ public function ping() {
+ $timeout = func_get_arg(0);
$start = microtime(TRUE);
if ($timeout <= 0.0) {
Index: Drupal_Apache_Solr_Service_Balancer.php
===================================================================
RCS file: Drupal_Apache_Solr_Service_Balancer.php
diff -N Drupal_Apache_Solr_Service_Balancer.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Drupal_Apache_Solr_Service_Balancer.php 27 Jan 2010 11:34:44 -0000
@@ -0,0 +1,107 @@
+_selectWriteService();
+
+ do {
+ try {
+ return $service->getStatsSummary();
+ }
+ catch (Exception $e) {
+ if ($e->getCode() != 0) { //IF NOT COMMUNICATION ERROR
+ throw $e;
+ }
+ }
+ $service = $this->_selectWriteService(TRUE);
+ } while ($service);
+
+ return FALSE;
+ }
+
+ /**
+ * Clear cached Solr data.
+ */
+ public function clearCache() {
+ foreach ($this->_readableServices as $service) {
+ @$service->clearCache;
+ }
+ foreach ($this->_writableServices as $service) {
+ @$service->clearCache;
+ }
+ }
+
+ /**
+ * Get meta-data about the index.
+ */
+ public function getLuke($num_terms = 0) {
+ $service = $this->_selectWriteService();
+
+ do {
+ try {
+ return $service->getLuke($num_terms);
+ }
+ catch (Exception $e) {
+ if ($e->getCode() != 0) { //IF NOT COMMUNICATION ERROR
+ throw $e;
+ }
+ }
+ $service = $this->_selectWriteService(TRUE);
+ } while ($service);
+
+ return FALSE;
+ }
+ /**
+ * Get just the field meta-data about the index.
+ */
+ public function getFields($num_terms = 0) {
+ return $this->getLuke($num_terms)->fields;
+ }
+
+ /**
+ * For some reasons this was not implemented in Balancer.
+ */
+ public function deleteByMultipleIds($ids, $fromPending = true, $fromCommitted = true, $timeout = 3600) {
+ $service = $this->_selectWriteService();
+
+ do {
+ try {
+ return $service->deleteByMultipleIds($ids, $fromPending = true, $fromCommitted = true, $timeout = 3600);
+ }
+ catch (Exception $e) {
+ if ($e->getCode() != 0) { //IF NOT COMMUNICATION ERROR
+ throw $e;
+ }
+ }
+ $service = $this->_selectWriteService(TRUE);
+ } while ($service);
+
+ return FALSE;
+ }
+
+ /**
+ * Check if an index or query server is vailable.
+ */
+ public function ping($timeout = 2, $service_type) {
+ $service = $service_type == 'index' ? $this->_selectWriteService() : $this->_selectReadService();
+
+ do {
+ try {
+ return $service->ping($timeout);
+ }
+ catch (Exception $e) {
+ if ($e->getCode() != 0) { //IF NOT COMMUNICATION ERROR
+ throw $e;
+ }
+ }
+ $service = $service_type == 'index' ? $this->_selectWriteService(TRUE) : $this->_selectReadService(TRUE);
+ } while ($service);
+
+ return FALSE;
+ }
+}
Index: apachesolr.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/apachesolr/apachesolr.admin.inc,v
retrieving revision 1.1.2.32.2.16
diff -u -p -r1.1.2.32.2.16 apachesolr.admin.inc
--- apachesolr.admin.inc 22 Jan 2010 17:26:39 -0000 1.1.2.32.2.16
+++ apachesolr.admin.inc 27 Jan 2010 11:34:44 -0000
@@ -22,27 +22,6 @@ function apachesolr_settings() {
}
}
- $form['apachesolr_host'] = array(
- '#type' => 'textfield',
- '#title' => t('Solr host name'),
- '#default_value' => variable_get('apachesolr_host', 'localhost'),
- '#description' => t('Host name of your Solr server, e.g. localhost
or example.com
.'),
- '#required' => TRUE,
- );
- $form['apachesolr_port'] = array(
- '#type' => 'textfield',
- '#title' => t('Solr port'),
- '#default_value' => variable_get('apachesolr_port', '8983'),
- '#description' => t('Port on which the Solr server listens. The Jetty example server is 8983, while Tomcat is 8080 by default.'),
- '#required' => TRUE,
- );
- $form['apachesolr_path'] = array(
- '#type' => 'textfield',
- '#title' => t('Solr path'),
- '#default_value' => variable_get('apachesolr_path', '/solr'),
- '#description' => t('Path that identifies the Solr request handler to be used.'),
- );
-
$numbers = drupal_map_assoc(array(1, 5, 10, 20, 50, 100, 200));
$form['apachesolr_cron_limit'] = array(
'#type' => 'select',
@@ -92,6 +71,239 @@ function apachesolr_settings() {
}
/**
+ * Callback for configuring Solr servers.
+ */
+function apachesolr_settings_servers($server_id = NULL, $delete = NULL) {
+ $output = '';
+ $servers = variable_get('apachesolr_servers', array());
+ if ($delete == 'delete' && isset($servers[$server_id])) {
+ return drupal_get_form('apachesolr_settings_servers_delete', $server_id);
+ }
+ if (count($servers)) {
+ $server_id = is_null($server_id) ? 'add' : $server_id;
+ $header = array('#', t('Server name'), t('Host name'), t('Port'), t('Path'), t('Query server'), t('Index server'), t('Status'), array('data' => t('Operations'), 'colspan' => 2));
+ $rows = array();
+ foreach ($servers as $delta => $server) {
+ $ping = FALSE;
+ try {
+ $solr = apachesolr_get_server($server['host'], $server['port'], $server['path']);
+ $ping = @$solr->ping(variable_get('apachesolr_ping_timeout', 4));
+ // If there is no $solr object, there is no server available, so don't continue.
+ if (!$ping) {
+ throw new Exception(t('No Solr instance available for !host:!port/!path', array('!host' => $server['host'], '!port' => $server['port'], '!path' => ltrim($server['path'], '/'))));
+ }
+ }
+ catch (Exception $e) {
+ watchdog('Apache Solr', nl2br(check_plain($e->getMessage())), WATCHDOG_ERROR);
+ }
+
+ $row = array($delta, $server['name'], $server['host'], $server['port'], $server['path'], $server['query'] ? t('Yes') : t('No'), $server['index'] ? t('Yes') : t('No'), $ping ? t('Successfully contacted') : t('Cannot be contacted!'), l(t('modify'), 'admin/settings/apachesolr/servers/'. $delta), l(t('delete'), 'admin/settings/apachesolr/servers/'. $delta .'/delete'));
+ if ($server_id == (string)$delta) {
+ $rows[] = array(
+ 'data' => $row,
+ 'class' => 'apachesolr-servers-active-server',
+ );
+ }
+ else {
+ $rows[] = $row;
+ }
+ }
+ $element = array(
+ '#type' => 'fieldset',
+ '#title' => t('Solr servers currentlly configured on this site'),
+ '#collapsible' => TRUE,
+ '#collpased' => FALSE,
+ '#value' => theme('table', $header, $rows) . ($server_id != 'add' ? '
'. print_r(array($server), TRUE) .''); + + // @todo: Delete old variables + // variable_del('apachesolr_host'); + // variable_del('apachesolr_port'); + // variable_del('apachesolr_path'); + // $ret[] = array('success' => TRUE, 'query' => 'Drupal variables: "apachesolr_host", "apachesolr_port", "apachesolr_path" were deleted.'); + + return $ret; +} Index: apachesolr.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/apachesolr/apachesolr.module,v retrieving revision 1.1.2.12.2.161.2.18 diff -u -p -r1.1.2.12.2.161.2.18 apachesolr.module --- apachesolr.module 22 Jan 2010 19:06:56 -0000 1.1.2.12.2.161.2.18 +++ apachesolr.module 27 Jan 2010 11:34:44 -0000 @@ -34,6 +34,14 @@ function apachesolr_menu($may_cache) { 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items[] = array( + 'path' => 'admin/settings/apachesolr/servers', + 'title' => t('Solr Servers'), + 'callback' => 'apachesolr_settings_servers', + 'weight' => -9, + 'access' => user_access('administer search'), + 'type' => MENU_LOCAL_TASK, + ); + $items[] = array( 'path' => 'admin/settings/apachesolr/enabled-filters', 'title' => t('Enabled filters'), 'callback' => 'drupal_get_form', @@ -338,7 +346,7 @@ function apachesolr_index_nodes($rows, $ // Get the $solr object $solr = apachesolr_get_solr(); // If there is no server available, don't continue. - if (!$solr->ping(variable_get('apachesolr_ping_timeout', 4))) { + if (!$solr->ping(variable_get('apachesolr_ping_timeout', 4), 'index')) { throw new Exception(t('No Solr instance available during indexing.')); } } @@ -1120,24 +1128,56 @@ function apachesolr_has_searched($search } /** - * Factory method for solr singleton object. Structure allows for an arbitrary - * number of solr objects to be used based on the host, port, path combination. - * Get an instance like this: - * $solr = apachesolr_get_solr(); + * Method used to obtain the Solr load balancer object */ -function apachesolr_get_solr($host = NULL, $port = NULL, $path = NULL) { - static $solr_cache; - - if (empty($host)) { - $host = variable_get('apachesolr_host', 'localhost'); - } - if (empty($port)) { - $port = variable_get('apachesolr_port', '8983'); - } - if (empty($path)) { - $path = variable_get('apachesolr_path', '/solr'); +function apachesolr_get_solr() { + static $solr; + $servers = variable_get('apachesolr_servers', array()); + if (!isset($solr)) { + // We use only one Solr server (this may be the main usage of this module) + // Do not load the entire Balancer API use only a single Solr object. + if (count($servers) == 1) { + $solr = apachesolr_get_server($servers[0]['host'], $servers[0]['port'], $servers[0]['path']); + } + // More than one Solr servers are configured on the site so prepare the Solr + // object as a Balancer object. + else { + $query_services = $index_services = array(); + foreach ($servers as $delta => $server) { + + $service = ($server['query'] || $server['index']) ? apachesolr_get_server($server['host'], $server['port'], $server['path']) : FALSE; + + // Collect query services (AKA readable services). + if ($server['query'] && $service) { + $query_services[] = $service; + } + + // Collect index services (AKA writable services). + if ($server['index'] && $service) { + $index_services[] = $service; + } + } + + include_once(drupal_get_path('module', 'apachesolr') .'/Drupal_Apache_Solr_Service_Balancer.php'); + try { + $solr = new Drupal_Apache_Solr_Service_Balancer($query_services, $index_services); + } + catch (Exception $e) { + watchdog('Apache Solr', nl2br(check_plain($e->getMessage())), WATCHDOG_ERROR); + return; + } + } } + return $solr; +} + +/** + * Method used to obtain a single Solr object. A clone of old apachesolr_get_solr() function but arguments are mandatory. + */ +function apachesolr_get_server($host, $port, $path) { + static $solr_cache; + if (empty($solr_cache[$host][$port][$path])) { list($module, $filepath, $class) = variable_get('apachesolr_service_class', array('apachesolr', 'Drupal_Apache_Solr_Service.php', 'Drupal_Apache_Solr_Service')); include_once(drupal_get_path('module', $module) .'/'. $filepath);