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 2010 Sun Microsystems, Inc. 015 * Portions Copyright 2012-2016 ForgeRock AS. 016 */ 017package org.opends.server.tools.dsreplication; 018 019import static org.opends.messages.AdminToolMessages.*; 020 021import java.io.File; 022 023import org.forgerock.i18n.LocalizableMessage; 024import org.forgerock.i18n.slf4j.LocalizedLogger; 025 026import org.opends.quicksetup.util.ProgressMessageFormatter; 027import org.opends.server.replication.plugin.LDAPReplicationDomain; 028import org.forgerock.opendj.ldap.DN; 029import org.opends.server.types.DirectoryEnvironmentConfig; 030import org.opends.server.types.DirectoryException; 031import org.opends.server.types.OpenDsException; 032import org.forgerock.opendj.ldap.ResultCode; 033import org.opends.server.util.EmbeddedUtils; 034import org.opends.server.util.TimeThread; 035import com.forgerock.opendj.cli.ConsoleApplication; 036import org.opends.server.util.cli.PointAdder; 037 038/** 039 * The class that is in charge of taking the different information provided 040 * by the user through the command-line and actually executing the local 041 * purge. 042 * 043 */ 044public class LocalPurgeHistorical 045{ 046 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 047 048 private final PurgeHistoricalUserData uData; 049 private final ConsoleApplication app; 050 private final ProgressMessageFormatter formatter; 051 private final String configFile; 052 053 /** 054 * The default constructor. 055 * @param uData the object containing the information provided by the user. 056 * @param app the console application that is used to write the progress 057 * and error messages. 058 * @param formatter the formatter to be used to generated the messages. 059 * @param configFile the file that contains the configuration. This is 060 * required to initialize properly the server. 061 */ 062 public LocalPurgeHistorical(PurgeHistoricalUserData uData, 063 ConsoleApplication app, 064 ProgressMessageFormatter formatter, String configFile) 065 { 066 this.uData = uData; 067 this.app = app; 068 this.formatter = formatter; 069 this.configFile = configFile; 070 } 071 072 /** 073 * Executes the purge historical operation locally. 074 * @return the result code. 075 */ 076 public ReplicationCliReturnCode execute() 077 { 078 boolean applyTimeout = uData.getMaximumDuration() > 0; 079 080 long startTime = TimeThread.getTime(); 081 long purgeMaxTime = getTimeoutInSeconds() * 1000L; 082 083 long endMaxTime = startTime + purgeMaxTime; 084 085 app.print(formatter.getFormattedProgress( 086 INFO_REPLICATION_PURGE_HISTORICAL_LOCAL_ENVIRONMENT.get())); 087 088 PointAdder pointAdder = new PointAdder(app); 089 pointAdder.start(); 090 091 try 092 { 093 // Create a configuration for the server. 094 DirectoryEnvironmentConfig environmentConfig = 095 new DirectoryEnvironmentConfig(); 096 environmentConfig.setConfigFile(new File(configFile)); 097 environmentConfig.setDisableConnectionHandlers(true); 098 EmbeddedUtils.startServer(environmentConfig); 099 } 100 catch (OpenDsException ode) 101 { 102 pointAdder.stop(); 103 app.println(ode.getMessageObject()); 104 logger.error(LocalizableMessage.raw("Error starting server with file "+configFile+ 105 ": "+ode, ode)); 106 return ReplicationCliReturnCode.ERROR_LOCAL_PURGE_HISTORICAL_SERVER_START; 107 } 108 pointAdder.stop(); 109 app.print(formatter.getFormattedDone()); 110 app.println(); 111 app.println(); 112 app.print(formatter.getFormattedProgress( 113 INFO_REPLICATION_PURGE_HISTORICAL_LOCAL_STARTING.get())); 114 app.println(); 115 116 if (applyTimeout && timeoutOccurred(endMaxTime)) 117 { 118 return handleTimeout(); 119 } 120 121 try 122 { 123 // launch the job 124 for (String baseDN : uData.getBaseDNs()) 125 { 126 DN dn = DN.valueOf(baseDN); 127 // We can assume that this is an LDAP replication domain 128 LDAPReplicationDomain domain = 129 LDAPReplicationDomain.retrievesReplicationDomain(dn); 130 131 domain.purgeConflictsHistorical(null, startTime + purgeMaxTime); 132 } 133 134 } 135 catch (DirectoryException de) 136 { 137 if (de.getResultCode() == ResultCode.ADMIN_LIMIT_EXCEEDED) 138 { 139 return handleTimeout(); 140 } 141 else 142 { 143 return handleGenericExecuting(de); 144 } 145 } 146 return ReplicationCliReturnCode.SUCCESSFUL; 147 } 148 149 private ReplicationCliReturnCode handleGenericExecuting(OpenDsException ode) 150 { 151 logger.error(LocalizableMessage.raw("Error executing purge historical: "+ode, ode)); 152 app.println(); 153 app.println(ERR_REPLICATION_PURGE_HISTORICAL_EXECUTING.get( 154 ode.getMessageObject())); 155 return ReplicationCliReturnCode.ERROR_LOCAL_PURGE_HISTORICAL_EXECUTING; 156 } 157 158 private ReplicationCliReturnCode handleTimeout() 159 { 160 app.println(); 161 app.println(ERR_REPLICATION_PURGE_HISTORICAL_TIMEOUT.get( 162 getTimeoutInSeconds())); 163 return ReplicationCliReturnCode.ERROR_LOCAL_PURGE_HISTORICAL_TIMEOUT; 164 } 165 166 /** 167 * Returns the time-out provided by the user in seconds. 168 * @return the time-out provided by the user in seconds. 169 */ 170 private int getTimeoutInSeconds() 171 { 172 return uData.getMaximumDuration(); 173 } 174 175 /** 176 * A method that tells whether the maximum time to execute the operation was 177 * elapsed or not. 178 * @param endMaxTime the latest time in milliseconds when the operation should 179 * be completed. 180 * @return {@code true} if the time-out occurred and {@code false} otherwise. 181 */ 182 private boolean timeoutOccurred(long endMaxTime) 183 { 184 return TimeThread.getTime() > endMaxTime; 185 } 186}