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