Source Code Cross Referenced for SolrCore.java in  » Search-Engine » apache-solr-1.2.0 » org » apache » solr » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Search Engine » apache solr 1.2.0 » org.apache.solr.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */package org.apache.solr.core;
017:
018:        import java.io.File;
019:        import java.io.IOException;
020:        import java.util.ArrayList;
021:        import java.util.HashMap;
022:        import java.util.List;
023:        import java.util.Map;
024:        import java.util.concurrent.Callable;
025:        import java.util.concurrent.ExecutorService;
026:        import java.util.concurrent.Executors;
027:        import java.util.concurrent.Future;
028:        import java.util.logging.Logger;
029:
030:        import javax.xml.xpath.XPathConstants;
031:
032:        import org.apache.lucene.index.IndexReader;
033:        import org.apache.lucene.index.IndexWriter;
034:        import org.apache.lucene.search.BooleanQuery;
035:        import org.apache.lucene.store.Directory;
036:        import org.apache.lucene.store.FSDirectory;
037:        import org.apache.solr.request.JSONResponseWriter;
038:        import org.apache.solr.request.PythonResponseWriter;
039:        import org.apache.solr.request.QueryResponseWriter;
040:        import org.apache.solr.request.RubyResponseWriter;
041:        import org.apache.solr.request.SolrParams;
042:        import org.apache.solr.request.SolrQueryRequest;
043:        import org.apache.solr.request.SolrQueryResponse;
044:        import org.apache.solr.request.SolrRequestHandler;
045:        import org.apache.solr.request.XMLResponseWriter;
046:        import org.apache.solr.request.SolrParams.EchoParamStyle;
047:        import org.apache.solr.schema.IndexSchema;
048:        import org.apache.solr.search.SolrIndexSearcher;
049:        import org.apache.solr.update.DirectUpdateHandler;
050:        import org.apache.solr.update.SolrIndexConfig;
051:        import org.apache.solr.update.SolrIndexWriter;
052:        import org.apache.solr.update.UpdateHandler;
053:        import org.apache.solr.util.DOMUtil;
054:        import org.apache.solr.util.NamedList;
055:        import org.apache.solr.util.RefCounted;
056:        import org.apache.solr.util.SimpleOrderedMap;
057:        import org.w3c.dom.Element;
058:        import org.w3c.dom.Node;
059:        import org.w3c.dom.NodeList;
060:
061:        /**
062:         * @author yonik
063:         * @author <a href='mailto:mbaranczak@epublishing.com'> Mike Baranczak </a> 
064:         * @version $Id: SolrCore.java 542679 2007-05-29 22:28:21Z ryan $
065:         */
066:
067:        public final class SolrCore {
068:            public static final String version = "1.0";
069:
070:            public static Logger log = Logger.getLogger(SolrCore.class
071:                    .getName());
072:
073:            private final IndexSchema schema;
074:            private final String dataDir;
075:            private final String index_path;
076:            private final UpdateHandler updateHandler;
077:            private static final long startTime = System.currentTimeMillis();
078:            private final RequestHandlers reqHandlers = new RequestHandlers();
079:
080:            public long getStartTime() {
081:                return startTime;
082:            }
083:
084:            public static SolrIndexConfig mainIndexConfig = new SolrIndexConfig(
085:                    "mainIndex");
086:
087:            static {
088:                BooleanQuery.setMaxClauseCount(SolrConfig.config.getInt(
089:                        "query/maxBooleanClauses", BooleanQuery
090:                                .getMaxClauseCount()));
091:                if (mainIndexConfig.writeLockTimeout != -1)
092:                    IndexWriter
093:                            .setDefaultWriteLockTimeout(mainIndexConfig.writeLockTimeout);
094:            }
095:
096:            public static List<SolrEventListener> parseListener(String path) {
097:                List<SolrEventListener> lst = new ArrayList<SolrEventListener>();
098:                log.info("Searching for listeners: " + path);
099:                NodeList nodes = (NodeList) SolrConfig.config.evaluate(path,
100:                        XPathConstants.NODESET);
101:                if (nodes != null) {
102:                    for (int i = 0; i < nodes.getLength(); i++) {
103:                        Node node = nodes.item(i);
104:                        String className = DOMUtil.getAttr(node, "class");
105:                        SolrEventListener listener = (SolrEventListener) Config
106:                                .newInstance(className);
107:                        listener.init(DOMUtil.childNodesToNamedList(node));
108:                        lst.add(listener);
109:                        log.info("added SolrEventListener: " + listener);
110:                    }
111:                }
112:                return lst;
113:            }
114:
115:            List<SolrEventListener> firstSearcherListeners;
116:            List<SolrEventListener> newSearcherListeners;
117:
118:            private void parseListeners() {
119:                firstSearcherListeners = parseListener("//listener[@event=\"firstSearcher\"]");
120:                newSearcherListeners = parseListener("//listener[@event=\"newSearcher\"]");
121:            }
122:
123:            public IndexSchema getSchema() {
124:                return schema;
125:            }
126:
127:            public String getDataDir() {
128:                return dataDir;
129:            }
130:
131:            public String getIndexDir() {
132:                return index_path;
133:            }
134:
135:            // gets a non-caching searcher
136:            public SolrIndexSearcher newSearcher(String name)
137:                    throws IOException {
138:                return new SolrIndexSearcher(schema, name, getIndexDir(), false);
139:            }
140:
141:            void initIndex() {
142:                try {
143:                    File dirFile = new File(getIndexDir());
144:                    boolean indexExists = dirFile.canRead();
145:
146:                    boolean removeLocks = SolrConfig.config.getBool(
147:                            "mainIndex/unlockOnStartup", false);
148:                    if (removeLocks) {
149:                        // to remove locks, the directory must already exist... so we create it
150:                        // if it didn't exist already...
151:                        Directory dir = FSDirectory.getDirectory(dirFile,
152:                                !indexExists);
153:                        if (IndexReader.isLocked(dir)) {
154:                            log.warning("WARNING: Solr index directory '"
155:                                    + getIndexDir()
156:                                    + "' is locked.  Unlocking...");
157:                            IndexReader.unlock(dir);
158:                        }
159:                    }
160:
161:                    // Create the index if it doesn't exist. Note that indexExists was tested *before*
162:                    // lock removal, since that will result in the creation of the directory.
163:                    if (!indexExists) {
164:                        log
165:                                .warning("Solr index directory '" + dirFile
166:                                        + "' doesn't exist."
167:                                        + " Creating new index...");
168:
169:                        SolrIndexWriter writer = new SolrIndexWriter(
170:                                "SolrCore.initIndex", getIndexDir(), true,
171:                                schema, mainIndexConfig);
172:                        writer.close();
173:
174:                    }
175:
176:                } catch (IOException e) {
177:                    throw new RuntimeException(e);
178:                }
179:            }
180:
181:            private UpdateHandler createUpdateHandler(String className) {
182:                try {
183:                    Class handlerClass = Config.findClass(className);
184:                    java.lang.reflect.Constructor cons = handlerClass
185:                            .getConstructor(new Class[] { SolrCore.class });
186:                    return (UpdateHandler) cons
187:                            .newInstance(new Object[] { this  });
188:                } catch (SolrException e) {
189:                    throw e;
190:                } catch (Exception e) {
191:                    throw new SolrException(
192:                            SolrException.ErrorCode.SERVER_ERROR,
193:                            "Error Instantiating Update Handler " + className,
194:                            e);
195:                }
196:            }
197:
198:            // Singleton for now...
199:            private static SolrCore core;
200:
201:            public static SolrCore getSolrCore() {
202:                synchronized (SolrCore.class) {
203:                    if (core == null)
204:                        core = new SolrCore(null, null);
205:                    return core;
206:                }
207:            }
208:
209:            public SolrCore(String dataDir, IndexSchema schema) {
210:                synchronized (SolrCore.class) {
211:                    // this is for backward compatibility (and also the reason
212:                    // the sync block is needed)
213:                    core = this ; // set singleton
214:
215:                    if (dataDir == null) {
216:                        dataDir = SolrConfig.config.get("dataDir", Config
217:                                .getInstanceDir()
218:                                + "data");
219:                    }
220:
221:                    log.info("Opening new SolrCore at "
222:                            + Config.getInstanceDir() + ", dataDir=" + dataDir);
223:
224:                    if (schema == null) {
225:                        schema = new IndexSchema("schema.xml");
226:                    }
227:
228:                    this .schema = schema;
229:                    this .dataDir = dataDir;
230:                    this .index_path = dataDir + "/" + "index";
231:
232:                    this .maxWarmingSearchers = SolrConfig.config.getInt(
233:                            "query/maxWarmingSearchers", Integer.MAX_VALUE);
234:
235:                    parseListeners();
236:
237:                    initIndex();
238:
239:                    initWriters();
240:
241:                    reqHandlers.initHandlersFromConfig(SolrConfig.config);
242:
243:                    try {
244:                        // Open the searcher *before* the handler so we don't end up opening
245:                        // one in the middle.
246:                        getSearcher(false, false, null);
247:
248:                        updateHandler = createUpdateHandler(SolrConfig.config
249:                                .get("updateHandler/@class",
250:                                        DirectUpdateHandler.class.getName()));
251:
252:                    } catch (IOException e) {
253:                        throw new RuntimeException(e);
254:                    }
255:                }
256:            }
257:
258:            public void close() {
259:                log.info("CLOSING SolrCore!");
260:                try {
261:                    closeSearcher();
262:                } catch (Exception e) {
263:                    SolrException.log(log, e);
264:                }
265:                try {
266:                    searcherExecutor.shutdown();
267:                } catch (Exception e) {
268:                    SolrException.log(log, e);
269:                }
270:                try {
271:                    updateHandler.close();
272:                } catch (Exception e) {
273:                    SolrException.log(log, e);
274:                }
275:            }
276:
277:            @Override
278:            protected void finalize() {
279:                close();
280:            }
281:
282:            ////////////////////////////////////////////////////////////////////////////////
283:            // Request Handler
284:            ////////////////////////////////////////////////////////////////////////////////
285:
286:            /**
287:             * Get the request handler registered to a given name.  
288:             * 
289:             * This function is thread safe.
290:             */
291:            public SolrRequestHandler getRequestHandler(String handlerName) {
292:                return reqHandlers.get(handlerName);
293:            }
294:
295:            /**
296:             * Returns an unmodifieable Map containing the registered handlers
297:             */
298:            public Map<String, SolrRequestHandler> getRequestHandlers() {
299:                return reqHandlers.getRequestHandlers();
300:            }
301:
302:            /**
303:             * Registers a handler at the specified location.  If one exists there, it will be replaced.
304:             * To remove a handler, register <code>null</code> at its path
305:             * 
306:             * Once registered the handler can be accessed through:
307:             * <pre>
308:             *   http://${host}:${port}/${context}/${handlerName}
309:             * or:  
310:             *   http://${host}:${port}/${context}/select?qt=${handlerName}
311:             * </pre>  
312:             * 
313:             * Handlers <em>must</em> be initalized before getting registered.  Registered
314:             * handlers can immediatly accept requests.
315:             * 
316:             * This call is thread safe.
317:             *  
318:             * @return the previous <code>SolrRequestHandler</code> registered to this name <code>null</code> if none.
319:             */
320:            public SolrRequestHandler registerRequestHandler(
321:                    String handlerName, SolrRequestHandler handler) {
322:                return reqHandlers.register(handlerName, handler);
323:            }
324:
325:            ////////////////////////////////////////////////////////////////////////////////
326:            // Update Handler
327:            ////////////////////////////////////////////////////////////////////////////////
328:
329:            /**
330:             * RequestHandlers need access to the updateHandler so they can all talk to the
331:             * same RAM indexer.  
332:             */
333:            public UpdateHandler getUpdateHandler() {
334:                return updateHandler;
335:            }
336:
337:            ////////////////////////////////////////////////////////////////////////////////
338:            // Searcher Control
339:            ////////////////////////////////////////////////////////////////////////////////
340:
341:            // The current searcher used to service queries.
342:            // Don't access this directly!!!! use getSearcher() to
343:            // get it (and it will increment the ref count at the same time)
344:            private RefCounted<SolrIndexSearcher> _searcher;
345:
346:            final ExecutorService searcherExecutor = Executors
347:                    .newSingleThreadExecutor();
348:            private int onDeckSearchers; // number of searchers preparing
349:            private Object searcherLock = new Object(); // the sync object for the searcher
350:            private final int maxWarmingSearchers; // max number of on-deck searchers allowed
351:
352:            public RefCounted<SolrIndexSearcher> getSearcher() {
353:                try {
354:                    return getSearcher(false, true, null);
355:                } catch (IOException e) {
356:                    SolrException.log(log, null, e);
357:                    return null;
358:                }
359:            }
360:
361:            /**
362:             * Get a {@link SolrIndexSearcher} or start the process of creating a new one.
363:             * <p>
364:             * The registered searcher is the default searcher used to service queries.
365:             * A searcher will normally be registered after all of the warming
366:             * and event handlers (newSearcher or firstSearcher events) have run.
367:             * In the case where there is no registered searcher, the newly created searcher will
368:             * be registered before running the event handlers (a slow searcher is better than no searcher).
369:             *
370:             * <p>
371:             * If <tt>forceNew==true</tt> then
372:             *  A new searcher will be opened and registered regardless of whether there is already
373:             *    a registered searcher or other searchers in the process of being created.
374:             * <p>
375:             * If <tt>forceNew==false</tt> then:<ul>
376:             *   <li>If a searcher is already registered, that searcher will be returned</li>
377:             *   <li>If no searcher is currently registered, but at least one is in the process of being created, then
378:             * this call will block until the first searcher is registered</li>
379:             *   <li>If no searcher is currently registered, and no searchers in the process of being registered, a new
380:             * searcher will be created.</li>
381:             * </ul>
382:             * <p>
383:             * If <tt>returnSearcher==true</tt> then a {@link RefCounted}&lt;{@link SolrIndexSearcher}&gt; will be returned with
384:             * the reference count incremented.  It <b>must</b> be decremented when no longer needed.
385:             * <p>
386:             * If <tt>waitSearcher!=null</tt> and a new {@link SolrIndexSearcher} was created,
387:             * then it is filled in with a Future that will return after the searcher is registered.  The Future may be set to
388:             * <tt>null</tt> in which case the SolrIndexSearcher created has already been registered at the time
389:             * this method returned.
390:             * <p>
391:             * @param forceNew           if true, force the open of a new index searcher regardless if there is already one open.
392:             * @param returnSearcher     if true, returns a {@link SolrIndexSearcher} holder with the refcount already incremented.
393:             * @param waitSearcher       if non-null, will be filled in with a {@link Future} that will return after the new searcher is registered.
394:             * @throws IOException
395:             */
396:            public RefCounted<SolrIndexSearcher> getSearcher(boolean forceNew,
397:                    boolean returnSearcher, final Future[] waitSearcher)
398:                    throws IOException {
399:                // it may take some time to open an index.... we may need to make
400:                // sure that two threads aren't trying to open one at the same time
401:                // if it isn't necessary.
402:
403:                synchronized (searcherLock) {
404:                    // see if we can return the current searcher
405:                    if (_searcher != null && !forceNew) {
406:                        if (returnSearcher) {
407:                            _searcher.incref();
408:                            return _searcher;
409:                        } else {
410:                            return null;
411:                        }
412:                    }
413:
414:                    // check to see if we can wait for someone else's searcher to be set
415:                    if (onDeckSearchers > 0 && !forceNew && _searcher == null) {
416:                        try {
417:                            searcherLock.wait();
418:                        } catch (InterruptedException e) {
419:                            log.info(SolrException.toStr(e));
420:                        }
421:                    }
422:
423:                    // check again: see if we can return right now
424:                    if (_searcher != null && !forceNew) {
425:                        if (returnSearcher) {
426:                            _searcher.incref();
427:                            return _searcher;
428:                        } else {
429:                            return null;
430:                        }
431:                    }
432:
433:                    // At this point, we know we need to open a new searcher...
434:                    // first: increment count to signal other threads that we are
435:                    //        opening a new searcher.
436:                    onDeckSearchers++;
437:                    if (onDeckSearchers < 1) {
438:                        // should never happen... just a sanity check
439:                        log.severe("ERROR!!! onDeckSearchers is "
440:                                + onDeckSearchers);
441:                        onDeckSearchers = 1; // reset
442:                    } else if (onDeckSearchers > maxWarmingSearchers) {
443:                        onDeckSearchers--;
444:                        String msg = "Error opening new searcher. exceeded limit of maxWarmingSearchers="
445:                                + maxWarmingSearchers + ", try again later.";
446:                        log.warning(msg);
447:                        // HTTP 503==service unavailable, or 409==Conflict
448:                        throw new SolrException(
449:                                SolrException.ErrorCode.SERVICE_UNAVAILABLE,
450:                                msg, true);
451:                    } else if (onDeckSearchers > 1) {
452:                        log
453:                                .info("PERFORMANCE WARNING: Overlapping onDeckSearchers="
454:                                        + onDeckSearchers);
455:                    }
456:                }
457:
458:                // open the index synchronously
459:                // if this fails, we need to decrement onDeckSearchers again.
460:                SolrIndexSearcher tmp;
461:                try {
462:                    tmp = new SolrIndexSearcher(schema, "main", index_path,
463:                            true);
464:                } catch (Throwable th) {
465:                    synchronized (searcherLock) {
466:                        onDeckSearchers--;
467:                        // notify another waiter to continue... it may succeed
468:                        // and wake any others.
469:                        searcherLock.notify();
470:                    }
471:                    // need to close the searcher here??? we shouldn't have to.
472:                    throw new RuntimeException(th);
473:                }
474:
475:                final SolrIndexSearcher newSearcher = tmp;
476:
477:                RefCounted<SolrIndexSearcher> currSearcherHolder = null;
478:                final RefCounted<SolrIndexSearcher> newSearchHolder = newHolder(newSearcher);
479:                if (returnSearcher)
480:                    newSearchHolder.incref();
481:
482:                // a signal to decrement onDeckSearchers if something goes wrong.
483:                final boolean[] decrementOnDeckCount = new boolean[1];
484:                decrementOnDeckCount[0] = true;
485:
486:                try {
487:
488:                    boolean alreadyRegistered = false;
489:                    synchronized (searcherLock) {
490:                        if (_searcher == null) {
491:                            // if there isn't a current searcher then we may
492:                            // want to register this one before warming is complete instead of waiting.
493:                            if (SolrConfig.config.getBool(
494:                                    "query/useColdSearcher", false)) {
495:                                registerSearcher(newSearchHolder);
496:                                decrementOnDeckCount[0] = false;
497:                                alreadyRegistered = true;
498:                            }
499:                        } else {
500:                            // get a reference to the current searcher for purposes of autowarming.
501:                            currSearcherHolder = _searcher;
502:                            currSearcherHolder.incref();
503:                        }
504:                    }
505:
506:                    final SolrIndexSearcher currSearcher = currSearcherHolder == null ? null
507:                            : currSearcherHolder.get();
508:
509:                    //
510:                    // Note! if we registered the new searcher (but didn't increment it's
511:                    // reference count because returnSearcher==false, it's possible for
512:                    // someone else to register another searcher, and thus cause newSearcher
513:                    // to close while we are warming.
514:                    //
515:                    // Should we protect against that by incrementing the reference count?
516:                    // Maybe we should just let it fail?   After all, if returnSearcher==false
517:                    // and newSearcher has been de-registered, what's the point of continuing?
518:                    //
519:
520:                    Future future = null;
521:
522:                    // warm the new searcher based on the current searcher.
523:                    // should this go before the other event handlers or after?
524:                    if (currSearcher != null) {
525:                        future = searcherExecutor.submit(new Callable() {
526:                            public Object call() throws Exception {
527:                                try {
528:                                    newSearcher.warm(currSearcher);
529:                                } catch (Throwable e) {
530:                                    SolrException.logOnce(log, null, e);
531:                                }
532:                                return null;
533:                            }
534:                        });
535:                    }
536:
537:                    if (currSearcher == null
538:                            && firstSearcherListeners.size() > 0) {
539:                        future = searcherExecutor.submit(new Callable() {
540:                            public Object call() throws Exception {
541:                                try {
542:                                    for (SolrEventListener listener : firstSearcherListeners) {
543:                                        listener.newSearcher(newSearcher, null);
544:                                    }
545:                                } catch (Throwable e) {
546:                                    SolrException.logOnce(log, null, e);
547:                                }
548:                                return null;
549:                            }
550:                        });
551:                    }
552:
553:                    if (currSearcher != null && newSearcherListeners.size() > 0) {
554:                        future = searcherExecutor.submit(new Callable() {
555:                            public Object call() throws Exception {
556:                                try {
557:                                    for (SolrEventListener listener : newSearcherListeners) {
558:                                        listener.newSearcher(newSearcher, null);
559:                                    }
560:                                } catch (Throwable e) {
561:                                    SolrException.logOnce(log, null, e);
562:                                }
563:                                return null;
564:                            }
565:                        });
566:                    }
567:
568:                    // WARNING: this code assumes a single threaded executor (that all tasks
569:                    // queued will finish first).
570:                    final RefCounted<SolrIndexSearcher> currSearcherHolderF = currSearcherHolder;
571:                    if (!alreadyRegistered) {
572:                        future = searcherExecutor.submit(new Callable() {
573:                            public Object call() throws Exception {
574:                                try {
575:                                    // signal that we no longer need to decrement
576:                                    // the count *before* registering the searcher since
577:                                    // registerSearcher will decrement even if it errors.
578:                                    decrementOnDeckCount[0] = false;
579:                                    registerSearcher(newSearchHolder);
580:                                } catch (Throwable e) {
581:                                    SolrException.logOnce(log, null, e);
582:                                } finally {
583:                                    // we are all done with the old searcher we used
584:                                    // for warming...
585:                                    if (currSearcherHolderF != null)
586:                                        currSearcherHolderF.decref();
587:                                }
588:                                return null;
589:                            }
590:                        });
591:                    }
592:
593:                    if (waitSearcher != null) {
594:                        waitSearcher[0] = future;
595:                    }
596:
597:                    // Return the searcher as the warming tasks run in parallel
598:                    // callers may wait on the waitSearcher future returned.
599:                    return returnSearcher ? newSearchHolder : null;
600:
601:                } catch (Exception e) {
602:                    SolrException.logOnce(log, null, e);
603:                    if (currSearcherHolder != null)
604:                        currSearcherHolder.decref();
605:
606:                    synchronized (searcherLock) {
607:                        if (decrementOnDeckCount[0]) {
608:                            onDeckSearchers--;
609:                        }
610:                        if (onDeckSearchers < 0) {
611:                            // sanity check... should never happen
612:                            log
613:                                    .severe("ERROR!!! onDeckSearchers after decrement="
614:                                            + onDeckSearchers);
615:                            onDeckSearchers = 0; // try and recover
616:                        }
617:                        // if we failed, we need to wake up at least one waiter to continue the process
618:                        searcherLock.notify();
619:                    }
620:
621:                    // since the indexreader was already opened, assume we can continue on
622:                    // even though we got an exception.
623:                    return returnSearcher ? newSearchHolder : null;
624:                }
625:
626:            }
627:
628:            private RefCounted<SolrIndexSearcher> newHolder(
629:                    SolrIndexSearcher newSearcher) {
630:                RefCounted<SolrIndexSearcher> holder = new RefCounted<SolrIndexSearcher>(
631:                        newSearcher) {
632:                    public void close() {
633:                        try {
634:                            resource.close();
635:                        } catch (IOException e) {
636:                            log.severe("Error closing searcher:"
637:                                    + SolrException.toStr(e));
638:                        }
639:                    }
640:                };
641:                holder.incref(); // set ref count to 1 to account for this._searcher
642:                return holder;
643:            }
644:
645:            // Take control of newSearcherHolder (which should have a reference count of at
646:            // least 1 already.  If the caller wishes to use the newSearcherHolder directly
647:            // after registering it, then they should increment the reference count *before*
648:            // calling this method.
649:            //
650:            // onDeckSearchers will also be decremented (it should have been incremented
651:            // as a result of opening a new searcher).
652:            private void registerSearcher(
653:                    RefCounted<SolrIndexSearcher> newSearcherHolder)
654:                    throws IOException {
655:                synchronized (searcherLock) {
656:                    try {
657:                        if (_searcher != null) {
658:                            _searcher.decref(); // dec refcount for this._searcher
659:                            _searcher = null;
660:                        }
661:
662:                        _searcher = newSearcherHolder;
663:                        SolrIndexSearcher newSearcher = newSearcherHolder.get();
664:
665:                        newSearcher.register(); // register subitems (caches)
666:                        log.info("Registered new searcher " + newSearcher);
667:
668:                    } catch (Throwable e) {
669:                        log(e);
670:                    } finally {
671:                        // wake up anyone waiting for a searcher
672:                        // even in the face of errors.
673:                        onDeckSearchers--;
674:                        searcherLock.notifyAll();
675:                    }
676:                }
677:            }
678:
679:            public void closeSearcher() {
680:                log.info("Closing main searcher on request.");
681:                synchronized (searcherLock) {
682:                    if (_searcher != null) {
683:                        _searcher.decref(); // dec refcount for this._searcher
684:                        _searcher = null;
685:                        SolrInfoRegistry.getRegistry()
686:                                .remove("currentSearcher");
687:                    }
688:                }
689:            }
690:
691:            public void execute(SolrRequestHandler handler,
692:                    SolrQueryRequest req, SolrQueryResponse rsp) {
693:                // setup response header and handle request
694:                final NamedList<Object> responseHeader = new SimpleOrderedMap<Object>();
695:                rsp.add("responseHeader", responseHeader);
696:                handler.handleRequest(req, rsp);
697:                setResponseHeaderValues(handler, responseHeader, req, rsp);
698:
699:                log.info(req.getContext().get("path") + " "
700:                        + req.getParamString() + " 0 "
701:                        + (int) (rsp.getEndTime() - req.getStartTime()));
702:            }
703:
704:            @Deprecated
705:            public void execute(SolrQueryRequest req, SolrQueryResponse rsp) {
706:                SolrRequestHandler handler = getRequestHandler(req
707:                        .getQueryType());
708:                if (handler == null) {
709:                    log.warning("Unknown Request Handler '"
710:                            + req.getQueryType() + "' :" + req);
711:                    throw new SolrException(
712:                            SolrException.ErrorCode.BAD_REQUEST,
713:                            "Unknown Request Handler '" + req.getQueryType()
714:                                    + "'", true);
715:                }
716:                execute(handler, req, rsp);
717:            }
718:
719:            protected void setResponseHeaderValues(SolrRequestHandler handler,
720:                    NamedList<Object> responseHeader, SolrQueryRequest req,
721:                    SolrQueryResponse rsp) {
722:                // TODO should check that responseHeader has not been replaced by handler
723:
724:                final int qtime = (int) (rsp.getEndTime() - req.getStartTime());
725:                responseHeader.add("status", rsp.getException() == null ? 0
726:                        : 500);
727:                responseHeader.add("QTime", qtime);
728:
729:                SolrParams params = req.getParams();
730:                if (params.getBool(SolrParams.HEADER_ECHO_HANDLER, false)) {
731:                    responseHeader.add("handler", handler.getName());
732:                }
733:
734:                // Values for echoParams... false/true/all or false/explicit/all ???
735:                String ep = params.get(SolrParams.HEADER_ECHO_PARAMS, null);
736:                if (ep != null) {
737:                    EchoParamStyle echoParams = EchoParamStyle.get(ep);
738:                    if (echoParams == null) {
739:                        throw new SolrException(
740:                                SolrException.ErrorCode.BAD_REQUEST,
741:                                "Invalid value '" + ep + "' for "
742:                                        + SolrParams.HEADER_ECHO_PARAMS
743:                                        + " parameter, use '"
744:                                        + EchoParamStyle.EXPLICIT + "' or '"
745:                                        + EchoParamStyle.ALL + "'");
746:                    }
747:                    if (echoParams == EchoParamStyle.EXPLICIT) {
748:                        responseHeader.add("params", req.getOriginalParams()
749:                                .toNamedList());
750:                    } else if (echoParams == EchoParamStyle.ALL) {
751:                        responseHeader.add("params", req.getParams()
752:                                .toNamedList());
753:                    }
754:                }
755:            }
756:
757:            final public static void log(Throwable e) {
758:                SolrException.logOnce(log, null, e);
759:            }
760:
761:            private QueryResponseWriter defaultResponseWriter;
762:            private final Map<String, QueryResponseWriter> responseWriters = new HashMap<String, QueryResponseWriter>();
763:
764:            /** Configure the query response writers. There will always be a default writer; additional 
765:             * writers may also be configured. */
766:            private void initWriters() {
767:                String xpath = "queryResponseWriter";
768:                NodeList nodes = (NodeList) SolrConfig.config.evaluate(xpath,
769:                        XPathConstants.NODESET);
770:                int length = nodes.getLength();
771:                for (int i = 0; i < length; i++) {
772:                    Element elm = (Element) nodes.item(i);
773:
774:                    try {
775:                        String name = DOMUtil.getAttr(elm, "name", xpath
776:                                + " config");
777:                        String className = DOMUtil.getAttr(elm, "class", xpath
778:                                + " config");
779:                        log.info("adding queryResponseWriter " + name + "="
780:                                + className);
781:
782:                        QueryResponseWriter writer = (QueryResponseWriter) Config
783:                                .newInstance(className);
784:                        writer.init(DOMUtil.childNodesToNamedList(elm));
785:                        responseWriters.put(name, writer);
786:                    } catch (Exception ex) {
787:                        SolrConfig.severeErrors.add(ex);
788:                        SolrException.logOnce(log, null, ex);
789:                        // if a writer can't be created, skip it and continue
790:                    }
791:                }
792:
793:                // configure the default response writer; this one should never be null
794:                if (responseWriters.containsKey("standard")) {
795:                    defaultResponseWriter = responseWriters.get("standard");
796:                }
797:                if (defaultResponseWriter == null) {
798:                    defaultResponseWriter = new XMLResponseWriter();
799:                }
800:
801:                // make JSON response writers available by default
802:                if (responseWriters.get("json") == null) {
803:                    responseWriters.put("json", new JSONResponseWriter());
804:                }
805:                if (responseWriters.get("python") == null) {
806:                    responseWriters.put("python", new PythonResponseWriter());
807:                }
808:                if (responseWriters.get("ruby") == null) {
809:                    responseWriters.put("ruby", new RubyResponseWriter());
810:                }
811:
812:            }
813:
814:            /** Finds a writer by name, or returns the default writer if not found. */
815:            public final QueryResponseWriter getQueryResponseWriter(
816:                    String writerName) {
817:                if (writerName != null) {
818:                    QueryResponseWriter writer = responseWriters
819:                            .get(writerName);
820:                    if (writer != null) {
821:                        return writer;
822:                    }
823:                }
824:                return defaultResponseWriter;
825:            }
826:
827:            /** Returns the appropriate writer for a request. If the request specifies a writer via the
828:             * 'wt' parameter, attempts to find that one; otherwise return the default writer.
829:             */
830:            public final QueryResponseWriter getQueryResponseWriter(
831:                    SolrQueryRequest request) {
832:                return getQueryResponseWriter(request.getParam("wt"));
833:            }
834:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.