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