/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** */ package org.apache.solr.update; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.TermDocs; import org.apache.lucene.index.Term; import org.apache.lucene.document.Document; import org.apache.lucene.search.Query; import java.util.HashSet; import java.util.concurrent.Future; import java.util.concurrent.ExecutionException; import java.io.IOException; import java.net.URL; import org.apache.solr.search.SolrIndexSearcher; import org.apache.solr.search.QueryParsing; import org.apache.solr.update.UpdateHandler; import org.apache.solr.common.SolrException; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.core.SolrCore; import org.apache.solr.handler.NonUpdateHandler; /** * <code>DirectUpdateHandler</code> implements an UpdateHandler where documents are added * directly to the main lucene index as opposed to adding to a separate smaller index. * For this reason, not all combinations to/from pending and committed are supported. * * @version $Id: DirectUpdateHandler.java 1065312 2011-01-30 16:08:25Z rmuir $ * @since solr 0.9 * * @deprecated Use {@link DirectUpdateHandler2} instead. This is only kept around for back-compatibility (way back). */ @Deprecated public class DirectUpdateHandler extends NonUpdateHandler { public DirectUpdateHandler(SolrCore core) throws IOException { super(core); } // // // the set of ids in the "pending set" (those docs that have been added, but // // that are not yet visible. // final HashSet<String> pset; // IndexWriter writer; // SolrIndexSearcher searcher; // int numAdds=0; // number of docs added to the pending set // int numPending=0; // number of docs currently in this pending set // int numDeleted=0; // number of docs deleted or // // // public DirectUpdateHandler(SolrCore core) throws IOException { // super(core); // pset = new HashSet<String>(256); // } // // // protected void openWriter() throws IOException { // if (writer==null) { // writer = createMainIndexWriter("DirectUpdateHandler", false); // } // } // // protected void closeWriter() throws IOException { // try { // if (writer!=null) writer.close(); // } finally { // // TODO: if an exception causes the writelock to not be // // released, we could delete it here. // writer=null; // } // } // // protected void openSearcher() throws IOException { // if (searcher==null) { // searcher = core.newSearcherForUpdate("DirectUpdateHandler",UpdateHandler.UPDATEPARTION); // } // } // // protected void closeSearcher() throws IOException { // try { // if (searcher!=null) searcher.close(); // } finally { // // TODO: if an exception causes the writelock to not be // // released, we could delete it here. // searcher=null; // } // } // // protected void doAdd(Document doc) throws IOException { // closeSearcher(); openWriter(); // writer.addDocument(doc); // } // // protected boolean existsInIndex(String indexedId) throws IOException { // if (idField == null) throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"Operation requires schema to have a unique key field"); // // closeWriter(); // openSearcher(); // IndexReader ir = searcher.getReader(); // TermDocs tdocs = null; // boolean exists=false; // try { // tdocs = ir.termDocs(idTerm(indexedId)); // if (tdocs.next()) exists=true; // } finally { // try { if (tdocs != null) tdocs.close(); } catch (Exception e) {} // } // return exists; // } // // // protected int deleteInIndex(String indexedId) throws IOException { // if (idField == null) throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"Operation requires schema to have a unique key field"); // // closeWriter(); openSearcher(); // IndexReader ir = searcher.getReader(); // TermDocs tdocs = null; // int num=0; // try { // Term term = new Term(idField.getName(), indexedId); // num = ir.deleteDocuments(term); // if (core.log.isTraceEnabled()) { // core.log.trace( core.getLogId()+"deleted " + num + " docs matching id " + idFieldType.indexedToReadable(indexedId)); // } // } finally { // try { if (tdocs != null) tdocs.close(); } catch (Exception e) {} // } // return num; // } // // protected void overwrite(String indexedId, Document doc) throws IOException { // if (indexedId ==null) indexedId =getIndexedId(doc); // deleteInIndex(indexedId); // doAdd(doc); // } // // /************** Direct update handler - pseudo code *********** // def add(doc, id, allowDups, overwritePending, overwriteCommitted): // if not overwritePending and not overwriteCommitted: // #special case... no need to check pending set, and we don't keep // #any state around about this addition // if allowDups: // committed[id]=doc #100 // return // else: // #if no dups allowed, we must check the *current* index (pending and committed) // if not committed[id]: committed[id]=doc #000 // return // #001 (searchd addConditionally) // if not allowDups and not overwritePending and pending[id]: return // del committed[id] #delete from pending and committed 111 011 // committed[id]=doc // pending[id]=True // ****************************************************************/ // // // could return the number of docs deleted, but is that always possible to know??? // @Override // public void delete(DeleteUpdateCommand cmd) throws IOException { // if (!cmd.fromPending && !cmd.fromCommitted) // throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"meaningless command: " + cmd); // if (!cmd.fromPending || !cmd.fromCommitted) // throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"operation not supported" + cmd); // String indexedId = idFieldType.toInternal(cmd.id); // synchronized(this) { // deleteInIndex(indexedId); // pset.remove(indexedId); // } // } // // // TODO - return number of docs deleted? // // Depending on implementation, we may not be able to immediately determine num... // @Override // public void deleteByQuery(DeleteUpdateCommand cmd) throws IOException { // if (!cmd.fromPending && !cmd.fromCommitted) // throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"meaningless command: " + cmd); // if (!cmd.fromPending || !cmd.fromCommitted) // throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"operation not supported: " + cmd); // // Query q = QueryParsing.parseQuery(cmd.query, schema); // // int totDeleted = 0; // synchronized(this) { // closeWriter(); openSearcher(); // // // if we want to count the number of docs that were deleted, then // // we need a new instance of the DeleteHitCollector // final DeleteHitCollector deleter = new DeleteHitCollector(searcher); // searcher.search(q, null, deleter); // totDeleted = deleter.deleted; // } // // if (core.log.isDebugEnabled()) { // core.log.debug(core.getLogId()+"docs deleted:" + totDeleted); // } // // } // // /**************** old hit collector... new one is in base class // // final DeleteHitCollector deleter = new DeleteHitCollector(); // class DeleteHitCollector extends HitCollector { // public int deleted=0; // public void collect(int doc, float score) { // try { // searcher.getReader().delete(doc); // deleted++; // } catch (IOException e) { // try { closeSearcher(); } catch (Exception ee) { SolrException.log(SolrCore.log,ee); } // SolrException.log(SolrCore.log,e); // throw new SolrException( SolrException.StatusCode.SERVER_ERROR,"Error deleting doc# "+doc,e); // } // } // } // ***************************/ // // @Override // public int mergeIndexes(MergeIndexesCommand cmd) throws IOException { // throw new SolrException( // SolrException.ErrorCode.BAD_REQUEST, // "DirectUpdateHandler doesn't support mergeIndexes. Use DirectUpdateHandler2 instead."); // } // // @Override // public void commit(CommitUpdateCommand cmd) throws IOException { // Future[] waitSearcher = null; // if (cmd.waitSearcher) { // waitSearcher = new Future[1]; // } // // synchronized (this) { // pset.clear(); // closeSearcher(); // flush any deletes // if (cmd.optimize || cmd.expungeDeletes) { // openWriter(); // writer needs to be open to optimize // if(cmd.optimize) writer.optimize(cmd.maxOptimizeSegments); // if(cmd.expungeDeletes) writer.expungeDeletes(cmd.expungeDeletes); // } // closeWriter(); // // callPostCommitCallbacks(); // if (cmd.optimize) { // callPostOptimizeCallbacks(); // } // // core.getSearcher(UpdateHandler.UPDATEPARTION,true,true); // } // // if (waitSearcher!=null && waitSearcher[0] != null) { // try { // waitSearcher[0].get(); // } catch (InterruptedException e) { // SolrException.log(log,e); // } catch (ExecutionException e) { // SolrException.log(log,e); // } // } // // return; // } // // /** // * @since Solr 1.4 // */ // @Override // public void rollback(RollbackUpdateCommand cmd) throws IOException { // throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, // "DirectUpdateHandler doesn't support rollback. Use DirectUpdateHandler2 instead."); // } // // // /////////////////////////////////////////////////////////////////// // /////////////////// helper method for each add type /////////////// // /////////////////////////////////////////////////////////////////// // // protected int addNoOverwriteNoDups(AddUpdateCommand cmd) throws IOException { // if (cmd.indexedId ==null) { // cmd.indexedId =getIndexedId(cmd.doc); // } // synchronized (this) { // if (existsInIndex(cmd.indexedId)) return 0; // doAdd(cmd.doc); // } // return 1; // } // // protected int addConditionally(AddUpdateCommand cmd) throws IOException { // if (cmd.indexedId ==null) { // cmd.indexedId =getIndexedId(cmd.doc); // } // synchronized(this) { // if (pset.contains(cmd.indexedId)) return 0; // // since case 001 is currently the only case to use pset, only add // // to it in that instance. // pset.add(cmd.indexedId); // overwrite(cmd.indexedId,cmd.doc); // return 1; // } // } // // // // overwrite both pending and committed // protected synchronized int overwriteBoth(AddUpdateCommand cmd) throws IOException { // overwrite(cmd.indexedId, cmd.doc); // return 1; // } // // // // add without checking // protected synchronized int allowDups(AddUpdateCommand cmd) throws IOException { // doAdd(cmd.doc); // return 1; // } // // // @Override // public int addDoc(AddUpdateCommand cmd) throws IOException { // // // if there is no ID field, use allowDups // if( idField == null ) { // cmd.allowDups = true; // cmd.overwriteCommitted = false; // cmd.overwritePending = false; // } // // if (!cmd.allowDups && !cmd.overwritePending && !cmd.overwriteCommitted) { // return addNoOverwriteNoDups(cmd); // } else if (!cmd.allowDups && !cmd.overwritePending && cmd.overwriteCommitted) { // return addConditionally(cmd); // } else if (!cmd.allowDups && cmd.overwritePending && !cmd.overwriteCommitted) { // // return overwriteBoth(cmd); // throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"unsupported param combo:" + cmd); // } else if (!cmd.allowDups && cmd.overwritePending && cmd.overwriteCommitted) { // return overwriteBoth(cmd); // } else if (cmd.allowDups && !cmd.overwritePending && !cmd.overwriteCommitted) { // return allowDups(cmd); // } else if (cmd.allowDups && !cmd.overwritePending && cmd.overwriteCommitted) { // // return overwriteBoth(cmd); // throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"unsupported param combo:" + cmd); // } else if (cmd.allowDups && cmd.overwritePending && !cmd.overwriteCommitted) { // // return overwriteBoth(cmd); // throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"unsupported param combo:" + cmd); // } else if (cmd.allowDups && cmd.overwritePending && cmd.overwriteCommitted) { // return overwriteBoth(cmd); // } // throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"unsupported param combo:" + cmd); // } // // @Override // public void close() throws IOException { // synchronized(this) { // closeSearcher(); // closeWriter(); // } // } // // // // ///////////////////////////////////////////////////////////////////// // // SolrInfoMBean stuff: Statistics and Module Info // ///////////////////////////////////////////////////////////////////// // // public String getName() { // return DirectUpdateHandler.class.getName(); // } // // public String getVersion() { // return SolrCore.version; // } // // public String getDescription() { // return "Update handler that directly changes the on-disk main lucene index"; // } // // public Category getCategory() { // return Category.CORE; // } // // public String getSourceId() { // return "$Id: DirectUpdateHandler.java 1065312 2011-01-30 16:08:25Z rmuir $"; // } // // public String getSource() { // return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene_solr_3_5/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler.java $"; // } // // public URL[] getDocs() { // return null; // } // // public NamedList getStatistics() { // NamedList lst = new SimpleOrderedMap(); // return lst; // } // }