Author: markus
Date: Fri Mar 18 15:07:14 2011
New Revision: 1082944
URL: http://svn.apache.org/viewvc?rev=1082944&view=rev
Log:
NUTCH-963 SolrClean is now added
Added:
nutch/branches/branch-1.3/src/java/org/apache/nutch/indexer/solr/SolrClean.java
Added:
nutch/branches/branch-1.3/src/java/org/apache/nutch/indexer/solr/SolrClean.java
URL:
http://svn.apache.org/viewvc/nutch/branches/branch-1.3/src/java/org/apache/nutch/indexer/solr/SolrClean.java?rev=1082944&view=auto
==============================================================================
---
nutch/branches/branch-1.3/src/java/org/apache/nutch/indexer/solr/SolrClean.java
(added)
+++
nutch/branches/branch-1.3/src/java/org/apache/nutch/indexer/solr/SolrClean.java
Fri Mar 18 15:07:14 2011
@@ -0,0 +1,190 @@
+/*
+ * 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.nutch.indexer.solr;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.text.SimpleDateFormat;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.io.ByteWritable;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.mapred.FileInputFormat;
+import org.apache.hadoop.mapred.JobClient;
+import org.apache.hadoop.mapred.JobConf;
+import org.apache.hadoop.mapred.Mapper;
+import org.apache.hadoop.mapred.OutputCollector;
+import org.apache.hadoop.mapred.Reducer;
+import org.apache.hadoop.mapred.Reporter;
+import org.apache.hadoop.mapred.SequenceFileInputFormat;
+import org.apache.hadoop.mapred.lib.NullOutputFormat;
+import org.apache.hadoop.util.Tool;
+import org.apache.hadoop.util.ToolRunner;
+import org.apache.nutch.crawl.CrawlDatum;
+import org.apache.nutch.crawl.CrawlDb;
+import org.apache.nutch.util.NutchConfiguration;
+import org.apache.nutch.util.NutchJob;
+import org.apache.nutch.util.TimingUtil;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
+import org.apache.solr.client.solrj.request.UpdateRequest;
+
+/**
+* The class scans CrawlDB looking for entries with status DB_GONE (404) and
sends delete requests to Solr
+* for those documents.
+*
+*
+* @author Claudio Martella
+*
+*/
+
+public class SolrClean implements Tool {
+ public static final Log LOG = LogFactory.getLog(SolrClean.class);
+ private Configuration conf;
+
+ @Override
+ public Configuration getConf() {
+ return conf;
+ }
+
+ @Override
+ public void setConf(Configuration conf) {
+ this.conf = conf;
+ }
+
+ public static class DBFilter implements Mapper<Text, CrawlDatum,
ByteWritable, Text> {
+ private ByteWritable OUT = new ByteWritable(CrawlDatum.STATUS_DB_GONE);
+
+ @Override
+ public void configure(JobConf arg0) { }
+
+ @Override
+ public void close() throws IOException { }
+
+ @Override
+ public void map(Text key, CrawlDatum value,
+ OutputCollector<ByteWritable, Text> output, Reporter reporter)
+ throws IOException {
+
+ if (value.getStatus() == CrawlDatum.STATUS_DB_GONE) {
+ output.collect(OUT, key);
+ }
+ }
+ }
+
+ public static class SolrDeleter implements Reducer<ByteWritable, Text, Text,
ByteWritable> {
+ private static final int NUM_MAX_DELETE_REQUEST = 1000;
+ private int numDeletes = 0;
+ private int totalDeleted = 0;
+ private SolrServer solr;
+ private UpdateRequest updateRequest = new UpdateRequest();
+
+ @Override
+ public void configure(JobConf job) {
+ try {
+ solr = new CommonsHttpSolrServer(job.get(SolrConstants.SERVER_URL));
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ if (numDeletes > 0) {
+ LOG.info("SolrClean: deleting " + numDeletes + " documents");
+ updateRequest.process(solr);
+ totalDeleted += numDeletes;
+ }
+
+ if (totalDeleted > 0) {
+ solr.commit();
+ }
+
+ LOG.info("SolrClean: deleted a total of " + totalDeleted + "
documents");
+ } catch (SolrServerException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public void reduce(ByteWritable key, Iterator<Text> values,
+ OutputCollector<Text, ByteWritable> output, Reporter reporter)
+ throws IOException {
+ while (values.hasNext()) {
+ Text document = values.next();
+ updateRequest.deleteById(document.toString());
+ numDeletes++;
+ if (numDeletes >= NUM_MAX_DELETE_REQUEST) {
+ try {
+ LOG.info("SolrClean: deleting " + numDeletes + " documents");
+ updateRequest.process(solr);
+ } catch (SolrServerException e) {
+ throw new IOException(e);
+ }
+ updateRequest = new UpdateRequest();
+ totalDeleted += numDeletes;
+ numDeletes = 0;
+ }
+ }
+ }
+ }
+
+ public void delete(String crawldb, String solrUrl) throws IOException {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ long start = System.currentTimeMillis();
+ LOG.info("SolrClean: starting at " + sdf.format(start));
+
+ JobConf job = new NutchJob(getConf());
+
+ FileInputFormat.addInputPath(job, new Path(crawldb, CrawlDb.CURRENT_NAME));
+ job.set(SolrConstants.SERVER_URL, solrUrl);
+ job.setInputFormat(SequenceFileInputFormat.class);
+ job.setOutputFormat(NullOutputFormat.class);
+ job.setMapOutputKeyClass(ByteWritable.class);
+ job.setMapOutputValueClass(Text.class);
+ job.setMapperClass(DBFilter.class);
+ job.setReducerClass(SolrDeleter.class);
+
+ JobClient.runJob(job);
+
+ long end = System.currentTimeMillis();
+ LOG.info("SolrClean: finished at " + sdf.format(end) + ", elapsed: " +
TimingUtil.elapsedTime(start, end));
+ }
+
+ public int run(String[] args) throws IOException {
+ if (args.length != 2) {
+ System.err.println("Usage: SolrClean <crawldb> <solrurl>");
+ return 1;
+ }
+
+ delete(args[0], args[1]);
+
+ return 0;
+ }
+
+ public static void main(String[] args) throws Exception {
+ int result = ToolRunner.run(NutchConfiguration.create(),
+ new SolrClean(), args);
+ System.exit(result);
+ }
+}
\ No newline at end of file