You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-commits@lucene.apache.org by ma...@apache.org on 2010/01/01 01:17:33 UTC
svn commit: r894959 [1/2] - in /lucene/solr/branches/cloud/src:
java/org/apache/solr/cloud/ java/org/apache/solr/core/
java/org/apache/solr/handler/ java/org/apache/solr/handler/component/
java/org/apache/solr/util/ java/org/apache/solr/util/zookeeper/...
Author: markrmiller
Date: Fri Jan 1 00:17:31 2010
New Revision: 894959
URL: http://svn.apache.org/viewvc?rev=894959&view=rev
Log:
various pushes forward
Added:
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CollectionInfo.java
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CountdownWatcher.java
- copied, changed from r892824, lucene/solr/branches/cloud/src/java/org/apache/solr/util/zookeeper/CountdownWatcher.java
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ReconnectionHandler.java
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfo.java
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfoList.java
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperController.java
- copied, changed from r892824, lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperReader.java
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperSolrResourceLoader.java
- copied, changed from r892824, lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZKSolrResourceLoader.java
lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperWriter.java
lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/
lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/AbstractDistributedZooKeeperTestCase.java
- copied, changed from r892824, lucene/solr/branches/cloud/src/test/org/apache/solr/AbstractDistributedZooKeeperTestCase.java
lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/AbstractZooKeeperTestCase.java
- copied, changed from r892824, lucene/solr/branches/cloud/src/test/org/apache/solr/AbstractZooKeeperTestCase.java
lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/BasicDistributedZooKeeperTest.java
- copied, changed from r892824, lucene/solr/branches/cloud/src/test/org/apache/solr/BasicDistributedZooKeeperTest.java
lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/BasicZooKeeperTest.java
- copied, changed from r892824, lucene/solr/branches/cloud/src/test/org/apache/solr/BasicZooKeeperTest.java
lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/DistributedZooKeeperFailuresTest.java
lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/TestShardInfoList.java
lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/ZooKeeperReaderTest.java
lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/ZooKeeperTestServer.java
lucene/solr/branches/cloud/src/test/test-files/solr/solr.lowZkTimeout.xml
Removed:
lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZKSolrResourceLoader.java
lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java
lucene/solr/branches/cloud/src/java/org/apache/solr/util/ZooPut.java
lucene/solr/branches/cloud/src/java/org/apache/solr/util/zookeeper/
lucene/solr/branches/cloud/src/test/org/apache/solr/AbstractDistributedZooKeeperTestCase.java
lucene/solr/branches/cloud/src/test/org/apache/solr/AbstractZooKeeperTestCase.java
lucene/solr/branches/cloud/src/test/org/apache/solr/BasicDistributedZooKeeperTest.java
lucene/solr/branches/cloud/src/test/org/apache/solr/BasicZooKeeperTest.java
Modified:
lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java
lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreDescriptor.java
lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrConfig.java
lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java
lucene/solr/branches/cloud/src/java/org/apache/solr/handler/ReplicationHandler.java
lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java
lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryElevationComponent.java
lucene/solr/branches/cloud/src/java/org/apache/solr/util/AbstractSolrTestCase.java
lucene/solr/branches/cloud/src/test/org/apache/solr/BaseDistributedSearchTestCase.java
lucene/solr/branches/cloud/src/test/org/apache/solr/servlet/NoCacheHeaderTest.java
lucene/solr/branches/cloud/src/test/test-files/solr/solr.xml
lucene/solr/branches/cloud/src/webapp/src/org/apache/solr/client/solrj/embedded/JettySolrRunner.java
lucene/solr/branches/cloud/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java
Added: lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CollectionInfo.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CollectionInfo.java?rev=894959&view=auto
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CollectionInfo.java (added)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CollectionInfo.java Fri Jan 1 00:17:31 2010
@@ -0,0 +1,65 @@
+package org.apache.solr.cloud;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Information about the Collection.
+ *
+ */
+public final class CollectionInfo {
+
+ // maps shard name to the shard addresses and roles
+ private final Map<String,ShardInfoList> shardNameToShardInfoList;
+ private final long updateTime;
+
+ public CollectionInfo(Map<String,ShardInfoList> shardNameToShardInfoList) {
+ //nocommit: defensive copy?
+ this.shardNameToShardInfoList = shardNameToShardInfoList;
+ this.updateTime = System.currentTimeMillis();
+ }
+
+ /**
+ * //nocommit
+ *
+ * @return
+ */
+ public List<String> getSearchShards() {
+ List<String> nodeList = new ArrayList<String>();
+ for (ShardInfoList nodes : shardNameToShardInfoList.values()) {
+ nodeList.add(nodes.getShardUrl());
+ }
+ return nodeList;
+ }
+
+ public ShardInfoList getShardInfoList(String shardName) {
+ return shardNameToShardInfoList.get(shardName);
+ }
+
+
+ /**
+ * @return last time info was updated.
+ */
+ public long getUpdateTime() {
+ return updateTime;
+ }
+
+}
Copied: lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CountdownWatcher.java (from r892824, lucene/solr/branches/cloud/src/java/org/apache/solr/util/zookeeper/CountdownWatcher.java)
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CountdownWatcher.java?p2=lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CountdownWatcher.java&p1=lucene/solr/branches/cloud/src/java/org/apache/solr/util/zookeeper/CountdownWatcher.java&r1=892824&r2=894959&rev=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/util/zookeeper/CountdownWatcher.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/CountdownWatcher.java Fri Jan 1 00:17:31 2010
@@ -16,8 +16,9 @@
* limitations under the License.
*/
-package org.apache.solr.util.zookeeper;
+package org.apache.solr.cloud;
+import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeoutException;
@@ -28,7 +29,7 @@
import org.slf4j.LoggerFactory;
public class CountdownWatcher implements Watcher {
- protected static final Logger LOG = LoggerFactory
+ protected static final Logger log = LoggerFactory
.getLogger(CountdownWatcher.class);
private final String name;
@@ -39,8 +40,14 @@
private boolean connected;
- public CountdownWatcher(String name) {
+ private ReconnectionHandler reconnectionHandler;
+
+ //private ZooKeeper keeper;
+
+ public CountdownWatcher(String name, ReconnectionHandler handler) {
+ //this.keeper = keeper;
this.name = name;
+ this.reconnectionHandler = handler;
reset();
}
@@ -51,12 +58,28 @@
}
public synchronized void process(WatchedEvent event) {
- LOG.info("Watcher " + name + " got event " + event);
+ if(log.isInfoEnabled()) {
+ log.info("Watcher " + name + " got event " + event);
+ }
state = event.getState();
if (state == KeeperState.SyncConnected) {
connected = true;
clientConnected.countDown();
+ } else if(state == KeeperState.Expired) {
+ connected = false;
+ try {
+ reconnectionHandler.handleReconnect();
+ } catch (Exception e) {
+ // nocommit
+ System.out.println("connection failed:");
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ // nocommit: start reconnect attempts
+ } else if(state == KeeperState.Disconnected) {
+ connected = false;
+ // nocommit: start reconnect attempts
} else {
connected = false;
}
@@ -81,7 +104,6 @@
}
if (!connected) {
throw new TimeoutException("Did not connect");
-
}
}
@@ -95,7 +117,6 @@
}
if (connected) {
throw new TimeoutException("Did not disconnect");
-
}
}
}
Added: lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ReconnectionHandler.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ReconnectionHandler.java?rev=894959&view=auto
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ReconnectionHandler.java (added)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ReconnectionHandler.java Fri Jan 1 00:17:31 2010
@@ -0,0 +1,24 @@
+package org.apache.solr.cloud;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+import java.io.IOException;
+
+public abstract class ReconnectionHandler {
+ public abstract boolean handleReconnect() throws IOException;
+}
Added: lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfo.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfo.java?rev=894959&view=auto
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfo.java (added)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfo.java Fri Jan 1 00:17:31 2010
@@ -0,0 +1,47 @@
+package org.apache.solr.cloud;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/**
+ * Information about a Shard.
+ *
+ */
+public final class ShardInfo {
+
+ private final String url;
+ //nocommit do role based on existing ReplicationHandler role detection?
+ private final Role role;
+
+ public ShardInfo(String url) {
+ this.url = url;
+ role = Role.SLAVE;
+ }
+
+ public ShardInfo(String url, Role role) {
+ this.url = url;
+ this.role = role;
+ }
+
+ public Role getRole() {
+ return role;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+}
Added: lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfoList.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfoList.java?rev=894959&view=auto
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfoList.java (added)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ShardInfoList.java Fri Jan 1 00:17:31 2010
@@ -0,0 +1,69 @@
+package org.apache.solr.cloud;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * List of Shards (URL + Role)
+ *
+ */
+public final class ShardInfoList {
+
+ private final List<ShardInfo> shards;
+
+ public ShardInfoList(List<ShardInfo> shards) {
+ //nocommit: defensive copy?
+ this.shards = shards;
+ }
+
+ public List<ShardInfo> getShards() {
+ return Collections.unmodifiableList(shards);
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ ShardInfo shardInfo;
+ int sz = shards.size();
+ for(int i = 0; i < sz; i++) {
+ shardInfo = shards.get(i);
+ sb.append(shardInfo.getUrl() + ", " + shardInfo.getRole());
+ if(i != sz-1) {
+ sb.append(" : ");
+ }
+ }
+ return sb.toString();
+ }
+
+ // nocommit: return one URL from list of shards
+ public String getShardUrl() {
+ // nocommit
+ for (ShardInfo shard : shards) {
+ System.out.println("getNode:" + shard.getUrl());
+ if (shard.getRole() != Role.MASTER) {
+ return shard.getUrl();
+ }
+ }
+ throw new IllegalStateException("No slaves for shard");
+ }
+}
+
+enum Role {
+ MASTER, SLAVE
+}
Copied: lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperController.java (from r892824, lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java)
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperController.java?p2=lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperController.java&p1=lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java&r1=892824&r2=894959&rev=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZooKeeperController.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperController.java Fri Jan 1 00:17:31 2010
@@ -1,196 +1,419 @@
-package org.apache.solr.core;
+package org.apache.solr.cloud;
-import java.io.ByteArrayInputStream;
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.util.List;
+import java.util.Map;
+import java.util.Properties;
import java.util.concurrent.TimeoutException;
-
-import javax.xml.parsers.ParserConfigurationException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.apache.solr.common.SolrException;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.util.ZooPut;
-import org.apache.solr.util.zookeeper.CountdownWatcher;
+import org.apache.solr.core.SolrCore;
+import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
/**
* Handle ZooKeeper interactions.
+ *
+ * notes: loads everything on init, creates what's not there - further updates
+ * are prompted with Watches.
+ *
+ * TODO: handle ZooKeeper goes down / failures, Solr still runs
*/
-public class ZooKeeperController {
- private static final String CONFIGS_NODE = "configs";
+public final class ZooKeeperController {
+ private static final String COLLECTIONS_ZKNODE = "/collections/";
+
+ static final String NODE_ZKPREFIX = "/node";
+
+ private static final String SHARDS_ZKNODE = "/shards";
+
+ static final String PROPS_DESC = "NodeDesc";
+
+ static final String SHARD_LIST_PROP = "shard_list";
+
+ static final String URL_PROP = "url";
+
+ // nocommit - explore handling shard changes
+ // watches the shards zkNode
+ static class ShardsWatcher implements Watcher {
+
+ private ZooKeeperController controller;
+
+ public ShardsWatcher(ZooKeeperController controller) {
+ this.controller = controller;
+ }
+
+ public void process(WatchedEvent event) {
+ // nocommit : this will be called too often as shards register themselves
+ System.out.println("shards changed");
+
+ try {
+ // refresh watcher
+ controller.getKeeper().exists(event.getPath(), this);
+
+ // TODO: need to load whole state?
+ controller.loadCollectionInfo();
+
+ } catch (KeeperException e) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+ "ZooKeeper Exception", e);
+ } catch (InterruptedException e) {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+ }
+
+ }
+
+ }
+
+ final ShardsWatcher SHARD_WATCHER = new ShardsWatcher(this);
+
+ private final static Pattern URL_POST = Pattern.compile("https?://(.*)");
+
+ private final static Pattern URL_PREFIX = Pattern.compile("(https?://).*");
+
+ private final ReconnectionHandler RECONNECTION_HANDLER = new ReconnectionHandler() {
+
+ @Override
+ public boolean handleReconnect() throws IOException {
+ // nocommit : reconnection experimentation
+ log.info("Attempting to reconnect to ZooKeeper...");
+ boolean connected = true;
+ CountdownWatcher countdownWatcher = new CountdownWatcher(
+ "ZooKeeperController", RECONNECTION_HANDLER);
+ // nocommit : close old ZooKeeper client?
+ keeper = new ZooKeeper(zooKeeperHost, zkClientTimeout, countdownWatcher);
+ try {
+ countdownWatcher.waitForConnected(5000);
+ } catch (InterruptedException e) {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+ connected = false;
+ } catch (TimeoutException e) {
+ connected = false;
+ }
+ log.info("Connected:" + connected);
+ return connected;
+ }
+ };
private static Logger log = LoggerFactory
.getLogger(ZooKeeperController.class);
- private ZooKeeper keeper;
+ // nocommit : consider reconnects more closely
+ private volatile ZooKeeper keeper;
- private String configName;
+ ZooKeeper getKeeper() {
+ return keeper;
+ }
+
+ private ZooKeeperReader zkReader;
private String collectionName;
- private String shardAddress;
+ private volatile CollectionInfo collectionInfo;
+
+ private String shardsZkPath;
+
+ private ZooKeeperWriter zkWriter;
+
+ private String zooKeeperHost;
+
+
+ private String hostPort;
+
+ private String hostContext;
+
+ private String configName;
+
+ private int zkClientTimeout;
+
+ private String zooKeeperHostName;
+
/**
- * @param zookeeperHost ZooKeeper host service
- * @param shardAddress
+ *
+ * @param zooKeeperHost ZooKeeper host address
+ * @param collection
+ * @param hostUrl
+ * @param hostPort
+ * @param hostContext
* @param zkClientTimeout
- * @param zkSolrPathPrefix Solr ZooKeeper node (default is /solr)
*/
- public ZooKeeperController(String zookeeperHost, String collection,
- String shardAddress, int zkClientTimeout) {
+ public ZooKeeperController(String zooKeeperHost, String collection,
+ String hostUrl, String hostPort, String hostContext, int zkClientTimeout) {
+
this.collectionName = collection;
- this.shardAddress = shardAddress;
- CountdownWatcher countdownWatcher = new CountdownWatcher(
- "ZooKeeperController");
- System.out.println("timeout:" + zkClientTimeout);
+ this.zooKeeperHost = zooKeeperHost;
+ this.hostPort = hostPort;
+ this.hostContext = hostContext;
+ this.zkClientTimeout = zkClientTimeout;
+
+ shardsZkPath = COLLECTIONS_ZKNODE + collectionName + SHARDS_ZKNODE;
+
+ init();
+ }
+
+ private void init() {
+
try {
- keeper = new ZooKeeper(zookeeperHost, zkClientTimeout, countdownWatcher);
+ CountdownWatcher countdownWatcher = new CountdownWatcher(
+ "ZooKeeperController", RECONNECTION_HANDLER);
+ keeper = new ZooKeeper(zooKeeperHost, zkClientTimeout, countdownWatcher);
countdownWatcher.waitForConnected(5000);
- loadConfigPath();
- register();
+ zkReader = new ZooKeeperReader(keeper);
+ zkWriter = new ZooKeeperWriter(keeper);
+
+ configName = zkReader.readConfigName(collectionName);
+
+ zooKeeperHostName = getHostAddress();
+ Matcher m = URL_POST.matcher(zooKeeperHostName);
+ if (m.matches()) {
+ String hostName = m.group(1);
+
+ // register host
+ zkWriter.makePath(hostName);
+ } else {
+ // nocommit
+ throw new IllegalStateException("Bad host:" + zooKeeperHostName);
+ }
+
+ // build layout if not exists
+ buildZkLayoutZkNodes();
+
+ // load the state of the cloud
+ loadCollectionInfo();
+
} catch (IOException e) {
+ log.error("", e);
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
- "Can't create ZooKeeper instance", e);
+ "Can't create ZooKeeperController", e);
} catch (InterruptedException e) {
- // nocommit
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
} catch (TimeoutException e) {
+ log.error("", e);
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
- "Can't create ZooKeeper instance", e);
+ "Timeout waiting for ZooKeeper connection", e);
+ } catch (KeeperException e) {
+ log.error("KeeperException", e);
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "", e);
}
}
+
+ public boolean configFileExists(String fileName) throws KeeperException, InterruptedException {
+ return zkReader.configFileExists(configName, fileName);
+ }
- // nocommit: fooling around
- private void register() throws IOException {
+ /**
+ * nocommit: adds nodes if they don't exist, eg /shards/ node. consider race
+ * conditions
+ */
+ private void buildZkLayoutZkNodes() throws IOException {
try {
- if (shardAddress == null) {
- shardAddress = InetAddress.getLocalHost().getHostName();
+ // shards node
+ if (!zkReader.exists(shardsZkPath)) {
+ if (log.isInfoEnabled()) {
+ log.info("creating zk shards node:" + shardsZkPath);
+ }
+ // makes shards zkNode if it doesn't exist
+ zkWriter.makePath(shardsZkPath, CreateMode.PERSISTENT, SHARD_WATCHER);
}
- ZooPut zooPut = new ZooPut(keeper);
- zooPut.makePath("/hosts/" + shardAddress);
- } catch (UnknownHostException e) {
- throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
- "Could not determine IP of host", e);
} catch (KeeperException e) {
- throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
- "ZooKeeper Exception", e);
+ // its okay if another beats us creating the node
+ if (e.code() != KeeperException.Code.NODEEXISTS) {
+ log.error("ZooKeeper Exception", e);
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+ "ZooKeeper Exception", e);
+ }
} catch (InterruptedException e) {
- // nocommit: handle
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
}
}
- private void loadConfigPath() {
- // nocommit: load all config at once or organize differently
+ /**
+ * Closes the underlying ZooKeeper client.
+ */
+ public void close() {
try {
- String path = "/collections/" + collectionName;
- // nocommit
- System.out.println("look for collection config:" + path);
- List<String> children = keeper.getChildren(path, null);
- for (String node : children) {
- // nocommit
- System.out.println("check child:" + node);
- // nocommit: do we actually want to handle settings in the node name?
- if (node.startsWith("config=")) {
- configName = node.substring(node.indexOf("=") + 1);
- // nocommit
- System.out.println("config:" + configName);
- }
- }
- } catch (KeeperException e) {
- throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
- "ZooKeeper Exception", e);
+ keeper.close();
} catch (InterruptedException e) {
- // nocommit
- }
- if (configName == null) {
- throw new IllegalStateException("no config specified for collection:"
- + collectionName);
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
}
}
/**
- * Load IndexSchema from ZooKeeper.
- *
- * @param resourceLoader
- * @param schemaName
- * @param config
- * @return
+ * @return information about the current collection from ZooKeeper
*/
- public IndexSchema getSchema(String schemaName, SolrConfig config,
- SolrResourceLoader resourceLoader) {
- byte[] configBytes = getFile("/" + CONFIGS_NODE + "/" + configName,
- schemaName);
- InputStream is = new ByteArrayInputStream(configBytes);
- IndexSchema schema = new IndexSchema(config, schemaName, is);
- return schema;
+ public CollectionInfo getCollectionInfo() {
+ return collectionInfo;
}
/**
- * Load SolrConfig from ZooKeeper.
- *
- * @param resourceLoader
- * @param solrConfigName
- * @return
- * @throws IOException
- * @throws ParserConfigurationException
- * @throws SAXException
- */
- public SolrConfig getConfig(String solrConfigName,
- SolrResourceLoader resourceLoader) throws IOException,
- ParserConfigurationException, SAXException {
- byte[] config = getFile("/" + CONFIGS_NODE + "/" + configName,
- solrConfigName);
- InputStream is = new ByteArrayInputStream(config);
- SolrConfig cfg = solrConfigName == null ? new SolrConfig(resourceLoader,
- SolrConfig.DEFAULT_CONF_FILE, is) : new SolrConfig(resourceLoader,
- solrConfigName, is);
+ * @return an object that encapsulates most of the ZooKeeper read util operations.
+ */
+ public ZooKeeperReader getZkReader() {
+ return zkReader;
+ }
- return cfg;
+ /**
+ * @return an object that encapsulates most of the ZooKeeper write util operations.
+ */
+ public ZooKeeperWriter getZkWriter() {
+ return zkWriter;
}
+
- public boolean exists(String path) {
- Object exists = null;
+ /**
+ * @return
+ */
+ public String getZooKeeperHost() {
+ return zooKeeperHost;
+ }
+
+ // load and publish a new CollectionInfo
+ private void loadCollectionInfo() {
+ // build immutable CollectionInfo
+ boolean updateCollectionInfo = false;
+ Map<String,ShardInfoList> shardNameToShardList = null;
try {
- exists = keeper.exists(path, null);
+ shardNameToShardList = zkReader.readShardInfo(shardsZkPath);
+ updateCollectionInfo = true;
} catch (KeeperException e) {
- throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
- "ZooKeeper Exception", e);
+ // nocommit: its okay if we cannot access ZK - just log
+ // and continue
+ log.error("", e);
+ } catch (IOException e) {
+ log.error("", e);
} catch (InterruptedException e) {
- // nocommit: handle
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
}
- return exists != null;
+
+ if(updateCollectionInfo) {
+ CollectionInfo collectionInfo = new CollectionInfo(shardNameToShardList);
+ // update volatile
+ this.collectionInfo = collectionInfo;
+ }
+ }
+
+ /**
+ * @return name of configuration zkNode to use
+ */
+ public String getConfigName() {
+ return configName;
}
- public byte[] getFile(String path, String file) {
- byte[] bytes = null;
- String configPath = path + "/" + file;
+ // nocommit - testing
+ public String getSearchNodes() {
+ StringBuilder nodeString = new StringBuilder();
+ boolean first = true;
+ List<String> nodes;
+
+ nodes = collectionInfo.getSearchShards();
+ // nocommit
+ System.out.println("there are " + nodes.size() + " node(s)");
+ for (String node : nodes) {
+ nodeString.append(node);
+ if (first) {
+ first = false;
+ } else {
+ nodeString.append(',');
+ }
+ }
+ return nodeString.toString();
+ }
+
+ /**
+ * Register shard. A SolrCore calls this on startup to register with
+ * ZooKeeper.
+ *
+ * @param core
+ */
+ public void registerShard(SolrCore core) {
+ String coreName = core.getCoreDescriptor().getName();
+ String shardUrl = zooKeeperHost + ":" + hostPort + "/" + hostContext + "/"
+ + coreName;
+
+ // nocommit:
+ if (log.isInfoEnabled()) {
+ log.info("Register shard - core:" + core.getName() + " address:"
+ + shardUrl);
+ }
+
try {
- log.info("Reading " + file + " from zookeeper at " + configPath);
- bytes = keeper.getData(configPath, false, null);
- } catch (KeeperException e) {
+ // create node
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ // nocommit: could do xml
+ Properties props = new Properties();
+ props.put(URL_PROP, shardUrl);
+
+ String shardList = core.getCoreDescriptor().getShardList();
+
+ props.put(SHARD_LIST_PROP, shardList == null ? "" : shardList);
+ props.store(baos, PROPS_DESC);
+
+ zkWriter.makeEphemeralSeqPath(shardsZkPath + NODE_ZKPREFIX, baos
+ .toByteArray(), SHARD_WATCHER);
+
+ } catch (InterruptedException e) {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+ } catch (Exception e) {
+ log.error("ZooKeeper Exception", e);
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"ZooKeeper Exception", e);
- } catch (InterruptedException e) {
- // nocommit: handle
}
- return bytes;
}
- public void close() {
- try {
- keeper.close();
- } catch (InterruptedException e) {
- // nocommit: handle
+ // nocommit: fooling around
+ private String getHostAddress() throws IOException {
+ String host = null;
+
+ if (host == null) {
+ host = "http://" + InetAddress.getLocalHost().getHostName();
+ } else {
+ Matcher m = URL_PREFIX.matcher(host);
+ if (m.matches()) {
+ String prefix = m.group(1);
+ host = prefix + host;
+ }
+ }
+ if (log.isInfoEnabled()) {
+ log.info("Register host with ZooKeeper:" + host);
}
+
+ return host;
}
}
Added: lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperReader.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperReader.java?rev=894959&view=auto
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperReader.java (added)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperReader.java Fri Jan 1 00:17:31 2010
@@ -0,0 +1,351 @@
+package org.apache.solr.cloud;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.TimeoutException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.core.SolrConfig;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.Stat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ */
+public class ZooKeeperReader {
+ static final String NEWL = System.getProperty("line.separator");
+
+ private static Logger log = LoggerFactory.getLogger(ZooKeeperReader.class);
+
+ private static final String SHARD_LIST_PROP = "shard_list";
+
+ private static final String URL_PROP = "url";
+
+ private static final String CONFIGS_ZKNODE = "/configs/";
+
+ private static final String COLLECTIONS_ZKNODE = "/collections/";
+
+ private ZooKeeper keeper;
+
+ private boolean closeKeeper;
+
+ /**
+ * @param zooKeeper
+ */
+ ZooKeeperReader(ZooKeeper zooKeeper) {
+ this.keeper = zooKeeper;
+ // this.configName = readConfigName(collection);
+ }
+
+ /**
+ *
+ * For testing. For regular use see {@link #ZooKeeperReader(ZooKeeper)}.
+ *
+ * @param zooKeeperHost
+ * @param zkClientTimeout
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws TimeoutException
+ */
+ ZooKeeperReader(String zooKeeperHost, int zkClientTimeout)
+ throws IOException, InterruptedException, TimeoutException {
+ closeKeeper = true;
+ CountdownWatcher countdownWatcher = new CountdownWatcher(
+ "ZooKeeperController", new ReconnectionHandler() {
+ @Override
+ public boolean handleReconnect() throws IOException {
+ return false;
+ }
+ });
+ keeper = new ZooKeeper(zooKeeperHost, zkClientTimeout, countdownWatcher);
+ countdownWatcher.waitForConnected(5000);
+ }
+
+ /**
+ * Check if path exists in ZooKeeper.
+ *
+ * @param path ZooKeeper path
+ * @return true if path exists in ZooKeeper
+ */
+ public boolean exists(String path) {
+ Object exists = null;
+ try {
+ exists = keeper.exists(path, null);
+ } catch (KeeperException e) {
+ log.error("ZooKeeper Exception", e);
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+ "ZooKeeper Exception", e);
+ } catch (InterruptedException e) {
+ // nocommit: handle
+ }
+ return exists != null;
+ }
+
+ public void close() throws InterruptedException {
+ if (closeKeeper) {
+ keeper.close();
+ }
+ }
+
+ /**
+ * Load SolrConfig from ZooKeeper.
+ *
+ * TODO: consider *many* cores firing up at once and loading the same files
+ * from ZooKeeper
+ *
+ * @param resourceLoader
+ * @param solrConfigFileName
+ * @return
+ * @throws IOException
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ * @throws InterruptedException
+ * @throws KeeperException
+ */
+ public SolrConfig getConfig(String zkConfigName, String solrConfigFileName,
+ SolrResourceLoader resourceLoader) throws IOException,
+ ParserConfigurationException, SAXException, KeeperException,
+ InterruptedException {
+ byte[] config = getFile(CONFIGS_ZKNODE + zkConfigName, solrConfigFileName);
+ InputStream is = new ByteArrayInputStream(config);
+ SolrConfig cfg = solrConfigFileName == null ? new SolrConfig(
+ resourceLoader, SolrConfig.DEFAULT_CONF_FILE, is) : new SolrConfig(
+ resourceLoader, solrConfigFileName, is);
+
+ return cfg;
+ }
+
+ public byte[] getConfigFileData(String zkConfigName, String fileName) throws KeeperException, InterruptedException {
+ return keeper.getData(CONFIGS_ZKNODE + zkConfigName, null, null);
+ }
+
+ /**
+ * Get data at zkNode path/fileName.
+ *
+ * @param path to zkNode
+ * @param fileName name of zkNode
+ * @return data at path/file
+ * @throws InterruptedException
+ * @throws KeeperException
+ */
+ public byte[] getFile(String path, String fileName) throws KeeperException,
+ InterruptedException {
+ byte[] bytes = null;
+ String configPath = path + "/" + fileName;
+
+ if (log.isInfoEnabled()) {
+ log.info("Reading " + fileName + " from zookeeper at " + configPath);
+ }
+ bytes = keeper.getData(configPath, false, null);
+
+ return bytes;
+ }
+
+ /**
+ * Load IndexSchema from ZooKeeper.
+ *
+ * TODO: consider *many* cores firing up at once and loading the same files
+ * from ZooKeeper
+ *
+ * @param resourceLoader
+ * @param schemaName
+ * @param config
+ * @return
+ * @throws InterruptedException
+ * @throws KeeperException
+ */
+ public IndexSchema getSchema(String zkConfigName, String schemaName,
+ SolrConfig config, SolrResourceLoader resourceLoader)
+ throws KeeperException, InterruptedException {
+ byte[] configBytes = getFile(CONFIGS_ZKNODE + zkConfigName, schemaName);
+ InputStream is = new ByteArrayInputStream(configBytes);
+ IndexSchema schema = new IndexSchema(config, schemaName, is);
+ return schema;
+ }
+
+ /**
+ * Fills string with printout of current ZooKeeper layout.
+ *
+ * @param path
+ * @param indent
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void printLayout(String path, int indent, StringBuilder string)
+ throws KeeperException, InterruptedException {
+ byte[] data = keeper.getData(path, null, null);
+ List<String> children = keeper.getChildren(path, false);
+ StringBuilder dent = new StringBuilder();
+ for (int i = 0; i < indent; i++) {
+ dent.append(" ");
+ }
+ string.append(dent + path + " (" + children.size() + ")" + NEWL);
+ if (data != null) {
+ try {
+ String dataString = new String(data, "UTF-8");
+ if (!path.endsWith(".txt") && !path.endsWith(".xml")) {
+ string.append(dent + "DATA:\n" + dent + " "
+ + dataString.replaceAll("\n", "\n" + dent + " ") + NEWL);
+ } else {
+ string.append(dent + "DATA: ...supressed..." + NEWL);
+ }
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ for (String child : children) {
+ if (!child.equals("quota")) {
+ printLayout(path + (path.equals("/") ? "" : "/") + child, indent + 1,
+ string);
+ }
+ }
+
+ }
+
+ /**
+ * Prints current ZooKeeper layout to stdout.
+ *
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void printLayoutToStdOut() throws KeeperException,
+ InterruptedException {
+ StringBuilder sb = new StringBuilder();
+ printLayout("/", 0, sb);
+ System.out.println(sb.toString());
+ }
+
+ public String readConfigName(String collection) throws KeeperException,
+ InterruptedException {
+ // nocommit: load all config at once or organize differently (Properties?)
+ String configName = null;
+
+ String path = COLLECTIONS_ZKNODE + collection;
+ if (log.isInfoEnabled()) {
+ log.info("Load collection config from:" + path);
+ }
+ List<String> children = keeper.getChildren(path, null);
+ for (String node : children) {
+ // nocommit
+ System.out.println("check child:" + node);
+ // nocommit: do we actually want to handle settings in the node name?
+ if (node.startsWith("config=")) {
+ configName = node.substring(node.indexOf("=") + 1);
+ if (log.isInfoEnabled()) {
+ log.info("Using collection config:" + configName);
+ }
+ }
+ }
+
+ if (configName == null) {
+ throw new IllegalStateException("no config specified for collection:"
+ + collection);
+ }
+
+ return configName;
+ }
+
+ /**
+ * Read info on the available Shards and Nodes.
+ *
+ * @param path to the shards zkNode
+ * @return Map from shard name to a {@link ShardInfoList}
+ * @throws InterruptedException
+ * @throws KeeperException
+ * @throws IOException
+ */
+ public Map<String,ShardInfoList> readShardInfo(String path)
+ throws KeeperException, InterruptedException, IOException {
+ // for now, just reparse everything
+ HashMap<String,ShardInfoList> shardNameToShardList = new HashMap<String,ShardInfoList>();
+
+ if (!exists(path)) {
+ throw new IllegalStateException("Cannot find zk node that should exist:"
+ + path);
+ }
+ List<String> nodes = keeper.getChildren(path, null);
+
+ for (String zkNodeName : nodes) {
+ byte[] data = keeper.getData(path + "/" + zkNodeName, null, null);
+
+ Properties props = new Properties();
+ props.load(new ByteArrayInputStream(data));
+
+ String url = (String) props.get(URL_PROP);
+ String shardNameList = (String) props.get(SHARD_LIST_PROP);
+ String[] shardsNames = shardNameList.split(",");
+ for (String shardName : shardsNames) {
+ ShardInfoList sList = shardNameToShardList.get(shardName);
+ List<ShardInfo> shardList;
+ if (sList == null) {
+ shardList = new ArrayList<ShardInfo>(1);
+ } else {
+ List<ShardInfo> oldShards = sList.getShards();
+ shardList = new ArrayList<ShardInfo>(oldShards.size() + 1);
+ shardList.addAll(oldShards);
+ }
+
+ ShardInfo shard = new ShardInfo(url);
+ shardList.add(shard);
+ ShardInfoList list = new ShardInfoList(shardList);
+
+ shardNameToShardList.put(shardName, list);
+ }
+
+ }
+
+ return Collections.unmodifiableMap(shardNameToShardList);
+ }
+
+ /**
+ * Get Stat for path.
+ *
+ * @param path
+ * @return Stat for path or null if it doesn't exist
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public Stat stat(String path) throws KeeperException, InterruptedException {
+ return keeper.exists(path, null);
+ }
+
+ public boolean configFileExists(String configName, String fileName) throws KeeperException, InterruptedException {
+ Stat stat = keeper.exists(CONFIGS_ZKNODE + configName, null);
+ return stat != null;
+ }
+
+}
Copied: lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperSolrResourceLoader.java (from r892824, lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZKSolrResourceLoader.java)
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperSolrResourceLoader.java?p2=lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperSolrResourceLoader.java&p1=lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZKSolrResourceLoader.java&r1=892824&r2=894959&rev=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/core/ZKSolrResourceLoader.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperSolrResourceLoader.java Fri Jan 1 00:17:31 2010
@@ -1,45 +1,66 @@
-package org.apache.solr.core;
+package org.apache.solr.cloud;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Properties;
-public class ZKSolrResourceLoader extends SolrResourceLoader {
+import org.apache.solr.core.SolrResourceLoader;
+
+/**
+ * ResourceLoader that works with ZooKeeper.
+ *
+ */
+public class ZooKeeperSolrResourceLoader extends SolrResourceLoader {
- private ZooKeeperController zooKeeperController;
+ private String collection;
-
- String collection;
+ private ZooKeeperReader zkReader;
- public ZKSolrResourceLoader(String instanceDir, String collection,
+ public ZooKeeperSolrResourceLoader(String instanceDir, String collection,
ZooKeeperController zooKeeperController) {
super(instanceDir);
- this.zooKeeperController = zooKeeperController;
+ this.zkReader = zooKeeperController.getZkReader();
this.collection = collection;
}
/**
* <p>
- * This loader will delegate to the context classloader when possible,
+ * This loader will first attempt to load resources from ZooKeeper, but if not found
+ * will delegate to the context classloader when possible,
* otherwise it will attempt to resolve resources using any jar files found in
- * the "lib/" directory in the specified instance directory. If the instance
- * directory is not specified (=null), SolrResourceLoader#locateInstanceDir
- * will provide one.
+ * the "lib/" directory in the specified instance directory.
* <p>
*/
- public ZKSolrResourceLoader(String instanceDir, String collection, ClassLoader parent,
+ public ZooKeeperSolrResourceLoader(String instanceDir, String collection, ClassLoader parent,
Properties coreProperties, ZooKeeperController zooKeeperController) {
super(instanceDir, parent, coreProperties);
- this.zooKeeperController = zooKeeperController;
this.collection = collection;
+ this.zkReader = zooKeeperController.getZkReader();
}
/**
* Opens any resource by its name. By default, this will look in multiple
- * locations to load the resource: $configDir/$resource (if resource is not
- * absolute) $CWD/$resource otherwise, it will look for it in any jar
- * accessible through the class loader. Override this method to customize
- * loading resources.
+ * locations to load the resource: $configDir/$resource from ZooKeeper.
+ * It will look for it in any jar
+ * accessible through the class loader if it cannot be found in ZooKeeper.
+ * Override this method to customize loading resources.
*
* @return the stream for the named resource
*/
@@ -49,8 +70,8 @@
//nocommit:
System.out.println("look for:" + file);
try {
- if (zooKeeperController.exists(file)) {
- byte[] bytes = zooKeeperController.getFile(getConfigDir(), resource);
+ if (zkReader.exists(file)) {
+ byte[] bytes = zkReader.getFile(getConfigDir(), resource);
return new ByteArrayInputStream(bytes);
}
} catch (Exception e) {
Added: lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperWriter.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperWriter.java?rev=894959&view=auto
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperWriter.java (added)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/cloud/ZooKeeperWriter.java Fri Jan 1 00:17:31 2010
@@ -0,0 +1,251 @@
+package org.apache.solr.cloud;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public class ZooKeeperWriter {
+ private static Logger log = LoggerFactory.getLogger(ZooKeeperWriter.class);
+
+ private ZooKeeper keeper;
+
+ private boolean closeKeeper;
+
+ /**
+ * For testing. For regular use see {@link #ZooKeeperWriter(ZooKeeper)}.
+ *
+ * @param zooKeeperHost
+ * @param zkClientTimeout
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws TimeoutException
+ */
+ ZooKeeperWriter(String zooKeeperHost, int zkClientTimeout)
+ throws IOException, InterruptedException, TimeoutException {
+ closeKeeper = true;
+ CountdownWatcher countdownWatcher = new CountdownWatcher("ZooKeeperWriter", new ReconnectionHandler() {
+ @Override
+ public boolean handleReconnect() throws IOException {
+ return false;
+ }
+ });
+ keeper = new ZooKeeper(zooKeeperHost, zkClientTimeout, countdownWatcher);
+ countdownWatcher.waitForConnected(5000);
+ }
+
+ /**
+ * @param keeper
+ */
+ ZooKeeperWriter(ZooKeeper keeper) {
+ this.keeper = keeper;
+ }
+
+ /**
+ * Close underling ZooKeeper client if this owns it.
+ *
+ * Only for tests.
+ *
+ * @throws InterruptedException
+ */
+ public void close() throws InterruptedException {
+ if (closeKeeper) {
+ keeper.close();
+ }
+ }
+
+ /**
+ *
+ * @param path
+ * @param data
+ * @param watcher
+ * @return
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public String makeEphemeralSeqPath(String path, byte[] data,
+ Watcher watcher) throws KeeperException, InterruptedException {
+
+ String zkPath = keeper.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE,
+ CreateMode.EPHEMERAL_SEQUENTIAL);
+
+ keeper.exists(zkPath, watcher);
+
+ return zkPath;
+ }
+
+ /**
+ * Creates the path in ZooKeeper, creating each node as necessary.
+ *
+ * e.g. If <code>path=/solr/group/node</code> and none of the nodes, solr,
+ * group, node exist, each will be created.
+ *
+ * @param path
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void makePath(String path) throws KeeperException,
+ InterruptedException {
+ makePath(path, null, CreateMode.PERSISTENT);
+ }
+
+ /**
+ * Creates the path in ZooKeeper, creating each node as necessary.
+ *
+ * @param path
+ * @param data to set on the last zkNode
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void makePath(String path, byte[] data) throws KeeperException,
+ InterruptedException {
+ makePath(path, data, CreateMode.PERSISTENT);
+ }
+
+ /**
+ * Creates the path in ZooKeeper, creating each node as necessary.
+ *
+ * e.g. If <code>path=/solr/group/node</code> and none of the nodes, solr,
+ * group, node exist, each will be created.
+ *
+ * @param path
+ * @param data to set on the last zkNode
+ * @param createMode
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void makePath(String path, byte[] data, CreateMode createMode)
+ throws KeeperException, InterruptedException {
+ makePath(path, data, createMode, null);
+ }
+
+ /**
+ * Creates the path in ZooKeeper, creating each node as necessary.
+ *
+ * e.g. If <code>path=/solr/group/node</code> and none of the nodes, solr,
+ * group, node exist, each will be created.
+ *
+ * @param path
+ * @param data to set on the last zkNode
+ * @param createMode
+ * @param watcher
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void makePath(String path, byte[] data, CreateMode createMode,
+ Watcher watcher) throws KeeperException, InterruptedException {
+ if (log.isInfoEnabled()) {
+ log.info("makePath: " + path);
+ }
+
+ if (path.startsWith("/")) {
+ path = path.substring(1, path.length());
+ }
+ String[] paths = path.split("/");
+ StringBuilder sbPath = new StringBuilder();
+ for (int i = 0; i < paths.length; i++) {
+ byte[] bytes = null;
+ String pathPiece = paths[i];
+ sbPath.append("/" + pathPiece);
+ String currentPath = sbPath.toString();
+ Object exists = keeper.exists(currentPath, watcher);
+ if (exists == null) {
+ CreateMode mode = CreateMode.PERSISTENT;
+ if (i == paths.length - 1) {
+ mode = createMode;
+ bytes = data;
+ }
+ keeper.create(currentPath, bytes, ZooDefs.Ids.OPEN_ACL_UNSAFE, mode);
+ // set new watch
+ keeper.exists(currentPath, watcher);
+ } else if (i == paths.length - 1) {
+ // nocommit: version ?
+ keeper.setData(currentPath, data, -1);
+ // set new watch
+ keeper.exists(currentPath, watcher);
+ }
+ }
+ }
+
+ /**
+ * @param zkPath
+ * @param createMode
+ * @param watcher
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void makePath(String zkPath, CreateMode createMode, Watcher watcher)
+ throws KeeperException, InterruptedException {
+ makePath(zkPath, null, createMode, watcher);
+ }
+
+ /**
+ * Write data to ZooKeeper.
+ *
+ * @param path
+ * @param data
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void write(String path, byte[] data) throws KeeperException,
+ InterruptedException {
+
+ makePath(path);
+
+ Object exists = keeper.exists(path, null);
+ if (exists != null) {
+ keeper.setData(path, data, -1);
+ } else {
+ keeper.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE,
+ CreateMode.PERSISTENT);
+ }
+ }
+
+ /**
+ * Write file to ZooKeeper - default system encoding used.
+ *
+ * @param path path to upload file to e.g. /solr/conf/solrconfig.xml
+ * @param file path to file to be uploaded
+ * @throws IOException
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void write(String path, File file) throws IOException,
+ KeeperException, InterruptedException {
+ if(log.isInfoEnabled()) {
+ log.info("Write to ZooKeepeer " + file.getAbsolutePath() + " to " + path);
+ }
+
+ String data = FileUtils.readFileToString(file);
+ write(path, data.getBytes());
+ }
+
+}
Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java?rev=894959&r1=894958&r2=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java Fri Jan 1 00:17:31 2010
@@ -31,6 +31,8 @@
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
+import org.apache.solr.cloud.ZooKeeperSolrResourceLoader;
+import org.apache.solr.cloud.ZooKeeperController;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.common.util.DOMUtil;
@@ -38,6 +40,7 @@
import org.apache.solr.common.util.FileUtils;
import org.apache.solr.handler.admin.CoreAdminHandler;
import org.apache.solr.schema.IndexSchema;
+import org.apache.zookeeper.KeeperException;
import org.apache.commons.io.IOUtils;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -59,7 +62,9 @@
protected String adminPath = null;
protected String managementPath = null;
protected int zkClientTimeout;
- protected String shardAddress;
+ protected String hostPort;
+ protected String hostContext;
+ protected String host;
protected CoreAdminHandler coreAdminHandler = null;
protected File configFile = null;
protected String libDir = null;
@@ -74,19 +79,29 @@
protected String solrHome;
protected String solrConfigFilenameOverride;
protected String solrDataDirOverride;
+ protected String zkPortOverride;
protected String collection;
+ private String testShardsListOverride;
private ZooKeeperController zooKeeperController;
+ private String zkHost;
+
+
public CoreContainer() {
solrHome = SolrResourceLoader.locateSolrHome();
}
- private void initZooKeeper(int zkClientTimeout) {
- //nocommit: pull zookeeper integration into a new CoreContainer? leaning towards no.
- String zookeeperHost = System.getProperty("zkHost");
+ private void initZooKeeper(String zkHost, int zkClientTimeout) {
+ // nocommit: perhaps get from solr.xml
+ String zookeeperHost;
+ if(zkHost == null) {
+ zookeeperHost = System.getProperty("zkHost");
+ } else {
+ zookeeperHost = zkHost;
+ }
if (zookeeperHost != null) {
- zooKeeperController = new ZooKeeperController(zookeeperHost, collection, shardAddress, zkClientTimeout);
+ zooKeeperController = new ZooKeeperController(zookeeperHost, collection, host, hostPort, hostContext, zkClientTimeout);
}
}
@@ -99,6 +114,8 @@
protected String solrConfigFilename = null;
protected boolean abortOnConfigurationError = true;
protected String dataDir = null; // override datadir for single core mode
+ private String zkPortOverride;
+ protected String testShardListOverride;
public boolean isAbortOnConfigurationError() {
return abortOnConfigurationError;
@@ -115,22 +132,34 @@
public void setSolrConfigFilename(String solrConfigFilename) {
this.solrConfigFilename = solrConfigFilename;
}
+
+ public void setZKPortOverride(String port) {
+ this.zkPortOverride = port;
+ }
+
+ public void setTestShardListOverride(String shardList) {
+ this.testShardListOverride = shardList;
+ }
// core container instantiation
public CoreContainer initialize() throws IOException, ParserConfigurationException, SAXException {
CoreContainer cores = null;
String solrHome = SolrResourceLoader.locateSolrHome();
+ // nocommit : fix broken logic confusing solr.xml with solrconfig.xml
File fconf = new File(solrHome, solrConfigFilename == null ? "solr.xml"
: solrConfigFilename);
log.info("looking for solr.xml: " + fconf.getAbsolutePath());
cores = new CoreContainer();
- cores.solrConfigFilenameOverride = solrConfigFilename;
cores.solrDataDirOverride = dataDir;
+ cores.zkPortOverride = zkPortOverride;
+ cores.testShardsListOverride = testShardListOverride;
if (fconf.exists())
cores.load(solrHome, fconf);
else {
- cores.load(solrHome, new ByteArrayInputStream(DEF_SOLR_XML.getBytes()));
+ log.info("no solr.xml file found - using default");
+ cores.solrConfigFilenameOverride = solrConfigFilename;
cores.configFile = fconf;
+ cores.load(solrHome, new ByteArrayInputStream(DEF_SOLR_XML.getBytes()));
}
abortOnConfigurationError = false;
// if any core aborts on startup, then abort
@@ -144,6 +173,7 @@
return cores;
}
+
}
private static Properties getCoreProps(String instanceDir, String file, Properties defaults) {
@@ -229,20 +259,29 @@
try {
Config cfg = new Config(loader, null, cfgis, null);
- persistent = cfg.getBool( "solr/@persistent", false );
- libDir = cfg.get( "solr/@sharedLib", null);
- adminPath = cfg.get( "solr/cores/@adminPath", null );
- shareSchema = cfg.getBool("solr/cores/@shareSchema", false );
+ persistent = cfg.getBool("solr/@persistent", false);
+ libDir = cfg.get("solr/@sharedLib", null);
+ zkHost = cfg.get("solr/@zkHost" , null);
+ adminPath = cfg.get("solr/cores/@adminPath", null);
+ shareSchema = cfg.getBool("solr/cores/@shareSchema", false);
zkClientTimeout = cfg.getInt("solr/cores/@zkClientTimeout", 10000);
- shardAddress = cfg.get("solr/cores/@shardAddress", null);
+ if (zkPortOverride == null) {
+ hostPort = cfg.get("solr/cores/@hostPort", "8983");
+ } else {
+ hostPort = zkPortOverride;
+ }
+ hostContext = cfg.get("solr/cores/@hostContext", "solr");
+ host = cfg.get("solr/cores/@host", null);
+
collection = cfg.get("solr/cores/@collection", "collection1"); //nocommit: default collection
+
if(shareSchema){
indexSchemaCache = new ConcurrentHashMap<String ,IndexSchema>();
}
adminHandler = cfg.get("solr/cores/@adminHandler", null );
managementPath = cfg.get("solr/cores/@managementPath", null );
- initZooKeeper(zkClientTimeout);
+ initZooKeeper(zkHost, zkClientTimeout);
if (libDir != null) {
File f = FileUtils.resolvePath(new File(dir), libDir);
@@ -280,6 +319,8 @@
// deal with optional settings
String opt = DOMUtil.getAttr(node, "config", null);
+ //nocommit
+ System.out.println("name:" + name + " c:" + solrConfigFilenameOverride);
if(solrConfigFilenameOverride != null && name.equals("")) {
p.setConfigName(solrConfigFilenameOverride);
} else if (opt != null) {
@@ -289,6 +330,12 @@
if (opt != null) {
p.setSchemaName(opt);
}
+ opt = DOMUtil.getAttr(node, "shardList", null);
+ if(testShardsListOverride != null && name.equals("")) {
+ p.setShardList(testShardsListOverride);
+ } else if(opt != null) {
+ p.setShardList(opt);
+ }
opt = DOMUtil.getAttr(node, "properties", null);
if (opt != null) {
p.setPropertiesName(opt);
@@ -425,13 +472,23 @@
// Initialize the solr config
SolrResourceLoader solrLoader ;
- SolrConfig config;
+ SolrConfig config = null;
if(zooKeeperController == null) {
solrLoader = new SolrResourceLoader(instanceDir, libLoader, getCoreProps(instanceDir, dcore.getPropertiesName(),dcore.getCoreProperties()));
config = new SolrConfig(solrLoader, dcore.getConfigName(), null);
} else {
- solrLoader = new ZKSolrResourceLoader(instanceDir, collection, libLoader, getCoreProps(instanceDir, dcore.getPropertiesName(),dcore.getCoreProperties()), zooKeeperController);
- config = zooKeeperController.getConfig(dcore.getConfigName(), solrLoader);
+ solrLoader = new ZooKeeperSolrResourceLoader(instanceDir, collection, libLoader, getCoreProps(instanceDir, dcore.getPropertiesName(),dcore.getCoreProperties()), zooKeeperController);
+ try {
+ config = zooKeeperController.getZkReader().getConfig(zooKeeperController.getConfigName(), dcore.getConfigName(), solrLoader);
+ } catch (KeeperException e) {
+ log.error("ZooKeeper Exception", e);
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+ "ZooKeeper Exception", e);
+ } catch (InterruptedException e) {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+ //nocommit: we may not know the config name - now what
+ }
}
IndexSchema schema = null;
if (indexSchemaCache != null) {
@@ -464,7 +521,17 @@
}
if(schema == null){
if(zooKeeperController != null) {
- schema = zooKeeperController.getSchema(dcore.getSchemaName(), config, solrLoader);
+ try {
+ schema = zooKeeperController.getZkReader().getSchema(zooKeeperController.getConfigName(), dcore.getSchemaName(), config, solrLoader);
+ } catch (KeeperException e) {
+ log.error("ZooKeeper Exception", e);
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+ "ZooKeeper Exception", e);
+ } catch (InterruptedException e) {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+ //nocommit: we may not know have the schema - now what
+ }
} else {
schema = new IndexSchema(config, dcore.getSchemaName(), null);
}
Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreDescriptor.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreDescriptor.java?rev=894959&r1=894958&r2=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreDescriptor.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreDescriptor.java Fri Jan 1 00:17:31 2010
@@ -34,6 +34,7 @@
protected String schemaName;
private final CoreContainer coreContainer;
private Properties coreProperties;
+ private String shardList;
public CoreDescriptor(CoreContainer coreContainer, String name, String instanceDir) {
this.coreContainer = coreContainer;
@@ -171,4 +172,14 @@
this.coreProperties.putAll(coreProperties);
}
}
+
+ public void setShardList(String shardList) {
+ System.out.println("set shard list:" + shardList);
+ this.shardList = shardList;
+ }
+
+ //nocommit: may be null
+ public String getShardList() {
+ return shardList;
+ }
}
Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrConfig.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrConfig.java?rev=894959&r1=894958&r2=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrConfig.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrConfig.java Fri Jan 1 00:17:31 2010
@@ -125,7 +125,7 @@
*@param name the configuration name
*@param is the configuration stream
*/
- SolrConfig(SolrResourceLoader loader, String name, InputStream is)
+ public SolrConfig(SolrResourceLoader loader, String name, InputStream is)
throws ParserConfigurationException, IOException, SAXException {
super(loader, name, is, "/config/");
initLibs();
Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java?rev=894959&r1=894958&r2=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java Fri Jan 1 00:17:31 2010
@@ -22,6 +22,7 @@
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.store.Directory;
+import org.apache.solr.cloud.ZooKeeperController;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.CommonParams.EchoParamStyle;
@@ -283,6 +284,8 @@
List<SolrEventListener> firstSearcherListeners;
List<SolrEventListener> newSearcherListeners;
+ private ZooKeeperController zooKeeperComponent;
+
/**
* NOTE: this function is not thread safe. However, it is safe to call within the
* <code>inform( SolrCore core )</code> function for <code>SolrCoreAware</code> classes.
@@ -522,6 +525,11 @@
if (schema==null) {
schema = new IndexSchema(config, IndexSchema.DEFAULT_SCHEMA_FILE, null);
}
+
+ zooKeeperComponent = cd.getCoreContainer().getZooKeeperController();
+ if(zooKeeperComponent != null) {
+ zooKeeperComponent.registerShard(this);
+ }
//Initialize JMX
if (config.jmxConfig.enabled) {
Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/handler/ReplicationHandler.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/handler/ReplicationHandler.java?rev=894959&r1=894958&r2=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/handler/ReplicationHandler.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/handler/ReplicationHandler.java Fri Jan 1 00:17:31 2010
@@ -252,6 +252,8 @@
void doFetch(SolrParams solrParams) {
String masterUrl = solrParams == null ? null : solrParams.get(MASTER_URL);
+ // nocommit : override master url using info from ZooKeeper
+
if (!snapPullLock.tryLock())
return;
try {
Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java?rev=894959&r1=894958&r2=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java Fri Jan 1 00:17:31 2010
@@ -110,6 +110,8 @@
// TODO: temporary... this should go in a different component.
String shards = params.get(ShardParams.SHARDS);
+ // nocommit : get shards based on ZooKeeper info, using load balancing
+ // shards = req.getCore().getCoreDescriptor().getCoreContainer().getZooKeeperController().getSearchNodes();
if (shards != null) {
List<String> lst = StrUtils.splitSmart(shards, ",", true);
rb.shards = lst.toArray(new String[lst.size()]);
Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryElevationComponent.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryElevationComponent.java?rev=894959&r1=894958&r2=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryElevationComponent.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryElevationComponent.java Fri Jan 1 00:17:31 2010
@@ -44,6 +44,7 @@
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.apache.lucene.util.StringHelper;
+import org.apache.solr.cloud.ZooKeeperController;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.DOMUtil;
@@ -169,20 +170,29 @@
"QueryElevationComponent must specify argument: '"+CONFIG_FILE
+"' -- path to elevate.xml" );
}
- //nocommit: add resourceloader.exists? needs to be handled with zookeeper
- File fC = new File( core.getResourceLoader().getConfigDir(), f );
- File fD = new File( core.getDataDir(), f );
- if( fC.exists() == fD.exists() ) {
- throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
- "QueryElevationComponent missing config file: '"+f + "\n"
- +"either: "+fC.getAbsolutePath() + " or " + fD.getAbsolutePath() + " must exist, but not both." );
- }
- if( fC.exists() ) {
- log.info( "Loading QueryElevation from: "+fC.getAbsolutePath() );
- Config cfg = new Config( core.getResourceLoader(), f );
- elevationCache.put(null, loadElevationMap( cfg ));
+ boolean exists = false;
+ //nocommit: double check this how we want to handle this
+ // check if using ZooKeeper
+ ZooKeeperController zooKeeperController = core.getCoreDescriptor().getCoreContainer().getZooKeeperController();
+ if(zooKeeperController != null) {
+ exists = zooKeeperController.configFileExists(f);
+ } else {
+ File fC = new File( core.getResourceLoader().getConfigDir(), f );
+ File fD = new File( core.getDataDir(), f );
+ if( fC.exists() == fD.exists() ) {
+ throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
+ "QueryElevationComponent missing config file: '"+f + "\n"
+ +"either: "+fC.getAbsolutePath() + " or " + fD.getAbsolutePath() + " must exist, but not both." );
+ }
+ if( fC.exists() ) {
+ exists = true;
+ log.info( "Loading QueryElevation from: "+ fC.getAbsolutePath() );
+ Config cfg = new Config( core.getResourceLoader(), f );
+ elevationCache.put(null, loadElevationMap( cfg ));
+ }
}
- else {
+
+ if (!exists){
// preload the first data
RefCounted<SolrIndexSearcher> searchHolder = null;
try {
@@ -193,6 +203,7 @@
if (searchHolder != null) searchHolder.decref();
}
}
+
}
}
catch( Exception ex ) {
Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/util/AbstractSolrTestCase.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/util/AbstractSolrTestCase.java?rev=894959&r1=894958&r2=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/util/AbstractSolrTestCase.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/util/AbstractSolrTestCase.java Fri Jan 1 00:17:31 2010
@@ -110,7 +110,7 @@
String configFile = getSolrConfigFile();
if (configFile != null) {
- solrConfig = h.createConfig(getSolrConfigFile());
+ solrConfig = h.createConfig(configFile);
h = new TestHarness( dataDir.getAbsolutePath(),
solrConfig,
getSchemaFile());
Modified: lucene/solr/branches/cloud/src/test/org/apache/solr/BaseDistributedSearchTestCase.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/test/org/apache/solr/BaseDistributedSearchTestCase.java?rev=894959&r1=894958&r2=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/test/org/apache/solr/BaseDistributedSearchTestCase.java (original)
+++ lucene/solr/branches/cloud/src/test/org/apache/solr/BaseDistributedSearchTestCase.java Fri Jan 1 00:17:31 2010
@@ -1,6 +1,19 @@
package org.apache.solr;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
import junit.framework.TestCase;
+
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
@@ -14,10 +27,6 @@
import org.apache.solr.schema.TrieDateField;
import org.apache.solr.util.AbstractSolrTestCase;
-import java.io.File;
-import java.io.IOException;
-import java.util.*;
-
/**
* Helper base class for distributed search test cases
*
@@ -33,6 +42,7 @@
protected String shards;
protected File testDir;
protected SolrServer controlClient;
+ protected int portSeed;
// to stress with higher thread counts and requests, make sure the junit
// xml formatter is not being used (all output will be buffered before
@@ -126,7 +136,7 @@
super.tearDown();
}
- private void createServers(int numShards) throws Exception {
+ protected void createServers(int numShards) throws Exception {
controlJetty = createJetty(testDir, "control");
controlClient = createNewSolrServer(controlJetty.getLocalPort());
@@ -148,18 +158,38 @@
clients.clear();
jettys.clear();
}
+
+ public JettySolrRunner createJetty(File baseDir, String dataDirName) throws Exception {
+ return createJetty(baseDir, dataDirName, null, null);
+ }
- public static JettySolrRunner createJetty(File baseDir, String dataDirName) throws Exception {
+ public JettySolrRunner createJetty(File baseDir, String dataDirName, String shardList) throws Exception {
+ return createJetty(baseDir, dataDirName, shardList, null);
+ }
+
+ public JettySolrRunner createJetty(File baseDir, String dataDirName, String shardList, String solrConfigOverride) throws Exception {
File subDir = new File(baseDir, dataDirName);
subDir.mkdirs();
System.setProperty("solr.data.dir", subDir.toString());
-
- JettySolrRunner jetty = new JettySolrRunner("/solr", 0);
-
+ int port = getPort();
+ JettySolrRunner jetty = new JettySolrRunner("/solr", port, solrConfigOverride);
+ if(port != 0) {
+ jetty.setPortOverride(port);
+ }
+ if(shardList != null) {
+ jetty.setTestShardListOverride(shardList);
+ }
jetty.start();
return jetty;
}
+ private int getPort() {
+ if(portSeed != 0) {
+ return portSeed++;
+ }
+ return 0;
+ }
+
protected SolrServer createNewSolrServer(int port) {
try {
// setup the server...
@@ -241,7 +271,7 @@
SolrServer client = clients.get(which);
QueryResponse rsp = client.query(params);
- compareResponses(rsp, controlRsp);
+ //compareResponses(rsp, controlRsp);
if (stress > 0) {
log.info("starting stress...");
Copied: lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/AbstractDistributedZooKeeperTestCase.java (from r892824, lucene/solr/branches/cloud/src/test/org/apache/solr/AbstractDistributedZooKeeperTestCase.java)
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/AbstractDistributedZooKeeperTestCase.java?p2=lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/AbstractDistributedZooKeeperTestCase.java&p1=lucene/solr/branches/cloud/src/test/org/apache/solr/AbstractDistributedZooKeeperTestCase.java&r1=892824&r2=894959&rev=894959&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/test/org/apache/solr/AbstractDistributedZooKeeperTestCase.java (original)
+++ lucene/solr/branches/cloud/src/test/org/apache/solr/cloud/AbstractDistributedZooKeeperTestCase.java Fri Jan 1 00:17:31 2010
@@ -1,15 +1,31 @@
-package org.apache.solr;
+package org.apache.solr.cloud;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
import java.io.File;
-import java.io.IOException;
+import java.util.HashSet;
+import org.apache.solr.BaseDistributedSearchTestCase;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.util.TestHarness;
-import org.apache.zookeeper.server.ServerConfig;
-import org.apache.zookeeper.server.ZooKeeperServerMain;
public abstract class AbstractDistributedZooKeeperTestCase extends BaseDistributedSearchTestCase {
- protected ZooKeeperServerMain zkServer = new ZooKeeperServerMain();
+ private ZooKeeperTestServer zkServer;
protected File tmpDir = new File(System.getProperty("java.io.tmpdir")
+ System.getProperty("file.separator") + getClass().getName() + "-"
@@ -19,31 +35,15 @@
public void setUp() throws Exception {
// we don't call super.setUp
log.info("####SETUP_START " + getName());
+ portSeed = 13000;
System.setProperty("zkHost", AbstractZooKeeperTestCase.ZOO_KEEPER_HOST);
- Thread zooThread = new Thread() {
- @Override
- public void run() {
- ServerConfig config = new ServerConfig() {
- {
- this.clientPort = 2181;
- this.dataDir = tmpDir.getAbsolutePath() + File.separator
- + "zookeeper/server1/data";
- this.dataLogDir = this.dataDir;
- }
- };
-
- try {
- zkServer.runFromConfig(config);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- }
- };
- zooThread.setDaemon(true);
- zooThread.start();
- Thread.sleep(500); // pause for ZooKeeper to start
+ String zkDir = tmpDir.getAbsolutePath() + File.separator
+ + "zookeeper/server1/data";
+ zkServer = new ZooKeeperTestServer(zkDir);
+ zkServer.run();
+
+
AbstractZooKeeperTestCase.buildZooKeeper(getSolrConfigFile(), getSchemaFile());
dataDir = tmpDir;
@@ -56,6 +56,7 @@
CoreContainer.Initializer init = new CoreContainer.Initializer() {
{
this.dataDir = AbstractDistributedZooKeeperTestCase.this.dataDir.getAbsolutePath();
+ this.solrConfigFilename = AbstractDistributedZooKeeperTestCase.this.getSolrConfigFilename();
}
};
@@ -70,8 +71,35 @@
testDir.mkdirs();
postSetUp();
}
+
+ protected String getSolrConfigFilename() {
+ return null;
+ }
+
+ public void testDistribSearch() throws Exception {
+ for (int nServers = 2; nServers < 3; nServers++) {
+ createServers(nServers);
+
+ RandVal.uniqueValues = new HashSet(); //reset random values
+ doTest();
+ printeLayout();
+
+ destroyServers();
+ }
+ }
public void tearDown() throws Exception {
+ printeLayout();
super.tearDown();
}
+
+ private void printeLayout() throws Exception {
+ ZooKeeperReader zkReader = new ZooKeeperReader(
+ AbstractZooKeeperTestCase.ZOO_KEEPER_HOST.substring(0,
+ AbstractZooKeeperTestCase.ZOO_KEEPER_HOST.indexOf('/')),
+ AbstractZooKeeperTestCase.TIMEOUT);
+
+ zkReader.printLayoutToStdOut();
+ zkReader.close();
+ }
}