/*
|
* The contents of this file are subject to the terms of the Common Development and
|
* Distribution License (the License). You may not use this file except in compliance with the
|
* License.
|
*
|
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
|
* specific language governing permission and limitations under the License.
|
*
|
* When distributing Covered Software, include this CDDL Header Notice in each file and include
|
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
|
* Header, with the fields enclosed by brackets [] replaced by your own identifying
|
* information: "Portions Copyright [year] [name of copyright owner]".
|
*
|
* Copyright 2013-2016 ForgeRock AS.
|
*/
|
package org.opends.server.replication.server;
|
|
import java.util.HashSet;
|
import java.util.Map;
|
import java.util.Set;
|
import java.util.concurrent.ConcurrentSkipListMap;
|
|
import net.jcip.annotations.ThreadSafe;
|
|
import org.opends.server.replication.common.CSN;
|
import org.opends.server.replication.common.MultiDomainServerState;
|
import org.forgerock.opendj.ldap.DN;
|
|
/**
|
* This is the changelog state stored in the changelogStateDB. For each
|
* replication domain, it contains:
|
* <ul>
|
* <li>its generationId</li>
|
* <li>the list of serverIds composing it</li>
|
* </ul>
|
* <p>
|
* This class is used during replication initialization to decouple the code
|
* that reads the changelogStateDB from the code that makes use of its data.
|
*/
|
@ThreadSafe
|
public class ChangelogState
|
{
|
private final ConcurrentSkipListMap<DN, Long> domainToGenerationId = new ConcurrentSkipListMap<>();
|
private final ConcurrentSkipListMap<DN, Set<Integer>> domainToServerIds = new ConcurrentSkipListMap<>();
|
private final MultiDomainServerState offlineReplicas = new MultiDomainServerState();
|
|
/**
|
* Sets the generationId for the supplied replication domain.
|
*
|
* @param baseDN
|
* the targeted replication domain baseDN
|
* @param generationId
|
* the generation Id to set
|
*/
|
public void setDomainGenerationId(DN baseDN, long generationId)
|
{
|
domainToGenerationId.put(baseDN, generationId);
|
}
|
|
/**
|
* Adds the serverId to the serverIds list of the supplied replication domain.
|
*
|
* @param serverId
|
* the serverId to add
|
* @param baseDN
|
* the targeted replication domain baseDN
|
*/
|
public void addServerIdToDomain(int serverId, DN baseDN)
|
{
|
Set<Integer> serverIds = domainToServerIds.get(baseDN);
|
if (serverIds == null)
|
{
|
serverIds = new HashSet<>();
|
final Set<Integer> existingServerIds =
|
domainToServerIds.putIfAbsent(baseDN, serverIds);
|
if (existingServerIds != null)
|
{
|
serverIds = existingServerIds;
|
}
|
}
|
serverIds.add(serverId);
|
}
|
|
/**
|
* Adds the following replica information to the offline list.
|
*
|
* @param baseDN
|
* the baseDN of the offline replica
|
* @param offlineCSN
|
* the CSN (serverId + timestamp) of the offline replica
|
*/
|
public void addOfflineReplica(DN baseDN, CSN offlineCSN)
|
{
|
offlineReplicas.update(baseDN, offlineCSN);
|
}
|
|
/**
|
* Removes the following replica information from the offline list.
|
*
|
* @param baseDN
|
* the baseDN of the offline replica
|
* @param serverId
|
* the serverId that is not offline anymore
|
*/
|
public void removeOfflineReplica(DN baseDN, int serverId)
|
{
|
CSN csn;
|
do
|
{
|
csn = offlineReplicas.getCSN(baseDN, serverId);
|
}
|
while (csn != null && !offlineReplicas.removeCSN(baseDN, csn));
|
}
|
|
/**
|
* Returns the Map of domainBaseDN => generationId.
|
*
|
* @return a Map of domainBaseDN => generationId
|
*/
|
public Map<DN, Long> getDomainToGenerationId()
|
{
|
return domainToGenerationId;
|
}
|
|
/**
|
* Returns the Map of domainBaseDN => List<serverId>.
|
*
|
* @return a Map of domainBaseDN => List<serverId>.
|
*/
|
public Map<DN, Set<Integer>> getDomainToServerIds()
|
{
|
return domainToServerIds;
|
}
|
|
/**
|
* Returns the internal MultiDomainServerState for offline replicas.
|
*
|
* @return the MultiDomainServerState for offline replicas.
|
*/
|
public MultiDomainServerState getOfflineReplicas()
|
{
|
return offlineReplicas;
|
}
|
|
/**
|
* Returns whether the current ChangelogState is equal to the provided
|
* ChangelogState.
|
* <p>
|
* Note: Only use for tests!!<br>
|
* This method should only be used by tests because it creates a lot of
|
* intermediate objects which is not suitable for production.
|
*
|
* @param other
|
* the ChangelogState to compare with
|
* @return true if the current ChangelogState is equal to the provided
|
* ChangelogState, false otherwise.
|
*/
|
public boolean isEqualTo(ChangelogState other)
|
{
|
if (other == null)
|
{
|
return false;
|
}
|
if (this == other)
|
{
|
return true;
|
}
|
return domainToGenerationId.equals(other.domainToGenerationId)
|
&& domainToServerIds.equals(other.domainToServerIds)
|
// Note: next line is not suitable for production
|
// because it creates lots of Lists and Maps
|
&& offlineReplicas.getSnapshot().equals(other.offlineReplicas.getSnapshot());
|
}
|
|
/** {@inheritDoc} */
|
@Override
|
public String toString()
|
{
|
return "domainToGenerationId=" + domainToGenerationId
|
+ ", domainToServerIds=" + domainToServerIds
|
+ ", offlineReplicas=" + offlineReplicas;
|
}
|
}
|