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 }