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