/**
* 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;
// }
//
}