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