001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2013-2015 ForgeRock AS 026 */ 027package org.opends.server.tasks; 028 029import static org.opends.server.config.ConfigConstants.*; 030import static org.opends.server.core.DirectoryServer.*; 031 032import java.util.List; 033 034import org.forgerock.i18n.LocalizableMessage; 035import org.forgerock.i18n.LocalizableMessageBuilder; 036import org.forgerock.i18n.slf4j.LocalizedLogger; 037import org.forgerock.opendj.ldap.ResultCode; 038import org.opends.messages.TaskMessages; 039import org.opends.server.backends.task.Task; 040import org.opends.server.backends.task.TaskState; 041import org.opends.server.replication.plugin.LDAPReplicationDomain; 042import org.opends.server.types.Attribute; 043import org.opends.server.types.AttributeType; 044import org.opends.server.types.DN; 045import org.opends.server.types.DirectoryException; 046import org.opends.server.types.Entry; 047 048/** 049 * This class provides an implementation of a Directory Server task that can 050 * be used to import data over the replication protocol from another 051 * server hosting the same replication domain. 052 */ 053public class InitializeTask extends Task 054{ 055 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 056 057 private String domainString; 058 private int source; 059 private LDAPReplicationDomain domain; 060 private TaskState initState; 061 062 /** The total number of entries expected to be processed when this import will end successfully. */ 063 private long total; 064 /** The number of entries still to be processed for this import to be completed. */ 065 private long left; 066 private LocalizableMessage taskCompletionError; 067 068 /** {@inheritDoc} */ 069 @Override 070 public LocalizableMessage getDisplayName() { 071 return TaskMessages.INFO_TASK_INITIALIZE_NAME.get(); 072 } 073 074 /** {@inheritDoc} */ 075 @Override public void initializeTask() throws DirectoryException 076 { 077 if (TaskState.isDone(getTaskState())) 078 { 079 return; 080 } 081 082 // FIXME -- Do we need any special authorization here? 083 Entry taskEntry = getTaskEntry(); 084 085 AttributeType typeDomainBase = getAttributeTypeOrDefault(ATTR_TASK_INITIALIZE_DOMAIN_DN); 086 AttributeType typeSourceScope = getAttributeTypeOrDefault(ATTR_TASK_INITIALIZE_SOURCE); 087 088 List<Attribute> attrList; 089 attrList = taskEntry.getAttribute(typeDomainBase); 090 domainString = TaskUtils.getSingleValueString(attrList); 091 092 try 093 { 094 DN dn = DN.valueOf(domainString); 095 // We can assume that this is an LDAP replication domain 096 domain = LDAPReplicationDomain.retrievesReplicationDomain(dn); 097 } 098 catch(DirectoryException e) 099 { 100 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 101 mb.append(TaskMessages.ERR_TASK_INITIALIZE_INVALID_DN.get()); 102 mb.append(e.getMessage()); 103 throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, e); 104 } 105 106 attrList = taskEntry.getAttribute(typeSourceScope); 107 String sourceString = TaskUtils.getSingleValueString(attrList); 108 source = domain.decodeSource(sourceString); 109 110 replaceAttributeValue(ATTR_TASK_INITIALIZE_LEFT, String.valueOf(0)); 111 replaceAttributeValue(ATTR_TASK_INITIALIZE_DONE, String.valueOf(0)); 112 } 113 114 /** {@inheritDoc} */ 115 @Override 116 protected TaskState runTask() 117 { 118 if (logger.isTraceEnabled()) 119 { 120 logger.trace("[IE] InitializeTask is starting on domain: %s from source:%d", domain.getBaseDN(), source); 121 } 122 initState = getTaskState(); 123 try 124 { 125 // launch the import 126 domain.initializeFromRemote(source, this); 127 128 synchronized(initState) 129 { 130 // Waiting for the end of the job 131 while (initState == TaskState.RUNNING) 132 { 133 initState.wait(1000); 134 replaceAttributeValue(ATTR_TASK_INITIALIZE_LEFT, String.valueOf(left)); 135 replaceAttributeValue(ATTR_TASK_INITIALIZE_DONE, String.valueOf(total-left)); 136 } 137 } 138 replaceAttributeValue(ATTR_TASK_INITIALIZE_LEFT, String.valueOf(left)); 139 replaceAttributeValue(ATTR_TASK_INITIALIZE_DONE, String.valueOf(total-left)); 140 141 // Error raised at completion time 142 if (taskCompletionError != null) 143 { 144 logger.error(taskCompletionError); 145 } 146 147 } 148 catch(InterruptedException ie) {} 149 catch(DirectoryException de) 150 { 151 // Error raised at submission time 152 logger.error(de.getMessageObject()); 153 initState = TaskState.STOPPED_BY_ERROR; 154 } 155 156 logger.trace("[IE] InitializeTask is ending with state: %s", initState); 157 return initState; 158 } 159 160 /** 161 * Set the state for the current task. 162 * 163 * @param de When the new state is different from COMPLETED_SUCCESSFULLY 164 * this is the exception that contains the cause of the failure. 165 */ 166 public void updateTaskCompletionState(DirectoryException de) 167 { 168 initState = TaskState.STOPPED_BY_ERROR; 169 try 170 { 171 if (de == null) 172 { 173 initState = TaskState.COMPLETED_SUCCESSFULLY; 174 } 175 else 176 { 177 taskCompletionError = de.getMessageObject(); 178 } 179 } 180 finally 181 { 182 // Wake up runTask method waiting for completion 183 synchronized (initState) 184 { 185 initState.notify(); 186 } 187 } 188 } 189 190 191 /** 192 * Set the total number of entries expected to be imported. 193 * @param total The total number of entries. 194 */ 195 public void setTotal(long total) 196 { 197 this.total = total; 198 } 199 200 /** 201 * Set the total number of entries still to be imported. 202 * @param left The total number of entries to be imported. 203 */ 204 public void setLeft(long left) 205 { 206 this.left = left; 207 } 208}