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 2015-2016 ForgeRock AS. 015 */ 016package org.opends.server.tasks; 017 018import org.forgerock.i18n.LocalizableMessage; 019import org.forgerock.i18n.slf4j.LocalizedLogger; 020import org.forgerock.opendj.ldap.schema.AttributeType; 021import org.opends.server.backends.task.Task; 022import org.opends.server.backends.task.TaskState; 023import org.opends.server.replication.common.CSN; 024import org.opends.server.replication.server.ReplicationServer; 025import org.opends.server.replication.server.changelog.api.ChangelogException; 026import org.opends.server.types.Attribute; 027import org.forgerock.opendj.ldap.DN; 028import org.opends.server.types.DirectoryException; 029import org.opends.server.types.Entry; 030 031import java.util.List; 032 033import static org.forgerock.opendj.ldap.ResultCode.*; 034import static org.opends.server.config.ConfigConstants.ATTR_TASK_RESET_CHANGE_NUMBER_BASE_DN; 035import static org.opends.server.config.ConfigConstants.ATTR_TASK_RESET_CHANGE_NUMBER_CSN; 036import static org.opends.server.config.ConfigConstants.ATTR_TASK_RESET_CHANGE_NUMBER_TO; 037import static org.opends.server.core.DirectoryServer.getSchema; 038import static org.opends.messages.TaskMessages.*; 039 040/** 041 * This class provides an implementation of a Directory Server task that can 042 * be used to rebuild the change number index with a given change number and a 043 * change represented by its CSN. 044 */ 045public class ResetChangeNumberTask extends Task 046{ 047 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 048 049 private int newFirstChangeNumber; 050 private DN baseDN; 051 private CSN newFirstCSN; 052 private ReplicationServer targetRS; 053 054 @Override 055 public LocalizableMessage getDisplayName() { 056 return INFO_TASK_RESET_CHANGE_NUMBER.get(); 057 } 058 059 @Override public void initializeTask() throws DirectoryException 060 { 061 if (TaskState.isDone(getTaskState())) 062 { 063 return; 064 } 065 066 final Entry taskEntry = getTaskEntry(); 067 newFirstChangeNumber = TaskUtils.getSingleValueInteger( 068 getTaskParameter(taskEntry, ATTR_TASK_RESET_CHANGE_NUMBER_TO), 1); 069 newFirstCSN = CSN.valueOf(TaskUtils.getSingleValueString( 070 getTaskParameter(taskEntry, ATTR_TASK_RESET_CHANGE_NUMBER_CSN))); 071 baseDN = DN.valueOf(TaskUtils.getSingleValueString( 072 getTaskParameter(taskEntry, ATTR_TASK_RESET_CHANGE_NUMBER_BASE_DN))); 073 074 if (newFirstChangeNumber < 1) 075 { 076 throw new DirectoryException(UNWILLING_TO_PERFORM, 077 ERR_TASK_RESET_CHANGE_NUMBER_INVALID.get(newFirstChangeNumber)); 078 } 079 080 List<ReplicationServer> allRSes = ReplicationServer.getAllInstances(); 081 if (allRSes.isEmpty()) 082 { 083 throw new DirectoryException(NO_SUCH_OBJECT, ERR_TASK_RESET_CHANGE_NUMBER_NO_RSES.get()); 084 } 085 086 for (ReplicationServer rs : allRSes) 087 { 088 if (rs.getReplicationServerDomain(baseDN) != null) 089 { 090 targetRS = rs; 091 return; 092 } 093 } 094 throw new DirectoryException(NO_SUCH_OBJECT, ERR_TASK_RESET_CHANGE_NUMBER_CHANGELOG_NOT_FOUND.get(baseDN)); 095 } 096 097 private List<Attribute> getTaskParameter(Entry taskEntry, String attrTaskResetChangeNumberTo) 098 { 099 AttributeType taskAttr = getSchema().getAttributeType(attrTaskResetChangeNumberTo); 100 return taskEntry.getAttribute(taskAttr); 101 } 102 103 @Override 104 protected TaskState runTask() 105 { 106 logger.trace("Reset change number task is starting with new changeNumber %d having CSN %s", 107 newFirstChangeNumber, newFirstCSN); 108 109 try 110 { 111 targetRS.getChangelogDB().getChangeNumberIndexDB().resetChangeNumberTo(newFirstChangeNumber, baseDN, newFirstCSN); 112 return returnWithDebug(TaskState.COMPLETED_SUCCESSFULLY); 113 } 114 catch (ChangelogException ce) 115 { 116 logger.error(ERR_TASK_RESET_CHANGE_NUMBER_FAILED, ce.getMessageObject()); 117 return returnWithDebug(TaskState.STOPPED_BY_ERROR); 118 } 119 } 120 121 private TaskState returnWithDebug(TaskState state) 122 { 123 logger.trace("state: %s", state); 124 return state; 125 } 126}