001/* 002 * Copyright 2008-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2018 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk.unboundidds.tasks; 022 023 024 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Collections; 028import java.util.Date; 029import java.util.LinkedHashMap; 030import java.util.List; 031import java.util.Map; 032 033import com.unboundid.ldap.sdk.Attribute; 034import com.unboundid.ldap.sdk.Entry; 035import com.unboundid.util.Debug; 036import com.unboundid.util.NotMutable; 037import com.unboundid.util.ThreadSafety; 038import com.unboundid.util.ThreadSafetyLevel; 039import com.unboundid.util.Validator; 040 041import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*; 042 043 044 045/** 046 * This class defines a Directory Server task that can be used to generate 047 * and/or rebuild one or more indexes a Berkeley DB Java Edition backend. 048 * <BR> 049 * <BLOCKQUOTE> 050 * <B>NOTE:</B> This class, and other classes within the 051 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 052 * supported for use against Ping Identity, UnboundID, and 053 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 054 * for proprietary functionality or for external specifications that are not 055 * considered stable or mature enough to be guaranteed to work in an 056 * interoperable way with other types of LDAP servers. 057 * </BLOCKQUOTE> 058 * <BR> 059 * The properties that are available for use with this type of task include: 060 * <UL> 061 * <LI>The backend base DN for which to perform the index rebuild. This 062 * must be provided when scheduling a rebuild task.</LI> 063 * <LI>The names of the indexes to be built. At least one index name must be 064 * provided when scheduling a rebuild task.</LI> 065 * <LI>The maximum number of concurrent threads that should be used to perform 066 * the processing. A value of zero indicates that there is no limit.</LI> 067 * </UL> 068 069 */ 070@NotMutable() 071@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 072public final class RebuildTask 073 extends Task 074{ 075 /** 076 * The fully-qualified name of the Java class that is used for the rebuild 077 * task. 078 */ 079 static final String REBUILD_TASK_CLASS = 080 "com.unboundid.directory.server.tasks.RebuildTask"; 081 082 083 084 /** 085 * The name of the attribute used to specify the base DN for which to rebuild 086 * the specified indexes. 087 */ 088 private static final String ATTR_BASE_DN = "ds-task-rebuild-base-dn"; 089 090 091 092 /** 093 * The name of the attribute used to specify the names of the indexes to 094 * rebuild. 095 */ 096 private static final String ATTR_INDEX = "ds-task-rebuild-index"; 097 098 099 100 /** 101 * The name of the attribute used to specify the maximum number of concurrent 102 * threads to use to perform the rebuild. 103 */ 104 private static final String ATTR_MAX_THREADS = "ds-task-rebuild-max-threads"; 105 106 107 108 /** 109 * The name of the object class used in rebuild task entries. 110 */ 111 private static final String OC_REBUILD_TASK = "ds-task-rebuild"; 112 113 114 115 /** 116 * The task property for the base DN. 117 */ 118 private static final TaskProperty PROPERTY_BASE_DN = 119 new TaskProperty(ATTR_BASE_DN, INFO_DISPLAY_NAME_BASE_DN_REBUILD.get(), 120 INFO_DESCRIPTION_BASE_DN_REBUILD.get(), String.class, 121 true, false, false); 122 123 124 125 /** 126 * The task property for the index names. 127 */ 128 private static final TaskProperty PROPERTY_INDEX = 129 new TaskProperty(ATTR_INDEX, INFO_DISPLAY_NAME_INDEX_REBUILD.get(), 130 INFO_DESCRIPTION_INDEX_REBUILD.get(), String.class, 131 true, true, false); 132 133 134 135 /** 136 * The task property for the max threads value. 137 */ 138 private static final TaskProperty PROPERTY_MAX_THREADS = 139 new TaskProperty(ATTR_MAX_THREADS, 140 INFO_DISPLAY_NAME_MAX_THREADS_REBUILD.get(), 141 INFO_DESCRIPTION_MAX_THREADS_REBUILD.get(), Long.class, 142 false, false, true); 143 144 145 146 /** 147 * The serial version UID for this serializable class. 148 */ 149 private static final long serialVersionUID = 6015907901926792443L; 150 151 152 153 // The maximum number of threads to use to rebuild indexes. 154 private final int maxThreads; 155 156 // The base DN for which to rebuild indexes. 157 private final String baseDN; 158 159 // The names of the indexes to rebuild. 160 private final List<String> indexes; 161 162 163 164 /** 165 * Creates a new uninitialized rebuild task instance which should only be used 166 * for obtaining general information about this task, including the task name, 167 * description, and supported properties. Attempts to use a task created with 168 * this constructor for any other reason will likely fail. 169 */ 170 public RebuildTask() 171 { 172 baseDN = null; 173 maxThreads = -1; 174 indexes = null; 175 } 176 177 178 179 /** 180 * Creates a new rebuild task with the provided information. 181 * 182 * @param taskID The task ID to use for this task. If it is {@code null} 183 * then a UUID will be generated for use as the task ID. 184 * @param baseDN The base DN for which to rebuild the index. It must refer 185 * to a base DN for a Berkeley DB Java Edition backend. It 186 * must not be {@code null}. 187 * @param indexes A list containing the names of the indexes to rebuild. It 188 * must not be {@code null} or empty. 189 */ 190 public RebuildTask(final String taskID, final String baseDN, 191 final List<String> indexes) 192 { 193 this(taskID, baseDN, indexes, -1, null, null, null, null, null); 194 } 195 196 197 198 /** 199 * Creates a new rebuild task with the provided information. 200 * 201 * @param taskID The task ID to use for this task. If it is 202 * {@code null} then a UUID will be generated 203 * for use as the task ID. 204 * @param baseDN The base DN for which to rebuild the index. 205 * It must refer to a base DN for a Berkeley 206 * DB Java Edition backend. It must not be 207 * {@code null}. 208 * @param indexes A list containing the names of the indexes 209 * to rebuild. It must not be {@code null} or 210 * empty. 211 * @param maxThreads The maximum number of concurrent threads to 212 * use while performing the rebuild. A value 213 * less than or equal to zero indicates that 214 * there is no limit to the number of threads 215 * that may be used. 216 * @param scheduledStartTime The time that this task should start 217 * running. 218 * @param dependencyIDs The list of task IDs that will be required 219 * to complete before this task will be 220 * eligible to start. 221 * @param failedDependencyAction Indicates what action should be taken if 222 * any of the dependencies for this task do 223 * not complete successfully. 224 * @param notifyOnCompletion The list of e-mail addresses of individuals 225 * that should be notified when this task 226 * completes. 227 * @param notifyOnError The list of e-mail addresses of individuals 228 * that should be notified if this task does 229 * not complete successfully. 230 */ 231 public RebuildTask(final String taskID, final String baseDN, 232 final List<String> indexes, final int maxThreads, 233 final Date scheduledStartTime, 234 final List<String> dependencyIDs, 235 final FailedDependencyAction failedDependencyAction, 236 final List<String> notifyOnCompletion, 237 final List<String> notifyOnError) 238 { 239 this(taskID, baseDN, indexes, maxThreads, scheduledStartTime, dependencyIDs, 240 failedDependencyAction, null, notifyOnCompletion, null, notifyOnError, 241 null, null, null); 242 } 243 244 245 246 /** 247 * Creates a new rebuild task with the provided information. 248 * 249 * @param taskID The task ID to use for this task. If it is 250 * {@code null} then a UUID will be generated 251 * for use as the task ID. 252 * @param baseDN The base DN for which to rebuild the index. 253 * It must refer to a base DN for a Berkeley 254 * DB Java Edition backend. It must not be 255 * {@code null}. 256 * @param indexes A list containing the names of the indexes 257 * to rebuild. It must not be {@code null} or 258 * empty. 259 * @param maxThreads The maximum number of concurrent threads to 260 * use while performing the rebuild. A value 261 * less than or equal to zero indicates that 262 * there is no limit to the number of threads 263 * that may be used. 264 * @param scheduledStartTime The time that this task should start 265 * running. 266 * @param dependencyIDs The list of task IDs that will be required 267 * to complete before this task will be 268 * eligible to start. 269 * @param failedDependencyAction Indicates what action should be taken if 270 * any of the dependencies for this task do 271 * not complete successfully. 272 * @param notifyOnStart The list of e-mail addresses of individuals 273 * that should be notified when this task 274 * starts running. 275 * @param notifyOnCompletion The list of e-mail addresses of individuals 276 * that should be notified when this task 277 * completes. 278 * @param notifyOnSuccess The list of e-mail addresses of individuals 279 * that should be notified if this task 280 * completes successfully. 281 * @param notifyOnError The list of e-mail addresses of individuals 282 * that should be notified if this task does 283 * not complete successfully. 284 * @param alertOnStart Indicates whether the server should send an 285 * alert notification when this task starts. 286 * @param alertOnSuccess Indicates whether the server should send an 287 * alert notification if this task completes 288 * successfully. 289 * @param alertOnError Indicates whether the server should send an 290 * alert notification if this task fails to 291 * complete successfully. 292 */ 293 public RebuildTask(final String taskID, final String baseDN, 294 final List<String> indexes, final int maxThreads, 295 final Date scheduledStartTime, 296 final List<String> dependencyIDs, 297 final FailedDependencyAction failedDependencyAction, 298 final List<String> notifyOnStart, 299 final List<String> notifyOnCompletion, 300 final List<String> notifyOnSuccess, 301 final List<String> notifyOnError, 302 final Boolean alertOnStart, final Boolean alertOnSuccess, 303 final Boolean alertOnError) 304 { 305 super(taskID, REBUILD_TASK_CLASS, scheduledStartTime, dependencyIDs, 306 failedDependencyAction, notifyOnStart, notifyOnCompletion, 307 notifyOnSuccess, notifyOnError, alertOnStart, alertOnSuccess, 308 alertOnError); 309 310 Validator.ensureNotNull(baseDN, indexes); 311 Validator.ensureFalse(indexes.isEmpty(), 312 "RebuildTask.indexes must not be empty."); 313 314 this.baseDN = baseDN; 315 this.indexes = Collections.unmodifiableList(indexes); 316 this.maxThreads = maxThreads; 317 } 318 319 320 321 /** 322 * Creates a new rebuild task from the provided entry. 323 * 324 * @param entry The entry to use to create this rebuild task. 325 * 326 * @throws TaskException If the provided entry cannot be parsed as a rebuild 327 * task entry. 328 */ 329 public RebuildTask(final Entry entry) 330 throws TaskException 331 { 332 super(entry); 333 334 335 // Get the base DN. It must be present. 336 baseDN = entry.getAttributeValue(ATTR_BASE_DN); 337 if (baseDN == null) 338 { 339 throw new TaskException(ERR_REBUILD_TASK_NO_BASE_DN.get( 340 getTaskEntryDN())); 341 } 342 343 344 // Get the names of the indexes to rebuild. It must be present. 345 final String[] indexArray = entry.getAttributeValues(ATTR_INDEX); 346 if ((indexArray == null) || (indexArray.length == 0)) 347 { 348 throw new TaskException(ERR_REBUILD_TASK_NO_INDEXES.get( 349 getTaskEntryDN())); 350 } 351 else 352 { 353 indexes = Collections.unmodifiableList(Arrays.asList(indexArray)); 354 } 355 356 357 // Get the maximum number of threads to use. 358 final String threadsStr = entry.getAttributeValue(ATTR_MAX_THREADS); 359 if (threadsStr == null) 360 { 361 maxThreads = -1; 362 } 363 else 364 { 365 try 366 { 367 maxThreads = Integer.parseInt(threadsStr); 368 } 369 catch (final Exception e) 370 { 371 Debug.debugException(e); 372 throw new TaskException(ERR_REBUILD_TASK_INVALID_MAX_THREADS.get( 373 getTaskEntryDN(), threadsStr), e); 374 } 375 } 376 } 377 378 379 380 /** 381 * Creates a new rebuild task from the provided set of task properties. 382 * 383 * @param properties The set of task properties and their corresponding 384 * values to use for the task. It must not be 385 * {@code null}. 386 * 387 * @throws TaskException If the provided set of properties cannot be used to 388 * create a valid rebuild task. 389 */ 390 public RebuildTask(final Map<TaskProperty,List<Object>> properties) 391 throws TaskException 392 { 393 super(REBUILD_TASK_CLASS, properties); 394 395 long t = -1; 396 String b = null; 397 String[] i = null; 398 399 for (final Map.Entry<TaskProperty,List<Object>> entry : 400 properties.entrySet()) 401 { 402 final TaskProperty p = entry.getKey(); 403 final String attrName = p.getAttributeName(); 404 final List<Object> values = entry.getValue(); 405 406 if (attrName.equalsIgnoreCase(ATTR_BASE_DN)) 407 { 408 b = parseString(p, values, b); 409 } 410 else if (attrName.equalsIgnoreCase(ATTR_INDEX)) 411 { 412 i = parseStrings(p, values, i); 413 } 414 else if (attrName.equalsIgnoreCase(ATTR_MAX_THREADS)) 415 { 416 t = parseLong(p, values, t); 417 } 418 } 419 420 if (b == null) 421 { 422 throw new TaskException(ERR_REBUILD_TASK_NO_BASE_DN.get( 423 getTaskEntryDN())); 424 } 425 426 if (i == null) 427 { 428 throw new TaskException(ERR_REBUILD_TASK_NO_INDEXES.get( 429 getTaskEntryDN())); 430 } 431 432 baseDN = b; 433 indexes = Collections.unmodifiableList(Arrays.asList(i)); 434 maxThreads = (int) t; 435 } 436 437 438 439 /** 440 * {@inheritDoc} 441 */ 442 @Override() 443 public String getTaskName() 444 { 445 return INFO_TASK_NAME_REBUILD.get(); 446 } 447 448 449 450 /** 451 * {@inheritDoc} 452 */ 453 @Override() 454 public String getTaskDescription() 455 { 456 return INFO_TASK_DESCRIPTION_REBUILD.get(); 457 } 458 459 460 461 /** 462 * Retrieves the base DN for which to rebuild the specified indexes. 463 * 464 * @return The base DN for which to rebuild the specified indexes. 465 */ 466 public String getBaseDN() 467 { 468 return baseDN; 469 } 470 471 472 473 /** 474 * Retrieves the names of the indexes to be rebuilt. 475 * 476 * @return The names of the indexes to be rebuilt. 477 */ 478 public List<String> getIndexNames() 479 { 480 return indexes; 481 } 482 483 484 485 /** 486 * Retrieves the maximum number of concurrent threads that should be used when 487 * rebuilding the indexes. 488 * 489 * @return The maximum number of concurrent threads that should be used when 490 * rebuilding the indexes, or a value less than or equal to zero if 491 * there is no limit on the number of threads that may be used. 492 */ 493 public int getMaxRebuildThreads() 494 { 495 return maxThreads; 496 } 497 498 499 500 /** 501 * {@inheritDoc} 502 */ 503 @Override() 504 protected List<String> getAdditionalObjectClasses() 505 { 506 return Collections.singletonList(OC_REBUILD_TASK); 507 } 508 509 510 511 /** 512 * {@inheritDoc} 513 */ 514 @Override() 515 protected List<Attribute> getAdditionalAttributes() 516 { 517 final ArrayList<Attribute> attrs = new ArrayList<>(3); 518 519 attrs.add(new Attribute(ATTR_BASE_DN, baseDN)); 520 attrs.add(new Attribute(ATTR_INDEX, indexes)); 521 522 if (maxThreads > 0) 523 { 524 attrs.add(new Attribute(ATTR_MAX_THREADS, String.valueOf(maxThreads))); 525 } 526 527 return attrs; 528 } 529 530 531 532 /** 533 * {@inheritDoc} 534 */ 535 @Override() 536 public List<TaskProperty> getTaskSpecificProperties() 537 { 538 final List<TaskProperty> propList = Arrays.asList( 539 PROPERTY_BASE_DN, 540 PROPERTY_INDEX, 541 PROPERTY_MAX_THREADS); 542 543 return Collections.unmodifiableList(propList); 544 } 545 546 547 548 /** 549 * {@inheritDoc} 550 */ 551 @Override() 552 public Map<TaskProperty,List<Object>> getTaskPropertyValues() 553 { 554 final LinkedHashMap<TaskProperty,List<Object>> props = 555 new LinkedHashMap<>(10); 556 557 props.put(PROPERTY_BASE_DN, 558 Collections.<Object>singletonList(baseDN)); 559 560 props.put(PROPERTY_INDEX, 561 Collections.<Object>unmodifiableList(indexes)); 562 563 props.put(PROPERTY_MAX_THREADS, 564 Collections.<Object>singletonList((long) maxThreads)); 565 566 props.putAll(super.getTaskPropertyValues()); 567 return Collections.unmodifiableMap(props); 568 } 569}