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