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
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.tasks;
028    import org.opends.messages.Message;
029    import org.opends.messages.MessageBuilder;
030    
031    import static org.opends.server.config.ConfigConstants.*;
032    import static org.opends.server.core.DirectoryServer.getAttributeType;
033    import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
034    import static org.opends.server.loggers.debug.DebugLogger.getTracer;
035    
036    import java.util.List;
037    
038    import org.opends.messages.TaskMessages;
039    import org.opends.server.backends.task.Task;
040    import org.opends.server.backends.task.TaskState;
041    import org.opends.server.loggers.debug.DebugTracer;
042    import org.opends.server.replication.plugin.ReplicationDomain;
043    import org.opends.server.types.Attribute;
044    import org.opends.server.types.AttributeType;
045    import org.opends.server.types.DN;
046    import org.opends.server.types.DirectoryException;
047    import org.opends.server.types.Entry;
048    import org.opends.server.types.ResultCode;
049    
050    /**
051     * This class provides an implementation of a Directory Server task that can
052     * be used to import data over the replication protocol from another
053     * server hosting the same replication domain.
054     */
055    public class InitializeTask extends Task
056    {
057      /**
058       * The tracer object for the debug logger.
059       */
060      private static final DebugTracer TRACER = getTracer();
061    
062      boolean isCompressed            = false;
063      boolean isEncrypted             = false;
064      boolean skipSchemaValidation    = false;
065      String  domainString            = null;
066      short  source;
067      ReplicationDomain domain = null;
068      TaskState initState;
069    
070      // The total number of entries expected to be processed when this import
071      // will end successfully
072      long total = 0;
073    
074      // The number of entries still to be processed for this import to be
075      // completed
076      long left = 0;
077    
078      private Message initTaskError = null;
079    
080      /**
081       * {@inheritDoc}
082       */
083      public Message getDisplayName() {
084        return TaskMessages.INFO_TASK_INITIALIZE_NAME.get();
085      }
086    
087      /**
088       * {@inheritDoc}
089       */
090      @Override public void initializeTask() throws DirectoryException
091      {
092        if (TaskState.isDone(getTaskState()))
093        {
094          return;
095        }
096    
097        // FIXME -- Do we need any special authorization here?
098        Entry taskEntry = getTaskEntry();
099    
100        AttributeType typeDomainBase;
101        AttributeType typeSourceScope;
102    
103        typeDomainBase =
104          getAttributeType(ATTR_TASK_INITIALIZE_DOMAIN_DN, true);
105        typeSourceScope =
106          getAttributeType(ATTR_TASK_INITIALIZE_SOURCE, true);
107    
108        List<Attribute> attrList;
109        attrList = taskEntry.getAttribute(typeDomainBase);
110        domainString = TaskUtils.getSingleValueString(attrList);
111        DN domainDN = DN.nullDN();
112        try
113        {
114          domainDN = DN.decode(domainString);
115        }
116        catch(Exception e)
117        {
118          MessageBuilder mb = new MessageBuilder();
119          mb.append(TaskMessages.ERR_TASK_INITIALIZE_INVALID_DN.get());
120          mb.append(e.getMessage());
121          throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX,
122              mb.toMessage());
123        }
124    
125        domain = ReplicationDomain.retrievesReplicationDomain(domainDN);
126    
127        attrList = taskEntry.getAttribute(typeSourceScope);
128        String sourceString = TaskUtils.getSingleValueString(attrList);
129        source = domain.decodeSource(sourceString);
130    
131        replaceAttributeValue(ATTR_TASK_INITIALIZE_LEFT, String.valueOf(0));
132        replaceAttributeValue(ATTR_TASK_INITIALIZE_DONE, String.valueOf(0));
133      }
134    
135      /**
136       * {@inheritDoc}
137       */
138      protected TaskState runTask()
139      {
140        if (debugEnabled())
141        {
142          TRACER.debugInfo("InitializeTask is starting domain: %s source:%d",
143                    domain.getBaseDN(), source);
144        }
145        initState = getTaskState();
146        try
147        {
148          // launch the import
149          domain.initializeFromRemote(source, this);
150    
151          synchronized(initState)
152          {
153            // Waiting for the end of the job
154            while (initState == TaskState.RUNNING)
155            {
156              initState.wait(1000);
157              replaceAttributeValue(
158                  ATTR_TASK_INITIALIZE_LEFT, String.valueOf(left));
159              replaceAttributeValue(
160                  ATTR_TASK_INITIALIZE_DONE, String.valueOf(total-left));
161            }
162          }
163          replaceAttributeValue(ATTR_TASK_INITIALIZE_LEFT, String.valueOf(left));
164          replaceAttributeValue(
165              ATTR_TASK_INITIALIZE_DONE, String.valueOf(total-left));
166        }
167        catch(InterruptedException ie) {}
168        catch(DirectoryException de)
169        {
170          logError(de.getMessageObject());
171          initState = TaskState.STOPPED_BY_ERROR;
172        }
173    
174        if (initTaskError != null)
175          logError(initTaskError);
176    
177        if (debugEnabled())
178        {
179          TRACER.debugInfo("InitializeTask is ending with state:%s",
180              initState.toString());
181        }
182        return initState;
183      }
184    
185      /**
186       * Set the state for the current task.
187       *
188       * @param de  When the new state is different from COMPLETED_SUCCESSFULLY
189       * this is the exception that contains the cause of the failure.
190       */
191      public void updateTaskCompletionState(DirectoryException de)
192      {
193        try
194        {
195          if (de != null)
196          {
197            initTaskError = de.getMessageObject();
198          }
199          if (de == null)
200            initState =  TaskState.COMPLETED_SUCCESSFULLY;
201          else
202            initState =  TaskState.STOPPED_BY_ERROR;
203    
204          if (debugEnabled())
205          {
206            TRACER.debugInfo("InitializeTask/setState: %s", initState);
207          }
208          synchronized (initState)
209          {
210            initState.notify();
211          }
212        }
213        catch(Exception e)
214        {}
215      }
216    
217    
218      /**
219       * Set the total number of entries expected to be imported.
220       * @param total The total number of entries.
221       */
222      public void setTotal(long total)
223      {
224        this.total = total;
225      }
226    
227      /**
228       * Set the total number of entries still to be imported.
229       * @param left The total number of entries to be imported.
230       */
231      public void setLeft(long left)
232      {
233        this.left = left;
234      }
235    }