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 yo...@apache.org on 2006/01/26 06:40:05 UTC
svn commit: r372455 [4/11] - in /incubator/solr/trunk: ./ src/ src/apps/
src/apps/SolarTest/ src/apps/SolarTest/src/ src/java/ src/java/org/
src/java/org/apache/ src/java/org/apache/solr/
src/java/org/apache/solr/analysis/ src/java/org/apache/solr/core...
Added: incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,970 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.core;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrQueryResponse;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.update.*;
+import org.apache.solr.util.DOMUtil;
+import org.apache.solr.util.RefCounted;
+import org.apache.solr.util.StrUtils;
+import org.apache.solr.util.XML;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import javax.xml.xpath.XPathConstants;
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.logging.Logger;
+
+
+/**
+ * @author yonik
+ * @version $Id: SolrCore.java,v 1.47 2006/01/10 05:04:44 yonik Exp $
+ */
+
+public final class SolrCore {
+ public static final String cvsId="$Id: SolrCore.java,v 1.47 2006/01/10 05:04:44 yonik Exp $";
+ public static final String cvsSource="$Source: /cvs/main/searching/solr/solarcore/src/solr/SolrCore.java,v $";
+ public static final String cvsTag="$Name: $";
+ public static final String version="1.0";
+
+ public static Logger log = Logger.getLogger(SolrCore.class.getName());
+
+ private final IndexSchema schema;
+ private final String index_path;
+ private final UpdateHandler updateHandler;
+
+ public static SolrIndexConfig mainIndexConfig = new SolrIndexConfig("mainIndex");
+
+ static {
+ BooleanQuery.setMaxClauseCount(SolrConfig.config.getInt("query/maxBooleanClauses",BooleanQuery.getMaxClauseCount()));
+ }
+
+
+ public static List<SolrEventListener> parseListener(String path) {
+ List<SolrEventListener> lst = new ArrayList<SolrEventListener>();
+ log.info("Searching for listeners: " +path);
+ NodeList nodes = (NodeList)SolrConfig.config.evaluate(path, XPathConstants.NODESET);
+ if (nodes!=null) {
+ for (int i=0; i<nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ String className = DOMUtil.getAttr(node,"class");
+ SolrEventListener listener = (SolrEventListener)Config.newInstance(className);
+ listener.init(DOMUtil.childNodesToNamedList(node));
+ lst.add(listener);
+ log.info("added SolrEventListener: " + listener);
+ }
+ }
+ return lst;
+ }
+
+ List<SolrEventListener> firstSearcherListeners;
+ List<SolrEventListener> newSearcherListeners;
+ private void parseListeners() {
+ firstSearcherListeners = parseListener("//listener[@event=\"firstSearcher\"]");
+ newSearcherListeners = parseListener("//listener[@event=\"newSearcher\"]");
+ }
+
+
+ public IndexSchema getSchema() { return schema; }
+ public String getDir() { return index_path; }
+
+
+ private final RequestHandlers reqHandlers = new RequestHandlers(SolrConfig.config);
+
+ public SolrRequestHandler getRequestHandler(String handlerName) {
+ return reqHandlers.get(handlerName);
+ }
+
+
+ // TODO - what about a master that not might have a searcher normally open?
+ @Deprecated
+ public int maxDoc() {
+ RefCounted<SolrIndexSearcher> holder=null;
+ int num=0;
+ try {
+ holder = getSearcher();
+ SolrIndexSearcher searcher = holder.get();
+ num = searcher.maxDoc();
+ } catch (IOException e) {
+ log(e);
+ } finally {
+ if (holder != null) holder.decref();
+ }
+ return num;
+ }
+
+
+ // gets a non-caching searcher
+ public SolrIndexSearcher newSearcher(String name) throws IOException {
+ return new SolrIndexSearcher(schema, name,getDir(),false);
+ }
+
+
+ void initIndex() {
+ try {
+ File dirFile = new File(getDir());
+ boolean indexExists = dirFile.canRead();
+
+
+ boolean removeLocks = SolrConfig.config.getBool("mainIndex/unlockOnStartup", false);
+ if (removeLocks) {
+ // to remove locks, the directory must already exist... so we create it
+ // if it didn't exist already...
+ Directory dir = FSDirectory.getDirectory(dirFile, !indexExists);
+ if (IndexReader.isLocked(dir)) {
+ log.warning("WARNING: Solr index directory '" + getDir() + "' is locked. Unlocking...");
+ IndexReader.unlock(dir);
+ }
+ }
+
+ // Create the index if it doesn't exist. Note that indexExists was tested *before*
+ // lock removal, since that will result in the creation of the directory.
+ if(!indexExists) {
+ log.warning("Solr index directory '" + dirFile + "' doesn't exist."
+ + " Creating new index...");
+
+ SolrIndexWriter writer = new SolrIndexWriter("SolrCore.initIndex",getDir(), true, schema, mainIndexConfig);
+ writer.close();
+
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ private UpdateHandler createUpdateHandler(String className) {
+ try {
+ Class handlerClass = Config.findClass(className);
+ java.lang.reflect.Constructor cons = handlerClass.getConstructor(new Class[]{SolrCore.class});
+ return (UpdateHandler)cons.newInstance(new Object[]{this});
+ } catch (SolrException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SolrException(500,"Error Instantiating Update Handler "+className, e);
+ }
+ }
+
+
+ // Singleton for now...
+ private static SolrCore core;
+
+ public static SolrCore getSolrCore() {
+ synchronized (SolrCore.class) {
+ if (core==null) core = new SolrCore(null,null);
+ return core;
+ }
+ }
+
+
+ public SolrCore(String index_path, IndexSchema schema) {
+ synchronized (SolrCore.class) {
+ // this is for backward compatibility (and also the reason
+ // the sync block is needed)
+ core = this; // set singleton
+ try {
+ if (index_path==null) {
+ index_path=SolrConfig.config.get("indexDir","index");
+ }
+
+ log.info("Opening new SolrCore at " + index_path);
+
+ if (schema==null) {
+ schema = new IndexSchema("schema.xml");
+ }
+
+ this.schema = schema;
+ this.index_path = index_path;
+
+ parseListeners();
+
+ initIndex();
+
+ try {
+ // Open the searcher *before* the handler so we don't end up opening
+ // one in the middle.
+ getSearcher(false,false,null);
+
+ updateHandler = createUpdateHandler(
+ SolrConfig.config.get("updateHandler/@class", DirectUpdateHandler.class.getName())
+ );
+
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ } finally {
+
+ }
+
+
+ }
+ }
+
+
+ public void close() {
+ log.info("CLOSING SolrCore!");
+ try {
+ closeSearcher();
+ } catch (Exception e) {
+ SolrException.log(log,e);
+ }
+ try {
+ searcherExecutor.shutdown();
+ } catch (Exception e) {
+ SolrException.log(log,e);
+ }
+ try {
+ updateHandler.close();
+ } catch (Exception e) {
+ SolrException.log(log,e);
+ }
+ }
+
+
+ void finalizer() { close(); }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Searcher Control
+ ////////////////////////////////////////////////////////////////////////////////
+
+ // The current searcher used to service queries.
+ // Don't access this directly!!!! use getSearcher() to
+ // get it (and it will increment the ref count at the same time)
+ private RefCounted<SolrIndexSearcher> _searcher;
+
+ final ExecutorService searcherExecutor = Executors.newSingleThreadExecutor();
+ private int onDeckSearchers; // number of searchers preparing
+ private Object searcherLock = new Object(); // the sync object for the searcher
+
+
+ public RefCounted<SolrIndexSearcher> getSearcher() {
+ try {
+ return getSearcher(false,true,null);
+ } catch (IOException e) {
+ SolrException.log(log,null,e);
+ return null;
+ }
+ }
+
+ /**
+ * Get a {@link SolrIndexSearcher} or start the process of creating a new one.
+ * <p>
+ * The registered searcher is the default searcher used to service queries.
+ * A searcher will normally be registered after all of the warming
+ * and event handlers (newSearcher or firstSearcher events) have run.
+ * In the case where there is no registered searcher, the newly created searcher will
+ * be registered before running the event handlers (a slow searcher is better than no searcher).
+ *
+ * <p>
+ * If <tt>forceNew==true</tt> then
+ * A new searcher will be opened and registered irregardless if there is already
+ * a registered searcher or other searchers in the process of being created.
+ * <p>
+ * If <tt>forceNew==false</tt> then:<ul>
+ * <li>If a searcher is already registered, that searcher will be returned</li>
+ * <li>If no searcher is currently registered, but at least one is in the process of being created, then
+ * this call will block until the first searcher is registered</li>
+ * <li>If no searcher is currently registered, and no searchers in the process of being registered, a new
+ * searcher will be created.</li>
+ * </ul>
+ * <p>
+ * If <tt>returnSearcher==true</tt> then a {@link RefCounted}<{@link SolrIndexSearcher}> will be returned with
+ * the reference count incremented. It <b>must</b> be decremented when no longer needed.
+ * <p>
+ * If <tt>waitSearcher!=null</tt> and a new {@link SolrIndexSearcher} was created,
+ * then it is filled in with a Future that will return after the searcher is registered. The Future may be set to
+ * <tt>null</tt> in which case the SolrIndexSearcher created has already been registered at the time
+ * this method returned.
+ * <p>
+ * @param forceNew if true, force the open of a new index searcher regardless if there is already one open.
+ * @param returnSearcher if true, returns a {@link <SolrIndexSearcher>} holder with the refcount already incremented.
+ * @param waitSearcher if non-null, will be filled in with a {@link Future} that will return after the new searcher is registered.
+ * @return
+ * @throws IOException
+ */
+ public RefCounted<SolrIndexSearcher> getSearcher(boolean forceNew, boolean returnSearcher, final Future[] waitSearcher) throws IOException {
+ // it may take some time to open an index.... we may need to make
+ // sure that two threads aren't trying to open one at the same time
+ // if it isn't necessary.
+
+ synchronized (searcherLock) {
+ // see if we can return the current searcher
+ if (_searcher!=null && !forceNew) {
+ if (returnSearcher) {
+ _searcher.incref();
+ return _searcher;
+ } else {
+ return null;
+ }
+ }
+
+ // check to see if we can wait for someone elses searcher to be set
+ if (onDeckSearchers>0 && !forceNew && _searcher==null) {
+ try {
+ searcherLock.wait();
+ } catch (InterruptedException e) {
+ log.info(SolrException.toStr(e));
+ }
+ }
+
+ // check again: see if we can return right now
+ if (_searcher!=null && !forceNew) {
+ if (returnSearcher) {
+ _searcher.incref();
+ return _searcher;
+ } else {
+ return null;
+ }
+ }
+
+ // At this point, we know we need to open a new searcher...
+ // first: increment count to signal other threads that we are
+ // opening a new searcher.
+ onDeckSearchers++;
+ }
+
+ // open the index synchronously
+ // if this fails, we need to decrement onDeckSearchers again.
+ SolrIndexSearcher tmp;
+ try {
+ if (onDeckSearchers < 1) {
+ // should never happen... just a sanity check
+ log.severe("ERROR!!! onDeckSearchers is " + onDeckSearchers);
+ // reset to 1 (don't bother synchronizing)
+ onDeckSearchers=1;
+ } else if (onDeckSearchers > 1) {
+ log.info("PERFORMANCE WARNING: Overlapping onDeckSearchers=" + onDeckSearchers);
+ }
+ tmp = new SolrIndexSearcher(schema, "main", index_path, true);
+ } catch (Throwable th) {
+ synchronized(searcherLock) {
+ onDeckSearchers--;
+ // notify another waiter to continue... it may succeed
+ // and wake any others.
+ searcherLock.notify();
+ }
+ // need to close the searcher here??? we shouldn't have to.
+ throw new RuntimeException(th);
+ }
+
+ final SolrIndexSearcher newSearcher=tmp;
+
+ RefCounted<SolrIndexSearcher> currSearcherHolder=null;
+ final RefCounted<SolrIndexSearcher> newSearchHolder=newHolder(newSearcher);
+ if (returnSearcher) newSearchHolder.incref();
+
+ // a signal to decrement onDeckSearchers if something goes wrong.
+ final boolean[] decrementOnDeckCount=new boolean[1];
+ decrementOnDeckCount[0]=true;
+
+ try {
+
+ synchronized (searcherLock) {
+ if (_searcher == null) {
+ // if there isn't a current searcher then register this one
+ // before warming is complete instead of waiting.
+ registerSearcher(newSearchHolder);
+ decrementOnDeckCount[0]=false;
+ } else {
+ // get a reference to the current searcher for purposes of autowarming.
+ currSearcherHolder=_searcher;
+ currSearcherHolder.incref();
+ }
+ }
+
+
+ final SolrIndexSearcher currSearcher = currSearcherHolder==null ? null : currSearcherHolder.get();
+
+ //
+ // Note! if we registered the new searcher (but didn't increment it's
+ // reference count because returnSearcher==false, it's possible for
+ // someone else to register another searcher, and thus cause newSearcher
+ // to close while we are warming.
+ //
+ // Should we protect against that by incrementing the reference count?
+ // Maybe we should just let it fail? After all, if returnSearcher==false
+ // and newSearcher has been de-registered, what's the point of continuing?
+ //
+
+ Future future=null;
+
+ // warm the new searcher based on the current searcher.
+ // should this go before the other event handlers or after?
+ if (currSearcher != null) {
+ future = searcherExecutor.submit(
+ new Callable() {
+ public Object call() throws Exception {
+ try {
+ newSearcher.warm(currSearcher);
+ } catch (Throwable e) {
+ SolrException.logOnce(log,null,e);
+ }
+ return null;
+ }
+ }
+ );
+ }
+
+ if (currSearcher==null && firstSearcherListeners.size() > 0) {
+ future = searcherExecutor.submit(
+ new Callable() {
+ public Object call() throws Exception {
+ try {
+ for (SolrEventListener listener : firstSearcherListeners) {
+ listener.newSearcher(newSearcher,null);
+ }
+ } catch (Throwable e) {
+ SolrException.logOnce(log,null,e);
+ }
+ return null;
+ }
+ }
+ );
+ }
+
+ if (currSearcher!=null && newSearcherListeners.size() > 0) {
+ future = searcherExecutor.submit(
+ new Callable() {
+ public Object call() throws Exception {
+ try {
+ for (SolrEventListener listener : newSearcherListeners) {
+ listener.newSearcher(newSearcher,null);
+ }
+ } catch (Throwable e) {
+ SolrException.logOnce(log,null,e);
+ }
+ return null;
+ }
+ }
+ );
+ }
+
+ // WARNING: this code assumes a single threaded executor (that all tasks
+ // queued will finish first).
+ final RefCounted<SolrIndexSearcher> currSearcherHolderF = currSearcherHolder;
+ Future finalFuture=null;
+ if (currSearcherHolder != null) {
+ finalFuture = searcherExecutor.submit(
+ new Callable() {
+ public Object call() throws Exception {
+ try {
+ // signal that we no longer need to decrement
+ // the count *before* registering the searcher since
+ // registertSearcher will decrement even if it errors.
+ decrementOnDeckCount[0]=false;
+ registerSearcher(newSearchHolder);
+ } catch (Throwable e) {
+ SolrException.logOnce(log,null,e);
+ } finally {
+ // we are all done with the old searcher we used
+ // for warming...
+ currSearcherHolderF.decref();
+ }
+ return null;
+ }
+ }
+ );
+ }
+
+ if (waitSearcher != null) {
+ waitSearcher[0] = finalFuture;
+ }
+
+ // Return the searcher as the warming tasks run in parallel
+ // callers may wait on the waitSearcher future returned.
+ return returnSearcher ? newSearchHolder : null;
+
+ }
+ catch (Exception e) {
+ SolrException.logOnce(log,null,e);
+ if (currSearcherHolder != null) currSearcherHolder.decref();
+
+ synchronized (searcherLock) {
+ if (decrementOnDeckCount[0]) {
+ onDeckSearchers--;
+ }
+ if (onDeckSearchers < 0) {
+ // sanity check... should never happen
+ log.severe("ERROR!!! onDeckSearchers after decrement=" + onDeckSearchers);
+ onDeckSearchers=0; // try and recover
+ }
+ // if we failed, we need to wake up at least one waiter to continue the process
+ searcherLock.notify();
+ }
+
+ // since the indexreader was already opened, assume we can continue on
+ // even though we got an exception.
+ return returnSearcher ? newSearchHolder : null;
+ }
+
+ }
+
+
+ private RefCounted<SolrIndexSearcher> newHolder(SolrIndexSearcher newSearcher) {
+ RefCounted<SolrIndexSearcher> holder = new RefCounted<SolrIndexSearcher>(newSearcher)
+ {
+ public void close() {
+ try {
+ resource.close();
+ } catch (IOException e) {
+ log.severe("Error closing searcher:" + SolrException.toStr(e));
+ }
+ }
+ };
+ holder.incref(); // set ref count to 1 to account for this._searcher
+ return holder;
+ }
+
+
+ // Take control of newSearcherHolder (which should have a reference count of at
+ // least 1 already. If the caller wishes to use the newSearcherHolder directly
+ // after registering it, then they should increment the reference count *before*
+ // calling this method.
+ //
+ // onDeckSearchers will also be decremented (it should have been incremented
+ // as a result of opening a new searcher).
+ private void registerSearcher(RefCounted<SolrIndexSearcher> newSearcherHolder) throws IOException {
+ synchronized (searcherLock) {
+ try {
+ if (_searcher != null) {
+ _searcher.decref(); // dec refcount for this._searcher
+ _searcher=null;
+ }
+
+ _searcher = newSearcherHolder;
+ SolrIndexSearcher newSearcher = newSearcherHolder.get();
+
+ SolrInfoRegistry.getRegistry().put("currentSearcher", newSearcher);
+ newSearcher.register(); // register subitems (caches)
+ log.info("Registered new searcher " + newSearcher);
+
+ } catch (Throwable e) {
+ log(e);
+ } finally {
+ // wake up anyone waiting for a searcher
+ // even in the face of errors.
+ onDeckSearchers--;
+ searcherLock.notifyAll();
+ }
+ }
+ }
+
+
+
+ public void closeSearcher() {
+ log.info("Closing main searcher on request.");
+ synchronized (searcherLock) {
+ if (_searcher != null) {
+ _searcher.decref(); // dec refcount for this._searcher
+ _searcher=null;
+ SolrInfoRegistry.getRegistry().remove("currentSearcher");
+ }
+ }
+ }
+
+
+
+ public void execute(SolrQueryRequest req, SolrQueryResponse rsp) {
+ SolrRequestHandler handler = getRequestHandler(req.getQueryType());
+ if (handler==null) {
+ log.warning("Unknown Request Handler '" + req.getQueryType() +"' :" + req);
+ throw new SolrException(400,"Unknown Request Handler '" + req.getQueryType() + "'", true);
+ }
+ handler.handleRequest(req,rsp);
+ log.info(req.getParamString()+ " 0 "+
+ (int)(rsp.getEndTime() - req.getStartTime()));
+ }
+
+
+
+
+
+ XmlPullParserFactory factory;
+ {
+ try {
+ factory = XmlPullParserFactory.newInstance();
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+ factory.setNamespaceAware(false);
+ }
+
+
+ private int findNextTag(XmlPullParser xpp, String tag) throws XmlPullParserException, IOException {
+ int eventType;
+ while((eventType=xpp.next()) != XmlPullParser.END_DOCUMENT) {
+ if(eventType == XmlPullParser.START_TAG) {
+ if (tag.equals(xpp.getName())) break;
+ }
+ }
+ return eventType;
+ }
+
+
+ public void update(Reader reader, Writer writer) {
+
+ // TODO: add param to specify maximum time to commit?
+
+ // todo - might be nice to separate command parsing w/ a factory
+ // then new commands could be added w/o risk to old ones
+
+
+ XmlPullParser xpp = null;
+ try {
+ xpp = factory.newPullParser();
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+
+ long startTime=System.currentTimeMillis();
+
+ try {
+ xpp.setInput(reader);
+ xpp.nextTag();
+
+ String currTag = xpp.getName();
+ if ("add".equals(currTag)) {
+ log.finest("SolrCore.update(add)");
+ AddUpdateCommand cmd = new AddUpdateCommand();
+ cmd.allowDups=false; // the default
+
+ int status=0;
+ boolean pendingAttr=false, committedAttr=false;
+ int attrcount = xpp.getAttributeCount();
+ for (int i=0; i<attrcount; i++) {
+ String attrName = xpp.getAttributeName(i);
+ String attrVal = xpp.getAttributeValue(i);
+ if ("allowDups".equals(attrName)) {
+ cmd.allowDups = StrUtils.parseBoolean(attrVal);
+ } else if ("overwritePending".equals(attrName)) {
+ cmd.overwritePending = StrUtils.parseBoolean(attrVal);
+ pendingAttr=true;
+ } else if ("overwriteCommitted".equals(attrName)) {
+ cmd.overwriteCommitted = StrUtils.parseBoolean(attrVal);
+ committedAttr=true;
+ } else {
+ log.warning("Unknown attribute id in add:" + attrName);
+ }
+ }
+
+ //set defaults for committed and pending based on allowDups value
+ if (!pendingAttr) cmd.overwritePending=!cmd.allowDups;
+ if (!committedAttr) cmd.overwriteCommitted=!cmd.allowDups;
+
+ DocumentBuilder builder = new DocumentBuilder(schema);
+ int eventType=0;
+ while(true) {
+ // this may be our second time through the loop in the case
+ // that there are multiple docs in the add... so make sure that
+ // objects can handle that.
+
+ cmd.id = null; // reset the id for this add
+
+ if (eventType !=0) {
+ eventType=xpp.getEventType();
+ if (eventType==XmlPullParser.END_DOCUMENT) break;
+ }
+ // eventType = xpp.next();
+ eventType = xpp.nextTag();
+ if (eventType == XmlPullParser.END_TAG || eventType == XmlPullParser.END_DOCUMENT) break; // should match </add>
+
+ try {
+ readDoc(builder,xpp);
+ builder.endDoc();
+ cmd.doc = builder.getDoc();
+ log.finest("adding doc...");
+ updateHandler.addDoc(cmd);
+ log.info("add "+status+" "+(System.currentTimeMillis()-startTime));
+ writer.write("<result status=\"" + status + "\"></result>");
+ } catch (SolrException e) {
+ log(e);
+ log.info("add "+e.code+" "+(System.currentTimeMillis()-startTime));
+ writeResult(writer,e);
+ // we may not have finised reading the XML for this cmd,
+ // so eat any unused input up till "</add>"
+ eventType = xpp.getEventType();
+ while (true) {
+ if ( eventType == XmlPullParser.END_DOCUMENT
+ || (eventType == XmlPullParser.END_TAG && "add".equals(xpp.getName())))
+ {
+ break;
+ }
+ eventType = xpp.next();
+ }
+ }
+ }
+
+ /***
+ while (findNextTag(xpp,"doc") != XmlPullParser.END_DOCUMENT) {
+ readDoc(builder,xpp);
+ Document doc = builder.endDoc();
+ indexWriter.addDocument(doc);
+ docsAdded++;
+ }
+ ***/
+
+ } // end add
+
+ else if ("commit".equals(currTag) || "optimize".equals(currTag)) {
+ log.finest("parsing "+currTag);
+ try {
+ CommitUpdateCommand cmd = new CommitUpdateCommand("optimize".equals(currTag));
+
+ boolean sawWaitSearcher=false, sawWaitFlush=false;
+ int attrcount = xpp.getAttributeCount();
+ for (int i=0; i<attrcount; i++) {
+ String attrName = xpp.getAttributeName(i);
+ String attrVal = xpp.getAttributeValue(i);
+ if ("waitFlush".equals(attrName)) {
+ cmd.waitFlush = StrUtils.parseBoolean(attrVal);
+ sawWaitFlush=true;
+ } else if ("waitSearcher".equals(attrName)) {
+ cmd.waitSearcher = StrUtils.parseBoolean(attrVal);
+ sawWaitSearcher=true;
+ } else {
+ log.warning("unexpected attribute commit/@" + attrName);
+ }
+ }
+
+ // If waitFlush is specified and waitSearcher wasn't, then
+ // clear waitSearcher.
+ if (sawWaitFlush && !sawWaitSearcher) {
+ cmd.waitSearcher=false;
+ }
+
+ updateHandler.commit(cmd);
+ if ("optimize".equals(currTag)) {
+ log.info("optimize 0 "+(System.currentTimeMillis()-startTime));
+ }
+ else {
+ log.info("commit 0 "+(System.currentTimeMillis()-startTime));
+ }
+ while (true) {
+ int eventType = xpp.nextTag();
+ if (eventType == XmlPullParser.END_TAG) break; // match </commit>
+ }
+ writer.write("<result status=\"0\"></result>");
+ } catch (SolrException e) {
+ log(e);
+ if ("optimize".equals(currTag)) {
+ log.info("optimize "+e.code+" "+
+ (System.currentTimeMillis()-startTime));
+ }
+ else {
+ log.info("commit "+e.code+" "+
+ (System.currentTimeMillis()-startTime));
+ }
+ writeResult(writer,e);
+ } catch (Exception e) {
+ SolrException.log(log, "Exception during commit/optimize",e);
+ writeResult(writer,e);
+ }
+ } // end commit
+
+ else if ("delete".equals(currTag)) {
+ log.finest("parsing delete");
+ try {
+ DeleteUpdateCommand cmd = new DeleteUpdateCommand();
+ cmd.fromPending=true;
+ cmd.fromCommitted=true;
+ int attrcount = xpp.getAttributeCount();
+ for (int i=0; i<attrcount; i++) {
+ String attrName = xpp.getAttributeName(i);
+ String attrVal = xpp.getAttributeValue(i);
+ if ("fromPending".equals(attrName)) {
+ cmd.fromPending = StrUtils.parseBoolean(attrVal);
+ } else if ("fromCommitted".equals(attrName)) {
+ cmd.fromCommitted = StrUtils.parseBoolean(attrVal);
+ } else {
+ log.warning("unexpected attribute delete/@" + attrName);
+ }
+ }
+
+ int eventType = xpp.nextTag();
+ currTag = xpp.getName();
+ String val = xpp.nextText();
+
+ if ("id".equals(currTag)) {
+ cmd.id = val;
+ updateHandler.delete(cmd);
+ log.info("delete(id " + val + ") 0 " +
+ (System.currentTimeMillis()-startTime));
+ } else if ("query".equals(currTag)) {
+ cmd.query = val;
+ updateHandler.deleteByQuery(cmd);
+ log.info("deleteByQuery(query " + val + ") 0 " +
+ (System.currentTimeMillis()-startTime));
+ } else {
+ log.warning("unexpected XML tag /delete/"+currTag);
+ throw new SolrException(400,"unexpected XML tag /delete/"+currTag);
+ }
+
+ writer.write("<result status=\"0\"></result>");
+
+ while (xpp.nextTag() != XmlPullParser.END_TAG);
+
+ } catch (SolrException e) {
+ log(e);
+ log.info("delete "+e.code+" "+(System.currentTimeMillis()-startTime));
+ writeResult(writer,e);
+ } catch (Exception e) {
+ log(e);
+ writeResult(writer,e);
+ }
+ } // end delete
+
+
+ } catch (XmlPullParserException e) {
+ log(e);
+ writeResult(writer,e);
+ } catch (IOException e) {
+ log(e);
+ writeResult(writer,e);
+ } catch (SolrException e) {
+ log(e);
+ log.info("update "+e.code+" "+(System.currentTimeMillis()-startTime));
+ writeResult(writer,e);
+ } catch (Throwable e) {
+ log(e);
+ writeResult(writer,e);
+ }
+
+ }
+
+ private void readDoc(DocumentBuilder builder, XmlPullParser xpp) throws IOException, XmlPullParserException {
+ // xpp should be at <doc> at this point
+
+ builder.startDoc();
+
+ int attrcount = xpp.getAttributeCount();
+ float docBoost = 1.0f;
+
+ for (int i=0; i<attrcount; i++) {
+ String attrName = xpp.getAttributeName(i);
+ String attrVal = xpp.getAttributeValue(i);
+ if ("boost".equals(attrName)) {
+ docBoost = Float.parseFloat(attrVal);
+ } else {
+ log.warning("Unknown attribute doc/@" + attrName);
+ }
+ }
+ if (docBoost != 1.0f) builder.setBoost(docBoost);
+
+ // while (findNextTag(xpp,"field") != XmlPullParser.END_DOCUMENT) {
+
+ while(true) {
+ int eventType = xpp.nextTag();
+ if (eventType == XmlPullParser.END_TAG) break; // </doc>
+
+ String tname=xpp.getName();
+ // System.out.println("FIELD READER AT TAG " + tname);
+
+ if (!"field".equals(tname)) {
+ log.warning("unexpected XML tag doc/"+tname);
+ throw new SolrException(400,"unexpected XML tag doc/"+tname);
+ }
+
+ //
+ // get field name and parse field attributes
+ //
+ attrcount = xpp.getAttributeCount();
+ String name=null;
+ float boost=1.0f;
+ boolean isNull=false;
+
+ for (int i=0; i<attrcount; i++) {
+ String attrName = xpp.getAttributeName(i);
+ String attrVal = xpp.getAttributeValue(i);
+ if ("name".equals(attrName)) {
+ name=attrVal;
+ } else if ("boost".equals(attrName)) {
+ boost=Float.parseFloat(attrVal);
+ } else if ("null".equals(attrName)) {
+ isNull=StrUtils.parseBoolean(attrVal);
+ } else {
+ log.warning("Unknown attribute doc/field/@" + attrName);
+ }
+ }
+
+ // now get the field value
+ String val = xpp.nextText(); // todo... text event for <field></field>???
+ // need this line for isNull???
+ // Don't add fields marked as null (for now at least)
+ if (!isNull) {
+ if (docBoost != 1.0f) {
+ builder.addField(name,val,docBoost);
+ } else {
+ builder.addField(name,val);
+ }
+ }
+
+ // do I have to do a nextTag here to read the end_tag?
+
+ } // end field loop
+
+ }
+
+
+ final public static void log(Throwable e) {
+ SolrException.logOnce(log,null,e);
+ }
+
+
+ final static void writeResult(Writer out, SolrException e) {
+ try {
+ XML.writeXML(out,"result",e.getMessage(),"status",e.code());
+ } catch (Exception ee) {
+ log.severe("Error writing to putput stream: "+ee);
+ }
+ }
+
+ final static void writeResult(Writer out, Throwable e) {
+ try {
+ XML.writeXML(out,"result",SolrException.toStr(e),"status","1");
+ } catch (Exception ee) {
+ log.severe("Error writing to putput stream: "+ee);
+ }
+ }
+
+
+}
+
+
+
+
Propchange: incubator/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/core/SolrEventListener.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/core/SolrEventListener.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/core/SolrEventListener.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/core/SolrEventListener.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.core;
+
+import org.apache.solr.util.NamedList;
+import org.apache.solr.search.SolrIndexSearcher;
+
+import java.util.logging.Logger;
+
+/**
+ * @author yonik
+ * @version $Id: SolrEventListener.java,v 1.4 2005/05/25 04:26:47 yonik Exp $
+ */
+public interface SolrEventListener {
+ static final Logger log = Logger.getLogger(SolrCore.class.getName());
+
+ public void init(NamedList args);
+
+ public void postCommit();
+
+ public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher);
+
+}
\ No newline at end of file
Propchange: incubator/solr/trunk/src/java/org/apache/solr/core/SolrEventListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/core/SolrException.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/core/SolrException.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/core/SolrException.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/core/SolrException.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,108 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.core;
+
+import java.util.logging.Logger;
+import java.io.CharArrayWriter;
+import java.io.PrintWriter;
+
+/**
+ * @author yonik
+ * @version $Id: SolrException.java,v 1.6 2005/06/14 20:42:26 yonik Exp $
+ */
+
+
+public class SolrException extends RuntimeException {
+ public boolean logged=false;
+
+ public SolrException(int code, String msg) {
+ super(msg);
+ this.code=code;
+ }
+ public SolrException(int code, String msg, boolean alreadyLogged) {
+ super(msg);
+ this.code=code;
+ this.logged=alreadyLogged;
+ }
+
+ public SolrException(int code, String msg, Throwable th, boolean alreadyLogged) {
+ super(msg,th);
+ this.code=code;
+ logged=alreadyLogged;
+ }
+
+ public SolrException(int code, String msg, Throwable th) {
+ this(code,msg,th,true);
+ }
+
+ public SolrException(int code, Throwable th) {
+ super(th);
+ this.code=code;
+ logged=true;
+ }
+
+ int code=0;
+ public int code() { return code; }
+
+
+
+
+ public void log(Logger log) { log(log,this); }
+ public static void log(Logger log, Throwable e) {
+ log.severe(toStr(e));
+ if (e instanceof SolrException) {
+ ((SolrException)e).logged = true;
+ }
+ }
+
+ public static void log(Logger log, String msg, Throwable e) {
+ log.severe(msg + ':' + toStr(e));
+ if (e instanceof SolrException) {
+ ((SolrException)e).logged = true;
+ }
+ }
+
+ public static void logOnce(Logger log, String msg, Throwable e) {
+ if (e instanceof SolrException) {
+ if(((SolrException)e).logged) return;
+ }
+ if (msg!=null) log(log,msg,e);
+ else log(log,e);
+ }
+
+
+ // public String toString() { return toStr(this); } // oops, inf loop
+ public String toString() { return super.toString(); }
+
+ public static String toStr(Throwable e) {
+ CharArrayWriter cw = new CharArrayWriter();
+ PrintWriter pw = new PrintWriter(cw);
+ e.printStackTrace(pw);
+ pw.flush();
+ return cw.toString();
+
+/** This doesn't work for some reason!!!!!
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ System.out.println("The STRING:" + sw.toString());
+ return sw.toString();
+**/
+ }
+
+}
Propchange: incubator/solr/trunk/src/java/org/apache/solr/core/SolrException.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfo.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfo.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfo.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfo.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.core;
+
+import java.net.URL;
+import org.apache.solr.util.*;
+
+/**
+ * @author ronp
+ * @version $Id: SolrInfo.java,v 1.3 2005/05/02 19:04:59 ronp Exp $
+ */
+
+// MBean pattern for holding various ui friendly strings and URLs
+// for use by objects which are 'plugable' to make administering
+// production use easier
+ // name - simple common usage name, e.g. BasicQueryHandler
+ // version - simple common usage version, e.g. 2.0
+ // description - simple one or two line description
+ // cvsId - yes, really the CVS Id (type 'man co')
+ // cvsName - yes, really the CVS Name (type 'man co')
+ // cvsSource - yes, really the CVS Source (type 'man co')
+ // docs - URL list: TWIKI, Faq, Design doc, something! :)
+
+abstract class SolrInfo implements SolrInfoMBean {
+ public static String _cvsId="$Id: SolrInfo.java,v 1.3 2005/05/02 19:04:59 ronp Exp $";
+ public static String _cvsSource="$Source: /cvs/main/searching/solr/solarcore/src/solr/SolrInfo.java,v $";
+ public static String _cvsName="$Name: $";
+
+
+ public String getName() { return this.name; }
+ public String getVersion() { return this.version; }
+ public String getDescription() { return this.description; }
+ public Category getCategory() { return SolrInfoMBean.Category.QUERYHANDLER; }
+ public String getCvsId() { return this.cvsId; }
+ public String getCvsName() { return this.cvsName; }
+ public String getCvsSource() { return this.cvsSource; }
+ public URL[] getDocs() { return this.docs; }
+ public NamedList getStatistics() { return null; }
+
+
+ public void setName(String name ) { this.name = name; }
+ public void setVersion(String vers) { this.version = vers; }
+ public void setDescription(String desc) { this.description = desc; }
+ public void setCvsId(String cvsId) { this.cvsId = cvsId; }
+ public void setCvsName(String cvsName) { this.cvsName = cvsName; }
+ public void setCvsSource(String cvsSource) { this.cvsSource = cvsSource; }
+ public void setDocs(URL[] docs) { this.docs = docs; }
+
+ public void addDoc(URL doc)
+ {
+ if (doc == null) {
+ // should throw runtime exception
+ return;
+ }
+ if (docs != null) {
+ URL[] newDocs = new URL[docs.length+1];
+ int i;
+ for (i = 0; i < docs.length; i++) {
+ newDocs[i] = docs[i];
+ }
+ newDocs[i] = doc;
+ docs = newDocs;
+ } else {
+ docs = new URL[1];
+ docs[0] = doc;
+ }
+ }
+
+ public void addDoc(String doc)
+ {
+ if (doc == null) {
+ // should throw runtime exception
+ return;
+ }
+ try {
+ URL docURL = new URL(doc);
+ addDoc(docURL);
+ } catch (Exception e) {
+ // ignore for now
+ }
+ }
+
+ private String name;
+ private String version;
+ private String description;
+ public String cvsId;
+ public String cvsSource;
+ public String cvsName;
+ private URL[] docs;
+}
Propchange: incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfo.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoMBean.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoMBean.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoMBean.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoMBean.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.core;
+
+import java.net.URL;
+import org.apache.solr.util.*;
+
+/**
+ * @author ronp
+ * @version $Id: SolrInfoMBean.java,v 1.3 2005/05/04 19:15:23 ronp Exp $
+ */
+
+// MBean interface for getting various ui friendly strings and URLs
+// for use by objects which are 'plugable' to make administering
+// production use easier
+ // name - simple common usage name, e.g. BasicQueryHandler
+ // version - simple common usage version, e.g. 2.0
+ // description - simple one or two line description
+ // cvsId - yes, really the CVS Id (type 'man co')
+ // cvsName - yes, really the CVS Name (type 'man co')
+ // cvsSource - yes, really the CVS Source (type 'man co')
+ // docs - URL list: TWIKI, Faq, Design doc, something! :)
+
+public interface SolrInfoMBean {
+
+ public enum Category { CORE, QUERYHANDLER, UPDATEHANDLER, CACHE, OTHER };
+
+ public String getName();
+ public String getVersion();
+ public String getDescription();
+ public Category getCategory();
+ public String getCvsId();
+ public String getCvsName();
+ public String getCvsSource();
+ public URL[] getDocs();
+ public NamedList getStatistics();
+
+}
Propchange: incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoMBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoRegistry.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoRegistry.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoRegistry.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoRegistry.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.core;
+
+import org.apache.solr.core.SolrInfoMBean;
+
+import java.util.*;
+
+/**
+ * @author ronp
+ * @version $Id: SolrInfoRegistry.java,v 1.5 2005/05/14 03:34:39 yonik Exp $
+ */
+
+// A Registry to hold a collection of SolrInfo objects
+
+public class SolrInfoRegistry {
+ public static final String cvsId="$Id: SolrInfoRegistry.java,v 1.5 2005/05/14 03:34:39 yonik Exp $";
+ public static final String cvsSource="$Source: /cvs/main/searching/solr/solarcore/src/solr/SolrInfoRegistry.java,v $";
+ public static final String cvsName="$Name: $";
+
+ private static final Map<String,SolrInfoMBean> inst = Collections.synchronizedMap(new LinkedHashMap<String,SolrInfoMBean>());
+
+ public static Map<String, SolrInfoMBean> getRegistry()
+ {
+ return inst;
+ }
+
+}
Propchange: incubator/solr/trunk/src/java/org/apache/solr/core/SolrInfoRegistry.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/request/LocalSolrQueryRequest.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/request/LocalSolrQueryRequest.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/LocalSolrQueryRequest.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/LocalSolrQueryRequest.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,198 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.request;
+
+import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.util.RefCounted;
+import org.apache.solr.util.StrUtils;
+import org.apache.solr.util.NamedList;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.core.SolrCore;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author yonik
+ * @version $Id: LocalSolrQueryRequest.java,v 1.6 2005/06/02 22:03:38 yonik Exp $
+ */
+public class LocalSolrQueryRequest extends SolrQueryRequestBase {
+ private final NamedList args;
+ private final String query;
+ private final String qtype;
+ private final int start;
+ private final int limit;
+
+ public final static Map emptyArgs = new HashMap(0,1);
+
+ public LocalSolrQueryRequest(SolrCore core, String query, String qtype, int start, int limit, Map args) {
+ super(core);
+ this.query=query;
+ this.qtype=qtype;
+ this.start=start;
+ this.limit=limit;
+
+ this.args = new NamedList();
+ if (query!=null) this.args.add(SolrQueryRequestBase.QUERY_NAME, query);
+ if (qtype!=null) this.args.add(SolrQueryRequestBase.QUERYTYPE_NAME, qtype);
+ this.args.add(SolrQueryRequestBase.START_NAME, Integer.toString(start));
+ this.args.add(SolrQueryRequestBase.ROWS_NAME, Integer.toString(limit));
+
+ if (args!=null) this.args.addAll(args);
+ }
+
+
+ public LocalSolrQueryRequest(SolrCore core, NamedList args) {
+ super(core);
+ this.args=args;
+ this.query=getStrParam(QUERY_NAME,null);
+ this.qtype=getStrParam(QUERYTYPE_NAME,null);;
+ this.start=getIntParam(START_NAME,0);
+ this.limit=getIntParam(ROWS_NAME,10);
+ }
+
+
+ public String getParam(String name) {
+ return (String)args.get(name);
+ }
+
+ public String getQueryString() {
+ return query;
+ }
+
+ // signifies the syntax and the handler that should be used
+ // to execute this query.
+ public String getQueryType() {
+ return qtype;
+ }
+
+
+ // starting position in matches to return to client
+ public int getStart() {
+ return start;
+ }
+
+ // number of matching documents to return
+ public int getLimit() {
+ return limit;
+ }
+
+ final long startTime=System.currentTimeMillis();
+ // Get the start time of this request in milliseconds
+ public long getStartTime() {
+ return startTime;
+ }
+
+ // The index searcher associated with this request
+ RefCounted<SolrIndexSearcher> searcherHolder;
+ public SolrIndexSearcher getSearcher() {
+ // should this reach out and get a searcher from the core singleton, or
+ // should the core populate one in a factory method to create requests?
+ // or there could be a setSearcher() method that Solr calls
+
+ if (searcherHolder==null) {
+ searcherHolder = core.getSearcher();
+ }
+
+ return searcherHolder.get();
+ }
+
+ // The solr core (coordinator, etc) associated with this request
+ public SolrCore getCore() {
+ return core;
+ }
+
+ // The index schema associated with this request
+ public IndexSchema getSchema() {
+ return core.getSchema();
+ }
+
+ public String getParamString() {
+ StringBuilder sb = new StringBuilder(128);
+ try {
+
+ boolean first=true;
+ if (query!=null) {
+ if (!first) {
+ sb.append('&');
+ }
+ first=false;
+ sb.append("q=");
+ StrUtils.partialURLEncodeVal(sb,query);
+ }
+
+ // null, "", and "standard" are all the default query handler.
+ if (qtype!=null && !(qtype.equals("") || qtype.equals("standard"))) {
+ if (!first) {
+ sb.append('&');
+ }
+ first=false;
+ sb.append("qt=");
+ sb.append(qtype);
+ }
+
+ if (start!=0) {
+ if (!first) {
+ sb.append('&');
+ }
+ first=false;
+ sb.append("start=");
+ sb.append(start);
+ }
+
+ if (!first) {
+ sb.append('&');
+ }
+ first=false;
+ sb.append("rows=");
+ sb.append(limit);
+
+ if (args != null && args.size() > 0) {
+ for (int i=0; i<args.size(); i++) {
+ if (!first) {
+ sb.append('&');
+ }
+ first=false;
+
+ sb.append(args.getName(i));
+ sb.append('=');
+ StrUtils.partialURLEncodeVal(sb,args.getVal(i).toString());
+ }
+ }
+
+ } catch (Exception e) {
+ // should never happen... we only needed this because
+ // partialURLEncodeVal can throw an IOException, but it
+ // never will when adding to a StringBuilder.
+ throw new RuntimeException(e);
+ }
+
+ return sb.toString();
+ }
+
+
+ public void close() {
+ if (searcherHolder!=null) {
+ searcherHolder.decref();
+ }
+ }
+
+
+
+}
+
+
Propchange: incubator/solr/trunk/src/java/org/apache/solr/request/LocalSolrQueryRequest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.request;
+
+import java.io.Writer;
+import java.io.IOException;
+
+/**
+ * @author yonik
+ * @version $Id: QueryResponseWriter.java,v 1.2 2005/04/24 02:53:35 yonik Exp $
+ */
+public interface QueryResponseWriter {
+ public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response) throws IOException;
+}
+
Propchange: incubator/solr/trunk/src/java/org/apache/solr/request/QueryResponseWriter.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequest.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequest.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequest.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequest.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.request;
+
+import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.core.SolrCore;
+
+/**
+ * @author yonik
+ * @version $Id: SolrQueryRequest.java,v 1.3 2005/05/10 19:40:12 yonik Exp $
+ */
+public interface SolrQueryRequest {
+ public String getParam(String name);
+
+ public String getQueryString();
+
+ // signifies the syntax and the handler that should be used
+ // to execute this query.
+ public String getQueryType();
+
+ // starting position in matches to return to client
+ public int getStart();
+
+ // number of matching documents to return
+ public int getLimit();
+
+ // Get the start time of this request in milliseconds
+ public long getStartTime();
+
+ // The index searcher associated with this request
+ public SolrIndexSearcher getSearcher();
+
+ // The solr core (coordinator, etc) associated with this request
+ public SolrCore getCore();
+
+ // The index schema associated with this request
+ public IndexSchema getSchema();
+
+ /**
+ * Returns a string representing all the important parameters.
+ * Suitable for logging.
+ */
+ public String getParamString();
+
+ /******
+ // Get the current elapsed time in milliseconds
+ public long getElapsedTime();
+ ******/
+}
+
Propchange: incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequestBase.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequestBase.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequestBase.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequestBase.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,130 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.request;
+
+import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.util.RefCounted;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.SolrException;
+
+/**
+* @author yonik
+* @version $Id: SolrQueryRequestBase.java,v 1.6 2005/06/12 02:36:09 yonik Exp $
+*/
+public abstract class SolrQueryRequestBase implements SolrQueryRequest {
+ // some standard query argument names
+ public static final String QUERY_NAME="q";
+ public static final String START_NAME="start";
+ public static final String ROWS_NAME="rows";
+ public static final String XSL_NAME="xsl";
+ public static final String QUERYTYPE_NAME="qt";
+
+
+ protected final SolrCore core;
+
+ public SolrQueryRequestBase(SolrCore core) {
+ this.core=core;
+ }
+
+ public int getIntParam(String name) {
+ String s = getParam(name);
+ if (s==null) {
+ throw new SolrException(500,"Missing required parameter '"+name+"' from " + this);
+ }
+ return Integer.parseInt(s);
+ }
+
+ public int getIntParam(String name, int defval) {
+ String s = getParam(name);
+ return s==null ? defval : Integer.parseInt(s);
+ }
+
+ public String getStrParam(String name) {
+ String s = getParam(name);
+ if (s==null) {
+ throw new SolrException(500,"Missing required parameter '"+name+"' from " + this);
+ }
+ return s;
+ }
+
+ public String getStrParam(String name, String defval) {
+ String s = getParam(name);
+ return s==null ? defval : s;
+ }
+
+ public String getQueryString() {
+ return getParam(QUERY_NAME);
+ }
+
+ public String getQueryType() {
+ return getParam(QUERYTYPE_NAME);
+ }
+
+ // starting position in matches to return to client
+ public int getStart() {
+ return getIntParam(START_NAME, 0);
+ }
+
+ // number of matching documents to return
+ public int getLimit() {
+ return getIntParam(ROWS_NAME, 10);
+ }
+
+
+ protected final long startTime=System.currentTimeMillis();
+ // Get the start time of this request in milliseconds
+ public long getStartTime() {
+ return startTime;
+ }
+
+ // The index searcher associated with this request
+ protected RefCounted<SolrIndexSearcher> searcherHolder;
+ public SolrIndexSearcher getSearcher() {
+ // should this reach out and get a searcher from the core singleton, or
+ // should the core populate one in a factory method to create requests?
+ // or there could be a setSearcher() method that Solr calls
+
+ if (searcherHolder==null) {
+ searcherHolder = core.getSearcher();
+ }
+
+ return searcherHolder.get();
+ }
+
+ // The solr core (coordinator, etc) associated with this request
+ public SolrCore getCore() {
+ return core;
+ }
+
+ // The index schema associated with this request
+ public IndexSchema getSchema() {
+ return core.getSchema();
+ }
+
+
+ public void close() {
+ if (searcherHolder!=null) {
+ searcherHolder.decref();
+ }
+ }
+
+ public String toString() {
+ return this.getClass().getSimpleName() + '{' + getParamString() + '}';
+ }
+
+}
Propchange: incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryRequestBase.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,125 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.request;
+
+import org.apache.solr.util.NamedList;
+
+import java.util.*;
+
+/**
+ * <code>SolrQueryResponse</code> is used by a query handler to return
+ * the response to a query.
+ * @author yonik
+ * @version $Id: SolrQueryResponse.java,v 1.5 2005/08/10 04:27:04 yonik Exp $
+ * @since solr 0.9
+ */
+
+public class SolrQueryResponse {
+
+ protected NamedList values = new NamedList();
+ // current holder for user defined values
+
+ protected Set<String> defaultReturnFields;
+
+ // error if this is set...
+ protected Exception err;
+
+ /***
+ // another way of returning an error
+ int errCode;
+ String errMsg;
+ ***/
+
+ public NamedList getValues() { return values; }
+
+ /**
+ * Sets a list of all the named values to return.
+ */
+ public void setAllValues(NamedList nameValuePairs) {
+ values=nameValuePairs;
+ }
+
+ /**
+ * Sets the document field names of fields to return by default.
+ */
+ public void setReturnFields(Set<String> fields) {
+ defaultReturnFields=fields;
+ }
+ // TODO: should this be represented as a String[] such
+ // that order can be maintained if needed?
+
+ /**
+ * The document field names to return by default.
+ */
+ public Set<String> getReturnFields() {
+ return defaultReturnFields;
+ }
+
+
+ /**
+ * Appends a named value to the list of named values to be returned.
+ * @param name the name of the value - may be null if unnamed
+ * @param val the value to add - also may be null since null is a legal value
+ */
+ public void add(String name, Object val) {
+ values.add(name,val);
+ }
+
+ /**
+ * Causes an error to be returned instead of the results.
+ */
+ public void setException(Exception e) {
+ err=e;
+ }
+
+ /**
+ * Returns an Exception if there was a fatal error in processing the request.
+ * Returns null if the request succeeded.
+ */
+ public Exception getException() {
+ return err;
+ }
+
+ // Get and Set the endtime in milliseconds... used
+ // to calculate query time.
+ protected long endtime;
+
+ /** Time in milliseconds when the response officially finished.
+ */
+ public long getEndTime() {
+ if (endtime==0) {
+ setEndTime();
+ }
+ return endtime;
+ }
+
+ /**
+ * Stop the timer for how long this query took.
+ */
+ public long setEndTime() {
+ return setEndTime(System.currentTimeMillis());
+ }
+
+ public long setEndTime(long endtime) {
+ if (endtime!=0) {
+ this.endtime=endtime;
+ }
+ return this.endtime;
+ }
+
+
+}
Propchange: incubator/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/request/SolrRequestHandler.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/request/SolrRequestHandler.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/SolrRequestHandler.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/SolrRequestHandler.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.request;
+
+import org.apache.solr.util.NamedList;
+import org.apache.solr.core.SolrInfoMBean;
+
+/**
+ * Implementations of <code>SolrRequestHandler</code> are called to handle query requests.
+ *
+ * Different <code>SolrRequestHandler</code>s are registered with the <code>SolrCore</code>.
+ * One way to register a SolrRequestHandler with the core is thorugh the <code>solarconfig.xml</code> file.
+ * <p>
+ * Example <code>solarconfig.xml</code> entry to register a <code>SolrRequestHandler</code> implementation to
+ * handle all queries with a query type of "test":
+ * <p>
+ * <code>
+ * <requestHandler name="test" class="solr.tst.TestRequestHandler" />
+ * </code>
+ * <p>
+ * A single instance of any registered SolrRequestHandler is created
+ * via the default constructor and is reused for all relevant queries.
+ *
+ * @author yonik
+ * @version $Id: SolrRequestHandler.java,v 1.7 2005/12/02 04:31:06 yonik Exp $
+ */
+public interface SolrRequestHandler extends SolrInfoMBean {
+
+ /** <code>init</code> will be called just once, immediately after creation.
+ * <p>The args are user-level initialization parameters that
+ * may be specified when declaring a request handler in
+ * solarconfig.xml
+ */
+ public void init(NamedList args);
+
+
+ /**
+ * Handles a query request. This method must be thread safe.
+ * <p>
+ * Information about the request may be obtained from <code>req</code> and
+ * response information may be set using <code>rsp</code>.
+ * <p>
+ * There are no mandatory actions that handleRequest must perform.
+ * An empty handleRequest implementation would fulfill
+ * all interface obligations.
+ */
+ public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp);
+}
+
Propchange: incubator/solr/trunk/src/java/org/apache/solr/request/SolrRequestHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,225 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.request;
+
+import org.apache.lucene.search.*;
+import org.apache.lucene.document.Document;
+
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.logging.Level;
+import java.util.regex.Pattern;
+import java.io.IOException;
+import java.net.URL;
+
+import org.apache.solr.util.StrUtils;
+import org.apache.solr.util.NamedList;
+import org.apache.solr.search.*;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.core.SolrException;
+
+/**
+ * @author yonik
+ * @version $Id: StandardRequestHandler.java,v 1.17 2005/12/02 04:31:06 yonik Exp $
+ */
+public class StandardRequestHandler implements SolrRequestHandler, SolrInfoMBean {
+
+ // statistics
+ // TODO: should we bother synchronizing these, or is an off-by-one error
+ // acceptable every million requests or so?
+ long numRequests;
+ long numErrors;
+
+
+ public void init(NamedList args) {
+ SolrCore.log.log(Level.INFO, "Unused request handler arguments:" + args);
+ }
+
+
+ private final Pattern splitList=Pattern.compile(",| ");
+
+ public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
+ numRequests++;
+
+
+ // TODO: test if lucene will accept an escaped ';', otherwise
+ // we need to un-escape them before we pass to QueryParser
+ try {
+ String sreq = req.getQueryString();
+ String debug = req.getParam("debugQuery");
+
+ // find fieldnames to return (fieldlist)
+ String fl = req.getParam("fl");
+ int flags=0;
+ if (fl != null) {
+ // TODO - this could become more efficient if widely used.
+ // TODO - should field order be maintained?
+ String[] flst = splitList.split(fl,0);
+ if (flst.length > 0 && !(flst.length==1 && flst[0].length()==0)) {
+ Set<String> set = new HashSet<String>();
+ for (String fname : flst) {
+ if ("score".equals(fname)) flags |= SolrIndexSearcher.GET_SCORES;
+ set.add(fname);
+ }
+ rsp.setReturnFields(set);
+ }
+ }
+
+ if (sreq==null) throw new SolrException(400,"Missing queryString");
+ List<String> commands = StrUtils.splitSmart(sreq,';');
+
+ String qs = commands.size() >= 1 ? commands.get(0) : "";
+ Query query = QueryParsing.parseQuery(qs, req.getSchema());
+
+ // If the first non-query, non-filter command is a simple sort on an indexed field, then
+ // we can use the Lucene sort ability.
+ Sort sort = null;
+ if (commands.size() >= 2) {
+ QueryParsing.SortSpec sortSpec = QueryParsing.parseSort(commands.get(1), req.getSchema());
+ if (sortSpec != null) {
+ sort = sortSpec.getSort();
+ // ignore the count for now... it's currently only controlled by start & limit on req
+ // count = sortSpec.getCount();
+ }
+ }
+
+ DocList results = req.getSearcher().getDocList(query, null, sort, req.getStart(), req.getLimit(), flags);
+ rsp.add(null,results);
+
+ if (debug!=null) {
+ NamedList dbg = new NamedList();
+ try {
+ dbg.add("querystring",qs);
+ dbg.add("parsedquery",QueryParsing.toString(query,req.getSchema()));
+ dbg.add("explain", getExplainList(query, results, req.getSearcher(), req.getSchema()));
+ String otherQueryS = req.getParam("explainOther");
+ if (otherQueryS != null && otherQueryS.length() > 0) {
+ DocList otherResults = doQuery(otherQueryS,req.getSearcher(), req.getSchema(),0,10);
+ dbg.add("otherQuery",otherQueryS);
+ dbg.add("explainOther", getExplainList(query, otherResults, req.getSearcher(), req.getSchema()));
+ }
+ } catch (Exception e) {
+ SolrException.logOnce(SolrCore.log,"Exception during debug:",e);
+ dbg.add("exception_during_debug", SolrException.toStr(e));
+ }
+ rsp.add("debug",dbg);
+ }
+
+ } catch (SolrException e) {
+ rsp.setException(e);
+ numErrors++;
+ return;
+ } catch (Exception e) {
+ SolrException.log(SolrCore.log,e);
+ rsp.setException(e);
+ numErrors++;
+ return;
+ }
+ }
+
+ private NamedList getExplainList(Query query, DocList results, SolrIndexSearcher searcher, IndexSchema schema) throws IOException {
+ NamedList explainList = new NamedList();
+ DocIterator iterator = results.iterator();
+ for (int i=0; i<results.size(); i++) {
+ int id = iterator.nextDoc();
+
+ Explanation explain = searcher.explain(query, id);
+ //explainList.add(Integer.toString(id), explain.toString().split("\n"));
+
+ Document doc = searcher.doc(id);
+ String strid = schema.printableUniqueKey(doc);
+ String docname = "";
+ if (strid != null) docname="id="+strid+",";
+ docname = docname + "internal_docid="+id;
+
+ explainList.add(docname, "\n" +explain.toString());
+ }
+ return explainList;
+ }
+
+
+ private DocList doQuery(String sreq, SolrIndexSearcher searcher, IndexSchema schema, int start, int limit) throws IOException {
+ List<String> commands = StrUtils.splitSmart(sreq,';');
+
+ String qs = commands.size() >= 1 ? commands.get(0) : "";
+ Query query = QueryParsing.parseQuery(qs, schema);
+
+ // If the first non-query, non-filter command is a simple sort on an indexed field, then
+ // we can use the Lucene sort ability.
+ Sort sort = null;
+ if (commands.size() >= 2) {
+ QueryParsing.SortSpec sortSpec = QueryParsing.parseSort(commands.get(1), schema);
+ if (sortSpec != null) {
+ sort = sortSpec.getSort();
+ if (sortSpec.getCount() >= 0) {
+ limit = sortSpec.getCount();
+ }
+ }
+ }
+
+ DocList results = searcher.getDocList(query,(DocSet)null, sort, start, limit);
+ return results;
+ }
+
+
+
+ //////////////////////// SolrInfoMBeans methods //////////////////////
+
+
+ public String getName() {
+ return StandardRequestHandler.class.getName();
+ }
+
+ public String getVersion() {
+ return SolrCore.version;
+ }
+
+ public String getDescription() {
+ return "The standard Solr request handler";
+ }
+
+ public Category getCategory() {
+ return Category.QUERYHANDLER;
+ }
+
+ public String getCvsId() {
+ return "$Id: StandardRequestHandler.java,v 1.17 2005/12/02 04:31:06 yonik Exp $";
+ }
+
+ public String getCvsName() {
+ return "$Name: $";
+ }
+
+ public String getCvsSource() {
+ return "$Source: /cvs/main/searching/solr/solarcore/src/solr/StandardRequestHandler.java,v $";
+ }
+
+ public URL[] getDocs() {
+ return null;
+ }
+
+ public NamedList getStatistics() {
+ NamedList lst = new NamedList();
+ lst.add("requests", numRequests);
+ lst.add("errors", numErrors);
+ return lst;
+ }
+}
+
Propchange: incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java
URL: http://svn.apache.org/viewcvs/incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java?rev=372455&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java (added)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java Wed Jan 25 21:37:29 2006
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+package org.apache.solr.request;
+
+import java.io.Writer;
+import java.io.IOException;
+
+/**
+ * @author yonik
+ * @version $Id: XMLResponseWriter.java,v 1.6 2005/04/24 02:53:35 yonik Exp $
+ */
+
+public class XMLResponseWriter implements QueryResponseWriter {
+ public void write(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
+ XMLWriter.writeResponse(writer,req,rsp);
+ }
+}
+
+
Propchange: incubator/solr/trunk/src/java/org/apache/solr/request/XMLResponseWriter.java
------------------------------------------------------------------------------
svn:eol-style = native