/** * InstanceMirror * Copyright 2013 by Michael Peter Christen * First released 18.02.2013 at 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.federate.solr.instance; import java.io.IOException; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import net.yacy.cora.federate.solr.connector.ConcurrentUpdateSolrConnector; import net.yacy.cora.federate.solr.connector.EmbeddedSolrConnector; import net.yacy.cora.federate.solr.connector.MirrorSolrConnector; import net.yacy.cora.federate.solr.connector.RemoteSolrConnector; import net.yacy.cora.federate.solr.connector.SolrConnector; import net.yacy.kelondro.util.MemoryControl; import net.yacy.search.Switchboard; import net.yacy.search.SwitchboardConstants; public class InstanceMirror { private EmbeddedInstance embeddedSolrInstance; private ShardInstance remoteSolrInstance; private Map<String, SolrConnector> mirrorConnectorCache; private Map<String, EmbeddedSolrConnector> embeddedConnectorCache; private Map<String, RemoteSolrConnector> remoteConnectorCache; public InstanceMirror() { this.embeddedSolrInstance = null; this.remoteSolrInstance = null; this.mirrorConnectorCache = new ConcurrentHashMap<>(); this.embeddedConnectorCache = new ConcurrentHashMap<>(); this.remoteConnectorCache = new ConcurrentHashMap<>(); } public boolean isConnectedEmbedded() { return this.embeddedSolrInstance != null; } public void connectEmbedded(EmbeddedInstance c) { disconnectEmbedded(); this.embeddedSolrInstance = c; } public EmbeddedInstance getEmbedded() { return this.embeddedSolrInstance; } public void disconnectEmbedded() { mirrorConnectorCache.clear(); if (this.embeddedSolrInstance == null) return; Set<SolrConnector> connectors = new HashSet<SolrConnector>(); connectors.addAll(this.embeddedConnectorCache.values()); for (SolrConnector connector: connectors) connector.close(); this.embeddedConnectorCache.clear(); this.embeddedSolrInstance.close(); this.embeddedSolrInstance = null; } public boolean isConnectedRemote() { return this.remoteSolrInstance != null; } public void connectRemote(ShardInstance c) { disconnectRemote(); this.remoteSolrInstance = c; } public ShardInstance getRemote() { return this.remoteSolrInstance; } public void disconnectRemote() { mirrorConnectorCache.clear(); if (this.remoteSolrInstance == null) return; for (RemoteSolrConnector connector: this.remoteConnectorCache.values()) connector.close(); this.remoteConnectorCache.clear(); this.remoteSolrInstance.close(); this.remoteSolrInstance = null; } /** * Close this instance and it's connectors and cores */ public synchronized void close() { Set<SolrConnector> connectors = new HashSet<SolrConnector>(); connectors.addAll(this.mirrorConnectorCache.values()); for (SolrConnector connector: connectors) connector.close(); this.mirrorConnectorCache.clear(); // solr core of embedded instance only closed by explicite closing the instance. // on mode switches a reopen of a core fails if instance did not close the core see http://mantis.tokeek.de/view.php?id=686 which this change solves. // (and a other alternative to deal with the issue) disconnectEmbedded(); } public String getDefaultCoreName() { if (this.embeddedSolrInstance != null) return this.embeddedSolrInstance.getDefaultCoreName(); if (this.remoteSolrInstance != null) return this.remoteSolrInstance.getDefaultCoreName(); return null; } public Collection<String> getCoreNames() { if (this.embeddedSolrInstance != null) return this.embeddedSolrInstance.getCoreNames(); if (this.remoteSolrInstance != null) return this.remoteSolrInstance.getCoreNames(); return null; } public EmbeddedSolrConnector getDefaultEmbeddedConnector() { if (this.embeddedSolrInstance == null) return null; String coreName = this.getDefaultCoreName(); if (coreName == null) return null; EmbeddedSolrConnector esc = this.embeddedConnectorCache.get(coreName); if (esc != null) return esc; esc = new EmbeddedSolrConnector(this.embeddedSolrInstance); this.embeddedConnectorCache.put(coreName, esc); return esc; } public RemoteSolrConnector getDefaultRemoteConnector(boolean useBinaryResponseWriter) throws IOException { if (this.remoteSolrInstance == null) return null; String coreName = this.getDefaultCoreName(); if (coreName == null) return null; RemoteSolrConnector esc = this.remoteConnectorCache.get(coreName); if (esc != null) return esc; esc = new RemoteSolrConnector(this.remoteSolrInstance, useBinaryResponseWriter); this.remoteConnectorCache.put(coreName, esc); return esc; } public EmbeddedSolrConnector getEmbeddedConnector(String corename) { if (this.embeddedSolrInstance == null) return null; EmbeddedSolrConnector esc = this.embeddedConnectorCache.get(corename); if (esc != null) return esc; esc = new EmbeddedSolrConnector(this.embeddedSolrInstance, corename); this.embeddedConnectorCache.put(corename, esc); return esc; } public RemoteSolrConnector getRemoteConnector(String corename) { if (this.remoteSolrInstance == null) return null; RemoteSolrConnector rsc = this.remoteConnectorCache.get(corename); if (rsc != null) return rsc; boolean useBinaryResponseWriter = SwitchboardConstants.REMOTE_SOLR_BINARY_RESPONSE_ENABLED_DEFAULT; if (Switchboard.getSwitchboard() != null) { useBinaryResponseWriter = Switchboard.getSwitchboard().getConfigBool( SwitchboardConstants.REMOTE_SOLR_BINARY_RESPONSE_ENABLED, SwitchboardConstants.REMOTE_SOLR_BINARY_RESPONSE_ENABLED_DEFAULT); } rsc = new RemoteSolrConnector(this.remoteSolrInstance, useBinaryResponseWriter, corename); this.remoteConnectorCache.put(corename, rsc); return rsc; } public SolrConnector getDefaultMirrorConnector() { String coreName = this.getDefaultCoreName(); if (coreName == null) return null; return getGenericMirrorConnector(coreName); } public SolrConnector getGenericMirrorConnector(String corename) { SolrConnector msc = this.mirrorConnectorCache.get(corename); if (msc != null) return msc; EmbeddedSolrConnector esc = getEmbeddedConnector(corename); RemoteSolrConnector rsc = getRemoteConnector(corename); int cacheSize = (int) (MemoryControl.available() / 30000); // will return about 10000 for standard ram size msc = new ConcurrentUpdateSolrConnector(new MirrorSolrConnector(esc, rsc), RemoteInstance.queueSizeByMemory(), cacheSize, Runtime.getRuntime().availableProcessors()); //msc = new MirrorSolrConnector(esc, rsc); this.mirrorConnectorCache.put(corename, msc); return msc; } public int bufferSize() { int b = 0; for (SolrConnector sc: this.mirrorConnectorCache.values()) b += sc.bufferSize(); for (EmbeddedSolrConnector esc: this.embeddedConnectorCache.values()) b += esc.bufferSize(); for (RemoteSolrConnector rsc: this.remoteConnectorCache.values()) b += rsc.bufferSize(); return b; } public void clearCaches() { for (SolrConnector csc: this.mirrorConnectorCache.values()) csc.clearCaches(); for (EmbeddedSolrConnector esc: this.embeddedConnectorCache.values()) esc.clearCaches(); for (RemoteSolrConnector rsc: this.remoteConnectorCache.values()) rsc.clearCaches(); } }