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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2015 ForgeRock AS 025 */ 026package org.opends.server.tasks; 027 028import org.forgerock.i18n.LocalizableMessage; 029import org.forgerock.i18n.slf4j.LocalizedLogger; 030import org.opends.server.backends.task.Task; 031import org.opends.server.backends.task.TaskState; 032import org.opends.server.replication.common.CSN; 033import org.opends.server.replication.server.ReplicationServer; 034import org.opends.server.replication.server.changelog.api.ChangelogException; 035import org.opends.server.types.Attribute; 036import org.opends.server.types.AttributeType; 037import org.opends.server.types.DN; 038import org.opends.server.types.DirectoryException; 039import org.opends.server.types.Entry; 040 041import java.util.List; 042 043import static org.forgerock.opendj.ldap.ResultCode.*; 044import static org.opends.server.config.ConfigConstants.ATTR_TASK_RESET_CHANGE_NUMBER_BASE_DN; 045import static org.opends.server.config.ConfigConstants.ATTR_TASK_RESET_CHANGE_NUMBER_CSN; 046import static org.opends.server.config.ConfigConstants.ATTR_TASK_RESET_CHANGE_NUMBER_TO; 047import static org.opends.server.core.DirectoryServer.getAttributeTypeOrDefault; 048import static org.opends.messages.TaskMessages.*; 049 050/** 051 * This class provides an implementation of a Directory Server task that can 052 * be used to rebuild the change number index with a given change number and a 053 * change represented by its CSN. 054 */ 055public class ResetChangeNumberTask extends Task 056{ 057 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 058 059 private int newFirstChangeNumber; 060 private DN baseDN; 061 private CSN newFirstCSN; 062 private ReplicationServer targetRS; 063 064 @Override 065 public LocalizableMessage getDisplayName() { 066 return INFO_TASK_RESET_CHANGE_NUMBER.get(); 067 } 068 069 @Override public void initializeTask() throws DirectoryException 070 { 071 if (TaskState.isDone(getTaskState())) 072 { 073 return; 074 } 075 076 final Entry taskEntry = getTaskEntry(); 077 newFirstChangeNumber = TaskUtils.getSingleValueInteger( 078 getTaskParameter(taskEntry, ATTR_TASK_RESET_CHANGE_NUMBER_TO), 1); 079 newFirstCSN = CSN.valueOf(TaskUtils.getSingleValueString( 080 getTaskParameter(taskEntry, ATTR_TASK_RESET_CHANGE_NUMBER_CSN))); 081 baseDN = DN.valueOf(TaskUtils.getSingleValueString( 082 getTaskParameter(taskEntry, ATTR_TASK_RESET_CHANGE_NUMBER_BASE_DN))); 083 084 if (newFirstChangeNumber < 1) 085 { 086 throw new DirectoryException(UNWILLING_TO_PERFORM, 087 ERR_TASK_RESET_CHANGE_NUMBER_INVALID.get(newFirstChangeNumber)); 088 } 089 090 List<ReplicationServer> allRSes = ReplicationServer.getAllInstances(); 091 if (allRSes.isEmpty()) 092 { 093 throw new DirectoryException(NO_SUCH_OBJECT, ERR_TASK_RESET_CHANGE_NUMBER_NO_RSES.get()); 094 } 095 096 for (ReplicationServer rs : allRSes) 097 { 098 if (rs.getReplicationServerDomain(baseDN) != null) 099 { 100 targetRS = rs; 101 return; 102 } 103 } 104 throw new DirectoryException(NO_SUCH_OBJECT, ERR_TASK_RESET_CHANGE_NUMBER_CHANGELOG_NOT_FOUND.get(baseDN)); 105 } 106 107 private List<Attribute> getTaskParameter(Entry taskEntry, String attrTaskResetChangeNumberTo) 108 { 109 AttributeType taskAttr = getAttributeTypeOrDefault(attrTaskResetChangeNumberTo); 110 return taskEntry.getAttribute(taskAttr); 111 } 112 113 @Override 114 protected TaskState runTask() 115 { 116 logger.trace("Reset change number task is starting with new changeNumber %d having CSN %s", 117 newFirstChangeNumber, newFirstCSN); 118 119 try 120 { 121 targetRS.getChangelogDB().getChangeNumberIndexDB().resetChangeNumberTo(newFirstChangeNumber, baseDN, newFirstCSN); 122 return returnWithDebug(TaskState.COMPLETED_SUCCESSFULLY); 123 } 124 catch (ChangelogException ce) 125 { 126 logger.error(ERR_TASK_RESET_CHANGE_NUMBER_FAILED, ce.getMessageObject()); 127 return returnWithDebug(TaskState.STOPPED_BY_ERROR); 128 } 129 } 130 131 private TaskState returnWithDebug(TaskState state) 132 { 133 logger.trace("state: %s", state); 134 return state; 135 } 136}