summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorMichael Peter Christen <mc@yacy.net>2026-07-05 12:04:42 +0200
committerMichael Peter Christen <mc@yacy.net>2026-07-05 12:04:42 +0200
commit35a1d85f8b7f34e3bcc45d30333a93383cb13493 (patch)
tree274bd072de827493d5452f60b9005599b0423770 /source
parent9e5958ab0e180a64d82490c6459510e6fe695c85 (diff)
removed the snapshot feature and all dependencies from non-java code
Diffstat (limited to 'source')
-rw-r--r--source/net/yacy/cora/federate/solr/responsewriter/SnapshotImagesReponseWriter.java205
-rw-r--r--source/net/yacy/cora/util/Html2Image.java581
-rw-r--r--source/net/yacy/crawler/CrawlSwitchboard.java13
-rw-r--r--source/net/yacy/crawler/RecrawlBusyThread.java858
-rw-r--r--source/net/yacy/crawler/data/CrawlProfile.java56
-rw-r--r--source/net/yacy/crawler/data/Snapshots.java516
-rw-r--r--source/net/yacy/crawler/data/Transactions.java403
-rw-r--r--source/net/yacy/document/parser/psParser.java72
-rw-r--r--source/net/yacy/htroot/ConfigSearchPage_p.java3
-rw-r--r--source/net/yacy/htroot/CrawlStartExpert.java13
-rw-r--r--source/net/yacy/htroot/Crawler_p.java10
-rw-r--r--source/net/yacy/htroot/QuickCrawlLink_p.java405
-rw-r--r--source/net/yacy/htroot/api/snapshot.java382
-rw-r--r--source/net/yacy/htroot/yacysearchitem.java29
-rw-r--r--source/net/yacy/http/servlets/SolrSelectServlet.java2
-rw-r--r--source/net/yacy/search/Switchboard.java8
-rw-r--r--source/net/yacy/search/SwitchboardConstants.java6
-rw-r--r--source/net/yacy/search/index/DocumentIndex.java4
-rw-r--r--source/net/yacy/search/index/Segment.java27
19 files changed, 637 insertions, 2956 deletions
diff --git a/source/net/yacy/cora/federate/solr/responsewriter/SnapshotImagesReponseWriter.java b/source/net/yacy/cora/federate/solr/responsewriter/SnapshotImagesReponseWriter.java
deleted file mode 100644
index f68c6ca48..000000000
--- a/source/net/yacy/cora/federate/solr/responsewriter/SnapshotImagesReponseWriter.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package net.yacy.cora.federate.solr.responsewriter;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.lucene.document.Document;
-import org.apache.lucene.index.IndexableField;
-import org.apache.solr.client.solrj.response.QueryResponse;
-import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrDocumentList;
-import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.QueryResponseWriter;
-import org.apache.solr.response.ResultContext;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.search.DocIterator;
-import org.apache.solr.search.DocList;
-import org.apache.solr.search.SolrIndexSearcher;
-
-import net.yacy.cora.util.CommonPattern;
-import net.yacy.search.schema.CollectionSchema;
-
-/**
- * this writer is supposed to be used to generate iframes. It generates links for the /api/snapshot.jpg servlet.
- */
-public class SnapshotImagesReponseWriter implements QueryResponseWriter, SolrjResponseWriter {
-
- private static final Set<String> DEFAULT_FIELD_LIST = new HashSet<>();
-
- static {
- DEFAULT_FIELD_LIST.add(CollectionSchema.id.getSolrFieldName());
- DEFAULT_FIELD_LIST.add(CollectionSchema.sku.getSolrFieldName());
- }
-
- /** Default width for each snapshot image */
- private static final int DEFAULT_WIDTH = 256;
-
- /** Default height for each snapshot image */
- private static final int DEFAULT_HEIGTH = 256;
-
- public SnapshotImagesReponseWriter() {
- super();
- }
-
- @Override
- public String getContentType(SolrQueryRequest arg0, SolrQueryResponse arg1) {
- return "text/html";
- }
-
- @Override
- public void init(@SuppressWarnings("rawtypes") NamedList n) {
- }
-
- /**
- * Compute the root path as a relative URL prefix from the original servlet
- * request URI if provided in the Solr request context, otherwise return a
- * regular "/". Using relative URLs when possible makes deployment behind a
- * reverse proxy more reliable and convenient as no URL rewriting is needed.
- *
- * @param request the Solr request.
- * @return the root context path to use as a prefix for resources URLs such as
- * stylesheets
- */
- private String getRootPath(final SolrQueryRequest request) {
- String rootPath = "/";
- if (request != null) {
- final Map<Object, Object> context = request.getContext();
- if (context != null) {
- final Object requestUriObj = context.get("requestURI");
- if (requestUriObj instanceof String) {
- String servletRequestUri = (String) requestUriObj;
- if (servletRequestUri.startsWith("/")) {
- servletRequestUri = servletRequestUri.substring(1);
-
- final String[] pathParts = CommonPattern.SLASH.split(servletRequestUri);
- if (pathParts.length > 1) {
- final StringBuilder sb = new StringBuilder();
- for (int i = 1; i < pathParts.length; i++) {
- sb.append("../");
- }
- rootPath = sb.toString();
- }
- }
- }
- }
- }
- return rootPath;
- }
-
- /**
- * Append the response HTML head to the writer.
- * @param writer an open output writer. Must not be null.
- * @param request the Solr request
- * @throws IOException when a write error occurred
- */
- private void writeHtmlHead(final Writer writer, final SolrQueryRequest request) throws IOException {
- final String rootPath = getRootPath(request);
-
- writer.write("<!DOCTYPE html>\n");
- writer.write("<html lang=\"en\">");
- writer.write("<head>\n");
- writer.write("<meta charset=\"UTF-8\">");
- writer.write("<title>Documents snapshots</title>\n");
- writer.write("<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"" + rootPath + "env/base.css\" />\n");
- writer.write("<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"" + rootPath + "env/style.css\" />\n");
- writer.write("</head>\n");
- }
-
- @Override
- public void write(final Writer writer, final SolrQueryRequest request, final SolrQueryResponse rsp) throws IOException {
- final NamedList<?> values = rsp.getValues();
- assert values.get("responseHeader") != null;
- assert values.get("response") != null;
-
- writeHtmlHead(writer, request);
- writer.write("<body id=\"SnapshotImagesReponseWriter\">\n");
- final SolrParams originalParams = request.getOriginalParams();
-
- final int width = originalParams != null ? originalParams.getInt("width", DEFAULT_WIDTH) : DEFAULT_WIDTH;
- final int height = originalParams != null ? originalParams.getInt("height", DEFAULT_HEIGTH) : DEFAULT_HEIGTH;
-
- final DocList response = ((ResultContext) values.get("response")).getDocList();
- final int sz = response.size();
- if (sz > 0) {
- final SolrIndexSearcher searcher = request.getSearcher();
- final DocIterator iterator = response.iterator();
- while (iterator.hasNext()) {
- final int id = iterator.nextDoc();
- final Document doc = searcher.doc(id, DEFAULT_FIELD_LIST);
- final IndexableField docId = doc.getField(CollectionSchema.id.getSolrFieldName());
- final IndexableField docSku = doc.getField(CollectionSchema.sku.getSolrFieldName());
- if(docId != null && docSku != null) {
- writeDoc(writer, width, height, docId.stringValue(), docSku.stringValue());
- }
- }
- }
-
- writer.write("</body></html>\n");
-
- }
-
- /**
- * Process a document and append its representation to the output writer.
- * @param writer an open ouput writer. Must not be null.
- * @param width the width of the snapshot image to render
- * @param height the height of the snapshot image to render
- * @param docId the document id (URL hash).
- * @param docUrl the document URL.
- * @throws IOException when a write error occurred
- */
- private void writeDoc(final Writer writer, final int width, final int height, final String docId, final String docUrl)
- throws IOException {
- if(docId != null && docUrl != null) {
- writer.write("<a href=\"");
- writer.write(docUrl);
- writer.write("\" class=\"forceNoExternalIcon\"><img width=\"");
- writer.write(String.valueOf(width));
- writer.write("\" height=\"");
- writer.write(String.valueOf(height));
- writer.write("\" src=\"/api/snapshot.jpg?urlhash=");
- writer.write(docId);
- writer.write("&amp;width=");
- writer.write(String.valueOf(width));
- writer.write("&amp;height=");
- writer.write(String.valueOf(height));
- writer.write("\" alt=\"");
- writer.write(docUrl);
- writer.write("\"></a>\n");
- }
- }
-
- @Override
- public void write(final Writer writer, final SolrQueryRequest request, final String coreName,
- final QueryResponse rsp) throws IOException {
-
- writeHtmlHead(writer, request);
- writer.write("<body id=\"SnapshotImagesReponseWriter\">\n");
- final SolrParams originalParams = request.getOriginalParams();
-
- final int width = originalParams != null ? originalParams.getInt("width", DEFAULT_WIDTH) : DEFAULT_WIDTH;
- final int height = originalParams != null ? originalParams.getInt("height", DEFAULT_HEIGTH) : DEFAULT_HEIGTH;
-
- final SolrDocumentList docList = rsp.getResults();
- final int sz = docList.size();
- if (sz > 0) {
- final Iterator<SolrDocument> iterator = docList.iterator();
- while (iterator.hasNext()) {
- final SolrDocument doc = iterator.next();
- final Object docId = doc.getFieldValue(CollectionSchema.id.getSolrFieldName());
- final Object docSku = doc.getFieldValue(CollectionSchema.sku.getSolrFieldName());
- if (docId != null && docSku != null) {
- writeDoc(writer, width, height, docId.toString(), docSku.toString());
- }
- }
- }
-
- writer.write("</body></html>\n");
- }
-
-}
diff --git a/source/net/yacy/cora/util/Html2Image.java b/source/net/yacy/cora/util/Html2Image.java
deleted file mode 100644
index ccd44d31a..000000000
--- a/source/net/yacy/cora/util/Html2Image.java
+++ /dev/null
@@ -1,581 +0,0 @@
-/**
- * Html2Image
- * Copyright 2014 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany
- * First published 26.11.2014 on http://yacy.net
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program in the file lgpl21.txt
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.yacy.cora.util;
-
-import java.awt.Container;
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.Image;
-import java.awt.MediaTracker;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import javax.imageio.ImageIO;
-import javax.swing.JEditorPane;
-import javax.swing.text.Document;
-import javax.swing.text.Element;
-import javax.swing.text.View;
-import javax.swing.text.ViewFactory;
-import javax.swing.text.html.HTMLDocument;
-import javax.swing.text.html.HTMLEditorKit;
-import javax.swing.text.html.ImageView;
-
-import org.apache.pdfbox.Loader;
-import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.rendering.ImageType;
-import org.apache.pdfbox.rendering.PDFRenderer;
-
-import net.yacy.cora.document.id.MultiProtocolURL;
-import net.yacy.cora.protocol.ClientIdentification;
-import net.yacy.cora.protocol.Domains;
-import net.yacy.cora.protocol.http.HTTPClient;
-import net.yacy.document.ImageParser;
-import net.yacy.kelondro.util.FileUtils;
-import net.yacy.kelondro.util.OS;
-
-/**
- * Convert html to an copy on disk-image in a other file format
- * currently (pdf and/or jpg)
- */
-public class Html2Image {
-
- // Mac
- /**
- * Path to wkhtmltopdf executable on Mac OS when installed using
- * wkhtmltox-n.n.n.macos-cocoa.pkg from https://wkhtmltopdf.org/downloads.html.
- * This can also be a path on Debian or another Gnu/Linux distribution.
- */
- private final static File wkhtmltopdfMac = new File("/usr/local/bin/wkhtmltopdf");
-
- // to install imagemagick, download from http://cactuslab.com/imagemagick/assets/ImageMagick-6.8.9-9.pkg.zip
- // the convert command from imagemagick needs ghostscript, if not present on older macs, download a version of gs from http://pages.uoregon.edu/koch/
-
- private final static File convertMac1 = new File("/opt/local/bin/convert");
- private final static File convertMac2 = new File("/opt/ImageMagick/bin/convert");
-
- /* Debian packages to install: apt-get install wkhtmltopdf imagemagick xvfb ghostscript
- The imagemagick policy at /etc should also be checked :
- if it contains a line such as <policy domain="coder" rights="none" pattern="PDF" /> it must be edited with rights="read" at minimum
- */
- private final static File wkhtmltopdfDebian = new File("/usr/bin/wkhtmltopdf"); // there is no wkhtmltoimage, use convert to create images
- private final static File convertDebian = new File("/usr/bin/convert");
-
- /**
- * Path to wkhtmltopdf executable on Windows, when installed with default
- * settings using wkhtmltox-n.n.n.msvc2015-win64.exe from
- * https://wkhtmltopdf.org/downloads.html
- */
- private static final File WKHTMLTOPDF_WINDOWS = new File("C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe");
-
- /**
- * Path to wkhtmltopdf executable on Windows, when installed with default
- * settings using wkhtmltox-n.n.n.msvc2015-win32.exe from
- * https://wkhtmltopdf.org/downloads.html
- */
- private static final File WKHTMLTOPDF_WINDOWS_X86 = new File(
- "C:\\Program Files (x86)\\wkhtmltopdf\\bin\\wkhtmltopdf.exe");
-
- /** Command to use when wkhtmltopdf is included in the system Path */
- private static final String WKHTMLTOPDF_COMMAND = "wkhtmltopdf";
-
- /** Command to use when imagemagick convert is included in the system Path */
- private static final String CONVERT_COMMAND = "convert";
-
- private static boolean usexvfb = false;
-
- /**
- * @return when the wkhtmltopdf command is detected as available in the system
- */
- public static boolean wkhtmltopdfAvailable() {
- /* Check wkhtmltopdf common installation paths and system Path */
- return wkhtmltopdfExecutable() != null || wkhtmltopdfAvailableInPath();
- }
-
- /**
- * @return a wkhtmltopdf executable file when one can be found, null otherwise
- */
- private static File wkhtmltopdfExecutable() {
- File executable = null;
- if(OS.isWindows) {
- if(WKHTMLTOPDF_WINDOWS.exists()) {
- executable = WKHTMLTOPDF_WINDOWS;
- } else if(WKHTMLTOPDF_WINDOWS_X86.exists()) {
- executable = WKHTMLTOPDF_WINDOWS_X86;
- }
- } else {
- if(wkhtmltopdfMac.exists()) {
- executable = wkhtmltopdfMac;
- } else if(wkhtmltopdfDebian.exists()) {
- executable = wkhtmltopdfDebian;
- }
- }
- return executable;
- }
-
- /**
- * @return true when wkhtmltopdf is available in system path
- */
- private static boolean wkhtmltopdfAvailableInPath() {
- boolean available = false;
- try {
- final Process p = Runtime.getRuntime().exec(WKHTMLTOPDF_COMMAND + " -V");
- available = p.waitFor(2, TimeUnit.SECONDS) && p.exitValue() == 0;
- } catch (final IOException e) {
- ConcurrentLog.fine("Html2Image", "wkhtmltopdf is not included in system path.");
- } catch (final InterruptedException e) {
- Thread.currentThread().interrupt(); // preserve thread interrupted state
- }
- return available;
- }
-
- /**
- * @return a imagemagick convert executable file when one can be found, null otherwise
- */
- private static File convertExecutable() {
- File executable = null;
- if(!OS.isWindows) {
- if(convertMac1.exists()) {
- executable = convertMac1;
- } else if(convertMac2.exists()) {
- executable = convertMac2;
- } else if(convertDebian.exists()) {
- executable = convertDebian;
- }
- }
- return executable;
- }
-
- /**
- * @return when the imagemagick convert command is detected as available in the system
- */
- public static boolean convertAvailable() {
- /* Check convert common installation paths and system Path */
- return convertExecutable() != null || convertAvailableInPath();
- }
-
- /**
- * @return when imagemagick convert is available in system path
- */
- private static boolean convertAvailableInPath() {
- boolean available = false;
- if(!OS.isWindows) { // on MS Windows convert is a system tool to convert volumes from FAT to NTFS
- try {
- final Process p = Runtime.getRuntime().exec(CONVERT_COMMAND + " -version");
- available = p.waitFor(2, TimeUnit.SECONDS) && p.exitValue() == 0;
- } catch (final IOException e) {
- ConcurrentLog.fine("Html2Image", "convert is not included in system path.");
- } catch (final InterruptedException e) {
- Thread.currentThread().interrupt(); // preserve thread interrupted state
- }
- }
- return available;
- }
-
- /**
- * Run the wkhtmltopdf external tool to fetch and render to PDF a web resource.
- * wKhtmltopdf may be called multiple times with various parameters flavors in
- * case of failure.
- *
- * @param url the URL of a web resource to fetch, render and convert to
- * a pdf file. Must not be null.
- * @param proxy the eventual proxy address to use. Can be null. Must be of
- * the form http://host:port; use YaCy here as proxy which is
- * mostly http://localhost:8090
- * @param destination the destination PDF file that should be written. Must not
- * be null.
- * @param maxSeconds the maximum time in seconds to wait for each wkhtmltopdf
- * call termination. Beyond this limit the process is killed.
- * @return true when the destination file was successfully written
- */
- public static boolean writeWkhtmltopdf(final String url, final String proxy, final String userAgent, final String acceptLanguage, final File destination, final long maxSeconds) {
- boolean success = false;
- for (final boolean ignoreErrors: new boolean[]{false, true}) {
- success = writeWkhtmltopdfInternal(url, proxy, destination, userAgent, acceptLanguage, ignoreErrors, maxSeconds);
- if (success) break;
- if (!success && proxy != null) {
- ConcurrentLog.warn("Html2Image", "trying to load without proxy: " + url);
- success = writeWkhtmltopdfInternal(url, null, destination, userAgent, acceptLanguage, ignoreErrors, maxSeconds);
- if (success) break;
- }
- }
- if (success) {
- ConcurrentLog.info("Html2Image", "wrote " + destination.toString() + " for " + url);
- } else {
- ConcurrentLog.warn("Html2Image", "could not generate snapshot for " + url);
- }
- return success;
- }
-
- /**
- * Run wkhtmltopdf in a separate process to fetch and render to PDF a web
- * resource.
- *
- * @param url the URL of a web resource to fetch, render and convert to
- * a pdf file. Must not be null.
- * @param proxy the eventual proxy address to use. Can be null.
- * @param destination the destination PDF file that should be written. Must not
- * be null.
- * @param userAgent TODO: implement
- * @param acceptLanguage TODO: implement
- * @param ignoreErrors when true wkhtmltopdf is instructed to ignore load errors
- * @param maxSeconds the maximum time in seconds to wait for the wkhtmltopdf
- * dedicated process termination. Beyond this limit the
- * process is killed.
- * @return true when the destination file was successfully written
- */
- private static boolean writeWkhtmltopdfInternal(final String url, final String proxy, final File destination,
- final String userAgent, final String acceptLanguage, final boolean ignoreErrors, final long maxSeconds) {
- final String wkhtmltopdfCmd;
- final File wkhtmltopdf = wkhtmltopdfExecutable();
- if(wkhtmltopdf != null) {
- wkhtmltopdfCmd = wkhtmltopdf.getAbsolutePath();
- } else if(wkhtmltopdfAvailableInPath()) {
- wkhtmltopdfCmd = WKHTMLTOPDF_COMMAND;
- } else {
- ConcurrentLog.warn("Html2Pdf", "Unable to locate wkhtmltopdf executable on this system!");
- return false;
- }
- String commandline =
- wkhtmltopdfCmd + " -q --title '" + url + "' " +
- //acceptLanguage == null ? "" : "--custom-header 'Accept-Language' '" + acceptLanguage + "' " +
- //(userAgent == null ? "" : "--custom-header \"User-Agent\" \"" + userAgent + "\" --custom-header-propagation ") +
- (proxy == null ? "" : "--proxy " + proxy + " ") +
- (ignoreErrors ? (OS.isMacArchitecture ? "--load-error-handling ignore " : "--ignore-load-errors ") : "") + // some versions do not have that flag and fail if attempting to use it...
- //"--footer-font-name 'Courier' --footer-font-size 9 --footer-left [webpage] --footer-right [date]/[time]([page]/[topage]) " +
- "--footer-left [webpage] --footer-right '[date]/[time]([page]/[topage])' --footer-font-size 7 " +
- url + " " + destination.getAbsolutePath();
- try {
- ConcurrentLog.info("Html2Pdf", "creating pdf from url " + url + " with command: " + commandline);
- if (!usexvfb && execWkhtmlToPdf(proxy, destination, commandline, maxSeconds)) {
- return true;
- }
- // if this fails, we should try to wrap the X server with a virtual screen using xvfb, this works on headless servers
- commandline = "xvfb-run -a " + commandline;
- return execWkhtmlToPdf(proxy, destination, commandline, maxSeconds);
- } catch (final IOException e) {
- ConcurrentLog.warn("Html2Pdf", "exception while creation of pdf with command: " + commandline, e);
- return false;
- }
- }
-
- /**
- * Run a wkhtmltopdf commandline in a separate process.
- *
- * @param proxy the eventual proxy address to use. Can be null.
- * @param destination the destination PDF file that should be written. Must not
- * be null.
- * @param commandline the wkhtmltopdf command line to execute. Must not be null.
- * @param maxSeconds the maximum time in seconds to wait for the process
- * termination. Beyond this limit the process is killed.
- * @return true when the destination file was successfully written
- * @throws IOException when an unexpected error occurred
- */
- private static boolean execWkhtmlToPdf(final String proxy, final File destination, final String commandline, final long maxSeconds) throws IOException {
- final Process p = Runtime.getRuntime().exec(commandline);
-
- try {
- p.waitFor(maxSeconds, TimeUnit.SECONDS);
- } catch (final InterruptedException e) {
- p.destroyForcibly();
- ConcurrentLog.warn("Html2Pdf", "Interrupted creation of pdf. Killing the process started with command : " + commandline);
- Thread.currentThread().interrupt(); // Keep the thread interrupted state
- return false;
- }
- if(p.isAlive()) {
- ConcurrentLog.warn("Html2Pdf", "Creation of pdf did not terminate within " + maxSeconds + " seconds. Killing the process started with command : " + commandline);
- p.destroyForcibly();
- return false;
- }
- if (p.exitValue() == 0 && destination.exists()) {
- return true;
- }
- final List<String> messages = OS.readStreams(p);
- ConcurrentLog.warn("Html2Image", "failed to create pdf " + (proxy == null ? "" : "using proxy " + proxy) + " with command : " + commandline);
- for (final String message : messages) {
- ConcurrentLog.warn("Html2Image", ">> " + message);
- }
- return false;
- }
-
- /**
- * Convert a pdf (first page) to an image. Proper values are i.e. width = 1024, height = 1024, density = 300, quality = 75
- * using internal pdf library or external command line tool on linux or mac
- * @param pdf input pdf file. Must not be null.
- * @param image output image file. Must not be null, and should end with ".jpg" or ".png".
- * @param width output width in pixels
- * @param height output height in pixels
- * @param density (dpi)
- * @param quality JPEG/PNG compression level
- * @return true when the ouput image file was successfully written.
- */
- public static boolean pdf2image(final File pdf, final File image, final int width, final int height, final int density, final int quality) {
- /* Deduce the ouput image format from the file extension */
- String imageFormat = MultiProtocolURL.getFileExtension(image.getName());
- if(imageFormat.isEmpty()) {
- /* Use JPEG as a default fallback */
- imageFormat = "jpg";
- }
- String convertCmd = null;
- final File convert = convertExecutable();
- if(convert != null) {
- convertCmd = convert.getAbsolutePath();
- } else if(convertAvailableInPath()) {
- convertCmd = CONVERT_COMMAND;
- } else {
- ConcurrentLog.info("Html2Image", "Unable to locate convert executable on this system!");
- }
-
- // convert pdf to jpg using internal pdfbox capability
- if (convertCmd == null) {
- try (final PDDocument pdoc = Loader.loadPDF(pdf);) {
-
- final BufferedImage bi = new PDFRenderer(pdoc).renderImageWithDPI(0, density, ImageType.RGB);
-
- return ImageIO.write(bi, imageFormat, image);
-
- } catch (final IOException ex) {
- ConcurrentLog.warn("Html2Image", "Failed to create image with pdfbox"
- + (ex.getMessage() != null ? " : " + ex.getMessage() : ""));
- return false;
- }
- }
-
- // convert using external command line utility
- try {
- // i.e. convert -density 300 -trim yacy.pdf[0] -trim -resize 1024x -crop x1024+0+0 -quality 75% yacy-convert-300.jpg
- // note: both -trim are necessary, otherwise it is trimmed only on one side. The [0] selects the first page of the pdf
- final String command = convertCmd + " -alpha remove -density " + density + " -trim " + pdf.getAbsolutePath() + "[0] -trim -resize " + width + "x -crop x" + height + "+0+0 -quality " + quality + "% " + image.getAbsolutePath();
- List<String> message = OS.execSynchronous(new String[] {
- convertCmd,
- "-alpha", "remove", "-density", Integer.toString(density),
- "-trim", pdf.getAbsolutePath() + "[0]", "-trim",
- "-resize", Integer.toString(width) + "x",
- "-crop", "x" + Integer.toString(height) + "+0+0",
- "-quality", Integer.toString(quality) + "%",
- image.getAbsolutePath()
- });
- if (image.exists()) return true;
- ConcurrentLog.warn("Html2Image", "failed to create image with command: " + command);
- for (final String m: message) ConcurrentLog.warn("Html2Image", ">> " + m);
-
- // another try for mac: use Image Events using AppleScript in osacript commands...
- // the following command overwrites a pdf with an png, so we must make a copy first
- if (!OS.isMacArchitecture) return false;
- final File pngFile = new File(pdf.getAbsolutePath() + ".tmp.pdf");
- org.apache.commons.io.FileUtils.copyFile(pdf, pngFile);
- final String[] commandx = {"osascript",
- "-e", "set ImgFile to \"" + pngFile.getAbsolutePath() + "\"",
- "-e", "tell application \"Image Events\"",
- "-e", "set Img to open file ImgFile",
- "-e", "save Img as PNG",
- "-e", "end tell"};
- //ConcurrentLog.warn("Html2Image", "failed to create image with command: " + commandx);
- message = OS.execSynchronous(commandx);
- for (final String m: message) ConcurrentLog.warn("Html2Image", ">> " + m);
- // now we must read and convert this file to the target format with the target size 1024x1024
- try {
- final File newPngFile = new File(pngFile.getAbsolutePath() + ".png");
- pngFile.renameTo(newPngFile);
- final Image img = ImageParser.parse(pngFile.getAbsolutePath(), FileUtils.read(newPngFile));
- if(img == null) {
- /* Should not happen. If so, ImageParser.parse() should already have logged about the error */
- return false;
- }
- final Image scaled = img.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING);
- final MediaTracker mediaTracker = new MediaTracker(new Container());
- mediaTracker.addImage(scaled, 0);
- try {mediaTracker.waitForID(0);} catch (final InterruptedException e) {}
- // finally write the image
- final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- bi.createGraphics().drawImage(scaled, 0, 0, width, height, null);
- ImageIO.write(bi, imageFormat, image);
- newPngFile.delete();
- return image.exists();
- } catch (final IOException e) {
- ConcurrentLog.logException(e);
- return false;
- }
- } catch (final IOException e) {
- e.printStackTrace();
- return false;
- }
- }
-
- /**
- * render a html page with a JEditorPane, which can do html up to html v 3.2. No CSS supported!
- * @param url
- * @param size
- * @throws IOException
- */
- public static void writeSwingImage(final String url, final Dimension size, final File destination) throws IOException {
-
- // set up a pane for rendering
- final JEditorPane htmlPane = new JEditorPane();
- htmlPane.setSize(size);
- htmlPane.setEditable(false);
- final HTMLEditorKit kit = new HTMLEditorKit() {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public Document createDefaultDocument() {
- final HTMLDocument doc = (HTMLDocument) super.createDefaultDocument();
- doc.setAsynchronousLoadPriority(-1);
- return doc;
- }
-
- @Override
- public ViewFactory getViewFactory() {
- return new HTMLFactory() {
- @Override
- public View create(final Element elem) {
- final View view = super.create(elem);
- if (view instanceof ImageView) {
- ((ImageView) view).setLoadsSynchronously(true);
- }
- return view;
- }
- };
- }
- };
- htmlPane.setEditorKitForContentType("text/html", kit);
- htmlPane.setContentType("text/html");
- htmlPane.addPropertyChangeListener(evt -> {
- });
-
- // load the page
- try {
- htmlPane.setPage(url);
- } catch (final IOException e) {
- e.printStackTrace();
- }
-
- // render the page
- final Dimension prefSize = htmlPane.getPreferredSize();
- final BufferedImage img = new BufferedImage(prefSize.width, htmlPane.getPreferredSize().height, BufferedImage.TYPE_INT_ARGB);
- final Graphics graphics = img.getGraphics();
- htmlPane.setSize(prefSize);
- htmlPane.paint(graphics);
- ImageIO.write(img, destination.getName().endsWith("jpg") ? "jpg" : "png", destination);
- }
-
- /**
- * Test PDF or image snapshot generation for a given URL.
- * @param args main arguments list:
- * <ol>
- * <li>Source remote URL (required)</li>
- * <li>Target local file path (required)</li>
- * <li>Snapshot generation method identifier (optional) :
- * <ul>
- * <li>"wkhtmltopdf" (default): generate a PDF snapshot using external wkhtmltopdf tool.</li>
- * <li>"swing" : use JRE provided Swing to generate a jpg or png image snapshot.</li>
- * </ul>
- * </li>
- * </ol>
- */
- public static void main(final String[] args) {
- final String usageMessage = "Usage : java " + Html2Image.class.getName()
- + " <url> <target-file[.pdf|.jpg|.png]> [wkhtmltopdf|swing]";
- int exitStatus = 0;
- try {
- if (args.length < 2) {
- System.out.println("Missing required parameter(s).");
- System.out.println(usageMessage);
- exitStatus = 1;
- return;
- }
- final String targetPath = args[1];
- if (args.length < 3 || "wkhtmltopdf".equals(args[2])) {
- if(Html2Image.wkhtmltopdfAvailable()) {
- final File targetPdfFile;
- if(targetPath.endsWith(".jpg") || targetPath.endsWith(".png")) {
- targetPdfFile = new File(targetPath.substring(0, targetPath.length() - 4) + ".pdf");
- } else if(targetPath.endsWith(".pdf")) {
- targetPdfFile = new File(targetPath);
- } else {
- System.out.println("Unsupported output format");
- System.out.println(usageMessage);
- exitStatus = 1;
- return;
- }
- if(Html2Image.writeWkhtmltopdf(args[0], null, ClientIdentification.yacyInternetCrawlerAgent.userAgent(),
- "en-us,en;q=0.5", targetPdfFile, 30)) {
- if(targetPath.endsWith(".jpg") || targetPath.endsWith(".png")) {
- if(Html2Image.pdf2image(targetPdfFile, new File(targetPath), 1024, 1024, 300, 75)) {
- ConcurrentLog.info("Html2Image", "wrote " + targetPath + " converted from " + targetPdfFile);
- } else {
- exitStatus = 1;
- return;
- }
- }
- } else {
- exitStatus = 1;
- return;
- }
- } else {
- System.out.println("Unable to locate wkhtmltopdf executable on this system!");
- exitStatus = 1;
- return;
- }
- } else if ("swing".equals(args[2])) {
- if(targetPath.endsWith(".pdf")) {
- System.out.println("Pdf output format is not supported with swing method.");
- exitStatus = 1;
- return;
- }
- if(!targetPath.endsWith(".jpg") && !targetPath.endsWith(".png")) {
- System.out.println("Unsupported output format");
- System.out.println(usageMessage);
- exitStatus = 1;
- return;
- }
-
- try {
- Html2Image.writeSwingImage(args[0], new Dimension(1200, 2000), new File(targetPath));
- } catch (final IOException e) {
- e.printStackTrace();
- exitStatus = 1;
- return;
- }
- } else {
- System.out.println("Unknown method : please specify either wkhtmltopdf or swing.");
- exitStatus = 1;
- return;
- }
- } finally {
- /* Shutdown running threads */
- Domains.close();
- try {
- HTTPClient.closeConnectionManager();
- } catch (final InterruptedException e) {
- Thread.currentThread().interrupt(); // restore interrupted state
- }
- ConcurrentLog.shutdown();
- if(exitStatus != 0) {
- System.exit(exitStatus);
- }
- }
- }
-
-}
diff --git a/source/net/yacy/crawler/CrawlSwitchboard.java b/source/net/yacy/crawler/CrawlSwitchboard.java
index 4f63608ad..8ad8373c2 100644
--- a/source/net/yacy/crawler/CrawlSwitchboard.java
+++ b/source/net/yacy/crawler/CrawlSwitchboard.java
@@ -304,8 +304,6 @@ public final class CrawlSwitchboard {
sb.getConfigBool(SwitchboardConstants.AUTOCRAWL_INDEX_MEDIA, true),
false,
false,
- -1,
- false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.NOCACHE,
"robot_" + CRAWL_PROFILE_AUTOCRAWL_DEEP,
ClientIdentification.yacyInternetCrawlerAgentName,
@@ -339,8 +337,6 @@ public final class CrawlSwitchboard {
sb.getConfigBool(SwitchboardConstants.AUTOCRAWL_INDEX_MEDIA, true),
false,
false,
- -1,
- false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.NOCACHE,
"robot_" + CRAWL_PROFILE_AUTOCRAWL_SHALLOW,
ClientIdentification.yacyInternetCrawlerAgentName,
@@ -374,7 +370,6 @@ public final class CrawlSwitchboard {
sb.getConfigBool(SwitchboardConstants.PROXY_INDEXING_LOCAL_MEDIA, true),
true,
sb.getConfigBool(SwitchboardConstants.PROXY_INDEXING_REMOTE, false),
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.IFFRESH,
"robot_" + CRAWL_PROFILE_PROXY,
ClientIdentification.yacyProxyAgentName,
@@ -408,7 +403,6 @@ public final class CrawlSwitchboard {
true,
false,
false,
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.IFFRESH,
"robot_" + CRAWL_PROFILE_REMOTE,
ClientIdentification.yacyInternetCrawlerAgentName,
@@ -442,7 +436,6 @@ public final class CrawlSwitchboard {
false,
true,
false,
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.IFEXIST,
"robot_" + CRAWL_PROFILE_SNIPPET_LOCAL_TEXT,
ClientIdentification.yacyIntranetCrawlerAgentName,
@@ -476,7 +469,6 @@ public final class CrawlSwitchboard {
true,
true,
false,
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.IFEXIST,
"robot_" + CRAWL_PROFILE_SNIPPET_GLOBAL_TEXT,
ClientIdentification.yacyIntranetCrawlerAgentName,
@@ -518,7 +510,6 @@ public final class CrawlSwitchboard {
false,
true,
false,
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.IFEXIST,
"robot_" + CRAWL_PROFILE_GREEDY_LEARNING_TEXT,
ClientIdentification.browserAgentName,
@@ -552,7 +543,6 @@ public final class CrawlSwitchboard {
false, // indexMedia
true,
false,
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.IFEXIST,
"robot_" + CRAWL_PROFILE_SNIPPET_LOCAL_MEDIA,
ClientIdentification.yacyIntranetCrawlerAgentName,
@@ -586,7 +576,6 @@ public final class CrawlSwitchboard {
true,
true,
false,
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.IFEXIST,
"robot_" + CRAWL_PROFILE_SNIPPET_GLOBAL_MEDIA,
ClientIdentification.yacyIntranetCrawlerAgentName,
@@ -620,7 +609,6 @@ public final class CrawlSwitchboard {
false,
false,
false,
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.NOCACHE,
"robot_" + CRAWL_PROFILE_PACKS,
ClientIdentification.yacyIntranetCrawlerAgentName,
@@ -657,7 +645,6 @@ public final class CrawlSwitchboard {
true,
false,
false,
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
CacheStrategy.NOCACHE,
collection,
ClientIdentification.yacyIntranetCrawlerAgentName,
diff --git a/source/net/yacy/crawler/RecrawlBusyThread.java b/source/net/yacy/crawler/RecrawlBusyThread.java
index 10867d2c0..b74586fc4 100644
--- a/source/net/yacy/crawler/RecrawlBusyThread.java
+++ b/source/net/yacy/crawler/RecrawlBusyThread.java
@@ -1,429 +1,429 @@
-/**
- * RecrawlBusyThread.java
- * SPDX-FileCopyrightText: 2015 by Burkhard Buelte
- * SPDX-License-Identifier: GPL-2.0-or-later
- * First released 15.05.2015 at https://yacy.net
- *
- * This is a part of YaCy, a peer-to-peer based web search engine
- *
- * LICENSE
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation; either version 2.1 of the License, or (at your option)
- * any later version.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program in the file lgpl21.txt If not, see
- * <http://www.gnu.org/licenses/>.
- */
-package net.yacy.crawler;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.time.LocalDateTime;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrDocumentList;
-
-import net.yacy.cora.document.encoding.ASCII;
-import net.yacy.cora.document.id.DigestURL;
-import net.yacy.cora.federate.solr.connector.SolrConnector;
-import net.yacy.cora.federate.yacy.CacheStrategy;
-import net.yacy.cora.protocol.ClientIdentification;
-import net.yacy.cora.util.ConcurrentLog;
-import net.yacy.crawler.data.CrawlProfile;
-import net.yacy.crawler.data.NoticedURL;
-import net.yacy.crawler.retrieval.Request;
-import net.yacy.document.parser.html.TagValency;
-import net.yacy.kelondro.workflow.AbstractBusyThread;
-import net.yacy.search.Switchboard;
-import net.yacy.search.schema.CollectionSchema;
-
-/**
- * Selects documents by a query from the local index
- * and feeds the found urls to the crawler to recrawl the documents.
- * This is intended to keep the index up-to-date
- * Currently the doucments are selected by expired fresh_date_dt field
- * an added to the crawler in smaller chunks (see chunksize) as long as no other crawl is running.
- */
-public class RecrawlBusyThread extends AbstractBusyThread {
-
- /** The thread name */
- public final static String THREAD_NAME = "recrawlindex";
-
- /** The default selection query */
- public static final String DEFAULT_QUERY = CollectionSchema.fresh_date_dt.getSolrFieldName()+":[* TO NOW/DAY-1DAY]";
-
- /** Default value for inclusion or not of documents with a https status different from 200 (success) */
- public static final boolean DEFAULT_INCLUDE_FAILED = false;
-
- /** The default value whether to delete on Recrawl */
- public static final boolean DEFAULT_DELETE_ON_RECRAWL = false;
-
- /** The current query selecting documents to recrawl */
- private String currentQuery;
-
- /** flag if docs with httpstatus_i <> 200 shall be recrawled */
- private boolean includefailed;
-
- /** flag whether to delete on Recrawl */
- private boolean deleteOnRecrawl;
-
- private int chunkstart = 0;
- private final int chunksize = 100;
- private final Switchboard sb;
-
- /** buffer of urls to recrawl */
- private final Set<DigestURL> urlstack;
-
- /** The total number of candidate URLs found for recrawl */
- private long urlsToRecrawl = 0;
-
- /** Total number of URLs added to the crawler queue for recrawl */
- private long recrawledUrlsCount = 0;
-
- /** Total number of URLs rejected for some reason by the crawl stacker or the crawler queue */
- private long rejectedUrlsCount = 0;
-
- /** Total number of malformed URLs found */
- private long malformedUrlsCount = 0;
-
- /** Total number of malformed URLs deleted from index */
- private long malformedUrlsDeletedCount = 0;
-
- private final String solrSortBy;
-
- /** Set to true when more URLs are still to be processed */
- private boolean moreToRecrawl = true;
-
- /** True when the job terminated early because an error occurred when requesting the Solr index, or the Solr index was closed */
- private boolean terminatedBySolrFailure = false;
-
- /** The recrawl job start time */
- private LocalDateTime startTime;
-
- /** The recrawl job end time */
- private LocalDateTime endTime;
-
- /**
- * @param xsb
- * the Switchboard instance holding server environment
- * @param query
- * the Solr selection query
- * @param includeFailed
- * set to true when documents with a https status different from 200
- * (success) must be included
- */
- public RecrawlBusyThread(final Switchboard xsb, final String query, final boolean includeFailed, final boolean deleteOnRecrawl) {
- super(3000, 1000); // set lower limits of cycle delay
- this.setName(THREAD_NAME);
- this.setIdleSleep(10*60000); // set actual cycle delays
- this.setBusySleep(2*60000);
- this.setPriority(Thread.MIN_PRIORITY);
- this.setLoadPreReqisite(1);
- this.sb = xsb;
- this.currentQuery = query;
- this.includefailed = includeFailed;
- this.deleteOnRecrawl = deleteOnRecrawl;
- this.urlstack = new HashSet<>();
- // workaround to prevent solr exception on existing index (not fully reindexed) since intro of schema with docvalues
- // org.apache.solr.core.SolrCore java.lang.IllegalStateException: unexpected docvalues type NONE for field 'load_date_dt' (expected=NUMERIC). Use UninvertingReader or index with docvalues.
- this.solrSortBy = CollectionSchema.load_date_dt.getSolrFieldName() + " asc";
-
- final SolrConnector solrConnector = this.sb.index.fulltext().getDefaultConnector();
- if (solrConnector != null && !solrConnector.isClosed()) {
- /* Ensure indexed data is up-to-date before running the main job */
- solrConnector.commit(true);
- }
- }
-
- /**
- * Set the query to select documents to recrawl
- * and resets the counter to start a fresh query loop
- * @param q select query
- * @param includefailedurls true=all http status docs are recrawled, false=httpstatus=200 docs are recrawled
- * @param deleteOnRecrawl
- */
- public void setQuery(String q, boolean includefailedurls, final boolean deleteOnRecrawl) {
- this.currentQuery = q;
- this.includefailed = includefailedurls;
- this.deleteOnRecrawl = deleteOnRecrawl;
- this.chunkstart = 0;
- }
-
- public String getQuery() {
- return this.currentQuery;
- }
-
- /**
- *
- * @param queryBase
- * the base query
- * @param includeFailed
- * set to true when documents with a https status different from 200
- * (success) must be included
- * @return the Solr selection query for candidate URLs to recrawl
- */
- public static final String buildSelectionQuery(final String queryBase, final boolean includeFailed) {
- return includeFailed ? queryBase : queryBase + " AND (" + CollectionSchema.httpstatus_i.name() + ":200)";
- }
-
- /**
- * Flag to include failed urls (httpstatus_i <> 200)
- * if true -> currentQuery is used as is,
- * if false -> the term " AND (httpstatus_i:200)" is appended to currentQuery
- * @param includefailedurls
- */
- public void setIncludeFailed(boolean includefailedurls) {
- this.includefailed = includefailedurls;
- }
-
- public boolean getIncludeFailed () {
- return this.includefailed;
- }
-
- public void setDeleteOnRecrawl(final boolean deleteOnRecrawl) {
- this.deleteOnRecrawl = deleteOnRecrawl;
- }
-
- public boolean getDeleteOnRecrawl() {
- return this.deleteOnRecrawl;
- }
-
- /**
- * feed urls to the local crawler
- * (Switchboard.addToCrawler() is not used here, as there existing urls are always skipped)
- *
- * @return true if urls were added/accepted to the crawler
- */
- private boolean feedToCrawler() {
-
- int added = 0;
-
- if (!this.urlstack.isEmpty()) {
- final CrawlProfile profile = this.sb.crawler.defaultRecrawlJobProfile;
-
- for (final DigestURL url : this.urlstack) {
- final Request request = new Request(ASCII.getBytes(this.sb.peers.mySeed().hash), url, null, "",
- new Date(), profile.handle(), 0, profile.timezoneOffset());
- String acceptedError = this.sb.crawlStacker.checkAcceptanceChangeable(url, profile, 0);
- if (!this.includefailed && acceptedError == null) { // skip check if failed docs to be included
- acceptedError = this.sb.crawlStacker.checkAcceptanceInitially(url, profile);
- }
- if (acceptedError != null) {
- this.rejectedUrlsCount++;
- ConcurrentLog.info(THREAD_NAME, "addToCrawler: cannot load " + url.toNormalform(true) + ": " + acceptedError);
- continue;
- }
- final String s;
- s = this.sb.crawlQueues.noticeURL.push(NoticedURL.StackType.LOCAL, request, profile, this.sb.robots);
-
- if (s != null) {
- this.rejectedUrlsCount++;
- ConcurrentLog.info(THREAD_NAME, "addToCrawler: failed to add " + url.toNormalform(true) + ": " + s);
- } else {
- added++;
- this.recrawledUrlsCount++;
- }
- }
- this.urlstack.clear();
- }
- return (added > 0);
- }
-
- /**
- * Process query and hand over urls to the crawler
- *
- * @return true if something processed
- */
- @Override
- public boolean job() {
- // more than chunksize crawls are running, do nothing
- if (this.sb.crawlQueues.coreCrawlJobSize() > this.chunksize) {
- return false;
- }
-
- boolean didSomething = false;
- if (this.urlstack.isEmpty()) {
- if(!this.moreToRecrawl) {
- /* We do not remove the thread from the Switchboard worker threads using serverSwitch.terminateThread(String,boolean),
- * because we want to be able to provide a report after its termination */
- this.terminate(false);
- } else {
- this.moreToRecrawl = this.processSingleQuery();
- /* Even if no more URLs are to recrawl, the job has done something by searching the Solr index */
- didSomething = true;
- }
- } else {
- didSomething = this.feedToCrawler();
- }
- return didSomething;
- }
-
- @Override
- public synchronized void start() {
- this.startTime = LocalDateTime.now();
- super.start();
- }
-
- @Override
- public void terminate(boolean waitFor) {
- super.terminate(waitFor);
- this.endTime = LocalDateTime.now();
- }
-
- /**
- * Selects documents to recrawl the urls
- * @return true if query has more results
- */
- private boolean processSingleQuery() {
- if (!this.urlstack.isEmpty()) {
- return true;
- }
- SolrDocumentList docList = null;
- final SolrConnector solrConnector = this.sb.index.fulltext().getDefaultConnector();
- if (solrConnector == null || solrConnector.isClosed()) {
- this.urlsToRecrawl = 0;
- this.terminatedBySolrFailure = true;
- return false;
- }
-
- try {
- // query all or only httpstatus=200 depending on includefailed flag
- docList = solrConnector.getDocumentListByQuery(RecrawlBusyThread.buildSelectionQuery(this.currentQuery, this.includefailed),
- this.solrSortBy, this.chunkstart, this.chunksize, CollectionSchema.id.getSolrFieldName(), CollectionSchema.sku.getSolrFieldName());
- this.urlsToRecrawl = docList.getNumFound();
- } catch (final Throwable e) {
- this.urlsToRecrawl = 0;
- this.terminatedBySolrFailure = true;
- }
-
- if (docList != null) {
- final Set<String> tobedeletedIDs = new HashSet<>();
- for (final SolrDocument doc : docList) {
- try {
- this.urlstack.add(new DigestURL((String) doc.getFieldValue(CollectionSchema.sku.getSolrFieldName())));
- if (this.deleteOnRecrawl) tobedeletedIDs.add((String) doc.getFieldValue(CollectionSchema.id.getSolrFieldName()));
- } catch (final MalformedURLException ex) {
- this.malformedUrlsCount++;
- // if index entry hasn't a valid url (useless), delete it
- tobedeletedIDs.add((String) doc.getFieldValue(CollectionSchema.id.getSolrFieldName()));
- this.malformedUrlsDeletedCount++;
- ConcurrentLog.severe(THREAD_NAME, "deleted index document with invalid url " + (String) doc.getFieldValue(CollectionSchema.sku.getSolrFieldName()));
- }
- }
-
- if (!tobedeletedIDs.isEmpty()) try {
- solrConnector.deleteByIds(tobedeletedIDs);
- solrConnector.commit(false);
- } catch (final IOException e) {
- ConcurrentLog.severe(THREAD_NAME, "error deleting IDs ", e);
- }
-
- this.chunkstart = this.deleteOnRecrawl? 0 : this.chunkstart + this.chunksize;
- }
-
- if (docList == null || docList.size() < this.chunksize) {
- return false;
- }
- return true;
- }
-
- /**
- * @return a new default CrawlProfile instance to be used for recrawl jobs.
- */
- public static CrawlProfile buildDefaultCrawlProfile() {
- final CrawlProfile profile = new CrawlProfile(CrawlSwitchboard.CRAWL_PROFILE_RECRAWL_JOB, CrawlProfile.MATCH_ALL_STRING, // crawlerUrlMustMatch
- CrawlProfile.MATCH_NEVER_STRING, // crawlerUrlMustNotMatch
- CrawlProfile.MATCH_ALL_STRING, // crawlerIpMustMatch
- CrawlProfile.MATCH_NEVER_STRING, // crawlerIpMustNotMatch
- CrawlProfile.MATCH_NEVER_STRING, // crawlerCountryMustMatch
- CrawlProfile.MATCH_NEVER_STRING, // crawlerNoDepthLimitMatch
- CrawlProfile.MATCH_ALL_STRING, // indexUrlMustMatch
- CrawlProfile.MATCH_NEVER_STRING, // indexUrlMustNotMatch
- CrawlProfile.MATCH_ALL_STRING, // indexContentMustMatch
- CrawlProfile.MATCH_NEVER_STRING, // indexContentMustNotMatch
- false, //noindexWhenCanonicalUnequalURL
- 0, false, CrawlProfile.getRecrawlDate(CrawlSwitchboard.CRAWL_PROFILE_RECRAWL_JOB_RECRAWL_CYCLE), -1,
- true, true, true, false, // crawlingQ, followFrames, obeyHtmlRobotsNoindex, obeyHtmlRobotsNofollow,
- true, true, true, false, -1, false, true, CrawlProfile.MATCH_NEVER_STRING, CacheStrategy.IFFRESH,
- "robot_" + CrawlSwitchboard.CRAWL_PROFILE_RECRAWL_JOB,
- ClientIdentification.yacyInternetCrawlerAgentName,
- TagValency.EVAL, null, null, 0);
- return profile;
- }
-
- @Override
- public int getJobCount() {
- return this.urlstack.size();
- }
-
- /**
- * @return The total number of candidate URLs found for recrawl
- */
- public long getUrlsToRecrawl() {
- return this.urlsToRecrawl;
- }
-
- /**
- * @return The total number of URLs added to the crawler queue for recrawl
- */
- public long getRecrawledUrlsCount() {
- return this.recrawledUrlsCount;
- }
-
- /**
- * @return The total number of URLs rejected for some reason by the crawl
- * stacker or the crawler queue
- */
- public long getRejectedUrlsCount() {
- return this.rejectedUrlsCount;
- }
-
- /**
- * @return The total number of malformed URLs found
- */
- public long getMalformedUrlsCount() {
- return this.malformedUrlsCount;
- }
-
- /**
- * @return The total number of malformed URLs deleted from index
- */
- public long getMalformedUrlsDeletedCount() {
- return this.malformedUrlsDeletedCount;
- }
-
- /**
- * @return true when the job terminated early because an error occurred when
- * requesting the Solr index, or the Solr index was closed
- */
- public boolean isTerminatedBySolrFailure() {
- return this.terminatedBySolrFailure;
- }
-
- /** @return The recrawl job start time */
- public LocalDateTime getStartTime() {
- return this.startTime;
- }
-
- /** @return The recrawl job end time */
- public LocalDateTime getEndTime() {
- return this.endTime;
- }
-
- @Override
- public void freemem() {
- this.urlstack.clear();
- }
-
-}
+/**
+ * RecrawlBusyThread.java
+ * SPDX-FileCopyrightText: 2015 by Burkhard Buelte
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * First released 15.05.2015 at https://yacy.net
+ *
+ * This is a part of YaCy, a peer-to-peer based web search engine
+ *
+ * LICENSE
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program in the file lgpl21.txt If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+package net.yacy.crawler;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrDocumentList;
+
+import net.yacy.cora.document.encoding.ASCII;
+import net.yacy.cora.document.id.DigestURL;
+import net.yacy.cora.federate.solr.connector.SolrConnector;
+import net.yacy.cora.federate.yacy.CacheStrategy;
+import net.yacy.cora.protocol.ClientIdentification;
+import net.yacy.cora.util.ConcurrentLog;
+import net.yacy.crawler.data.CrawlProfile;
+import net.yacy.crawler.data.NoticedURL;
+import net.yacy.crawler.retrieval.Request;
+import net.yacy.document.parser.html.TagValency;
+import net.yacy.kelondro.workflow.AbstractBusyThread;
+import net.yacy.search.Switchboard;
+import net.yacy.search.schema.CollectionSchema;
+
+/**
+ * Selects documents by a query from the local index
+ * and feeds the found urls to the crawler to recrawl the documents.
+ * This is intended to keep the index up-to-date
+ * Currently the doucments are selected by expired fresh_date_dt field
+ * an added to the crawler in smaller chunks (see chunksize) as long as no other crawl is running.
+ */
+public class RecrawlBusyThread extends AbstractBusyThread {
+
+ /** The thread name */
+ public final static String THREAD_NAME = "recrawlindex";
+
+ /** The default selection query */
+ public static final String DEFAULT_QUERY = CollectionSchema.fresh_date_dt.getSolrFieldName()+":[* TO NOW/DAY-1DAY]";
+
+ /** Default value for inclusion or not of documents with a https status different from 200 (success) */
+ public static final boolean DEFAULT_INCLUDE_FAILED = false;
+
+ /** The default value whether to delete on Recrawl */
+ public static final boolean DEFAULT_DELETE_ON_RECRAWL = false;
+
+ /** The current query selecting documents to recrawl */
+ private String currentQuery;
+
+ /** flag if docs with httpstatus_i <> 200 shall be recrawled */
+ private boolean includefailed;
+
+ /** flag whether to delete on Recrawl */
+ private boolean deleteOnRecrawl;
+
+ private int chunkstart = 0;
+ private final int chunksize = 100;
+ private final Switchboard sb;
+
+ /** buffer of urls to recrawl */
+ private final Set<DigestURL> urlstack;
+
+ /** The total number of candidate URLs found for recrawl */
+ private long urlsToRecrawl = 0;
+
+ /** Total number of URLs added to the crawler queue for recrawl */
+ private long recrawledUrlsCount = 0;
+
+ /** Total number of URLs rejected for some reason by the crawl stacker or the crawler queue */
+ private long rejectedUrlsCount = 0;
+
+ /** Total number of malformed URLs found */
+ private long malformedUrlsCount = 0;
+
+ /** Total number of malformed URLs deleted from index */
+ private long malformedUrlsDeletedCount = 0;
+
+ private final String solrSortBy;
+
+ /** Set to true when more URLs are still to be processed */
+ private boolean moreToRecrawl = true;
+
+ /** True when the job terminated early because an error occurred when requesting the Solr index, or the Solr index was closed */
+ private boolean terminatedBySolrFailure = false;
+
+ /** The recrawl job start time */
+ private LocalDateTime startTime;
+
+ /** The recrawl job end time */
+ private LocalDateTime endTime;
+
+ /**
+ * @param xsb
+ * the Switchboard instance holding server environment
+ * @param query
+ * the Solr selection query
+ * @param includeFailed
+ * set to true when documents with a https status different from 200
+ * (success) must be included
+ */
+ public RecrawlBusyThread(final Switchboard xsb, final String query, final boolean includeFailed, final boolean deleteOnRecrawl) {
+ super(3000, 1000); // set lower limits of cycle delay
+ this.setName(THREAD_NAME);
+ this.setIdleSleep(10*60000); // set actual cycle delays
+ this.setBusySleep(2*60000);
+ this.setPriority(Thread.MIN_PRIORITY);
+ this.setLoadPreReqisite(1);
+ this.sb = xsb;
+ this.currentQuery = query;
+ this.includefailed = includeFailed;
+ this.deleteOnRecrawl = deleteOnRecrawl;
+ this.urlstack = new HashSet<>();
+ // workaround to prevent solr exception on existing index (not fully reindexed) since intro of schema with docvalues
+ // org.apache.solr.core.SolrCore java.lang.IllegalStateException: unexpected docvalues type NONE for field 'load_date_dt' (expected=NUMERIC). Use UninvertingReader or index with docvalues.
+ this.solrSortBy = CollectionSchema.load_date_dt.getSolrFieldName() + " asc";
+
+ final SolrConnector solrConnector = this.sb.index.fulltext().getDefaultConnector();
+ if (solrConnector != null && !solrConnector.isClosed()) {
+ /* Ensure indexed data is up-to-date before running the main job */
+ solrConnector.commit(true);
+ }
+ }
+
+ /**
+ * Set the query to select documents to recrawl
+ * and resets the counter to start a fresh query loop
+ * @param q select query
+ * @param includefailedurls true=all http status docs are recrawled, false=httpstatus=200 docs are recrawled
+ * @param deleteOnRecrawl
+ */
+ public void setQuery(String q, boolean includefailedurls, final boolean deleteOnRecrawl) {
+ this.currentQuery = q;
+ this.includefailed = includefailedurls;
+ this.deleteOnRecrawl = deleteOnRecrawl;
+ this.chunkstart = 0;
+ }
+
+ public String getQuery() {
+ return this.currentQuery;
+ }
+
+ /**
+ *
+ * @param queryBase
+ * the base query
+ * @param includeFailed
+ * set to true when documents with a https status different from 200
+ * (success) must be included
+ * @return the Solr selection query for candidate URLs to recrawl
+ */
+ public static final String buildSelectionQuery(final String queryBase, final boolean includeFailed) {
+ return includeFailed ? queryBase : queryBase + " AND (" + CollectionSchema.httpstatus_i.name() + ":200)";
+ }
+
+ /**
+ * Flag to include failed urls (httpstatus_i <> 200)
+ * if true -> currentQuery is used as is,
+ * if false -> the term " AND (httpstatus_i:200)" is appended to currentQuery
+ * @param includefailedurls
+ */
+ public void setIncludeFailed(boolean includefailedurls) {
+ this.includefailed = includefailedurls;
+ }
+
+ public boolean getIncludeFailed () {
+ return this.includefailed;
+ }
+
+ public void setDeleteOnRecrawl(final boolean deleteOnRecrawl) {
+ this.deleteOnRecrawl = deleteOnRecrawl;
+ }
+
+ public boolean getDeleteOnRecrawl() {
+ return this.deleteOnRecrawl;
+ }
+
+ /**
+ * feed urls to the local crawler
+ * (Switchboard.addToCrawler() is not used here, as there existing urls are always skipped)
+ *
+ * @return true if urls were added/accepted to the crawler
+ */
+ private boolean feedToCrawler() {
+
+ int added = 0;
+
+ if (!this.urlstack.isEmpty()) {
+ final CrawlProfile profile = this.sb.crawler.defaultRecrawlJobProfile;
+
+ for (final DigestURL url : this.urlstack) {
+ final Request request = new Request(ASCII.getBytes(this.sb.peers.mySeed().hash), url, null, "",
+ new Date(), profile.handle(), 0, profile.timezoneOffset());
+ String acceptedError = this.sb.crawlStacker.checkAcceptanceChangeable(url, profile, 0);
+ if (!this.includefailed && acceptedError == null) { // skip check if failed docs to be included
+ acceptedError = this.sb.crawlStacker.checkAcceptanceInitially(url, profile);
+ }
+ if (acceptedError != null) {
+ this.rejectedUrlsCount++;
+ ConcurrentLog.info(THREAD_NAME, "addToCrawler: cannot load " + url.toNormalform(true) + ": " + acceptedError);
+ continue;
+ }
+ final String s;
+ s = this.sb.crawlQueues.noticeURL.push(NoticedURL.StackType.LOCAL, request, profile, this.sb.robots);
+
+ if (s != null) {
+ this.rejectedUrlsCount++;
+ ConcurrentLog.info(THREAD_NAME, "addToCrawler: failed to add " + url.toNormalform(true) + ": " + s);
+ } else {
+ added++;
+ this.recrawledUrlsCount++;
+ }
+ }
+ this.urlstack.clear();
+ }
+ return (added > 0);
+ }
+
+ /**
+ * Process query and hand over urls to the crawler
+ *
+ * @return true if something processed
+ */
+ @Override
+ public boolean job() {
+ // more than chunksize crawls are running, do nothing
+ if (this.sb.crawlQueues.coreCrawlJobSize() > this.chunksize) {
+ return false;
+ }
+
+ boolean didSomething = false;
+ if (this.urlstack.isEmpty()) {
+ if(!this.moreToRecrawl) {
+ /* We do not remove the thread from the Switchboard worker threads using serverSwitch.terminateThread(String,boolean),
+ * because we want to be able to provide a report after its termination */
+ this.terminate(false);
+ } else {
+ this.moreToRecrawl = this.processSingleQuery();
+ /* Even if no more URLs are to recrawl, the job has done something by searching the Solr index */
+ didSomething = true;
+ }
+ } else {
+ didSomething = this.feedToCrawler();
+ }
+ return didSomething;
+ }
+
+ @Override
+ public synchronized void start() {
+ this.startTime = LocalDateTime.now();
+ super.start();
+ }
+
+ @Override
+ public void terminate(boolean waitFor) {
+ super.terminate(waitFor);
+ this.endTime = LocalDateTime.now();
+ }
+
+ /**
+ * Selects documents to recrawl the urls
+ * @return true if query has more results
+ */
+ private boolean processSingleQuery() {
+ if (!this.urlstack.isEmpty()) {
+ return true;
+ }
+ SolrDocumentList docList = null;
+ final SolrConnector solrConnector = this.sb.index.fulltext().getDefaultConnector();
+ if (solrConnector == null || solrConnector.isClosed()) {
+ this.urlsToRecrawl = 0;
+ this.terminatedBySolrFailure = true;
+ return false;
+ }
+
+ try {
+ // query all or only httpstatus=200 depending on includefailed flag
+ docList = solrConnector.getDocumentListByQuery(RecrawlBusyThread.buildSelectionQuery(this.currentQuery, this.includefailed),
+ this.solrSortBy, this.chunkstart, this.chunksize, CollectionSchema.id.getSolrFieldName(), CollectionSchema.sku.getSolrFieldName());
+ this.urlsToRecrawl = docList.getNumFound();
+ } catch (final Throwable e) {
+ this.urlsToRecrawl = 0;
+ this.terminatedBySolrFailure = true;
+ }
+
+ if (docList != null) {
+ final Set<String> tobedeletedIDs = new HashSet<>();
+ for (final SolrDocument doc : docList) {
+ try {
+ this.urlstack.add(new DigestURL((String) doc.getFieldValue(CollectionSchema.sku.getSolrFieldName())));
+ if (this.deleteOnRecrawl) tobedeletedIDs.add((String) doc.getFieldValue(CollectionSchema.id.getSolrFieldName()));
+ } catch (final MalformedURLException ex) {
+ this.malformedUrlsCount++;
+ // if index entry hasn't a valid url (useless), delete it
+ tobedeletedIDs.add((String) doc.getFieldValue(CollectionSchema.id.getSolrFieldName()));
+ this.malformedUrlsDeletedCount++;
+ ConcurrentLog.severe(THREAD_NAME, "deleted index document with invalid url " + (String) doc.getFieldValue(CollectionSchema.sku.getSolrFieldName()));
+ }
+ }
+
+ if (!tobedeletedIDs.isEmpty()) try {
+ solrConnector.deleteByIds(tobedeletedIDs);
+ solrConnector.commit(false);
+ } catch (final IOException e) {
+ ConcurrentLog.severe(THREAD_NAME, "error deleting IDs ", e);
+ }
+
+ this.chunkstart = this.deleteOnRecrawl? 0 : this.chunkstart + this.chunksize;
+ }
+
+ if (docList == null || docList.size() < this.chunksize) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @return a new default CrawlProfile instance to be used for recrawl jobs.
+ */
+ public static CrawlProfile buildDefaultCrawlProfile() {
+ final CrawlProfile profile = new CrawlProfile(CrawlSwitchboard.CRAWL_PROFILE_RECRAWL_JOB, CrawlProfile.MATCH_ALL_STRING, // crawlerUrlMustMatch
+ CrawlProfile.MATCH_NEVER_STRING, // crawlerUrlMustNotMatch
+ CrawlProfile.MATCH_ALL_STRING, // crawlerIpMustMatch
+ CrawlProfile.MATCH_NEVER_STRING, // crawlerIpMustNotMatch
+ CrawlProfile.MATCH_NEVER_STRING, // crawlerCountryMustMatch
+ CrawlProfile.MATCH_NEVER_STRING, // crawlerNoDepthLimitMatch
+ CrawlProfile.MATCH_ALL_STRING, // indexUrlMustMatch
+ CrawlProfile.MATCH_NEVER_STRING, // indexUrlMustNotMatch
+ CrawlProfile.MATCH_ALL_STRING, // indexContentMustMatch
+ CrawlProfile.MATCH_NEVER_STRING, // indexContentMustNotMatch
+ false, //noindexWhenCanonicalUnequalURL
+ 0, false, CrawlProfile.getRecrawlDate(CrawlSwitchboard.CRAWL_PROFILE_RECRAWL_JOB_RECRAWL_CYCLE), -1,
+ true, true, true, false, // crawlingQ, followFrames, obeyHtmlRobotsNoindex, obeyHtmlRobotsNofollow,
+ true, true, true, false, CacheStrategy.IFFRESH,
+ "robot_" + CrawlSwitchboard.CRAWL_PROFILE_RECRAWL_JOB,
+ ClientIdentification.yacyInternetCrawlerAgentName,
+ TagValency.EVAL, null, null, 0);
+ return profile;
+ }
+
+ @Override
+ public int getJobCount() {
+ return this.urlstack.size();
+ }
+
+ /**
+ * @return The total number of candidate URLs found for recrawl
+ */
+ public long getUrlsToRecrawl() {
+ return this.urlsToRecrawl;
+ }
+
+ /**
+ * @return The total number of URLs added to the crawler queue for recrawl
+ */
+ public long getRecrawledUrlsCount() {
+ return this.recrawledUrlsCount;
+ }
+
+ /**
+ * @return The total number of URLs rejected for some reason by the crawl
+ * stacker or the crawler queue
+ */
+ public long getRejectedUrlsCount() {
+ return this.rejectedUrlsCount;
+ }
+
+ /**
+ * @return The total number of malformed URLs found
+ */
+ public long getMalformedUrlsCount() {
+ return this.malformedUrlsCount;
+ }
+
+ /**
+ * @return The total number of malformed URLs deleted from index
+ */
+ public long getMalformedUrlsDeletedCount() {
+ return this.malformedUrlsDeletedCount;
+ }
+
+ /**
+ * @return true when the job terminated early because an error occurred when
+ * requesting the Solr index, or the Solr index was closed
+ */
+ public boolean isTerminatedBySolrFailure() {
+ return this.terminatedBySolrFailure;
+ }
+
+ /** @return The recrawl job start time */
+ public LocalDateTime getStartTime() {
+ return this.startTime;
+ }
+
+ /** @return The recrawl job end time */
+ public LocalDateTime getEndTime() {
+ return this.endTime;
+ }
+
+ @Override
+ public void freemem() {
+ this.urlstack.clear();
+ }
+
+}
diff --git a/source/net/yacy/crawler/data/CrawlProfile.java b/source/net/yacy/crawler/data/CrawlProfile.java
index 574a164fb..af6c60926 100644
--- a/source/net/yacy/crawler/data/CrawlProfile.java
+++ b/source/net/yacy/crawler/data/CrawlProfile.java
@@ -120,10 +120,6 @@ public class CrawlProfile extends ConcurrentHashMap<String, String> implements M
STORE_HTCACHE ("storeHTCache", false, CrawlAttribute.BOOLEAN, "Store in HTCache"),
CACHE_STRAGEGY ("cacheStrategy", false, CrawlAttribute.STRING, "Cache Strategy (NOCACHE,IFFRESH,IFEXIST,CACHEONLY)"),
AGENT_NAME ("agentName", false, CrawlAttribute.STRING, "User Agent Profile Name"),
- SNAPSHOTS_MAXDEPTH ("snapshotsMaxDepth", false, CrawlAttribute.INTEGER, "Max Depth for Snapshots"),
- SNAPSHOTS_REPLACEOLD ("snapshotsReplaceOld", false, CrawlAttribute.BOOLEAN, "Multiple Snapshot Versions - replace old with new"),
- SNAPSHOTS_MUSTNOTMATCH ("snapshotsMustnotmatch", false, CrawlAttribute.STRING, "must-not-match filter for snapshot generation"),
- SNAPSHOTS_LOADIMAGE ("snapshotsLoadImage", false, CrawlAttribute.BOOLEAN, "Flag for Snapshot image generation"),
REMOTE_INDEXING ("remoteIndexing", false, CrawlAttribute.BOOLEAN, "Remote Indexing (only for p2p networks)"),
INDEX_TEXT ("indexText", false, CrawlAttribute.BOOLEAN, "Index Text"),
INDEX_MEDIA ("indexMedia", false, CrawlAttribute.BOOLEAN, "Index Media"),
@@ -174,7 +170,6 @@ public class CrawlProfile extends ConcurrentHashMap<String, String> implements M
* @see CollectionSchema#content_type */
private Pattern indexMediaTypeMustNotMatch = null;
- private Pattern snapshotsMustnotmatch = null;
private final Map<String, AtomicInteger> doms;
private final TagValency defaultValency;
@@ -204,10 +199,6 @@ public class CrawlProfile extends ConcurrentHashMap<String, String> implements M
* @param indexMedia true if media content of URL shall be indexed
* @param storeHTCache true if content chall be kept in cache after indexing
* @param remoteIndexing true if part of the crawl job shall be distributed
- * @param snapshotsMaxDepth if the current crawl depth is equal or below that given depth, a snapshot is generated
- * @param snapshotsLoadImage true if graphical (== pdf) shapshots shall be made
- * @param snapshotsReplaceOld true if snapshots shall not be historized
- * @param snapshotsMustnotmatch a regular expression; if it matches on the url, the snapshot is not generated
* @param xsstopw true if static stop words shall be ignored
* @param xdstopw true if dynamic stop words shall be ignored
* @param xpstopw true if parent stop words shall be ignored
@@ -235,10 +226,6 @@ public class CrawlProfile extends ConcurrentHashMap<String, String> implements M
final boolean indexMedia,
final boolean storeHTCache,
final boolean remoteIndexing,
- final int snapshotsMaxDepth,
- final boolean snapshotsLoadImage,
- final boolean snapshotsReplaceOld,
- final String snapshotsMustnotmatch,
final CacheStrategy cacheStrategy,
final String collections,
final String userAgentName,
@@ -281,10 +268,6 @@ public class CrawlProfile extends ConcurrentHashMap<String, String> implements M
this.put(CrawlAttribute.INDEX_MEDIA.key, indexMedia);
this.put(CrawlAttribute.STORE_HTCACHE.key, storeHTCache);
this.put(CrawlAttribute.REMOTE_INDEXING.key, remoteIndexing);
- this.put(CrawlAttribute.SNAPSHOTS_MAXDEPTH.key, snapshotsMaxDepth);
- this.put(CrawlAttribute.SNAPSHOTS_LOADIMAGE.key, snapshotsLoadImage);
- this.put(CrawlAttribute.SNAPSHOTS_REPLACEOLD.key, snapshotsReplaceOld);
- this.put(CrawlAttribute.SNAPSHOTS_MUSTNOTMATCH.key, snapshotsMustnotmatch);
this.put(CrawlAttribute.CACHE_STRAGEGY.key, cacheStrategy.toString());
this.put(CrawlAttribute.COLLECTIONS.key, CommonPattern.SPACE.matcher(collections.trim()).replaceAll(""));
// we transform the ignore_class_name and scraper information into a JSON Array
@@ -895,41 +878,6 @@ public class CrawlProfile extends ConcurrentHashMap<String, String> implements M
return (r.equals(Boolean.TRUE.toString()));
}
- public int snapshotMaxdepth() {
- final String r = this.get(CrawlAttribute.SNAPSHOTS_MAXDEPTH.key);
- if (r == null) return -1;
- try {
- final int i = Integer.parseInt(r);
- if (i < 0) return -1;
- return i;
- } catch (final NumberFormatException e) {
- ConcurrentLog.logException(e);
- return -1;
- }
- }
-
- public boolean snapshotLoadImage() {
- final String r = this.get(CrawlAttribute.SNAPSHOTS_LOADIMAGE.key);
- if (r == null) return false;
- return (r.equals(Boolean.TRUE.toString()));
- }
-
- public boolean snapshotReplaceold() {
- final String r = this.get(CrawlAttribute.SNAPSHOTS_REPLACEOLD.key);
- if (r == null) return false;
- return (r.equals(Boolean.TRUE.toString()));
- }
-
- public Pattern snapshotsMustnotmatch() {
- if (this.snapshotsMustnotmatch == null) {
- final String r = this.get(CrawlAttribute.SNAPSHOTS_MUSTNOTMATCH.key);
- try {
- this.snapshotsMustnotmatch = (r == null || r.equals(CrawlProfile.MATCH_ALL_STRING)) ? CrawlProfile.MATCH_ALL_PATTERN : Pattern.compile(r, Pattern.CASE_INSENSITIVE);
- } catch (final PatternSyntaxException e) { this.snapshotsMustnotmatch = CrawlProfile.MATCH_NEVER_PATTERN; }
- }
- return this.snapshotsMustnotmatch;
- }
-
public int timezoneOffset() {
final String timezoneOffset = this.get(CrawlAttribute.TIMEZONEOFFSET.key);
if (timezoneOffset == null) return 0;
@@ -1038,10 +986,6 @@ public class CrawlProfile extends ConcurrentHashMap<String, String> implements M
prop.put(CRAWL_PROFILE_PREFIX + count + "_storeHTCache", this.storeHTCache() ? 1 : 0);
prop.putXML(CRAWL_PROFILE_PREFIX + count + "_cacheStrategy", this.get(CrawlAttribute.CACHE_STRAGEGY.key));
prop.putXML(CRAWL_PROFILE_PREFIX + count + "_agentName", this.get(CrawlAttribute.AGENT_NAME.key));
- prop.putXML(CRAWL_PROFILE_PREFIX + count + "_" + CrawlAttribute.SNAPSHOTS_MAXDEPTH.key, this.get(CrawlAttribute.SNAPSHOTS_MAXDEPTH.key));
- prop.putXML(CRAWL_PROFILE_PREFIX + count + "_" + CrawlAttribute.SNAPSHOTS_REPLACEOLD.key, this.get(CrawlAttribute.SNAPSHOTS_REPLACEOLD.key));
- prop.putXML(CRAWL_PROFILE_PREFIX + count + "_" + CrawlAttribute.SNAPSHOTS_MUSTNOTMATCH.key, this.get(CrawlAttribute.SNAPSHOTS_MUSTNOTMATCH.key));
- prop.putXML(CRAWL_PROFILE_PREFIX + count + "_" + CrawlAttribute.SNAPSHOTS_LOADIMAGE.key, this.get(CrawlAttribute.SNAPSHOTS_LOADIMAGE.key));
prop.put(CRAWL_PROFILE_PREFIX + count + "_remoteIndexing", this.remoteIndexing() ? 1 : 0);
prop.put(CRAWL_PROFILE_PREFIX + count + "_indexText", this.indexText() ? 1 : 0);
prop.put(CRAWL_PROFILE_PREFIX + count + "_indexMedia", this.indexMedia() ? 1 : 0);
diff --git a/source/net/yacy/crawler/data/Snapshots.java b/source/net/yacy/crawler/data/Snapshots.java
deleted file mode 100644
index 0463d0d42..000000000
--- a/source/net/yacy/crawler/data/Snapshots.java
+++ /dev/null
@@ -1,516 +0,0 @@
-/**
- * DocumentImage
- * SPDX-FileCopyrightText: 2014 Michael Peter Christen <mc@yacy.net)>
- * SPDX-License-Identifier: GPL-2.0-or-later
- * First released 29.11.2014 at https://yacy.net
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program in the file lgpl21.txt
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.yacy.crawler.data;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-import org.apache.solr.common.SolrDocument;
-
-import net.yacy.cora.date.GenericFormatter;
-import net.yacy.cora.document.encoding.ASCII;
-import net.yacy.cora.document.id.DigestURL;
-import net.yacy.cora.util.ConcurrentLog;
-import net.yacy.search.index.Fulltext;
-import net.yacy.search.schema.CollectionSchema;
-
-/**
- * This class hosts document snapshots.
- *
- * The storage is organized in the following hierarchy:
- * - in the root path are subpaths for each host:port
- * - in the host:port path are subpaths for the crawl depth, two digits length
- * - in the crawl depth path are subpaths for the first two charaters of the url-hash, called shard
- * - in the shard path are files, named with <urlhash>'.'<date>.<ext>
- * .. where the <date> has the form "yyyyMMdd" and ext may be one of {pdf,jpg,png,xml,json}.
- * The pdf is created with wxhtmltopdf, jpg/png is created with convert
- * and the xml/json is an extract from solr.
- *
- * The construction of the file name with the date allows to make several copies of the same document
- * for different snapshot-times. The usage of the crawl depth makes it easier to extract a specific part
- * of the domain.
- */
-public class Snapshots {
-
- private File storageLocation;
-
- private Map<String, TreeMap<Integer, TreeSet<String>>> directory; // a TreeMap for each domain (host.port) where the key is the depth and the value is a Set containing a key/urlhash id to get all files into a specific order to provide a recent view on the documents
-
- public Snapshots(final File location) {
- this.storageLocation = location;
- this.storageLocation.mkdirs();
- // scan the location to fill the directory
- this.directory = new HashMap<>();
- for (String hostport: location.list()) {
- TreeMap<Integer, TreeSet<String>> domaindepth = new TreeMap<>();
- this.directory.put(hostport, domaindepth);
- File domaindir = new File(location, hostport);
- if (domaindir.isDirectory()) domainscan: for (String depth: domaindir.list()) {
- TreeSet<String> dateid = new TreeSet<>();
- Integer depthi = -1;
- try {
- depthi = Integer.parseInt(depth);
- } catch (NumberFormatException e) {
- continue domainscan;
- }
- domaindepth.put(depthi, dateid);
- File sharddir = new File(domaindir, depth);
- if (sharddir.isDirectory()) for (String shard: sharddir.list()) {
- File snapshotdir = new File(sharddir, shard);
- if (snapshotdir.isDirectory()) {
- for (String snapshotfile: snapshotdir.list()) {
- if (snapshotfile.endsWith(".xml")) {
- String s = snapshotfile.substring(0, snapshotfile.length() - 4);
- int p = s.indexOf('.');
- assert p == 12;
- if (p > 0) {
- String key = s.substring(p + 1) + '.' + s.substring(0, p);
- dateid.add(key);
- }
- }
- }
- }
- }
- if (dateid.size() == 0) domaindepth.remove(depthi);
- }
- if (domaindepth.size() == 0) this.directory.remove(hostport);
- }
- }
-
- /**
- * get the number of entries in the snapshot directory
- * @return the total number of different documents
- */
- public int size() {
- int c = 0;
- for (Map<Integer, TreeSet<String>> m: directory.values()) {
- for (TreeSet<String> n: m.values()) {
- c += n.size();
- }
- }
- return c;
- }
-
- /**
- * get a list of <host>.<port> names in the snapshot directory
- * @return
- */
- public Set<String> listHosts() {
- return directory.keySet();
- }
-
- public final class Revisions {
- public final int depth;
- public final Date[] dates;
- public final String urlhash;
- public final String url;
- public final File[] pathtoxml;
- public Revisions(final String hostport, final int depth, final String datehash) {
- this.depth = depth;
- int p = datehash.indexOf('.');
- this.dates = new Date[1];
- String datestring = datehash.substring(0, p);
- this.dates[0] = parseDate(datestring);
- this.urlhash = datehash.substring(p + 1);
- this.pathtoxml = new File[1];
- this.pathtoxml[0] = new File(pathToShard(hostport, urlhash, depth), this.urlhash + "." + datestring + ".xml");
- String u = null;
- if (this.pathtoxml[0].exists()) {
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new InputStreamReader(new FileInputStream(this.pathtoxml[0])));
- String line;
- while ((line = reader.readLine()) != null) {
- if (line.startsWith("<str name=\"sku\">")) {
- u = line.substring(16, line.length() - 6);
- break;
- }
- }
- } catch (IOException e) {
- ConcurrentLog.warn("SNAPSHOTS", "Error while reading file " + this.pathtoxml[0]);
- } finally {
- if(reader != null) {
- try {
- reader.close();
- } catch (IOException ignored) {
- ConcurrentLog.warn("SNAPSHOTS", "Could not close input stream on file " + this.pathtoxml[0]);
- }
- }
- }
- }
- this.url = u;
- }
- }
-
- public Revisions getRevisions(String urlhash) {
- if (urlhash == null || urlhash.length() == 0) return null;
- // search for the hash, we must iterate through all entries
- for (Map.Entry<String, TreeMap<Integer, TreeSet<String>>> hostportDomaindepth: this.directory.entrySet()) {
- String hostport = hostportDomaindepth.getKey();
- for (Map.Entry<Integer, TreeSet<String>> depthDateHash: hostportDomaindepth.getValue().entrySet()) {
- int depth = depthDateHash.getKey();
- for (String dateHash: depthDateHash.getValue()) {
- if (dateHash.endsWith(urlhash)) {
- return new Revisions(hostport, depth, dateHash);
- }
- }
- }
- }
- return null;
- }
-
- /**
- * list the snapshots for a given host name
- * @param hostport the <host>.<port> identifier for the domain (with the same format as applied by the Snapshots.pathToHostPortDir() function)
- * @param depth restrict the result to the given depth or if depth == -1 do not restrict to a depth
- * @return a map with a set for each depth in the domain of the host name
- */
- public TreeMap<Integer, Collection<Revisions>> listIDs(final String hostport, final int depth) {
- TreeMap<Integer, Collection<Revisions>> result = new TreeMap<>();
- TreeMap<Integer, TreeSet<String>> list = directory.get(hostport);
- if (list != null) {
- for (Map.Entry<Integer, TreeSet<String>> entry: list.entrySet()) {
- if (depth != -1 && entry.getKey() != depth) continue;
- Collection<Revisions> r = new ArrayList<>(entry.getValue().size());
- for (String datehash: entry.getValue()) {
- r.add(new Revisions(hostport, entry.getKey(), datehash));
- }
- result.put(entry.getKey(), r);
- }
- }
- return result;
- }
-
- /**
- * get the number of snapshots for the given host name
- * @param hostport the <host>.<port> identifier for the domain
- * @param depth restrict the result to the given depth or if depth == -1 do not restrict to a depth
- * @return a count, the total number of documents for the domain and depth
- */
- public int listIDsSize(final String hostport, final int depth) {
- int count = 0;
- TreeMap<Integer, TreeSet<String>> list = directory.get(hostport);
- if (list != null) {
- for (Map.Entry<Integer, TreeSet<String>> entry: list.entrySet()) {
- if (depth != -1 && entry.getKey() != depth) continue;
- count += entry.getValue().size();
- }
- }
- return count;
- }
-
- /**
- * Compute the path of a snapshot. This does not create the snapshot, only gives a path.
- * Also, the path to the storage location is not created.
- * @param url
- * @param ext
- * @param depth
- * @param date
- * @return a file to the snapshot
- */
- public File definePath(final DigestURL url, final int depth, final Date date, final String ext) {
- String id = ASCII.String(url.hash());
- String ds = GenericFormatter.SHORT_MINUTE_FORMATTER.format(date);
- return new File(pathToShard(url, depth), id + "." + ds + "." + ext);
- }
-
- /**
- * Write information about the storage of a snapshot to the Snapshot-internal index.
- * The actual writing of files to the target directory must be done elsewehre, this method does not store the snapshot files.
- * @param url
- * @param depth
- * @param date
- */
- public void announceStorage(final DigestURL url, final int depth, final Date date) {
- String id = ASCII.String(url.hash());
- String ds = GenericFormatter.SHORT_MINUTE_FORMATTER.format(date);
- String pathToHostPortDir = pathToHostPortDir(url.getHost(), url.getPort());
- TreeMap<Integer, TreeSet<String>> domaindepth = this.directory.get(pathToHostPortDir);
- if (domaindepth == null) {domaindepth = new TreeMap<Integer, TreeSet<String>>(); this.directory.put(pathToHostPortDir(url.getHost(), url.getPort()), domaindepth);}
- TreeSet<String> dateid = domaindepth.get(depth);
- if (dateid == null) {dateid = new TreeSet<String>(); domaindepth.put(depth, dateid);}
- dateid.add(ds + '.' + id);
- }
-
- /**
- * Delete information about the storage of a snapshot to the Snapshot-internal index.
- * The actual deletion of files in the target directory must be done elsewhere, this method does not store the snapshot files.
- * @param url
- * @param depth
- */
- public Set<Date> announceDeletion(final DigestURL url, final int depth) {
- HashSet<Date> dates = new HashSet<>();
- String id = ASCII.String(url.hash());
- String pathToHostPortDir = pathToHostPortDir(url.getHost(), url.getPort());
- TreeMap<Integer, TreeSet<String>> domaindepth = this.directory.get(pathToHostPortDir);
- if (domaindepth == null) return dates;
- TreeSet<String> dateid = domaindepth.get(depth);
- if (dateid == null) return dates;
- Iterator<String> i = dateid.iterator();
- while (i.hasNext()) {
- String dis = i.next();
- if (dis.endsWith("." + id)) {
- String d = dis.substring(0, dis.length() - id.length() - 1);
- Date date = parseDate(d);
- if (date != null) dates.add(date);
- i.remove();
- }
- }
- if (dateid.size() == 0) domaindepth.remove(depth);
- if (domaindepth.size() == 0) this.directory.remove(pathToHostPortDir);
- return dates;
- }
-
- /**
- * Order enum class for the select method
- */
- public static enum Order {
- ANY, OLDESTFIRST, LATESTFIRST;
- }
-
- /**
- * select a set of urlhashes from the snapshot directory. The selection either ordered
- * by generation date (upwards == OLDESTFIRST or downwards == LATESTFIRST) or with any
- * order. The result set can be selected either with a given host or a depth
- * @param host selected host or null for all hosts
- * @param depth selected depth or null for all depths
- * @param order Order.ANY, Order.OLDESTFIRST or Order.LATESTFIRST
- * @param maxcount the maximum number of hosthashes. If unlimited, submit Integer.MAX_VALUE
- * @return a map of hosthashes with the associated creation date
- */
- public LinkedHashMap<String, Revisions> select(final String host, final Integer depth, final Order order, int maxcount) {
- TreeMap<String, String[]> dateIdResult = new TreeMap<>();
- if (host == null && depth == null) {
- loop: for (Map.Entry<String, TreeMap<Integer, TreeSet<String>>> hostportDepths: this.directory.entrySet()) {
- for (Map.Entry<Integer, TreeSet<String>> depthIds: hostportDepths.getValue().entrySet()) {
- for (String id: depthIds.getValue()) {
- dateIdResult.put(id, new String[]{hostportDepths.getKey(), Integer.toString(depthIds.getKey())});
- if (order == Order.ANY && dateIdResult.size() >= maxcount) break loop;
- }
- }
- }
- }
- if (host == null && depth != null) {
- loop: for (Map.Entry<String, TreeMap<Integer, TreeSet<String>>> hostportDepths: this.directory.entrySet()) {
- TreeSet<String> ids = hostportDepths.getValue().get(depth);
- if (ids != null) for (String id: ids) {
- dateIdResult.put(id, new String[]{hostportDepths.getKey(), Integer.toString(depth)});
- if (order == Order.ANY && dateIdResult.size() >= maxcount) break loop;
- }
- }
- }
- if (host != null && depth == null) {
- String hostport = pathToHostPortDir(host, 80);
- TreeMap<Integer, TreeSet<String>> depthIdsMap = this.directory.get(hostport);
- if(depthIdsMap == null && isIpv6AddrHost(host)) {
- /* If the host is a raw IPV6 address, we check also if a snapshot was recorded with the old format (without percent-encoding) */
- hostport = pathToHostPortDir(host, 80, false);
- depthIdsMap = this.directory.get(hostport);
- }
- if (depthIdsMap != null) {
- loop: for (Map.Entry<Integer, TreeSet<String>> depthIds: depthIdsMap.entrySet()) {
- for (String id: depthIds.getValue()) {
- dateIdResult.put(id, new String[]{hostport, Integer.toString(depthIds.getKey())});
- if (order == Order.ANY && dateIdResult.size() >= maxcount) break loop;
- }
- }
- }
- }
- if (host != null && depth != null) {
- String hostport = pathToHostPortDir(host, 80);
- TreeMap<Integer, TreeSet<String>> domaindepth = this.directory.get(hostport);
- if(domaindepth == null && isIpv6AddrHost(host)) {
- /* If the host is a raw IPV6 address, we check also if a snapshot was recorded with the old format (without percent-encoding) */
- hostport = pathToHostPortDir(host, 80, false);
- domaindepth = this.directory.get(hostport);
- }
- if (domaindepth != null) {
- TreeSet<String> ids = domaindepth.get(depth);
- if (ids != null) loop: for (String id: ids) {
- dateIdResult.put(id, new String[]{hostport, Integer.toString(depth)});
- if (order == Order.ANY && dateIdResult.size() >= maxcount) break loop;
- }
- }
- }
- LinkedHashMap<String, Revisions> result = new LinkedHashMap<>();
- Iterator<Map.Entry<String, String[]>> i = order == Order.LATESTFIRST ? dateIdResult.descendingMap().entrySet().iterator() : dateIdResult.entrySet().iterator();
- while (i.hasNext() && result.size() < maxcount) {
- Map.Entry<String, String[]> entry = i.next();
- String datehash = entry.getKey();
- int p = datehash.indexOf('.');
- assert p >= 0;
- Revisions r = new Revisions(entry.getValue()[0], Integer.parseInt(entry.getValue()[1]), datehash);
- result.put(datehash.substring(p + 1), r);
- }
- return result;
- }
-
- private static Date parseDate(String d) {
- try {
- return GenericFormatter.SHORT_MINUTE_FORMATTER.parse(d, 0).getTime();
- } catch (ParseException e) {
- try {
- return GenericFormatter.SHORT_DAY_FORMATTER.parse(d, 0).getTime();
- } catch (ParseException ee) {
- return null;
- }
- }
- }
-
- /**
- * get the depth to a document, helper method for definePath to determine the depth value
- * @param url
- * @param fulltext
- * @return the crawldepth of the document
- */
- public int getDepth(final DigestURL url, final Fulltext fulltext) {
- Integer depth = null;
- if (fulltext.getDefaultConfiguration().contains(CollectionSchema.crawldepth_i)) {
- try {
- SolrDocument doc = fulltext.getDefaultConnector().getDocumentById(ASCII.String(url.hash()), CollectionSchema.crawldepth_i.getSolrFieldName());
- if (doc != null) {
- depth = (Integer) doc.getFieldValue(CollectionSchema.crawldepth_i.getSolrFieldName());
- }
- } catch (IOException e) {
- }
- }
- return depth == null ? 0 : depth;
- }
-
- /**
- * for a given url, get all paths for storage locations.
- * The locations are all for the single url but may represent different storage times.
- * This method is inefficient because it tests all different depths, it would be better to use
- * findPaths/3 with a given depth.
- * @param url
- * @param ext
- * @return a set of files for snapshots of the url
- */
- public Collection<File> findPaths(final DigestURL url, final String ext) {
- for (int i = 0; i < 100; i++) {
- Collection<File> paths = findPaths(url, i, ext);
- if (paths.size() > 0) return paths;
- }
- return new ArrayList<>(0);
- }
-
- // pathtoxml = <storageLocation>/<host>.<port>/<depth>/<shard>/<urlhash>.<date>.xml
-
- /**
- * for a given url, get all paths for storage locations.
- * The locations are all for the single url but may represent different storage times.
- * @param url
- * @param ext required extension or null if the extension must not be checked
- * @param depth
- * @return a set of files for snapshots of the url
- */
- public Collection<File> findPaths(final DigestURL url, final int depth, final String ext) {
- String id = ASCII.String(url.hash());
- File pathToShard = pathToShard(url, depth);
- if(!pathToShard.exists() && isIpv6AddrHost(url.getHost())) {
- /* If the host is a raw IPV6 address, we check also if a snapshot was recorded with the old format (without percent-encoding) */
- pathToShard = pathToShard(pathToHostPortDir(url.getHost(), url.getPort(), false), ASCII.String(url.hash()), depth);
- }
- String[] list = pathToShard.exists() && pathToShard.isDirectory() ? pathToShard.list() : null; // may be null if path does not exist
- ArrayList<File> paths = new ArrayList<>();
- if (list != null) {
- for (String f: list) {
- if (f.startsWith(id) && (ext == null || f.endsWith(ext))) paths.add(new File(pathToShard, f));
- }
- }
- return paths;
- }
-
- private File pathToShard(final DigestURL url, final int depth) {
- return pathToShard(pathToHostPortDir(url.getHost(), url.getPort()), ASCII.String(url.hash()), depth);
- }
-
- private File pathToShard(final String hostport, final String urlhash, final int depth) {
- File pathToHostDir = new File(storageLocation, hostport);
- File pathToDepthDir = new File(pathToHostDir, pathToDepthDir(depth));
- File pathToShard = new File(pathToDepthDir, pathToShard(urlhash));
- return pathToShard;
- }
-
- /**
- * @param host a domain name or IP address
- * @return true when the host string is a raw IPV6 address (with square brackets)
- */
- private boolean isIpv6AddrHost(final String host) {
- return (host != null && host.startsWith("[") && host.endsWith("]") && host.contains(":"));
- }
-
- /**
- * @param host a domain name or IP address
- * @param port a port number
- * @return a representation of the host and port encoding IPV6 addresses for better support accross file systems (notably FAT or NTFS)
- */
- private String pathToHostPortDir(final String host, final int port) {
- return pathToHostPortDir(host, port, true);
- }
-
- /**
- * @param host a domain name or IP address
- * @param port a port number
- * @param encodeIpv6 when true, encode the host for better support accross file systems (notably FAT or NTFS)
- * @return a representation of the host and port
- */
- private String pathToHostPortDir(final String host, final int port, final boolean encodeIpv6) {
- String encodedHost = host;
- if(encodeIpv6 && isIpv6AddrHost(host)) {
- /* Percent-encode the host name when it is an IPV6 address, as the ':' character is illegal in a file name on MS Windows FAT32 and NTFS file systems */
- try {
- encodedHost = URLEncoder.encode(host, StandardCharsets.UTF_8.name());
- } catch (final UnsupportedEncodingException e) {
- /* This should not happen has UTF-8 encoding support is required for any JVM implementation */
- }
- }
- return encodedHost + "." + port;
- }
-
- private String pathToDepthDir(final int depth) {
- return depth < 10 ? "0" + depth : Integer.toString(depth);
- }
-
- private String pathToShard(final String urlhash) {
- return urlhash.substring(0, 2);
- }
-
-}
diff --git a/source/net/yacy/crawler/data/Transactions.java b/source/net/yacy/crawler/data/Transactions.java
deleted file mode 100644
index 016cd06c6..000000000
--- a/source/net/yacy/crawler/data/Transactions.java
+++ /dev/null
@@ -1,403 +0,0 @@
-/**
- * Transactions
- * SPDX-FileCopyrightText: 2014 Michael Peter Christen <mc@yacy.net)>
- * SPDX-License-Identifier: GPL-2.0-or-later
- * First released 08.12.2014 at https://yacy.net
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program in the file lgpl21.txt
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.yacy.crawler.data;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.solr.common.SolrInputDocument;
-
-import net.yacy.cora.document.id.DigestURL;
-import net.yacy.cora.federate.solr.responsewriter.EnhancedXMLResponseWriter;
-import net.yacy.cora.protocol.ClientIdentification;
-import net.yacy.cora.util.ConcurrentLog;
-import net.yacy.cora.util.Html2Image;
-import net.yacy.crawler.data.Snapshots.Order;
-import net.yacy.crawler.data.Snapshots.Revisions;
-import net.yacy.search.schema.CollectionSchema;
-
-/**
- * This is a static class holding one or several Snapshot directories
- * Transacted snapshots are moved from the inventory snapshot directory to the archive snapshot directory.
- *
- */
-public class Transactions {
-
- private final static String XML_PREFIX = "<response>\n<!--\n";
- private final static char[] WHITESPACE = new char[132];
- //private final static int WHITESPACE_START = XML_PREFIX.length();
- //private final static int WHITESPACE_LENGTH = WHITESPACE.length;
- private static File transactionDir = null, inventoryDir = null, archiveDir = null;
- private static Snapshots inventory = null, archive = null;
- private static ExecutorService executor = Executors.newCachedThreadPool();
- private static AtomicInteger executorRunning = new AtomicInteger(0);
-
- /** the maximum to wait for each wkhtmltopdf call when rendering PDF snapshots */
- private static long wkhtmltopdfTimeout = 30;
-
- static {
- for (int i = 0; i < WHITESPACE.length; i++) WHITESPACE[i] = 32;
- }
-
- public static enum State {
- INVENTORY("inventory"), ARCHIVE("archive"), ANY(null);
- public String dirname;
- State(String dirname) {
- this.dirname = dirname;
- }
- }
-
- /**
- * @param dir the parent directory of inventory and archive snapshots.
- * @param wkhtmltopdfSecondsTimeout the maximum to wait for each wkhtmltopdf call when rendering PDF snapshots
- */
- public static void init(final File dir, final long wkhtmltopdfSecondsTimeout) {
- transactionDir = dir;
- transactionDir.mkdirs();
- inventoryDir = new File(transactionDir, State.INVENTORY.dirname);
- inventory = new Snapshots(inventoryDir);
- archiveDir = new File(transactionDir, State.ARCHIVE.dirname);
- archive = new Snapshots(archiveDir);
- wkhtmltopdfTimeout = wkhtmltopdfSecondsTimeout;
- }
-
- public static synchronized void migrateIPV6Snapshots() {
- executor.shutdown();
- try {
- executor.awaitTermination(10, TimeUnit.SECONDS);
- } catch (final InterruptedException e) {
- return;
- }
- }
-
- /**
- * get the number of entries for each of the transaction states
- * @return the total number of different documents for each transaction state
- */
- public static Map<String, Integer> sizes() {
- HashMap<String, Integer> m = new HashMap<>();
- m.put(State.INVENTORY.name(), inventory.size());
- m.put(State.ARCHIVE.name(), archive.size());
- return m;
- }
-
- public static Revisions getRevisions(final State state, final String urlhash) {
- switch (state) {
- case INVENTORY : return inventory.getRevisions(urlhash);
- case ARCHIVE : return archive.getRevisions(urlhash);
- default : Revisions a = inventory.getRevisions(urlhash); return a == null ? archive.getRevisions(urlhash) : a;
- }
- }
-
- /**
- * get a list of <host>.<port> names in the snapshot directory
- * @return the list of the given state. if the state is ALL or unknown, all lists are combined
- */
- public static Set<String> listHosts(final State state) {
- switch (state) {
- case INVENTORY : return inventory.listHosts();
- case ARCHIVE : return archive.listHosts();
- default : Set<String> a = inventory.listHosts(); a.addAll(archive.listHosts()); return a;
- }
- }
-
- /**
- * list the snapshots for a given host name
- * @param hostport the <host>.<port> identifier for the domain (with the same format as applied by the Snapshots.pathToHostPortDir() function).
- * @param depth restrict the result to the given depth or if depth == -1 do not restrict to a depth
- * @param state the wanted transaction state, State.INVENTORY, State.ARCHIVE or State.ANY
- * @return a map with a set for each depth in the domain of the host name
- */
- public static TreeMap<Integer, Collection<Revisions>> listIDs(final String hostport, final int depth, final State state) {
- switch (state) {
- case INVENTORY : return inventory.listIDs(hostport, depth);
- case ARCHIVE : return archive.listIDs(hostport, depth);
- default : TreeMap<Integer, Collection<Revisions>> a = inventory.listIDs(hostport, depth); a.putAll(archive.listIDs(hostport, depth)); return a;
- }
- }
-
- /**
- * get the number of snapshots for the given host name
- * @param hostport the <host>.<port> identifier for the domain
- * @param depth restrict the result to the given depth or if depth == -1 do not restrict to a depth
- * @param state the wanted transaction state, State.INVENTORY, State.ARCHIVE or State.ANY
- * @return a count, the total number of documents for the domain and depth
- */
- public static int listIDsSize(final String hostport, final int depth, final State state) {
- switch (state) {
- case INVENTORY : return inventory.listIDsSize(hostport, depth);
- case ARCHIVE : return archive.listIDsSize(hostport, depth);
- default : return inventory.listIDsSize(hostport, depth) + archive.listIDsSize(hostport, depth);
- }
- }
-
- public static boolean store(final SolrInputDocument doc, final boolean concurrency, final boolean loadImage, final boolean replaceOld, final String proxy, final String acceptLanguage) {
-
- // GET METADATA FROM DOC
- final String urls = (String) doc.getFieldValue(CollectionSchema.sku.getSolrFieldName());
- final Date date = (Date) doc.getFieldValue(CollectionSchema.load_date_dt.getSolrFieldName());
- final Integer o_depth = (Integer) doc.getFieldValue(CollectionSchema.crawldepth_i.getSolrFieldName()); // may return null
- final int depth = o_depth == null ? 0 : o_depth.intValue();
-
- DigestURL url;
- try {
- url = new DigestURL(urls);
- } catch (MalformedURLException e) {
- ConcurrentLog.logException(e);
- return false;
- }
-
- boolean success = loadImage ? store(url, date, depth, concurrency, replaceOld, proxy, acceptLanguage) : true;
- if (success) {
- // STORE METADATA FOR THE IMAGE
- File metadataPath = Transactions.definePath(url, depth, date, "xml", Transactions.State.INVENTORY);
- metadataPath.getParentFile().mkdirs();
- if (doc != null) {
- try (
- /* Resources automatically closed by this try-with-resources statement */
- final FileOutputStream fos = new FileOutputStream(metadataPath);
- final OutputStreamWriter osw = new OutputStreamWriter(fos);
- ) {
- osw.write(XML_PREFIX);
- osw.write(WHITESPACE); osw.write("\n-->\n"); // placeholder for transaction information properties (a hack to attach metadata to metadata)
- osw.write("<result name=\"response\" numFound=\"1\" start=\"0\">\n");
- EnhancedXMLResponseWriter.writeDoc(osw, doc);
- osw.write("</result>\n");
- osw.write("</response>\n");
- } catch (IOException e) {
- ConcurrentLog.logException(e);
- success = false;
- }
- if(success) {
- Transactions.announceStorage(url, depth, date, State.INVENTORY);
- }
- }
-
- }
-
- return success;
- }
-
-
- public static boolean store(final DigestURL url, final Date date, final int depth, final boolean concurrency, final boolean replaceOld, final String proxy, final String acceptLanguage) {
-
- // CLEAN UP OLD DATA (if wanted)
- Collection<File> oldPaths = Transactions.findPaths(url, depth, null, Transactions.State.INVENTORY);
- if (replaceOld && oldPaths != null) {
- for (File oldPath: oldPaths) {
- oldPath.delete();
- }
- }
-
- // STORE METADATA FOR THE IMAGE
- File metadataPath = Transactions.definePath(url, depth, date, "xml", Transactions.State.INVENTORY);
- metadataPath.getParentFile().mkdirs();
- boolean success = true;
-
- // STORE AN IMAGE
- final String urls = url.toNormalform(true);
- final File pdfPath = Transactions.definePath(url, depth, date, "pdf", Transactions.State.INVENTORY);
- if (concurrency && executorRunning.intValue() < Runtime.getRuntime().availableProcessors()) {
- Thread t = new Thread("Transactions.store"){
- @Override
- public void run() {
- executorRunning.incrementAndGet();
- try {
- Html2Image.writeWkhtmltopdf(urls, proxy, ClientIdentification.browserAgent.userAgent(), acceptLanguage, pdfPath, wkhtmltopdfTimeout);
- } catch (Throwable e) {} finally {
- executorRunning.decrementAndGet();
- }
- }
- };
- executor.execute(t);
- } else {
- success = Html2Image.writeWkhtmltopdf(urls, proxy, ClientIdentification.browserAgent.userAgent(), acceptLanguage, pdfPath, wkhtmltopdfTimeout);
- }
-
- return success;
- }
-
- /**
- * Announce the commit of a snapshot: this will move all data for the given urlhash from the inventory to the archive
- * The index within the snapshot management will update also.
- * @param urlhash
- * @return a revision object from the moved document if the commit has succeeded, null if something went wrong
- */
- public static Revisions commit(String urlhash) {
- return transact(urlhash, State.INVENTORY, State.ARCHIVE);
- }
-
- /**
- * Announce the rollback of a snapshot: this will move all data for the given urlhash from the archive to the inventory
- * The index within the snapshot management will update also.
- * @param urlhash
- * @return a revision object from the moved document if the commit has succeeded, null if something went wrong
- */
- public static Revisions rollback(String urlhash) {
- return transact(urlhash, State.ARCHIVE, State.INVENTORY);
- }
-
- private static Revisions transact(final String urlhash, final State from, final State to) {
- Revisions r = Transactions.getRevisions(from, urlhash);
- if (r == null) return null;
- // we take all pathtoxml and move that to archive
- for (File f: r.pathtoxml) {
- String name = f.getName();
- String nameStub = name.substring(0, name.length() - 4);
- File sourceParent = f.getParentFile();
- File targetParent = new File(sourceParent.getAbsolutePath().replace("/" + from.dirname + "/", "/" + to.dirname + "/"));
- targetParent.mkdirs();
- // list all files in the parent directory
- for (String a: sourceParent.list()) {
- if (a.startsWith(nameStub)) {
- new File(sourceParent, a).renameTo(new File(targetParent, a));
- }
- }
- // delete empty directories
- while (sourceParent.list().length == 0) {
- sourceParent.delete();
- sourceParent = sourceParent.getParentFile();
- }
- }
- // announce the movement
- DigestURL durl;
- try {
- durl = new DigestURL(r.url);
- Transactions.announceDeletion(durl, r.depth, from);
- Transactions.announceStorage(durl, r.depth, r.dates[0], to);
- return r;
- } catch (MalformedURLException e) {
- ConcurrentLog.logException(e);
- }
-
- return null;
- }
-
- /**
- * select a set of urlhashes from the snapshot directory. The selection either ordered
- * by generation date (upwards == OLDESTFIRST or downwards == LATESTFIRST) or with any
- * order. The result set can be selected either with a given host or a depth
- * @param host selected host or null for all hosts
- * @param depth selected depth or null for all depths
- * @param order Order.ANY, Order.OLDESTFIRST or Order.LATESTFIRST
- * @param maxcount the maximum number of hosthashes. If unlimited, submit Integer.MAX_VALUE
- * @param state the wanted transaction state, State.INVENTORY, State.ARCHIVE or State.ANY
- * @return a map of hosthashes with the associated creation date
- */
- public static LinkedHashMap<String, Revisions> select(String host, Integer depth, final Order order, int maxcount, State state) {
- LinkedHashMap<String, Revisions> result = new LinkedHashMap<>();
- if (state == State.INVENTORY || state == State.ANY) result.putAll(inventory.select(host, depth, order, maxcount));
- if (state == State.ARCHIVE || state == State.ANY) result.putAll(archive.select(host, depth, order, maxcount));
- return result;
- }
-
- /**
- * Compute the path of a snapshot. This does not create the snapshot, only gives a path.
- * Also, the path to the storage location is not created.
- * @param url
- * @param depth
- * @param date
- * @param ext
- * @param state the wanted transaction state, State.INVENTORY, State.ARCHIVE or State.ANY
- * @return a file to the snapshot
- */
- public static File definePath(final DigestURL url, final int depth, final Date date, final String ext, State state) {
- if (state == State.ANY) throw new RuntimeException("definePath must be selected with INVENTORY or ARCHIVE state");
- if (state == State.INVENTORY) return inventory.definePath(url, depth, date, ext);
- if (state == State.ARCHIVE) return archive.definePath(url, depth, date, ext);
- return null;
- }
-
- /**
- * Write information about the storage of a snapshot to the Snapshot-internal index.
- * The actual writing of files to the target directory must be done elsewehre, this method does not store the snapshot files.
- * @param state the wanted transaction state, State.INVENTORY, State.ARCHIVE or State.ANY
- * @param url
- * @param depth
- * @param date
- */
- public static void announceStorage(final DigestURL url, final int depth, final Date date, State state) {
- if (state == State.INVENTORY || state == State.ANY) inventory.announceStorage(url, depth, date);
- if (state == State.ARCHIVE || state == State.ANY) archive.announceStorage(url, depth, date);
- }
-
- /**
- * Delete information about the storage of a snapshot to the Snapshot-internal index.
- * The actual deletion of files in the target directory must be done elsewehre, this method does not store the snapshot files.
- * @param state the wanted transaction state, State.INVENTORY, State.ARCHIVE or State.ANY
- * @param url
- * @param depth
- */
- public static void announceDeletion(final DigestURL url, final int depth, final State state) {
- if (state == State.INVENTORY || state == State.ANY) inventory.announceDeletion(url, depth);
- if (state == State.ARCHIVE || state == State.ANY) archive.announceDeletion(url, depth);
- }
-
- /**
- * for a given url, get all paths for storage locations.
- * The locations are all for the single url but may represent different storage times.
- * This method is inefficient because it tests all different depths, it would be better to use
- * findPaths/3 with a given depth.
- * @param url
- * @param ext required extension or null if the extension must not be checked
- * @param state the wanted transaction state, State.INVENTORY, State.ARCHIVE or State.ANY
- * @return a set of files for snapshots of the url
- */
- public static Collection<File> findPaths(final DigestURL url, final String ext, State state) {
- Collection<File> result = new ArrayList<>();
- if (state == State.INVENTORY || state == State.ANY) result.addAll(inventory.findPaths(url, ext));
- if (state == State.ARCHIVE || state == State.ANY) result.addAll(archive.findPaths(url, ext));
- return result;
- }
-
- /**
- * for a given url, get all paths for storage locations.
- * The locations are all for the single url but may represent different storage times.
- * @param url
- * @param ext required extension or null if the extension must not be checked
- * @param depth
- * @param state the wanted transaction state, State.INVENTORY, State.ARCHIVE or State.ANY
- * @return a set of files for snapshots of the url
- */
- public static Collection<File> findPaths(final DigestURL url, final int depth, final String ext, State state) {
- Collection<File> result = new ArrayList<>();
- if (state == State.INVENTORY || state == State.ANY) result.addAll(inventory.findPaths(url, depth, ext));
- if (state == State.ARCHIVE || state == State.ANY) result.addAll(archive.findPaths(url, depth, ext));
- return result;
- }
-
-}
diff --git a/source/net/yacy/document/parser/psParser.java b/source/net/yacy/document/parser/psParser.java
index 86b4ca4d9..9d98e7f25 100644
--- a/source/net/yacy/document/parser/psParser.java
+++ b/source/net/yacy/document/parser/psParser.java
@@ -33,7 +33,6 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Date;
@@ -47,10 +46,6 @@ import net.yacy.kelondro.util.FileUtils;
public class psParser extends AbstractParser implements Parser {
- private final static Object modeScan = new Object();
- private static boolean modeScanDone = false;
- private static String parserMode = "java";
-
public psParser() {
super("PostScript Document Parser");
this.SUPPORTED_EXTENSIONS.add("ps");
@@ -59,33 +54,8 @@ public class psParser extends AbstractParser implements Parser {
this.SUPPORTED_MIME_TYPES.add("application/x-postscript");
this.SUPPORTED_MIME_TYPES.add("application/x-ps");
this.SUPPORTED_MIME_TYPES.add("application/x-postscript-not-eps");
- if (!modeScanDone) synchronized (modeScan) {
- if (testForPs2Ascii()) parserMode = "ps2ascii";
- else parserMode = "java";
- modeScanDone = true;
- }
}
- private boolean testForPs2Ascii() {
- try {
- String procOutputLine = null;
- final StringBuilder procOutput = new StringBuilder(80);
-
- final Process ps2asciiProc = Runtime.getRuntime().exec(new String[]{"ps2ascii", "--version"});
- final BufferedReader stdOut = new BufferedReader(new InputStreamReader(ps2asciiProc.getInputStream()));
- while ((procOutputLine = stdOut.readLine()) != null) {
- procOutput.append(procOutputLine).append(", ");
- }
- stdOut.close();
- final int returnCode = ps2asciiProc.waitFor();
- return (returnCode == 0);
- } catch (final Exception e) {
- if (AbstractParser.log != null) AbstractParser.log.info("ps2ascii not found. Switching to java parser mode.");
- return false;
- }
- }
-
-
private Document[] parse(final DigestURL location, final String mimeType, @SuppressWarnings("unused") final String charset, final File sourceFile) throws Parser.Failure, InterruptedException {
File outputFile = null;
@@ -93,12 +63,7 @@ public class psParser extends AbstractParser implements Parser {
// creating a temp file for the output
outputFile = FileUtils.createTempFile(this.getClass(), "ascii.txt");
- // decide with parser mode to use
- if (parserMode.equals("ps2ascii")) {
- parseUsingPS2ascii(sourceFile,outputFile);
- } else {
- parseUsingJava(sourceFile,outputFile);
- }
+ parseUsingJava(sourceFile,outputFile);
// return result
final Document[] docs = new Document[]{new Document(
@@ -221,41 +186,6 @@ public class psParser extends AbstractParser implements Parser {
}
- /**
- * This function requires the ghostscript-library
- * @param inputFile
- * @param outputFile
- * @throws Exception
- */
- private void parseUsingPS2ascii(final File inputFile, final File outputFile) throws Exception {
- int execCode = 0;
- StringBuilder procErr = null;
- try {
- String procOutputLine;
- final StringBuilder procOut = new StringBuilder();
- procErr = new StringBuilder();
-
- final Process ps2asciiProc = Runtime.getRuntime().exec(new String[]{"ps2ascii", inputFile.getAbsolutePath(),outputFile.getAbsolutePath()});
- final BufferedReader stdOut = new BufferedReader(new InputStreamReader(ps2asciiProc.getInputStream()));
- final BufferedReader stdErr = new BufferedReader(new InputStreamReader(ps2asciiProc.getErrorStream()));
- while ((procOutputLine = stdOut.readLine()) != null) {
- procOut.append(procOutputLine);
- }
- stdOut.close();
- while ((procOutputLine = stdErr.readLine()) != null) {
- procErr.append(procOutputLine);
- }
- stdErr.close();
- execCode = ps2asciiProc.waitFor();
- } catch (final Exception e) {
- final String errorMsg = "Unable to convert ps to ascii. " + e.getMessage();
- AbstractParser.log.severe(errorMsg);
- throw new Exception(errorMsg);
- }
-
- if (execCode != 0) throw new Exception("Unable to convert ps to ascii. ps2ascii returned statuscode " + execCode + "\n" + procErr.toString());
- }
-
@Override
public Document[] parse(
final DigestURL location,
diff --git a/source/net/yacy/htroot/ConfigSearchPage_p.java b/source/net/yacy/htroot/ConfigSearchPage_p.java
index 9b60ae6fb..11d70cb24 100644
--- a/source/net/yacy/htroot/ConfigSearchPage_p.java
+++ b/source/net/yacy/htroot/ConfigSearchPage_p.java
@@ -100,7 +100,6 @@ public class ConfigSearchPage_p {
sb.setConfig("search.result.show.cache", post.getBoolean("search.result.show.cache"));
sb.setConfig("search.result.show.proxy", post.getBoolean("search.result.show.proxy"));
sb.setConfig("search.result.show.indexbrowser", post.getBoolean("search.result.show.indexbrowser"));
- sb.setConfig("search.result.show.snapshots", post.getBoolean("search.result.show.snapshots"));
// construct navigation String
final Set<String> navConfigs = new HashSet<>();
@@ -190,7 +189,6 @@ public class ConfigSearchPage_p {
sb.setConfig("search.result.show.cache", config.getProperty("search.result.show.cache","true"));
sb.setConfig("search.result.show.proxy", config.getProperty("search.result.show.proxy","false"));
sb.setConfig("search.result.show.indexbrowser", config.getProperty("search.result.show.indexbrowser","true"));
- sb.setConfig("search.result.show.snapshots", config.getProperty("search.result.show.snapshots","true"));
sb.setConfig(SwitchboardConstants.SEARCH_NAVIGATION_MAXCOUNT,
config.getProperty(SwitchboardConstants.SEARCH_NAVIGATION_MAXCOUNT,
String.valueOf(QueryParams.FACETS_STANDARD_MAXCOUNT_DEFAULT)));
@@ -254,7 +252,6 @@ public class ConfigSearchPage_p {
prop.put("search.result.show.cache", sb.getConfigBool("search.result.show.cache", false) ? 1 : 0);
prop.put("search.result.show.proxy", sb.getConfigBool("search.result.show.proxy", false) ? 1 : 0);
prop.put("search.result.show.indexbrowser", sb.getConfigBool("search.result.show.indexbrowser", false) ? 1 : 0);
- prop.put("search.result.show.snapshots", sb.getConfigBool("search.result.show.snapshots", false) ? 1 : 0);
prop.put("search.result.show.ranking", sb.getConfigBool(SwitchboardConstants.SEARCH_RESULT_SHOW_RANKING, SwitchboardConstants.SEARCH_RESULT_SHOW_RANKING_DEFAULT) ? 1 : 0);
final Set<String> navConfigs = sb.getConfigSet("search.navigation");
diff --git a/source/net/yacy/htroot/CrawlStartExpert.java b/source/net/yacy/htroot/CrawlStartExpert.java
index c0d0f3a38..78bf9baaa 100644
--- a/source/net/yacy/htroot/CrawlStartExpert.java
+++ b/source/net/yacy/htroot/CrawlStartExpert.java
@@ -36,7 +36,6 @@ import net.yacy.cora.federate.solr.instance.EmbeddedInstance;
import net.yacy.cora.lod.vocabulary.Tagging;
import net.yacy.cora.protocol.ClientIdentification;
import net.yacy.cora.protocol.RequestHeader;
-import net.yacy.cora.util.Html2Image;
import net.yacy.crawler.data.CrawlProfile;
import net.yacy.crawler.data.CrawlProfile.CrawlAttribute;
import net.yacy.document.LibraryProvider;
@@ -633,18 +632,6 @@ public class CrawlStartExpert {
prop.put("vocabularySelect_vocabularyset", count);
}
- // ---------- Snapshot generation
- final boolean wkhtmltopdfAvailable = Html2Image.wkhtmltopdfAvailable();
- //boolean convertAvailable = Html2Image.convertAvailable();
- prop.put("snapshotsMaxDepth", post == null ? "-1" : post.get("snapshotsMaxDepth", "-1"));
- prop.put("snapshotsMustnotmatch", post == null ? "" : post.get("snapshotsMustnotmatch", ""));
- if (wkhtmltopdfAvailable) {
- prop.put("snapshotEnableImages", 1);
- prop.put("snapshotEnableImages_snapshotsLoadImageChecked", post == null ? 1 : post.getBoolean("snapshotsLoadImage") ? 1 : 0);
- } else {
- prop.put("snapshotEnableImages", 0);
- }
-
// ---------- Index Administration
// Do Local Indexing
if (post == null) {
diff --git a/source/net/yacy/htroot/Crawler_p.java b/source/net/yacy/htroot/Crawler_p.java
index fa94dbc6f..79934c786 100644
--- a/source/net/yacy/htroot/Crawler_p.java
+++ b/source/net/yacy/htroot/Crawler_p.java
@@ -480,12 +480,6 @@ public class Crawler_p {
}
}
- final String snapshotsMaxDepthString = post.get("snapshotsMaxDepth", "-1");
- final int snapshotsMaxDepth = Integer.parseInt(snapshotsMaxDepthString);
- final boolean snapshotsLoadImage = post.getBoolean("snapshotsLoadImage");
- final boolean snapshotsReplaceOld = post.getBoolean("snapshotsReplaceOld");
- final String snapshotsMustnotmatch = post.get("snapshotsMustnotmatch", "");
-
final String valency_switch_tag_names_s = post.get("valency_switch_tag_names");
final Set<String> valency_switch_tag_names = new HashSet<>();
if (valency_switch_tag_names_s != null) {
@@ -626,10 +620,6 @@ public class Crawler_p {
indexMedia,
storeHTCache,
crawlOrder,
- snapshotsMaxDepth,
- snapshotsLoadImage,
- snapshotsReplaceOld,
- snapshotsMustnotmatch,
cachePolicy,
collection,
agentName,
diff --git a/source/net/yacy/htroot/QuickCrawlLink_p.java b/source/net/yacy/htroot/QuickCrawlLink_p.java
index e78557c98..80c84f102 100644
--- a/source/net/yacy/htroot/QuickCrawlLink_p.java
+++ b/source/net/yacy/htroot/QuickCrawlLink_p.java
@@ -1,204 +1,203 @@
-//QuickCrawlLink_p.java
-//-----------------------
-//part of the AnomicHTTPD caching proxy
-//(C) by Michael Peter Christen; mc@yacy.net
-//first published on http://www.anomic.de
-//Frankfurt, Germany, 2004
-//
-//This file was contributed by Martin Thelian
-//$LastChangedDate$
-//$LastChangedBy$
-//$LastChangedRevision$
-//
-//This program is free software; you can redistribute it and/or modify
-//it under the terms of the GNU General Public License as published by
-//the Free Software Foundation; either version 2 of the License, or
-//(at your option) any later version.
-//
-//This program is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU General Public License for more details.
-//
-//You should have received a copy of the GNU General Public License
-//along with this program; if not, write to the Free Software
-//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//You must compile this file with
-//javac -classpath .:../classes IndexCreate_p.java
-//if the shell's current path is HTROOT
-
-
-package net.yacy.htroot;
-
-import java.net.MalformedURLException;
-import java.util.Date;
-
-import net.yacy.cora.document.encoding.UTF8;
-import net.yacy.cora.document.id.DigestURL;
-import net.yacy.cora.federate.yacy.CacheStrategy;
-import net.yacy.cora.protocol.ClientIdentification;
-import net.yacy.cora.protocol.Domains;
-import net.yacy.cora.protocol.HeaderFramework;
-import net.yacy.cora.protocol.RequestHeader;
-import net.yacy.crawler.data.CrawlProfile;
-import net.yacy.crawler.retrieval.Request;
-import net.yacy.document.parser.html.TagValency;
-import net.yacy.search.Switchboard;
-import net.yacy.search.SwitchboardConstants;
-import net.yacy.search.index.Segment;
-import net.yacy.server.serverObjects;
-import net.yacy.server.serverSwitch;
-
-public class QuickCrawlLink_p {
-
- /**
- * Example Javascript to call this servlet:
- * <code>javascript:w = window.open('http://user:pwd@localhost:8090/QuickCrawlLink_p.html?indexText=on&indexMedia=on&crawlingQ=on&xdstopw=on&title=' + escape(document.title) + '&url=' + location.href,'_blank','height=150,width=500,resizable=yes,scrollbar=no,directory=no,menubar=no,location=no'); w.focus();</code>
- * @param header the complete HTTP header of the request
- * @param post any arguments for this servlet, the request carried with (GET as well as POST)
- * @param env the serverSwitch object holding all runtime-data
- * @return the rewrite-properties for the template
- */
- public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
-
- final serverObjects prop = new serverObjects();
- final Switchboard sb = (Switchboard) env;
-
- int port;
-
- // get the http host header
- if (header.containsKey(HeaderFramework.HOST)) {
- port = header.getServerPort();
- } else {
- port = sb.getConfigInt(SwitchboardConstants.SERVER_PORT, 8090);
- }
-
- prop.put("mode_host", Domains.LOCALHOST);
- prop.put("mode_port", port);
-
- if (post == null) {
- // send back usage example
- prop.put("mode", "0");
- return prop;
- }
-
- // get the URL
- String crawlingStart = post.get("url", "");
-
- if (crawlingStart.length() != 0) {
- prop.put("mode", "1");
- crawlingStart = UTF8.decodeURL(crawlingStart);
-
- // get segment
- final Segment indexSegment = sb.index;
-
- // get the browser title
- String title = post.get("title", "");
+//QuickCrawlLink_p.java
+//-----------------------
+//part of the AnomicHTTPD caching proxy
+//(C) by Michael Peter Christen; mc@yacy.net
+//first published on http://www.anomic.de
+//Frankfurt, Germany, 2004
+//
+//This file was contributed by Martin Thelian
+//$LastChangedDate$
+//$LastChangedBy$
+//$LastChangedRevision$
+//
+//This program is free software; you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation; either version 2 of the License, or
+//(at your option) any later version.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with this program; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+//You must compile this file with
+//javac -classpath .:../classes IndexCreate_p.java
+//if the shell's current path is HTROOT
+
+
+package net.yacy.htroot;
+
+import java.net.MalformedURLException;
+import java.util.Date;
+
+import net.yacy.cora.document.encoding.UTF8;
+import net.yacy.cora.document.id.DigestURL;
+import net.yacy.cora.federate.yacy.CacheStrategy;
+import net.yacy.cora.protocol.ClientIdentification;
+import net.yacy.cora.protocol.Domains;
+import net.yacy.cora.protocol.HeaderFramework;
+import net.yacy.cora.protocol.RequestHeader;
+import net.yacy.crawler.data.CrawlProfile;
+import net.yacy.crawler.retrieval.Request;
+import net.yacy.document.parser.html.TagValency;
+import net.yacy.search.Switchboard;
+import net.yacy.search.SwitchboardConstants;
+import net.yacy.search.index.Segment;
+import net.yacy.server.serverObjects;
+import net.yacy.server.serverSwitch;
+
+public class QuickCrawlLink_p {
+
+ /**
+ * Example Javascript to call this servlet:
+ * <code>javascript:w = window.open('http://user:pwd@localhost:8090/QuickCrawlLink_p.html?indexText=on&indexMedia=on&crawlingQ=on&xdstopw=on&title=' + escape(document.title) + '&url=' + location.href,'_blank','height=150,width=500,resizable=yes,scrollbar=no,directory=no,menubar=no,location=no'); w.focus();</code>
+ * @param header the complete HTTP header of the request
+ * @param post any arguments for this servlet, the request carried with (GET as well as POST)
+ * @param env the serverSwitch object holding all runtime-data
+ * @return the rewrite-properties for the template
+ */
+ public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
+
+ final serverObjects prop = new serverObjects();
+ final Switchboard sb = (Switchboard) env;
+
+ int port;
+
+ // get the http host header
+ if (header.containsKey(HeaderFramework.HOST)) {
+ port = header.getServerPort();
+ } else {
+ port = sb.getConfigInt(SwitchboardConstants.SERVER_PORT, 8090);
+ }
+
+ prop.put("mode_host", Domains.LOCALHOST);
+ prop.put("mode_port", port);
+
+ if (post == null) {
+ // send back usage example
+ prop.put("mode", "0");
+ return prop;
+ }
+
+ // get the URL
+ String crawlingStart = post.get("url", "");
+
+ if (crawlingStart.length() != 0) {
+ prop.put("mode", "1");
+ crawlingStart = UTF8.decodeURL(crawlingStart);
+
+ // get segment
+ final Segment indexSegment = sb.index;
+
+ // get the browser title
+ String title = post.get("title", "");
if (title.length() != 0) {
- title = crawlingStart;
- /* Decode eventual special(non ASCII) characters in title */
- title = UTF8.decodeURL(title);
- }
-
- // get other parameters if set
- final String crawlingMustMatch = post.get("mustmatch", CrawlProfile.MATCH_ALL_STRING);
- final String crawlingMustNotMatch = post.get("mustnotmatch", CrawlProfile.MATCH_NEVER_STRING);
- final int CrawlingDepth = post.getInt("crawlingDepth", 0);
- final boolean crawlingQ = post.get("crawlingQ", "").equals("on");
- final boolean followFrames = post.get("followFrames", "").equals("on");
- final boolean obeyHtmlRobotsNoindex = post.get("obeyHtmlRobotsNoindex", "").equals("on");
- final boolean obeyHtmlRobotsNofollow = post.get("obeyHtmlRobotsNofollow", "").equals("on");
- final boolean indexText = post.get("indexText", "off").equals("on");
- final boolean indexMedia = post.get("indexMedia", "off").equals("on");
- final boolean storeHTCache = post.get("storeHTCache", "").equals("on");
- final boolean remoteIndexing = post.get("crawlOrder", "").equals("on");
- final String collection = post.get("collection", "user");
-
- prop.put("mode_url", (crawlingStart == null) ? "unknown" : crawlingStart);
- prop.putHTML("mode_title", (title == null) ? "unknown" : title);
-
- crawlingStart = crawlingStart.trim();
- try {crawlingStart = new DigestURL(crawlingStart).toNormalform(true);} catch (final MalformedURLException e1) {}
-
- // check if url is proper
- DigestURL crawlingStartURL = null;
- try {
- crawlingStartURL = new DigestURL(crawlingStart);
- } catch (final MalformedURLException e) {
- prop.put("mode_status", "1");
- prop.put("mode_code", "1");
- return prop;
- }
-
- final byte[] urlhash = crawlingStartURL.hash();
- indexSegment.fulltext().remove(urlhash);
- sb.crawlQueues.noticeURL.removeByURLHash(urlhash);
- final int timezoneOffset = post.getInt("timezoneOffset", 0);
-
- // create crawling profile
- CrawlProfile pe = null;
- try {
- pe = new CrawlProfile(
- (crawlingStartURL.getHost() == null) ? crawlingStartURL.toNormalform(true) : crawlingStartURL.getHost(),
- crawlingMustMatch, //crawlerUrlMustMatch
- crawlingMustNotMatch, //crawlerUrlMustNotMatch
- CrawlProfile.MATCH_ALL_STRING, //crawlerIpMustMatch
- CrawlProfile.MATCH_NEVER_STRING, //crawlerIpMustNotMatch
- CrawlProfile.MATCH_NEVER_STRING, //crawlerCountryMustMatch
- CrawlProfile.MATCH_NEVER_STRING, //crawlerNoDepthLimitMatch
- CrawlProfile.MATCH_ALL_STRING, //indexUrlMustMatch
- CrawlProfile.MATCH_NEVER_STRING, //indexUrlMustNotMatch
- CrawlProfile.MATCH_ALL_STRING, //indexContentMustMatch
- CrawlProfile.MATCH_NEVER_STRING, //indexContentMustNotMatch
- false,
- CrawlingDepth,
- true,
- CrawlProfile.getRecrawlDate(60 * 24 * 30), // recrawlIfOlder (minutes); here: one month
- -1, // domMaxPages, if negative: no count restriction
- crawlingQ, followFrames,
- obeyHtmlRobotsNoindex, obeyHtmlRobotsNofollow,
- indexText, indexMedia,
- storeHTCache, remoteIndexing,
- -1, false, true, CrawlProfile.MATCH_NEVER_STRING,
- CacheStrategy.IFFRESH,
- collection,
- ClientIdentification.yacyIntranetCrawlerAgentName,
- TagValency.EVAL, null, null,
- timezoneOffset);
- sb.crawler.putActive(pe.handle().getBytes(), pe);
- } catch (final Exception e) {
- // mist
- prop.put("mode_status", "2");//Error with url
- prop.put("mode_code", "2");
- prop.putHTML("mode_status_error", e.getMessage());
- return prop;
- }
-
- // stack URL
- String reasonString;
- reasonString = sb.crawlStacker.stackCrawl(new Request(
- sb.peers.mySeed().hash.getBytes(),
- crawlingStartURL,
- null,
- (title==null)?"CRAWLING-ROOT":title,
- new Date(),
- pe.handle(),
- 0,
- pe.timezoneOffset()
- ));
-
- // validate rejection reason
- if (reasonString == null) {
- prop.put("mode_status", "0");//start msg
- prop.put("mode_code", "0");
- } else {
- prop.put("mode_status", "3");//start msg
- prop.put("mode_code","3");
- prop.putHTML("mode_status_error", reasonString);
- }
- }
-
- return prop;
- }
-}
+ title = crawlingStart;
+ /* Decode eventual special(non ASCII) characters in title */
+ title = UTF8.decodeURL(title);
+ }
+
+ // get other parameters if set
+ final String crawlingMustMatch = post.get("mustmatch", CrawlProfile.MATCH_ALL_STRING);
+ final String crawlingMustNotMatch = post.get("mustnotmatch", CrawlProfile.MATCH_NEVER_STRING);
+ final int CrawlingDepth = post.getInt("crawlingDepth", 0);
+ final boolean crawlingQ = post.get("crawlingQ", "").equals("on");
+ final boolean followFrames = post.get("followFrames", "").equals("on");
+ final boolean obeyHtmlRobotsNoindex = post.get("obeyHtmlRobotsNoindex", "").equals("on");
+ final boolean obeyHtmlRobotsNofollow = post.get("obeyHtmlRobotsNofollow", "").equals("on");
+ final boolean indexText = post.get("indexText", "off").equals("on");
+ final boolean indexMedia = post.get("indexMedia", "off").equals("on");
+ final boolean storeHTCache = post.get("storeHTCache", "").equals("on");
+ final boolean remoteIndexing = post.get("crawlOrder", "").equals("on");
+ final String collection = post.get("collection", "user");
+
+ prop.put("mode_url", (crawlingStart == null) ? "unknown" : crawlingStart);
+ prop.putHTML("mode_title", (title == null) ? "unknown" : title);
+
+ crawlingStart = crawlingStart.trim();
+ try {crawlingStart = new DigestURL(crawlingStart).toNormalform(true);} catch (final MalformedURLException e1) {}
+
+ // check if url is proper
+ DigestURL crawlingStartURL = null;
+ try {
+ crawlingStartURL = new DigestURL(crawlingStart);
+ } catch (final MalformedURLException e) {
+ prop.put("mode_status", "1");
+ prop.put("mode_code", "1");
+ return prop;
+ }
+
+ final byte[] urlhash = crawlingStartURL.hash();
+ indexSegment.fulltext().remove(urlhash);
+ sb.crawlQueues.noticeURL.removeByURLHash(urlhash);
+ final int timezoneOffset = post.getInt("timezoneOffset", 0);
+
+ // create crawling profile
+ CrawlProfile pe = null;
+ try {
+ pe = new CrawlProfile(
+ (crawlingStartURL.getHost() == null) ? crawlingStartURL.toNormalform(true) : crawlingStartURL.getHost(),
+ crawlingMustMatch, //crawlerUrlMustMatch
+ crawlingMustNotMatch, //crawlerUrlMustNotMatch
+ CrawlProfile.MATCH_ALL_STRING, //crawlerIpMustMatch
+ CrawlProfile.MATCH_NEVER_STRING, //crawlerIpMustNotMatch
+ CrawlProfile.MATCH_NEVER_STRING, //crawlerCountryMustMatch
+ CrawlProfile.MATCH_NEVER_STRING, //crawlerNoDepthLimitMatch
+ CrawlProfile.MATCH_ALL_STRING, //indexUrlMustMatch
+ CrawlProfile.MATCH_NEVER_STRING, //indexUrlMustNotMatch
+ CrawlProfile.MATCH_ALL_STRING, //indexContentMustMatch
+ CrawlProfile.MATCH_NEVER_STRING, //indexContentMustNotMatch
+ false,
+ CrawlingDepth,
+ true,
+ CrawlProfile.getRecrawlDate(60 * 24 * 30), // recrawlIfOlder (minutes); here: one month
+ -1, // domMaxPages, if negative: no count restriction
+ crawlingQ, followFrames,
+ obeyHtmlRobotsNoindex, obeyHtmlRobotsNofollow,
+ indexText, indexMedia,
+ storeHTCache, remoteIndexing,
+ CacheStrategy.IFFRESH,
+ collection,
+ ClientIdentification.yacyIntranetCrawlerAgentName,
+ TagValency.EVAL, null, null,
+ timezoneOffset);
+ sb.crawler.putActive(pe.handle().getBytes(), pe);
+ } catch (final Exception e) {
+ // mist
+ prop.put("mode_status", "2");//Error with url
+ prop.put("mode_code", "2");
+ prop.putHTML("mode_status_error", e.getMessage());
+ return prop;
+ }
+
+ // stack URL
+ String reasonString;
+ reasonString = sb.crawlStacker.stackCrawl(new Request(
+ sb.peers.mySeed().hash.getBytes(),
+ crawlingStartURL,
+ null,
+ (title==null)?"CRAWLING-ROOT":title,
+ new Date(),
+ pe.handle(),
+ 0,
+ pe.timezoneOffset()
+ ));
+
+ // validate rejection reason
+ if (reasonString == null) {
+ prop.put("mode_status", "0");//start msg
+ prop.put("mode_code", "0");
+ } else {
+ prop.put("mode_status", "3");//start msg
+ prop.put("mode_code","3");
+ prop.putHTML("mode_status_error", reasonString);
+ }
+ }
+
+ return prop;
+ }
+}
diff --git a/source/net/yacy/htroot/api/snapshot.java b/source/net/yacy/htroot/api/snapshot.java
deleted file mode 100644
index 9b69e7751..000000000
--- a/source/net/yacy/htroot/api/snapshot.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/**
- * snapshot
- * Copyright 2014 by Michael Peter Christen, mc@yacy.net, Frankfurt am Main, Germany
- * First released 02.12.2014 at https://yacy.net
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program in the file lgpl21.txt
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.yacy.htroot.api;
-
-import java.awt.Container;
-import java.awt.Image;
-import java.awt.MediaTracker;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.apache.http.HttpStatus;
-import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrInputDocument;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import net.yacy.cora.document.encoding.ASCII;
-import net.yacy.cora.document.encoding.UTF8;
-import net.yacy.cora.document.feed.RSSFeed;
-import net.yacy.cora.document.feed.RSSMessage;
-import net.yacy.cora.document.id.DigestURL;
-import net.yacy.cora.protocol.HeaderFramework;
-import net.yacy.cora.protocol.RequestHeader;
-import net.yacy.cora.util.ConcurrentLog;
-import net.yacy.cora.util.Html2Image;
-import net.yacy.crawler.data.Snapshots;
-import net.yacy.crawler.data.Snapshots.Revisions;
-import net.yacy.crawler.data.Transactions;
-import net.yacy.document.ImageParser;
-import net.yacy.http.servlets.TemplateMissingParameterException;
-import net.yacy.http.servlets.TemplateProcessingException;
-import net.yacy.kelondro.util.FileUtils;
-import net.yacy.peers.graphics.EncodedImage;
-import net.yacy.search.Switchboard;
-import net.yacy.search.SwitchboardConstants;
-import net.yacy.server.serverObjects;
-import net.yacy.server.serverSwitch;
-
-public class snapshot {
-
- //width = 1024, height = 1024, density = 300, quality = 75
- private final static int DEFAULT_WIDTH = 1024;
- private final static int DEFAULT_HEIGHT = 1024;
- private final static int DEFAULT_DENSITY = 300;
- private final static int DEFAULT_QUALITY = 75;
- private final static String DEFAULT_EXT = "jpg";
-
- public static Object respond(final RequestHeader header, serverObjects post, final serverSwitch env) {
- final Switchboard sb = (Switchboard) env;
-
- final serverObjects defaultResponse = new serverObjects();
-
-
- final boolean authenticated = sb.adminAuthenticated(header) >= 2;
- final String ext = header.get(HeaderFramework.CONNECTION_PROP_EXT, "");
-
- if(ext.isEmpty()) {
- throw new TemplateProcessingException("Missing extension. Try with rss, xml, json, pdf, png or jpg." + ext,
- HttpStatus.SC_BAD_REQUEST);
- }
-
-
- if (ext.equals("rss")) {
- // create a report about the content of the snapshot directory
- if (!authenticated) {
- defaultResponse.authenticationRequired();
- return defaultResponse;
- }
- final int maxcount = post == null ? 10 : post.getInt("maxcount", 10);
- final int depthx = post == null ? -1 : post.getInt("depth", -1);
- final Integer depth = depthx == -1 ? null : depthx;
- final String orderx = post == null ? "ANY" : post.get("order", "ANY");
- final Snapshots.Order order = Snapshots.Order.valueOf(orderx);
- final String statex = post == null ? Transactions.State.INVENTORY.name() : post.get("state", Transactions.State.INVENTORY.name());
- final Transactions.State state = Transactions.State.valueOf(statex);
- final String host = post == null ? null : post.get("host");
- final Map<String, Revisions> iddate = Transactions.select(host, depth, order, maxcount, state);
- // now select the URL from the index for these ids in iddate and make an RSS feed
- final RSSFeed rssfeed = new RSSFeed(Integer.MAX_VALUE);
- rssfeed.setChannel(new RSSMessage("Snapshot list for host = " + host + ", depth = " + depth + ", order = " + order + ", maxcount = " + maxcount, "", ""));
- for (final Map.Entry<String, Revisions> e: iddate.entrySet()) {
- try {
- final String u = e.getValue().url == null ? sb.index.fulltext().getURL(e.getKey()) : e.getValue().url;
- if (u == null) continue;
- final RSSMessage message = new RSSMessage(u, "", new DigestURL(u), e.getKey());
- message.setPubDate(e.getValue().dates[0]);
- rssfeed.addMessage(message);
- } catch (final IOException ee) {
- ConcurrentLog.logException(ee);
- }
- }
- final byte[] rssBinary = UTF8.getBytes(rssfeed.toString());
- return new ByteArrayInputStream(rssBinary);
- }
-
- // for the following methods we (mostly) need an url or a url hash
- if (post == null) post = new serverObjects();
- final boolean xml = ext.equals("xml");
- final boolean pdf = ext.equals("pdf");
- if (pdf && !authenticated) {
- defaultResponse.authenticationRequired();
- return defaultResponse;
- }
- final boolean pngjpg = ext.equals("png") || ext.equals(DEFAULT_EXT);
- String urlhash = post.get("urlhash", "");
- final String url = post.get("url", "");
- DigestURL durl = null;
- if (urlhash.length() == 0 && url.length() > 0) {
- try {
- durl = new DigestURL(url);
- urlhash = ASCII.String(durl.hash());
- } catch (final MalformedURLException e) {
- }
- }
- if (durl == null && urlhash.length() > 0) {
- try {
- final String u = sb.index.fulltext().getURL(urlhash);
- durl = u == null ? null : new DigestURL(u);
- } catch (final IOException e) {
- ConcurrentLog.logException(e);
- }
- }
-
- if (ext.equals("json")) {
- // command interface: view and change a transaction state, get metadata about transactions in the past
- final String command = post.get("command", "metadata");
- final String statename = post.get("state");
- final JSONObject result = new JSONObject();
- try {
- if (command.equals("status")) {
- // return a status of the transaction archive
- final JSONObject sizes = new JSONObject();
- for (final Map.Entry<String, Integer> state: Transactions.sizes().entrySet()) sizes.put(state.getKey(), state.getValue());
- result.put("size", sizes);
- } else if (command.equals("list")) {
- if (!authenticated) {
- defaultResponse.authenticationRequired();
- return defaultResponse;
- }
- // return a status of the transaction archive
- final String host = post.get("host");
- final String depth = post.get("depth");
- final int depthi = depth == null ? -1 : Integer.parseInt(depth);
- for (final Transactions.State state: statename == null ?
- new Transactions.State[]{Transactions.State.INVENTORY, Transactions.State.ARCHIVE} :
- new Transactions.State[]{Transactions.State.valueOf(statename)}) {
- if (host == null) {
- final JSONObject hostCountInventory = new JSONObject();
- for (final String h: Transactions.listHosts(state)) {
- final int size = Transactions.listIDsSize(h, depthi, state);
- if (size > 0) hostCountInventory.put(h, size);
- }
- result.put("count." + state.name(), hostCountInventory);
- } else {
- final TreeMap<Integer, Collection<Revisions>> ids = Transactions.listIDs(host, depthi, state);
- if (ids == null) {
- result.put("result", "fail");
- result.put("comment", "no entries for host " + host + " found");
- } else {
- for (final Map.Entry<Integer, Collection<Revisions>> entry: ids.entrySet()) {
- for (final Revisions r: entry.getValue()) {
- try {
- final JSONObject metadata = new JSONObject();
- final String u = r.url != null ? r.url : sb.index.fulltext().getURL(r.urlhash);
- metadata.put("url", u == null ? "unknown" : u);
- metadata.put("dates", r.dates);
- assert r.depth == entry.getKey().intValue();
- metadata.put("depth", entry.getKey().intValue());
- result.put(r.urlhash, metadata);
- } catch (final IOException e) {}
- }
- }
- }
- }
- }
- } else if (command.equals("commit")) {
- if (!authenticated) {
- defaultResponse.authenticationRequired();
- return defaultResponse;
- }
- final Revisions r = Transactions.commit(urlhash);
- if (r != null) {
- result.put("result", "success");
- result.put("depth", r.depth);
- result.put("url", r.url);
- result.put("dates", r.dates);
- } else {
- result.put("result", "fail");
- }
- result.put("urlhash", urlhash);
- } else if (command.equals("rollback")) {
- if (!authenticated) {
- defaultResponse.authenticationRequired();
- return defaultResponse;
- }
- final Revisions r = Transactions.rollback(urlhash);
- if (r != null) {
- result.put("result", "success");
- result.put("depth", r.depth);
- result.put("url", r.url);
- result.put("dates", r.dates);
- } else {
- result.put("result", "fail");
- }
- result.put("urlhash", urlhash);
- } else if (command.equals("metadata")) {
- try {
- Revisions r;
- Transactions.State state = statename == null || statename.length() == 0 ? null : Transactions.State.valueOf(statename);
- if (state == null) {
- r = Transactions.getRevisions(Transactions.State.INVENTORY, urlhash);
- if (r != null) state = Transactions.State.INVENTORY;
- r = Transactions.getRevisions(Transactions.State.ARCHIVE, urlhash);
- if (r != null) state = Transactions.State.ARCHIVE;
- } else {
- r = Transactions.getRevisions(state, urlhash);
- }
- if (r != null) {
- final JSONObject metadata = new JSONObject();
- final String u = r.url != null ? r.url : sb.index.fulltext().getURL(r.urlhash);
- metadata.put("url", u == null ? "unknown" : u);
- metadata.put("dates", r.dates);
- metadata.put("depth", r.depth);
- metadata.put("state", state.name());
- result.put(r.urlhash, metadata);
- }
- } catch (IOException |IllegalArgumentException e) {}
- }
- } catch (final JSONException e) {
- ConcurrentLog.logException(e);
- }
- String json = result.toString();
- if (post.containsKey("callback")) json = post.get("callback") + "([" + json + "]);";
- return new ByteArrayInputStream(UTF8.getBytes(json));
- }
-
- // for the following methods we always need the durl to fetch data
- if (durl == null) {
- throw new TemplateMissingParameterException("Missing valid url or urlhash parameter");
- }
-
- if (xml) {
- final Collection<File> xmlSnapshots = Transactions.findPaths(durl, "xml", Transactions.State.ANY);
- File xmlFile = null;
- if (xmlSnapshots.isEmpty()) {
- throw new TemplateProcessingException("Could not find the xml snapshot file.", HttpStatus.SC_NOT_FOUND);
- }
- xmlFile = xmlSnapshots.iterator().next();
- try {
- final byte[] xmlBinary = FileUtils.read(xmlFile);
- return new ByteArrayInputStream(xmlBinary);
- } catch (final IOException e) {
- ConcurrentLog.logException(e);
- throw new TemplateProcessingException("Could not read the xml snapshot file.");
- }
- }
-
- if (pdf || pngjpg) {
- Collection<File> pdfSnapshots = Transactions.findPaths(durl, "pdf", Transactions.State.INVENTORY);
- File pdfFile = null;
- if (pdfSnapshots.isEmpty()) {
- // if the client is authenticated, we create the pdf on the fly!
- if (!authenticated) {
- throw new TemplateProcessingException(
- "Could not find the pdf snapshot file. You must be authenticated to generate one on the fly.",
- HttpStatus.SC_NOT_FOUND);
- }
- final SolrDocument sd = sb.index.fulltext().getMetadata(durl.hash());
- boolean success = false;
- if (sd == null) {
- success = Transactions.store(durl, new Date(), 99, false, true, sb.getConfigBool(SwitchboardConstants.PROXY_TRANSPARENT_PROXY, false) ? "http://127.0.0.1:" + sb.getConfigInt(SwitchboardConstants.SERVER_PORT, 8090) : null, sb.getConfig("crawler.http.acceptLanguage", null));
- } else {
- final SolrInputDocument sid = sb.index.fulltext().getDefaultConfiguration().toSolrInputDocument(sd);
- success = Transactions.store(sid, false, true, true, sb.getConfigBool(SwitchboardConstants.PROXY_TRANSPARENT_PROXY, false) ? "http://127.0.0.1:" + sb.getConfigInt(SwitchboardConstants.SERVER_PORT, 8090) : null, sb.getConfig("crawler.http.acceptLanguage", null));
- }
- if (success) {
- pdfSnapshots = Transactions.findPaths(durl, "pdf", Transactions.State.ANY);
- if (!pdfSnapshots.isEmpty()) {
- pdfFile = pdfSnapshots.iterator().next();
- }
- }
- } else {
- pdfFile = pdfSnapshots.iterator().next();
- }
- if (pdfFile == null) {
- throw new TemplateProcessingException(
- "Could not find the pdf snapshot file and could not generate one on the fly.",
- HttpStatus.SC_NOT_FOUND);
- }
- if (pdf) {
- try {
- final byte[] pdfBinary = FileUtils.read(pdfFile);
- return new ByteArrayInputStream(pdfBinary);
- } catch (final IOException e) {
- ConcurrentLog.logException(e);
- throw new TemplateProcessingException("Could not read the pdf snapshot file.");
- }
- }
-
- if (pngjpg) {
- final int width = Math.min(post.getInt("width", DEFAULT_WIDTH), DEFAULT_WIDTH);
- final int height = Math.min(post.getInt("height", DEFAULT_HEIGHT), DEFAULT_HEIGHT);
- String imageFileStub = pdfFile.getAbsolutePath(); imageFileStub = imageFileStub.substring(0, imageFileStub.length() - 3); // cut off extension
- final File imageFile = new File(imageFileStub + DEFAULT_WIDTH + "." + DEFAULT_HEIGHT + "." + ext);
- if (!imageFile.exists() && authenticated) {
- if(!Html2Image.pdf2image(pdfFile, imageFile, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_DENSITY, DEFAULT_QUALITY)) {
- throw new TemplateProcessingException(
- "Could not generate the " + ext + " image snapshot file.");
- }
- }
- if (!imageFile.exists()) {
- throw new TemplateProcessingException(
- "Could not find the " + ext
- + " image snapshot file. You must be authenticated to generate one on the fly.",
- HttpStatus.SC_NOT_FOUND);
- }
- if (width == DEFAULT_WIDTH && height == DEFAULT_HEIGHT) {
- try {
- final byte[] imageBinary = FileUtils.read(imageFile);
- return new ByteArrayInputStream(imageBinary);
- } catch (final IOException e) {
- ConcurrentLog.logException(e);
- throw new TemplateProcessingException("Could not read the " + ext + " image snapshot file.");
- }
- }
- // lets read the file and scale
- Image image;
- try {
- image = ImageParser.parse(imageFile.getAbsolutePath(), FileUtils.read(imageFile));
- if(image == null) {
- throw new TemplateProcessingException("Could not parse the " + ext + " image snapshot file.");
- }
- final Image scaled = image.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING);
- final MediaTracker mediaTracker = new MediaTracker(new Container());
- mediaTracker.addImage(scaled, 0);
- try {mediaTracker.waitForID(0);} catch (final InterruptedException e) {}
-
- /*
- * Ensure there is no alpha component on the ouput image, as it is pointless
- * here and it is not well supported by the JPEGImageWriter from OpenJDK
- */
- final BufferedImage scaledBufferedImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- scaledBufferedImg.createGraphics().drawImage(scaled, 0, 0, width, height, null);
- return new EncodedImage(scaledBufferedImg, ext, true);
- } catch (final IOException e) {
- ConcurrentLog.logException(e);
- throw new TemplateProcessingException("Could not scale the " + ext + " image snapshot file.");
- }
-
- }
- }
-
- throw new TemplateProcessingException(
- "Unsupported extension : " + ext + ". Try with rss, xml, json, pdf, png or jpg.",
- HttpStatus.SC_BAD_REQUEST);
- }
-}
diff --git a/source/net/yacy/htroot/yacysearchitem.java b/source/net/yacy/htroot/yacysearchitem.java
index 28a7ecac9..a85679f0a 100644
--- a/source/net/yacy/htroot/yacysearchitem.java
+++ b/source/net/yacy/htroot/yacysearchitem.java
@@ -27,7 +27,6 @@
package net.yacy.htroot;
import java.awt.Dimension;
-import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URLEncoder;
@@ -36,7 +35,6 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
-import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
@@ -55,8 +53,6 @@ import net.yacy.cora.protocol.RequestHeader.FileType;
import net.yacy.cora.util.ConcurrentLog;
import net.yacy.cora.util.Memory;
import net.yacy.crawler.data.Cache;
-import net.yacy.crawler.data.Transactions;
-import net.yacy.crawler.data.Transactions.State;
import net.yacy.crawler.retrieval.Response;
import net.yacy.data.URLLicense;
import net.yacy.data.UserDB;
@@ -291,7 +287,6 @@ public class yacysearchitem {
final Date[] events = result.events();
final boolean showEvent = events != null && events.length > 0 && sb.getConfig("search.navigation", "").indexOf("date",0) >= 0;
prop.put("content_showEvent", showEvent ? 1 : 0);
- final Collection<File> snapshotPaths = sb.getConfigBool("search.result.show.snapshots", true) ? Transactions.findPaths(result.url(), null, State.ANY) : null;
if (fileType == FileType.HTML) { // html template specific settings
final boolean showKeywords = (sb.getConfigBool(SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS,
SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS_DEFAULT) && !result.dc_subject().isEmpty());
@@ -305,7 +300,6 @@ public class yacysearchitem {
prop.put("content_showCache", sb.getConfigBool("search.result.show.cache", true) && Cache.has(resultURL.hash()) ? 1 : 0);
prop.put("content_showProxy", sb.getConfigBool("search.result.show.proxy", true) && sb.getConfigBool("proxyURL", false) ? 1 : 0);
prop.put("content_showIndexBrowser", sb.getConfigBool("search.result.show.indexbrowser", true) ? 1 : 0);
- prop.put("content_showSnapshots", snapshotPaths != null && snapshotPaths.size() > 0 && sb.getConfigBool("search.result.show.snapshots", true) ? 1 : 0);
prop.put("content_showVocabulary", sb.getConfigBool("search.result.show.vocabulary", true) ? 1 : 0);
prop.put("content_showRanking", sb.getConfigBool("search.result.show.ranking", false) ? 1 : 0);
@@ -376,29 +370,6 @@ public class yacysearchitem {
prop.put("content_showVocabulary_vocabulary", 0);
prop.put("content_showVocabulary", 0);
}
- if (snapshotPaths != null && snapshotPaths.size() > 0) {
- /* Only add a link to the eventual snapshot file in the format it is stored (no resource fetching and conversion here) */
- String selectedExt = null, ext;
- for(final File snapshot : snapshotPaths) {
- ext = MultiProtocolURL.getFileExtension(snapshot.getName());
- if("jpg".equals(ext) || "png".equals(ext)) {
- /* Prefer snapshots in jpeg or png format */
- selectedExt = ext;
- break;
- } else if("pdf".equals(ext)) {
- selectedExt = ext;
- } else if("xml".equals(ext) && selectedExt == null) {
- /* Use the XML metadata snapshot in last resort */
- selectedExt = ext;
- }
- }
- if(selectedExt != null) {
- prop.putHTML("content_showSnapshots_extension", selectedExt.toUpperCase(Locale.ROOT));
- prop.putHTML("content_showSnapshots_link", "api/snapshot." + selectedExt + "?url=" + resultURL);
- } else {
- prop.put("content_showSnapshots", 0);
- }
- }
prop.put("content_showRanking_ranking", Float.toString(result.score()));
prop.put("content_ranking", Float.toString(result.score()));
}
diff --git a/source/net/yacy/http/servlets/SolrSelectServlet.java b/source/net/yacy/http/servlets/SolrSelectServlet.java
index 50eb41fc6..5b29b9adc 100644
--- a/source/net/yacy/http/servlets/SolrSelectServlet.java
+++ b/source/net/yacy/http/servlets/SolrSelectServlet.java
@@ -45,7 +45,6 @@ import net.yacy.cora.federate.solr.responsewriter.EnhancedXMLResponseWriter;
import net.yacy.cora.federate.solr.responsewriter.GrepHTMLResponseWriter;
import net.yacy.cora.federate.solr.responsewriter.HTMLResponseWriter;
import net.yacy.cora.federate.solr.responsewriter.OpensearchResponseWriter;
-import net.yacy.cora.federate.solr.responsewriter.SnapshotImagesReponseWriter;
import net.yacy.cora.federate.solr.responsewriter.SolrjResponseWriter;
import net.yacy.cora.federate.solr.responsewriter.YJsonResponseWriter;
import net.yacy.cora.protocol.RequestHeader;
@@ -109,7 +108,6 @@ public class SolrSelectServlet extends HttpServlet {
RESPONSE_WRITER.put("xslt", xsltWriter); // try i.e. http://localhost:8090/solr/select?q=*:*&start=0&rows=10&wt=xslt&tr=json.xsl
RESPONSE_WRITER.put("exml", new EnhancedXMLResponseWriter());
RESPONSE_WRITER.put("html", new HTMLResponseWriter());
- RESPONSE_WRITER.put("snapshots", new SnapshotImagesReponseWriter());
RESPONSE_WRITER.put("grephtml", new GrepHTMLResponseWriter());
RESPONSE_WRITER.put("rss", opensearchResponseWriter); //try http://localhost:8090/solr/select?wt=rss&q=olympia&hl=true&hl.fl=text_t,h1,h2
RESPONSE_WRITER.put("opensearch", opensearchResponseWriter); //try http://localhost:8090/solr/select?wt=rss&q=olympia&hl=true&hl.fl=text_t,h1,h2
diff --git a/source/net/yacy/search/Switchboard.java b/source/net/yacy/search/Switchboard.java
index 4e813c782..1d0b8d42a 100644
--- a/source/net/yacy/search/Switchboard.java
+++ b/source/net/yacy/search/Switchboard.java
@@ -148,7 +148,6 @@ import net.yacy.crawler.data.NoticedURL.StackType;
import net.yacy.crawler.data.ResultImages;
import net.yacy.crawler.data.ResultURLs;
import net.yacy.crawler.data.ResultURLs.EventOrigin;
-import net.yacy.crawler.data.Transactions;
import net.yacy.crawler.retrieval.Request;
import net.yacy.crawler.retrieval.Response;
import net.yacy.crawler.robots.RobotsTxt;
@@ -789,9 +788,6 @@ public final class Switchboard extends serverSwitch {
SwitchboardConstants.HTCACHE_SYNC_LOCK_TIMEOUT_DEFAULT),
this.getConfigInt(SwitchboardConstants.HTCACHE_COMPRESSION_LEVEL,
SwitchboardConstants.HTCACHE_COMPRESSION_LEVEL_DEFAULT));
- final File transactiondir = new File(this.htCachePath, "snapshots");
- Transactions.init(transactiondir, this.getConfigLong(SwitchboardConstants.SNAPSHOTS_WKHTMLTOPDF_TIMEOUT,
- SwitchboardConstants.SNAPSHOTS_WKHTMLTOPDF_TIMEOUT_DEFAULT));
// create the packs directories
this.packsHoldPath = this.getDataPath(SwitchboardConstants.PACKS_HOLD_PATH, SwitchboardConstants.PACKS_HOLD_PATH_DEFAULT);
@@ -3455,9 +3451,7 @@ public final class Switchboard extends serverSwitch {
condenser,
searchEvent,
sourceName,
- this.getConfigBool(SwitchboardConstants.NETWORK_UNIT_DHT, false),
- this.getConfigBool(SwitchboardConstants.PROXY_TRANSPARENT_PROXY, false) ? "http://127.0.0.1:" + sb.getConfigInt(SwitchboardConstants.SERVER_PORT, 8090) : null,
- this.getConfig("crawler.http.acceptLanguage", null));
+ this.getConfigBool(SwitchboardConstants.NETWORK_UNIT_DHT, false));
final RSSFeed feed =
EventChannel.channels(queueEntry.initiator() == null
? EventChannel.PROXY
diff --git a/source/net/yacy/search/SwitchboardConstants.java b/source/net/yacy/search/SwitchboardConstants.java
index 0e391e8ac..c846d88ec 100644
--- a/source/net/yacy/search/SwitchboardConstants.java
+++ b/source/net/yacy/search/SwitchboardConstants.java
@@ -360,12 +360,6 @@ public final class SwitchboardConstants {
public static final String CRAWLER_USER_AGENT_MINIMUMDELTA = "crawler.userAgent.minimumdelta";
public static final String CRAWLER_USER_AGENT_CLIENTTIMEOUT = "crawler.userAgent.clienttimeout";
- /** Key of the setting controlling the maximum time to wait for each wkhtmltopdf call when rendering PDF snapshots */
- public static final String SNAPSHOTS_WKHTMLTOPDF_TIMEOUT = "snapshots.wkhtmltopdf.timeout";
-
- /** Default maximum time in seconds to wait for each wkhtmltopdf call when rendering PDF snapshots*/
- public static final long SNAPSHOTS_WKHTMLTOPDF_TIMEOUT_DEFAULT = 30;
-
/* --- debug flags --- */
/** when set to true : do not use the local dht/rwi index (which is not done if we do remote searches) */
diff --git a/source/net/yacy/search/index/DocumentIndex.java b/source/net/yacy/search/index/DocumentIndex.java
index 1d374c72d..e5da7a2ca 100644
--- a/source/net/yacy/search/index/DocumentIndex.java
+++ b/source/net/yacy/search/index/DocumentIndex.java
@@ -193,9 +193,7 @@ public class DocumentIndex extends Segment {
condenser,
null,
DocumentIndex.class.getName() + ".add",
- false,
- null,
- null);
+ false);
}
return rows;
}
diff --git a/source/net/yacy/search/index/Segment.java b/source/net/yacy/search/index/Segment.java
index 7333f463a..0a5a22fba 100644
--- a/source/net/yacy/search/index/Segment.java
+++ b/source/net/yacy/search/index/Segment.java
@@ -63,12 +63,10 @@ import net.yacy.cora.util.ConcurrentLog;
import net.yacy.cora.util.LookAheadIterator;
import net.yacy.cora.util.SpaceExceededException;
import net.yacy.crawler.data.CrawlProfile;
-import net.yacy.crawler.data.Transactions;
import net.yacy.crawler.retrieval.Response;
import net.yacy.document.Condenser;
import net.yacy.document.Document;
import net.yacy.document.Parser;
-import net.yacy.document.parser.htmlParser;
import net.yacy.kelondro.data.citation.CitationReference;
import net.yacy.kelondro.data.citation.CitationReferenceFactory;
import net.yacy.kelondro.data.word.Word;
@@ -596,9 +594,7 @@ public class Segment {
final Condenser condenser,
final SearchEvent searchEvent,
final String sourceName, // contains the crawl profile hash if this comes from a web crawl
- final boolean storeToRWI,
- final String proxy,
- final String acceptLanguage
+ final boolean storeToRWI
) {
final CollectionConfiguration collectionConfig = this.fulltext.getDefaultConfiguration();
final String language = votedLanguage(url, url.toNormalform(true), document, condenser); // identification of the language
@@ -608,7 +604,7 @@ public class Segment {
this.fulltext().useWebgraph() ? this.fulltext.getWebgraphConfiguration() : null, sourceName);
return storeDocument(url, crawlProfile, responseHeader, document, vector, language, condenser,
- searchEvent, sourceName, storeToRWI, proxy, acceptLanguage);
+ searchEvent, sourceName, storeToRWI);
}
public SolrInputDocument storeDocument(
@@ -621,9 +617,7 @@ public class Segment {
final Condenser condenser,
final SearchEvent searchEvent,
final String sourceName, // contains the crawl profile hash if this comes from a web crawl
- final boolean storeToRWI,
- final String proxy,
- final String acceptLanguage
+ final boolean storeToRWI
) {
final long startTime = System.currentTimeMillis();
@@ -647,21 +641,6 @@ public class Segment {
// ENRICH DOCUMENT WITH RANKING INFORMATION
this.fulltext.getDefaultConfiguration().postprocessing_references(this.getReferenceReportCache(), vector, url, null);
- // CREATE SNAPSHOT
- if ((url.getProtocol().equals("http") || url.getProtocol().equals("https")) &&
- crawlProfile != null && document.getDepth() <= crawlProfile.snapshotMaxdepth() &&
- !crawlProfile.snapshotsMustnotmatch().matcher(urlNormalform).matches()) {
- // load pdf in case that is wanted. This can later be used to compute a web page preview in the search results
- Parser p = document.getParserObject();
- boolean mimesupported = false;
- if (p instanceof htmlParser)
- mimesupported = ((htmlParser)p).supportedMimeTypes().contains(document.dc_format());
-
- if (mimesupported)
- // STORE IMAGE AND METADATA
- Transactions.store(vector, true, crawlProfile.snapshotLoadImage(), crawlProfile.snapshotReplaceold(), proxy, acceptLanguage);
- }
-
// STORE TO SOLR
this.putDocument(vector);
List<SolrInputDocument> webgraph = vector.getWebgraphDocuments();