001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.search.solr; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.util.Collection; 021import java.util.Iterator; 022import java.util.List; 023import java.util.Optional; 024import java.util.concurrent.TimeUnit; 025 026import org.apache.commons.lang.StringUtils; 027import org.apache.solr.client.solrj.SolrServerException; 028import org.apache.solr.client.solrj.impl.ConcurrentUpdateHttp2SolrClient; 029import org.apache.solr.client.solrj.impl.Http2SolrClient; 030import org.apache.solr.client.solrj.response.UpdateResponse; 031import org.apache.solr.common.SolrException; 032import org.apache.solr.common.SolrInputDocument; 033import org.eclipse.jetty.client.api.Response; 034import org.slf4j.Logger; 035 036/** 037 * Concurrent update solr client specific for Ametys.<br> 038 * Allow operations on only one collection (specified by the constructor), 039 * and forbid operations on all other collections. 040 * Delegate the processing to the ConcurrentUpdateSolrClient (superclass) if the collection is the one in use 041 */ 042public abstract class AbstractAmetysConcurrentUpdateClient extends ConcurrentUpdateHttp2SolrClient 043{ 044 /** Name of the collection, on which operation are allowed */ 045 private String _collectionName; 046 047 private Logger _logger; 048 049 /** 050 * Constructor 051 * @param solrServerUrl The Solr server URL 052 * @param solrSocketTimeout The Solr socket timeout (in millis) 053 * @param collectionName The name of the collection, on which operations will be allowed. Operations on other collections will be forbidden. 054 * @param queueSize The buffer size before the documents are sent to the server 055 * @param threadCount The number of background threads used to empty the queue 056 * @param logger internal logger 057 */ 058 public AbstractAmetysConcurrentUpdateClient(String solrServerUrl, Optional<Integer> solrSocketTimeout, String collectionName, int queueSize, int threadCount, Logger logger) 059 { 060 super(_getBuilder(solrServerUrl, solrSocketTimeout, queueSize, threadCount)); 061 062 if (collectionName == null) 063 { 064 throw new IllegalArgumentException("The collection name cannot be null."); 065 } 066 else 067 { 068 _collectionName = collectionName; 069 } 070 071 _logger = logger; 072 } 073 074 private static Builder _getBuilder(String solrServerUrl, Optional<Integer> solrSocketTimeout, int queueSize, int threadCount) 075 { 076 Http2SolrClient.Builder solrReadClientBuilder = new Http2SolrClient.Builder(solrServerUrl); 077 if (solrSocketTimeout.isPresent()) 078 { 079 solrReadClientBuilder.withRequestTimeout(solrSocketTimeout.get(), TimeUnit.MILLISECONDS); 080 } 081 082 Http2SolrClient solrReadClient = solrReadClientBuilder.build(); 083 084 Builder builder = new Builder(solrServerUrl, solrReadClient) 085 .withQueueSize(queueSize) 086 .withThreadCount(threadCount) 087 .setPollQueueTime(10, TimeUnit.MILLISECONDS); 088 089 return builder; 090 } 091 092 @Override 093 public void handleError(Throwable t) 094 { 095 StringBuilder msg = new StringBuilder("Solr client indexing error"); 096 if (t instanceof SolrException) 097 { 098 msg.append(" caused by the following errors: ").append(((SolrException) t).getMetadata()); 099 } 100 101 msg.append("\nPlease check the Solr logs for more details."); 102 _logger.error(msg.toString(), t); 103 } 104 105 @Override 106 public void onSuccess(Response resp, InputStream respBody) 107 { 108 if (_logger.isDebugEnabled()) 109 { 110 String reason = resp.getReason(); 111 _logger.debug("Successfully processed solr client request and obtained the response : " + StringUtils.defaultIfEmpty(reason, "unknown")); 112 } 113 114 super.onSuccess(resp, respBody); 115 } 116 117 private void _checkCollectionInUse(String collection) throws SolrServerException 118 { 119 if (collection == null) 120 { 121 throw new UnsupportedOperationException("Collection cannot be null"); 122 } 123 124 if (!StringUtils.equals(_collectionName, collection)) 125 { 126 String msg = String.format("Cannot process this update operation for collection '%s' because operations for this client can only be done in '%s'", collection, _collectionName); 127 throw new SolrServerException(msg); 128 } 129 } 130 131 @Override 132 public UpdateResponse add(String collection, Collection<SolrInputDocument> docs) throws SolrServerException, IOException 133 { 134 _checkCollectionInUse(collection); 135 return super.add(collection, docs); 136 } 137 138 @Override 139 public UpdateResponse add(Collection<SolrInputDocument> docs) throws SolrServerException, IOException 140 { 141 _checkCollectionInUse(null); 142 return super.add(docs); 143 } 144 145 @Override 146 public UpdateResponse add(String collection, Collection<SolrInputDocument> docs, int commitWithinMs) throws SolrServerException, IOException 147 { 148 _checkCollectionInUse(collection); 149 return super.add(collection, docs, commitWithinMs); 150 } 151 152 @Override 153 public UpdateResponse add(Collection<SolrInputDocument> docs, int commitWithinMs) throws SolrServerException, IOException 154 { 155 _checkCollectionInUse(null); 156 return super.add(docs, commitWithinMs); 157 } 158 159 @Override 160 public UpdateResponse add(String collection, SolrInputDocument doc) throws SolrServerException, IOException 161 { 162 _checkCollectionInUse(collection); 163 return super.add(collection, doc); 164 } 165 166 @Override 167 public UpdateResponse add(SolrInputDocument doc) throws SolrServerException, IOException 168 { 169 _checkCollectionInUse(null); 170 return super.add(doc); 171 } 172 173 @Override 174 public UpdateResponse add(String collection, SolrInputDocument doc, int commitWithinMs) throws SolrServerException, IOException 175 { 176 _checkCollectionInUse(collection); 177 return super.add(collection, doc, commitWithinMs); 178 } 179 180 @Override 181 public UpdateResponse add(SolrInputDocument doc, int commitWithinMs) throws SolrServerException, IOException 182 { 183 _checkCollectionInUse(null); 184 return super.add(doc, commitWithinMs); 185 } 186 187 @Override 188 public UpdateResponse add(String collection, Iterator<SolrInputDocument> docIterator) throws SolrServerException, IOException 189 { 190 _checkCollectionInUse(collection); 191 return super.add(collection, docIterator); 192 } 193 194 @Override 195 public UpdateResponse add(Iterator<SolrInputDocument> docIterator) throws SolrServerException, IOException 196 { 197 _checkCollectionInUse(null); 198 return super.add(docIterator); 199 } 200 201 @Override 202 public UpdateResponse addBean(String collection, Object obj) throws IOException, SolrServerException 203 { 204 _checkCollectionInUse(collection); 205 return super.addBean(collection, obj); 206 } 207 208 @Override 209 public UpdateResponse addBean(Object obj) throws IOException, SolrServerException 210 { 211 _checkCollectionInUse(null); 212 return super.addBean(obj); 213 } 214 215 @Override 216 public UpdateResponse addBean(String collection, Object obj, int commitWithinMs) throws IOException, SolrServerException 217 { 218 _checkCollectionInUse(collection); 219 return super.addBean(collection, obj, commitWithinMs); 220 } 221 222 @Override 223 public UpdateResponse addBean(Object obj, int commitWithinMs) throws IOException, SolrServerException 224 { 225 _checkCollectionInUse(null); 226 return super.addBean(obj, commitWithinMs); 227 } 228 229 @Override 230 public UpdateResponse addBeans(String collection, Collection<?> beans) throws SolrServerException, IOException 231 { 232 _checkCollectionInUse(collection); 233 return super.addBeans(collection, beans); 234 } 235 236 @Override 237 public UpdateResponse addBeans(Collection<?> beans) throws SolrServerException, IOException 238 { 239 _checkCollectionInUse(null); 240 return super.addBeans(beans); 241 } 242 243 @Override 244 public UpdateResponse addBeans(String collection, Collection<?> beans, int commitWithinMs) throws SolrServerException, IOException 245 { 246 _checkCollectionInUse(collection); 247 return super.addBeans(collection, beans, commitWithinMs); 248 } 249 250 @Override 251 public UpdateResponse addBeans(Collection<?> beans, int commitWithinMs) throws SolrServerException, IOException 252 { 253 _checkCollectionInUse(null); 254 return super.addBeans(beans, commitWithinMs); 255 } 256 257 @Override 258 public UpdateResponse addBeans(String collection, final Iterator<?> beanIterator) throws SolrServerException, IOException 259 { 260 _checkCollectionInUse(collection); 261 return super.addBeans(collection, beanIterator); 262 } 263 264 @Override 265 public UpdateResponse addBeans(final Iterator<?> beanIterator) throws SolrServerException, IOException 266 { 267 _checkCollectionInUse(null); 268 return super.addBeans(beanIterator); 269 } 270 271 @Override 272 public UpdateResponse commit(String collection) throws SolrServerException, IOException 273 { 274 _checkCollectionInUse(collection); 275 return super.commit(collection); 276 } 277 278 @Override 279 public UpdateResponse commit() throws SolrServerException, IOException 280 { 281 _checkCollectionInUse(null); 282 return super.commit(); 283 } 284 285 @Override 286 public UpdateResponse commit(String collection, boolean waitFlush, boolean waitSearcher) throws SolrServerException, IOException 287 { 288 _checkCollectionInUse(collection); 289 return super.commit(collection, waitFlush, waitSearcher); 290 } 291 292 @Override 293 public UpdateResponse commit(boolean waitFlush, boolean waitSearcher) throws SolrServerException, IOException 294 { 295 _checkCollectionInUse(null); 296 return super.commit(waitFlush, waitSearcher); 297 } 298 299 @Override 300 public UpdateResponse commit(String collection, boolean waitFlush, boolean waitSearcher, boolean softCommit) throws SolrServerException, IOException 301 { 302 _checkCollectionInUse(collection); 303 return super.commit(collection, waitFlush, waitSearcher, softCommit); 304 } 305 306 @Override 307 public UpdateResponse commit(boolean waitFlush, boolean waitSearcher, boolean softCommit) throws SolrServerException, IOException 308 { 309 _checkCollectionInUse(null); 310 return super.commit(waitFlush, waitSearcher, softCommit); 311 } 312 313 @Override 314 public UpdateResponse optimize(String collection) throws SolrServerException, IOException 315 { 316 _checkCollectionInUse(collection); 317 return super.optimize(collection); 318 } 319 320 @Override 321 public UpdateResponse optimize() throws SolrServerException, IOException 322 { 323 _checkCollectionInUse(null); 324 return super.optimize(); 325 } 326 327 @Override 328 public UpdateResponse optimize(String collection, boolean waitFlush, boolean waitSearcher) throws SolrServerException, IOException 329 { 330 _checkCollectionInUse(collection); 331 return super.optimize(collection, waitFlush, waitSearcher); 332 } 333 334 @Override 335 public UpdateResponse optimize(boolean waitFlush, boolean waitSearcher) throws SolrServerException, IOException 336 { 337 _checkCollectionInUse(null); 338 return super.optimize(waitFlush, waitSearcher); 339 } 340 341 @Override 342 public UpdateResponse optimize(String collection, boolean waitFlush, boolean waitSearcher, int maxSegments) throws SolrServerException, IOException 343 { 344 _checkCollectionInUse(collection); 345 return super.optimize(collection, waitFlush, waitSearcher, maxSegments); 346 } 347 348 @Override 349 public UpdateResponse optimize(boolean waitFlush, boolean waitSearcher, int maxSegments) throws SolrServerException, IOException 350 { 351 _checkCollectionInUse(null); 352 return super.optimize(waitFlush, waitSearcher, maxSegments); 353 } 354 355 @Override 356 public UpdateResponse rollback(String collection) throws SolrServerException, IOException 357 { 358 _checkCollectionInUse(collection); 359 return super.rollback(collection); 360 } 361 362 @Override 363 public UpdateResponse rollback() throws SolrServerException, IOException 364 { 365 _checkCollectionInUse(null); 366 return super.rollback(); 367 } 368 369 @Override 370 public UpdateResponse deleteById(String collection, String id) throws SolrServerException, IOException 371 { 372 _checkCollectionInUse(collection); 373 return super.deleteById(collection, id); 374 } 375 376 @Override 377 public UpdateResponse deleteById(String id) throws SolrServerException, IOException 378 { 379 _checkCollectionInUse(null); 380 return super.deleteById(id); 381 } 382 383 @Override 384 public UpdateResponse deleteById(String collection, String id, int commitWithinMs) throws SolrServerException, IOException 385 { 386 _checkCollectionInUse(collection); 387 return super.deleteById(collection, id, commitWithinMs); 388 } 389 390 @Override 391 public UpdateResponse deleteById(String id, int commitWithinMs) throws SolrServerException, IOException 392 { 393 _checkCollectionInUse(null); 394 return super.deleteById(id, commitWithinMs); 395 } 396 397 @Override 398 public UpdateResponse deleteById(String collection, List<String> ids) throws SolrServerException, IOException 399 { 400 _checkCollectionInUse(collection); 401 return super.deleteById(collection, ids); 402 } 403 404 @Override 405 public UpdateResponse deleteById(List<String> ids) throws SolrServerException, IOException 406 { 407 _checkCollectionInUse(null); 408 return super.deleteById(ids); 409 } 410 411 @Override 412 public UpdateResponse deleteById(String collection, List<String> ids, int commitWithinMs) throws SolrServerException, IOException 413 { 414 _checkCollectionInUse(collection); 415 return super.deleteById(collection, ids, commitWithinMs); 416 } 417 418 @Override 419 public UpdateResponse deleteById(List<String> ids, int commitWithinMs) throws SolrServerException, IOException 420 { 421 _checkCollectionInUse(null); 422 return super.deleteById(ids, commitWithinMs); 423 } 424 425 @Override 426 public UpdateResponse deleteByQuery(String collection, String query) throws SolrServerException, IOException 427 { 428 _checkCollectionInUse(collection); 429 return super.deleteByQuery(collection, query); 430 } 431 432 @Override 433 public UpdateResponse deleteByQuery(String query) throws SolrServerException, IOException 434 { 435 _checkCollectionInUse(null); 436 return super.deleteByQuery(query); 437 } 438 439 @Override 440 public UpdateResponse deleteByQuery(String collection, String query, int commitWithinMs) throws SolrServerException, IOException 441 { 442 _checkCollectionInUse(collection); 443 return super.deleteByQuery(collection, query, commitWithinMs); 444 } 445 446 @Override 447 public UpdateResponse deleteByQuery(String query, int commitWithinMs) throws SolrServerException, IOException 448 { 449 _checkCollectionInUse(null); 450 return super.deleteByQuery(query, commitWithinMs); 451 } 452}