serviceId => baseDN (To make the code less confusing)
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2009 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011 ForgeRock AS |
| | | * Portions Copyright 2011-2013 ForgeRock AS |
| | | */ |
| | | package org.opends.server.replication.common; |
| | | |
| | | import static org.opends.messages.ReplicationMessages.*; |
| | | |
| | | import java.util.Iterator; |
| | | import java.util.Map; |
| | | import java.util.TreeMap; |
| | | import java.util.Iterator; |
| | | |
| | | import org.opends.messages.Category; |
| | | import org.opends.messages.Message; |
| | |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | |
| | | /** |
| | | * This object is used to store a list of ServerState object, one by |
| | | * replication domain. Globally, it is the generalization of ServerState |
| | | * (that applies to one domain) to a list of domains. |
| | | * This object is used to store a list of ServerState object, one by replication |
| | | * domain. Globally, it is the generalization of ServerState (that applies to |
| | | * one domain) to a list of domains. |
| | | * <p> |
| | | * MultiDomainServerState is also known as "cookie" and is used with the |
| | | * cookie-based changelog. |
| | | */ |
| | | public class MultiDomainServerState implements Iterable<String> |
| | | { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Update the ServerState of the provided serviceId with the |
| | | * Update the ServerState of the provided baseDN with the |
| | | * replication change number provided. |
| | | * |
| | | * @param serviceId The provided serviceId. |
| | | * @param baseDN The provided baseDN. |
| | | * @param changeNumber The provided ChangeNumber. |
| | | * |
| | | * @return a boolean indicating if the update was meaningful. |
| | | */ |
| | | public boolean update(String serviceId, ChangeNumber changeNumber) |
| | | public boolean update(String baseDN, ChangeNumber changeNumber) |
| | | { |
| | | if (changeNumber == null) |
| | | return false; |
| | |
| | | synchronized(this) |
| | | { |
| | | int serverId = changeNumber.getServerId(); |
| | | ServerState oldServerState = list.get(serviceId); |
| | | ServerState oldServerState = list.get(baseDN); |
| | | if (oldServerState == null) |
| | | oldServerState = new ServerState(); |
| | | |
| | | if (changeNumber.newer(oldServerState.getMaxChangeNumber(serverId))) |
| | | { |
| | | oldServerState.update(changeNumber); |
| | | list.put(serviceId,oldServerState); |
| | | list.put(baseDN, oldServerState); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Update the ServerState of the provided serviceId with the |
| | | * Update the ServerState of the provided baseDN with the |
| | | * provided server state. |
| | | * |
| | | * @param serviceId The provided serviceId. |
| | | * @param baseDN The provided baseDN. |
| | | * @param serverState The provided serverState. |
| | | */ |
| | | public void update(String serviceId, ServerState serverState) |
| | | public void update(String baseDN, ServerState serverState) |
| | | { |
| | | list.put(serviceId,serverState.duplicate()); |
| | | list.put(baseDN,serverState.duplicate()); |
| | | } |
| | | |
| | | /** |
| | |
| | | String res = ""; |
| | | if ((list != null) && (!list.isEmpty())) |
| | | { |
| | | for (String serviceId : list.keySet()) |
| | | for (String baseDN : list.keySet()) |
| | | { |
| | | ServerState ss = list.get(serviceId); |
| | | res += serviceId + ":" + ss.toString(); |
| | | res += ";"; |
| | | ServerState ss = list.get(baseDN); |
| | | res += baseDN + ":" + ss + ";"; |
| | | } |
| | | } |
| | | return res; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public Iterator<String> iterator() |
| | | { |
| | | return list.keySet().iterator(); |
| | |
| | | */ |
| | | public boolean cover(MultiDomainServerState covered) |
| | | { |
| | | for (String serviceId : covered.list.keySet()) |
| | | for (String baseDN : covered.list.keySet()) |
| | | { |
| | | ServerState state = list.get(serviceId); |
| | | ServerState coveredState = covered.list.get(serviceId); |
| | | ServerState state = list.get(baseDN); |
| | | ServerState coveredState = covered.list.get(baseDN); |
| | | if ((state==null)||(coveredState == null) || (!state.cover(coveredState))) |
| | | { |
| | | return false; |
| | |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.util.zip.DataFormatException; |
| | | import org.opends.server.types.DirectoryException; |
| | | |
| | | import org.opends.server.replication.common.MultiDomainServerState; |
| | | import org.opends.server.types.DirectoryException; |
| | | |
| | | /** |
| | | * Container for the ECL information sent from the ReplicationServer |
| | |
| | | */ |
| | | public class ECLUpdateMsg extends ReplicationMsg |
| | | { |
| | | // The replication change returned. |
| | | /** The replication change returned. */ |
| | | private final LDAPUpdateMsg updateMsg; |
| | | |
| | | // The serviceId (baseDN) of the domain to which applies the change. |
| | | private final String serviceId; |
| | | /** The baseDN of the domain to which applies the change. */ |
| | | private final String baseDN; |
| | | |
| | | // The value of the cookie updated with the current change |
| | | /** The value of the cookie updated with the current change. */ |
| | | private MultiDomainServerState cookie; |
| | | |
| | | // The changenumber as specified by draft-good-ldap-changelog. |
| | | /** The changeNumber as specified by draft-good-ldap-changelog. */ |
| | | private int draftChangeNumber; |
| | | |
| | | /** |
| | | * Creates a new message. |
| | | * @param update The provided update. |
| | | * @param updateMsg The provided update message. |
| | | * @param cookie The provided cookie value |
| | | * @param serviceId The provided serviceId. |
| | | * @param baseDN The provided baseDN. |
| | | * @param draftChangeNumber The provided draft change number. |
| | | */ |
| | | public ECLUpdateMsg(LDAPUpdateMsg update, MultiDomainServerState cookie, |
| | | String serviceId, int draftChangeNumber) |
| | | public ECLUpdateMsg(LDAPUpdateMsg updateMsg, MultiDomainServerState cookie, |
| | | String baseDN, int draftChangeNumber) |
| | | { |
| | | this.cookie = cookie; |
| | | this.serviceId = serviceId; |
| | | this.updateMsg = update; |
| | | this.baseDN = baseDN; |
| | | this.updateMsg = updateMsg; |
| | | this.draftChangeNumber = draftChangeNumber; |
| | | } |
| | | |
| | |
| | | if (in[0] != MSG_TYPE_ECL_UPDATE) |
| | | { |
| | | throw new DataFormatException("byte[] is not a valid " + |
| | | this.getClass().getCanonicalName()); |
| | | getClass().getCanonicalName()); |
| | | } |
| | | int pos = 1; |
| | | |
| | |
| | | this.cookie = new MultiDomainServerState(cookieStr); |
| | | pos += length + 1; |
| | | |
| | | // Decode the serviceId |
| | | // Decode the baseDN |
| | | length = getNextLength(in, pos); |
| | | this.serviceId = new String(in, pos, length, "UTF-8"); |
| | | this.baseDN = new String(in, pos, length, "UTF-8"); |
| | | pos += length + 1; |
| | | |
| | | // Decode the draft changeNumber |
| | |
| | | } |
| | | |
| | | /** |
| | | * Getter for the serviceId. |
| | | * @return The serviceId. |
| | | * Getter for the baseDN. |
| | | * |
| | | * @return The baseDN. |
| | | */ |
| | | public String getServiceId() |
| | | public String getBaseDN() |
| | | { |
| | | return serviceId; |
| | | return baseDN; |
| | | } |
| | | |
| | | /** |
| | |
| | | " updateMsg: " + updateMsg + |
| | | " cookie: " + cookie + |
| | | " draftChangeNumber: " + draftChangeNumber + |
| | | " serviceId: " + serviceId + "]"; |
| | | " serviceId: " + baseDN + "]"; |
| | | } |
| | | |
| | | /** |
| | |
| | | throws UnsupportedEncodingException |
| | | { |
| | | byte[] byteCookie = String.valueOf(cookie).getBytes("UTF-8"); |
| | | byte[] byteServiceId = String.valueOf(serviceId).getBytes("UTF-8"); |
| | | byte[] byteBaseDN = String.valueOf(baseDN).getBytes("UTF-8"); |
| | | byte[] byteDraftChangeNumber = |
| | | Integer.toString(draftChangeNumber).getBytes("UTF-8"); |
| | | byte[] byteUpdateMsg = updateMsg.getBytes(protocolVersion); |
| | | |
| | | int length = 1 + byteCookie.length + |
| | | 1 + byteServiceId.length + |
| | | 1 + byteBaseDN.length + |
| | | 1 + byteDraftChangeNumber.length + |
| | | 1 + byteUpdateMsg.length + 1; |
| | | |
| | |
| | | resultByteArray[0] = MSG_TYPE_ECL_UPDATE; |
| | | int pos = 1; |
| | | |
| | | // Encode cookie |
| | | // Encode all fields |
| | | pos = addByteArray(byteCookie, resultByteArray, pos); |
| | | |
| | | // Encode serviceid |
| | | pos = addByteArray(byteServiceId, resultByteArray, pos); |
| | | |
| | | /* Put the draftChangeNumber */ |
| | | pos = addByteArray(byteBaseDN, resultByteArray, pos); |
| | | pos = addByteArray(byteDraftChangeNumber, resultByteArray, pos); |
| | | |
| | | // Encode msg |
| | | pos = addByteArray(byteUpdateMsg, resultByteArray, pos); |
| | | |
| | | return resultByteArray; |
| | |
| | | import org.opends.server.replication.common.ChangeNumber; |
| | | import org.opends.server.util.StaticUtils; |
| | | |
| | | |
| | | /** |
| | | * This class specifies the parameters of a search request on the ECL. |
| | | * It is used as an interface between the requestor (plugin part) |
| | |
| | | private String operationId = ""; |
| | | |
| | | /** Excluded domains. */ |
| | | private Set<String> excludedServiceIDs = new HashSet<String>(); |
| | | private Set<String> excludedBaseDNs = new HashSet<String>(); |
| | | |
| | | /** |
| | | * Creates a new StartSessionMsg message from its encoded form. |
| | |
| | | if (excludedDNsString.length()>0) |
| | | { |
| | | String[] excludedDNsStr = excludedDNsString.split(";"); |
| | | Collections.addAll(this.excludedServiceIDs, excludedDNsStr); |
| | | Collections.addAll(this.excludedBaseDNs, excludedDNsStr); |
| | | } |
| | | pos += length + 1; |
| | | |
| | |
| | | changeNumber = new ChangeNumber(0,0,0); |
| | | isPersistent = NON_PERSISTENT; |
| | | operationId = "-1"; |
| | | excludedServiceIDs = new HashSet<String>(); |
| | | excludedBaseDNs = new HashSet<String>(); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Override |
| | | public byte[] getBytes(short protocolVersion) |
| | | { |
| | | String excludedSIDsString = |
| | | StaticUtils.collectionToString(excludedServiceIDs, ";"); |
| | | String excludedBaseDNsString = |
| | | StaticUtils.collectionToString(excludedBaseDNs, ";"); |
| | | |
| | | try |
| | | { |
| | |
| | | byte[] byteOperationId = |
| | | String.valueOf(operationId).getBytes("UTF-8"); |
| | | byte[] byteExcludedDNs = |
| | | String.valueOf(excludedSIDsString).getBytes("UTF-8"); |
| | | String.valueOf(excludedBaseDNsString).getBytes("UTF-8"); |
| | | |
| | | int length = |
| | | byteMode.length + 1 + |
| | |
| | | " lastDraftChangeNumber=" + lastDraftChangeNumber + |
| | | " generalizedState=" + crossDomainServerState + |
| | | " operationId=" + operationId + |
| | | " excludedDNs=" + excludedServiceIDs + "]"; |
| | | " excludedDNs=" + excludedBaseDNs + "]"; |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | /** |
| | | * Setter of the operation id. |
| | | * @param operationId The provided opration id. |
| | | * @param operationId The provided operation id. |
| | | */ |
| | | public void setOperationId(String operationId) |
| | | { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Getter on the list of excluded ServiceIDs. |
| | | * @return the list of excluded ServiceIDs. |
| | | * Getter on the list of excluded baseDNs. |
| | | * |
| | | * @return the list of excluded baseDNs. |
| | | */ |
| | | public Set<String> getExcludedServiceIDs() |
| | | public Set<String> getExcludedBaseDNs() |
| | | { |
| | | return this.excludedServiceIDs; |
| | | return this.excludedBaseDNs; |
| | | } |
| | | |
| | | /** |
| | | * Setter on the list of excluded ServiceIDs. |
| | | * @param excludedServiceIDs the provided list of excluded ServiceIDs. |
| | | * Setter on the list of excluded baseDNs. |
| | | * |
| | | * @param excludedBaseDNs |
| | | * the provided list of excluded baseDNs. |
| | | */ |
| | | public void setExcludedDNs(Set<String> excludedServiceIDs) |
| | | public void setExcludedDNs(Set<String> excludedBaseDNs) |
| | | { |
| | | this.excludedServiceIDs = excludedServiceIDs; |
| | | this.excludedBaseDNs = excludedBaseDNs; |
| | | } |
| | | |
| | | } |
| | |
| | | "In RS " + |
| | | replicationServerDomain.getReplicationServer().getServerId() + |
| | | ". Closing connection to DS " + getServerId() + |
| | | " for baseDn " + getServiceId() + |
| | | " for baseDn " + getBaseDN() + |
| | | " to force reconnection as new local" + |
| | | " generationId and remote one match and DS is in bad gen id: " + |
| | | newGenId); |
| | |
| | | TRACER.debugInfo( |
| | | "In RS " + |
| | | replicationServerDomain.getReplicationServer().getServerId() + |
| | | ". DS " + getServerId() + " for baseDn " + getServiceId() + |
| | | ". DS " + getServerId() + " for baseDn " + getBaseDN() + |
| | | " has already generation id " + newGenId + |
| | | " so no ChangeStatusMsg sent to him."); |
| | | } |
| | |
| | | Message message = NOTE_BAD_GEN_ID_IN_FULL_UPDATE.get( |
| | | Integer.toString(replicationServerDomain. |
| | | getReplicationServer().getServerId()), |
| | | getServiceId(), |
| | | getBaseDN(), |
| | | Integer.toString(serverId), |
| | | Long.toString(generationId), |
| | | Long.toString(newGenId)); |
| | |
| | | |
| | | if (newStatus == ServerStatus.INVALID_STATUS) |
| | | { |
| | | Message msg = ERR_RS_CANNOT_CHANGE_STATUS.get(getServiceId(), |
| | | Message msg = ERR_RS_CANNOT_CHANGE_STATUS.get(getBaseDN(), |
| | | Integer.toString(serverId), status.toString(), event.toString()); |
| | | logError(msg); |
| | | return; |
| | |
| | | "In RS " + |
| | | replicationServerDomain.getReplicationServer().getServerId() + |
| | | " Sending change status for reset gen id to " + getServerId() + |
| | | " for baseDn " + getServiceId() + ":\n" + csMsg); |
| | | " for baseDn " + getBaseDN() + ":\n" + csMsg); |
| | | } |
| | | |
| | | session.publish(csMsg); |
| | |
| | | ServerStatus newStatus = StatusMachine.computeNewStatus(status, event); |
| | | if (newStatus == ServerStatus.INVALID_STATUS) |
| | | { |
| | | Message msg = ERR_RS_CANNOT_CHANGE_STATUS.get(getServiceId(), |
| | | Message msg = ERR_RS_CANNOT_CHANGE_STATUS.get(getBaseDN(), |
| | | Integer.toString(serverId), status.toString(), event.toString()); |
| | | logError(msg); |
| | | // Status analyzer must only change from NORMAL_STATUS to DEGRADED_STATUS |
| | |
| | | "In RS " + |
| | | replicationServerDomain.getReplicationServer().getServerId() + |
| | | " Sending change status from status analyzer to " + getServerId() + |
| | | " for baseDn " + getServiceId() + ":\n" + csMsg); |
| | | " for baseDn " + getBaseDN() + ":\n" + csMsg); |
| | | } |
| | | |
| | | session.publish(csMsg); |
| | |
| | | if (event == StatusMachineEvent.INVALID_EVENT) |
| | | { |
| | | Message msg = ERR_RS_INVALID_NEW_STATUS.get(reqStatus.toString(), |
| | | getServiceId(), Integer.toString(serverId)); |
| | | getBaseDN(), Integer.toString(serverId)); |
| | | logError(msg); |
| | | return ServerStatus.INVALID_STATUS; |
| | | } |
| | |
| | | ServerStatus newStatus = StatusMachine.computeNewStatus(status, event); |
| | | if (newStatus == ServerStatus.INVALID_STATUS) |
| | | { |
| | | Message msg = ERR_RS_CANNOT_CHANGE_STATUS.get(getServiceId(), |
| | | Message msg = ERR_RS_CANNOT_CHANGE_STATUS.get(getBaseDN(), |
| | | Integer.toString(serverId), status.toString(), event.toString()); |
| | | logError(msg); |
| | | return ServerStatus.INVALID_STATUS; |
| | |
| | | heartbeatInterval = serverStartMsg.getHeartbeatInterval(); |
| | | |
| | | // generic stuff |
| | | setServiceIdAndDomain(serverStartMsg.getBaseDn(), true); |
| | | setBaseDNAndDomain(serverStartMsg.getBaseDn(), true); |
| | | setInitialServerState(serverStartMsg.getServerState()); |
| | | setSendWindowSize(serverStartMsg.getWindowSize()); |
| | | |
| | |
| | | { |
| | | // Peer DS uses protocol < V4 : send it a ReplServerStartMsg |
| | | startMsg = new ReplServerStartMsg(replicationServerId, |
| | | replicationServerURL, getServiceId(), maxRcvWindow, |
| | | replicationServerURL, getBaseDN(), maxRcvWindow, |
| | | replicationServerDomain.getDbServerState(), |
| | | localGenerationId, sslEncryption, getLocalGroupId(), |
| | | replicationServerDomain.getReplicationServer() |
| | |
| | | { |
| | | // Peer DS uses protocol V4 : send it a ReplServerStartDSMsg |
| | | startMsg = new ReplServerStartDSMsg(replicationServerId, |
| | | replicationServerURL, getServiceId(), maxRcvWindow, |
| | | replicationServerURL, getBaseDN(), maxRcvWindow, |
| | | replicationServerDomain.getDbServerState(), |
| | | localGenerationId, sslEncryption, getLocalGroupId(), |
| | | replicationServerDomain.getReplicationServer() |
| | |
| | | { |
| | | Message message = ERR_RS_INVALID_INIT_STATUS.get( |
| | | this.status.toString(), |
| | | getServiceId(), |
| | | getBaseDN(), |
| | | Integer.toString(serverId)); |
| | | throw new DirectoryException(ResultCode.OTHER, message); |
| | | } |
| | |
| | | { |
| | | Message message = WARN_BAD_GENERATION_ID_FROM_DS.get( |
| | | serverId, session.getReadableRemoteAddress(), |
| | | generationId, getServiceId(), |
| | | generationId, getBaseDN(), |
| | | getReplicationServerId(), localGenerationId); |
| | | logError(message); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // We are an empty Replicationserver |
| | | // We are an empty ReplicationServer |
| | | if ((generationId > 0) && (!getServerState().isEmpty())) |
| | | { |
| | | // If the LDAP server has already sent changes |
| | | // it is not expected to connect to an empty RS |
| | | Message message = WARN_BAD_GENERATION_ID_FROM_DS.get( |
| | | serverId, session.getReadableRemoteAddress(), |
| | | generationId, getServiceId(), |
| | | generationId, getBaseDN(), |
| | | getReplicationServerId(), localGenerationId); |
| | | logError(message); |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * Getter for the serviceID field of the current cursor. |
| | | * @return The current serviceID. |
| | | * Getter for the baseDN field of the current cursor. |
| | | * @return The current baseDN. |
| | | */ |
| | | public String currentServiceID() |
| | | public String currentBaseDN() |
| | | { |
| | | if (isClosed) |
| | | { |
| | |
| | | { |
| | | if (seqnumData != null) |
| | | { |
| | | return seqnumData.getServiceID(); |
| | | return seqnumData.getBaseDN(); |
| | | } |
| | | } |
| | | catch(Exception e) |
| | |
| | | */ |
| | | package org.opends.server.replication.server; |
| | | |
| | | import static org.opends.server.util.StaticUtils.getBytes; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | |
| | |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | String value; |
| | | String serviceID; |
| | | ChangeNumber changeNumber; |
| | | private String value; |
| | | private String baseDN; |
| | | private ChangeNumber changeNumber; |
| | | |
| | | /** |
| | | * Creates a record to be stored in the DraftCNDB. |
| | | * @param value The value (cookie). |
| | | * @param serviceID The serviceID (domain DN). |
| | | * @param baseDN The baseDN (domain DN). |
| | | * @param changeNumber The replication change number. |
| | | */ |
| | | public DraftCNData(String value, |
| | | String serviceID, ChangeNumber changeNumber) |
| | | public DraftCNData(String value, String baseDN, ChangeNumber changeNumber) |
| | | { |
| | | String record = value |
| | | + FIELD_SEPARATOR + serviceID |
| | | + FIELD_SEPARATOR + baseDN |
| | | + FIELD_SEPARATOR + changeNumber; |
| | | setData(getBytes(record)); |
| | | } |
| | |
| | | |
| | | String[] str = stringData.split(FIELD_SEPARATOR, 3); |
| | | value = str[0]; |
| | | serviceID = str[1]; |
| | | baseDN = str[1]; |
| | | changeNumber = new ChangeNumber(str[2]); |
| | | } |
| | | catch (UnsupportedEncodingException e) |
| | |
| | | |
| | | /** |
| | | * Getter for the service ID. |
| | | * @return The serviceID.. |
| | | * @return The baseDN |
| | | * @throws Exception when a problem occurs. |
| | | */ |
| | | public String getServiceID() |
| | | public String getBaseDN() |
| | | throws Exception |
| | | { |
| | | if (value == null) |
| | | this.decodeData(this.getData()); |
| | | return this.serviceID; |
| | | return this.baseDN; |
| | | } |
| | | |
| | | /** |
| | |
| | | * Provide a string representation of these data. |
| | | * @return the string representation of these data. |
| | | */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | | StringBuilder buffer = new StringBuilder(); |
| | |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append("DraftCNData : [value=").append(value); |
| | | buffer.append("] [serviceID=").append(serviceID); |
| | | buffer.append("] [serviceID=").append(baseDN); |
| | | buffer.append("] [changeNumber=").append(changeNumber).append("]"); |
| | | } |
| | | } |
| | |
| | | * than its maximum. |
| | | * @param key The key for this record in the db. |
| | | * @param value The associated value. |
| | | * @param serviceID The associated serviceID. |
| | | * @param baseDN The associated baseDN. |
| | | * @param cn The associated replication change number. |
| | | */ |
| | | public synchronized void add(int key, String value, String serviceID, |
| | | public synchronized void add(int key, String value, String baseDN, |
| | | ChangeNumber cn) |
| | | { |
| | | db.addEntry(key, value, serviceID, cn); |
| | | db.addEntry(key, value, baseDN, cn); |
| | | |
| | | if (debugEnabled()) |
| | | TRACER.debugInfo( |
| | | "In DraftCNDbhandler.add, added: " |
| | | + " key=" + key |
| | | + " value=" + value |
| | | + " serviceID=" + serviceID |
| | | + " baseDN=" + baseDN |
| | | + " cn=" + cn); |
| | | } |
| | | |
| | |
| | | |
| | | /** |
| | | * Clear the changes from this DB (from both memory cache and DB storage) |
| | | * for the provided serviceID. |
| | | * @param serviceIDToClear The serviceID for which we want to remove |
| | | * for the provided baseDN. |
| | | * @param baseDNToClear The baseDN for which we want to remove |
| | | * all records from the DraftCNDb - null means all. |
| | | * @throws DatabaseException When an exception occurs while removing the |
| | | * changes from the DB. |
| | | * @throws Exception When an exception occurs while accessing a resource |
| | | * from the DB. |
| | | */ |
| | | public void clear(String serviceIDToClear) |
| | | public void clear(String baseDNToClear) |
| | | throws DatabaseException, Exception |
| | | { |
| | | // FIXME according to JE javadoc, this is a "fairly expensive operation" |
| | |
| | | ChangeNumber cn = cursor.currentChangeNumber(); |
| | | |
| | | // From the draftCNDb change record, get the domain and changeNumber |
| | | String serviceID = cursor.currentServiceID(); |
| | | String baseDN = cursor.currentBaseDN(); |
| | | |
| | | if ((serviceIDToClear != null) |
| | | && (serviceIDToClear.equalsIgnoreCase(serviceID))) |
| | | if ((baseDNToClear != null) |
| | | && (baseDNToClear.equalsIgnoreCase(baseDN))) |
| | | { |
| | | cursor.delete(); |
| | | continue; |
| | | } |
| | | |
| | | ReplicationServerDomain domain = replicationServer |
| | | .getReplicationServerDomain(serviceID, false); |
| | | .getReplicationServerDomain(baseDN, false); |
| | | |
| | | if (domain == null) |
| | | { |
| | |
| | | Map<String,ServerState> cnStartStates = |
| | | MultiDomainServerState.splitGenStateToServerStates( |
| | | cursor.currentValue()); |
| | | cnVector = cnStartStates.get(serviceID); |
| | | cnVector = cnStartStates.get(baseDN); |
| | | |
| | | if (debugEnabled()) |
| | | TRACER.debugInfo("DraftCNDBHandler:clear() - ChangeVector:" + |
| | |
| | | } |
| | | |
| | | /** |
| | | * Get the serviceID associated to a provided key. |
| | | * Get the baseDN associated to a provided key. |
| | | * @param key the provided key. |
| | | * @return the serviceID, null when none. |
| | | * @return the baseDN, null when none. |
| | | */ |
| | | public String getServiceID(int key) |
| | | public String getBaseDN(int key) |
| | | { |
| | | String sid = null; |
| | | DraftCNDBCursor draftCNDBCursor = null; |
| | | try |
| | | { |
| | | draftCNDBCursor = db.openReadCursor(key); |
| | | sid = draftCNDBCursor.currentServiceID(); |
| | | sid = draftCNDBCursor.currentBaseDN(); |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | TRACER.debugInfo("In DraftCNDbHandler.getServiceID, read: " + |
| | | " key=" + key + " serviceID returned is null" + |
| | | TRACER.debugInfo("In DraftCNDbHandler.getBaseDN(), read: " + |
| | | " key=" + key + " baseDN returned is null" + |
| | | " first=" + db.readFirstDraftCN() + |
| | | " last=" + db.readLastDraftCN() + |
| | | " count=" + db.count() + |
| | |
| | | * |
| | | * |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011 ForgeRock AS |
| | | * Portions Copyright 2011-2013 ForgeRock AS |
| | | */ |
| | | package org.opends.server.replication.server; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.getTracer; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import org.opends.server.replication.common.ChangeNumber; |
| | | import org.opends.server.replication.server.DraftCNDB.*; |
| | | import org.opends.server.replication.server.DraftCNDB.DraftCNDBCursor; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | |
| | | import com.sleepycat.je.DatabaseException; |
| | |
| | | } |
| | | |
| | | /** |
| | | * Getter for the serviceID field. |
| | | * Getter for the baseDN field. |
| | | * |
| | | * @return The service ID. |
| | | */ |
| | | public String getServiceID() |
| | | public String getBaseDN() |
| | | { |
| | | try |
| | | { |
| | | return this.draftCNDbCursor.currentServiceID(); |
| | | return this.draftCNDbCursor.currentBaseDN(); |
| | | } |
| | | catch(Exception e) |
| | | { |
| | |
| | | * Release the cursor in case the iterator was badly used and releaseCursor |
| | | * was never called. |
| | | */ |
| | | @Override |
| | | protected void finalize() |
| | | { |
| | | releaseCursor(); |
| | |
| | | /** |
| | | * Specifies the last draft changer number (seqnum) requested. |
| | | */ |
| | | public int lastDraftCN = 0; |
| | | private int lastDraftCN = 0; |
| | | /** |
| | | * Specifies whether the draft change number (seqnum) db has been read until |
| | | * its end. |
| | | */ |
| | | public boolean isEndOfDraftCNReached = false; |
| | | private boolean isEndOfDraftCNReached = false; |
| | | /** |
| | | * Specifies whether the current search has been requested to be persistent |
| | | * or not. |
| | | */ |
| | | public short isPersistent; |
| | | private short isPersistent; |
| | | /** |
| | | * Specifies the current search phase : INIT or PERSISTENT. |
| | | */ |
| | | public int searchPhase = INIT_PHASE; |
| | | private int searchPhase = INIT_PHASE; |
| | | /** |
| | | * Specifies the cookie contained in the request, specifying where |
| | | * to start serving the ECL. |
| | | */ |
| | | public String startCookie; |
| | | private String startCookie; |
| | | /** |
| | | * Specifies the value of the cookie before the change currently processed |
| | | * is returned. It is updated with the change number of the change |
| | | * currently processed (thus becoming the "current" cookie just |
| | | * before the change is returned. |
| | | */ |
| | | public MultiDomainServerState previousCookie = |
| | | private MultiDomainServerState previousCookie = |
| | | new MultiDomainServerState(); |
| | | /** |
| | | * Specifies the excluded DNs (like cn=admin, ...). |
| | | */ |
| | | public Set<String> excludedServiceIDs = new HashSet<String>(); |
| | | private Set<String> excludedBaseDNs = new HashSet<String>(); |
| | | |
| | | /** |
| | | * Eligible changeNumber - only changes older or equal to eligibleCN |
| | | * are published in the ECL. |
| | | */ |
| | | public ChangeNumber eligibleCN = null; |
| | | private ChangeNumber eligibleCN = null; |
| | | |
| | | /** |
| | | * Provides a string representation of this object. |
| | |
| | | */ |
| | | private class DomainContext |
| | | { |
| | | ReplicationServerDomain rsd; |
| | | private ReplicationServerDomain rsd; |
| | | |
| | | boolean active; // active when there are still changes |
| | | // supposed eligible for the ECL. |
| | | /** |
| | | * active when there are still changes supposed eligible for the ECL. |
| | | */ |
| | | private boolean active; |
| | | |
| | | MessageHandler mh; // the message handler from which are read |
| | | // the changes for this domain |
| | | /** |
| | | * the message handler from which are reading the changes for this domain. |
| | | */ |
| | | private MessageHandler mh; |
| | | private UpdateMsg nextMsg; |
| | | private UpdateMsg nextNonEligibleMsg; |
| | | ServerState startState; |
| | | ServerState currentState; |
| | | ServerState stopState; |
| | | long domainLatestTrimDate; |
| | | private ServerState startState; |
| | | private ServerState currentState; |
| | | private ServerState stopState; |
| | | private long domainLatestTrimDate; |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | |
| | | */ |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append("[ [active=").append(active).append("] [rsd=") |
| | | .append(rsd).append("] [nextMsg=").append(nextMsg).append("(") |
| | | buffer.append("[ [active=").append(active) |
| | | .append("] [rsd=").append(rsd) |
| | | .append("] [nextMsg=").append(nextMsg).append("(") |
| | | .append(nextMsg != null ? |
| | | new Date(nextMsg.getChangeNumber().getTime()).toString():"") |
| | | .append(")") |
| | | .append("] [nextNonEligibleMsg=").append(nextNonEligibleMsg) |
| | | .append("] [startState=").append(startState).append("] [stopState=") |
| | | .append(stopState).append("] [currentState=").append(currentState) |
| | | .append("] [startState=").append(startState) |
| | | .append("] [stopState=").append(stopState) |
| | | .append("] [currentState=").append(currentState) |
| | | .append("]]"); |
| | | } |
| | | |
| | |
| | | private void getNextEligibleMessageForDomain(String opid) |
| | | { |
| | | if (debugEnabled()) |
| | | TRACER.debugInfo(" In ECLServerHandler, for " + mh.getServiceId() + |
| | | TRACER.debugInfo(" In ECLServerHandler, for " + mh.getBaseDN() + |
| | | " getNextEligibleMessageForDomain(" + opid+ ") " |
| | | + "ctxt=" + toString()); |
| | | |
| | |
| | | <= eligibleCN.getTime()); |
| | | |
| | | if (debugEnabled()) |
| | | TRACER.debugInfo(" In ECLServerHandler, for " + mh.getServiceId() + |
| | | TRACER.debugInfo(" In ECLServerHandler, for " + mh.getBaseDN() + |
| | | " getNextEligibleMessageForDomain(" + opid+ ") " |
| | | + " stored nonEligibleMsg " + nextNonEligibleMsg |
| | | + " has now become eligible regarding " |
| | |
| | | (newMsg.getChangeNumber().getTime() < domainLatestTrimDate)); |
| | | |
| | | if (debugEnabled()) |
| | | TRACER.debugInfo(" In ECLServerHandler, for " + mh.getServiceId() + |
| | | TRACER.debugInfo(" In ECLServerHandler, for " + mh.getBaseDN() + |
| | | " getNextEligibleMessageForDomain(" + opid+ ") " |
| | | + " got new message : " |
| | | + " serviceId=[" + mh.getServiceId() |
| | | + " serviceId=[" + mh.getBaseDN() |
| | | + "] [newMsg=" + newMsg + "]" + dumpState()); |
| | | |
| | | // in non blocking mode, return null when no more msg |
| | |
| | | <= eligibleCN.getTime()); |
| | | |
| | | if (debugEnabled()) |
| | | TRACER.debugInfo(" In ECLServerHandler, for " + mh.getServiceId() |
| | | TRACER.debugInfo(" In ECLServerHandler, for " + mh.getBaseDN() |
| | | + " getNextEligibleMessageForDomain(" + opid+ ") " |
| | | + "newMsg isEligible=" + isEligible + " since " |
| | | + "newMsg=[" + newMsg.getChangeNumber() |
| | |
| | | } |
| | | } |
| | | |
| | | // The global list of contexts by domain for the search currently processed. |
| | | DomainContext[] domainCtxts = new DomainContext[0]; |
| | | /** |
| | | * The global list of contexts by domain for the search currently processed. |
| | | */ |
| | | private DomainContext[] domainCtxts = new DomainContext[0]; |
| | | |
| | | private String clDomCtxtsToString(String msg) |
| | | { |
| | |
| | | return buffer.toString(); |
| | | } |
| | | |
| | | static int UNDEFINED_PHASE = 0; |
| | | static int INIT_PHASE = 1; |
| | | static int PERSISTENT_PHASE = 2; |
| | | private static int UNDEFINED_PHASE = 0; |
| | | private static int INIT_PHASE = 1; |
| | | private static int PERSISTENT_PHASE = 2; |
| | | |
| | | /** |
| | | * Starts this handler based on a start message received from remote server. |
| | |
| | | { |
| | | // Peer DS uses protocol < V4 : send it a ReplServerStartMsg |
| | | startMsg = new ReplServerStartMsg(replicationServerId, |
| | | replicationServerURL, getServiceId(), maxRcvWindow, |
| | | replicationServerURL, getBaseDN(), maxRcvWindow, |
| | | replicationServerDomain.getDbServerState(), |
| | | localGenerationId, sslEncryption, getLocalGroupId(), |
| | | replicationServerDomain.getReplicationServer() |
| | |
| | | { |
| | | // Peer DS uses protocol V4 : send it a ReplServerStartDSMsg |
| | | startMsg = new ReplServerStartDSMsg(replicationServerId, |
| | | replicationServerURL, getServiceId(), maxRcvWindow, |
| | | replicationServerURL, getBaseDN(), maxRcvWindow, |
| | | new ServerState(), localGenerationId, sslEncryption, |
| | | getLocalGroupId(), 0, replicationServer.getWeight(), 0); |
| | | } |
| | |
| | | replicationServer, rcvWindowSize); |
| | | try |
| | | { |
| | | setServiceIdAndDomain(ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT, true); |
| | | setBaseDNAndDomain(ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT, true); |
| | | } |
| | | catch(DirectoryException de) |
| | | { |
| | | // no chance to have a bad domain set here |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | /** |
| | |
| | | replicationServer, 0); |
| | | try |
| | | { |
| | | setServiceIdAndDomain(ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT, true); |
| | | setBaseDNAndDomain(ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT, true); |
| | | } |
| | | catch(DirectoryException de) |
| | | { |
| | |
| | | // the operation) in order to have the first and possible last |
| | | // DraftCN. |
| | | int[] limits = replicationServer.getECLDraftCNLimits( |
| | | eligibleCN, excludedServiceIDs); |
| | | eligibleCN, excludedBaseDNs); |
| | | |
| | | // If the startDraftCN provided is lower than the first Draft CN in |
| | | // the DB, let's use the lower limit. |
| | |
| | | continue; |
| | | |
| | | // skip the excluded domains |
| | | if (excludedServiceIDs.contains(rsd.getBaseDn())) |
| | | if (excludedBaseDNs.contains(rsd.getBaseDn())) |
| | | { |
| | | // this is an excluded domain |
| | | if (allowUnknownDomains) |
| | |
| | | // Creates an unconnected SH for the domain |
| | | MessageHandler mh = new MessageHandler(maxQueueSize, |
| | | replicationServerURL, replicationServerId, replicationServer); |
| | | // set initial state |
| | | mh.setInitialServerState(newDomainCtxt.startState); |
| | | // set serviceID and domain |
| | | mh.setServiceIdAndDomain(rsd.getBaseDn(), false); |
| | | mh.setBaseDNAndDomain(rsd.getBaseDn(), false); |
| | | // register the unconnected into the domain |
| | | rsd.registerHandler(mh); |
| | | newDomainCtxt.mh = mh; |
| | |
| | | String localString; |
| | | localString = "External changelog Server "; |
| | | if (this.serverId != 0) |
| | | localString += serverId + " " + serverURL + " " + getServiceId() |
| | | localString += serverId + " " + serverURL + " " + getBaseDN() |
| | | + " " + this.getOperationId(); |
| | | else |
| | | localString += this.getClass().getCanonicalName()+ " " + operationId; |
| | |
| | | ERR_INVALID_COOKIE_SYNTAX.get()); |
| | | } |
| | | |
| | | excludedServiceIDs = startECLSessionMsg.getExcludedServiceIDs(); |
| | | replicationServer.disableEligibility(excludedServiceIDs); |
| | | excludedBaseDNs = startECLSessionMsg.getExcludedBaseDNs(); |
| | | replicationServer.disableEligibility(excludedBaseDNs); |
| | | eligibleCN = replicationServer.getEligibleCN(); |
| | | |
| | | if (startECLSessionMsg.getECLRequestType()== |
| | |
| | | |
| | | // the next change from the DraftCN db |
| | | ChangeNumber cnFromDraftCNDb = draftCNDbIter.getChangeNumber(); |
| | | String dnFromDraftCNDb = draftCNDbIter.getServiceID(); |
| | | String dnFromDraftCNDb = draftCNDbIter.getBaseDN(); |
| | | |
| | | // are replogcn and DraftCNcn should be the same change ? |
| | | int areCNEqual = cnFromChangelogDb.compareTo(cnFromDraftCNDb); |
| | |
| | | draftCNDb.add( |
| | | oldestChange.getDraftChangeNumber(), |
| | | previousCookie.toString(), |
| | | oldestChange.getServiceId(), |
| | | oldestChange.getBaseDN(), |
| | | oldestChange.getUpdateMsg().getChangeNumber()); |
| | | |
| | | break; |
| | |
| | | |
| | | // Update the current state |
| | | previousCookie.update( |
| | | oldestChange.getServiceId(), |
| | | oldestChange.getBaseDN(), |
| | | oldestChange.getUpdateMsg().getChangeNumber()); |
| | | |
| | | // Set the current value of global state in the returned message |
| | |
| | | writer = new ECLServerWriter(session,this,replicationServerDomain); |
| | | writer.start(); // start suspended |
| | | } |
| | | |
| | | } |
| | | else |
| | | { |
| | |
| | | * Portions copyright 2011-2013 ForgeRock AS |
| | | */ |
| | | package org.opends.server.replication.server; |
| | | |
| | | import static org.opends.messages.ReplicationMessages.*; |
| | | import static org.opends.server.loggers.ErrorLogger.logError; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import static org.opends.server.loggers.debug.DebugLogger.getTracer; |
| | | import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; |
| | | import static org.opends.server.loggers.ErrorLogger.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import java.io.IOException; |
| | | import java.net.SocketException; |
| | |
| | | import org.opends.server.workflowelement.externalchangelog.ECLSearchOperation; |
| | | import org.opends.server.workflowelement.externalchangelog.ECLWorkflowElement; |
| | | |
| | | |
| | | /** |
| | | * This class defines a server writer, which is used to send changes to a |
| | | * directory server. |
| | |
| | | * Loops waiting for changes from the ReplicationServerDomain and |
| | | * forward them to the other servers |
| | | */ |
| | | @Override |
| | | public void run() |
| | | { |
| | | try |
| | |
| | | handler.getReplicationServerId(), |
| | | handler.getServerId(), |
| | | session.getReadableRemoteAddress(), |
| | | handler.getServiceId()); |
| | | handler.getBaseDN()); |
| | | } |
| | | else |
| | | { |
| | |
| | | handler.getReplicationServerId(), |
| | | handler.getServerId(), |
| | | session.getReadableRemoteAddress(), |
| | | handler.getServiceId()); |
| | | handler.getBaseDN()); |
| | | } |
| | | logError(errMessage); |
| | | } |
| | |
| | | // An unexpected error happened. |
| | | // Log an error and close the connection. |
| | | Message errMessage = ERR_WRITER_UNEXPECTED_EXCEPTION |
| | | .get(handler.toString() + " " |
| | | + stackTraceToSingleLineString(e)); |
| | | .get(handler + " " + stackTraceToSingleLineString(e)); |
| | | logError(errMessage); |
| | | } |
| | | finally |
| | |
| | | */ |
| | | package org.opends.server.replication.server; |
| | | |
| | | import static org.opends.messages.ReplicationMessages.ERR_RS_DN_DOES_NOT_MATCH; |
| | | import static org.opends.messages.ReplicationMessages.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | |
| | | import java.util.ArrayList; |
| | |
| | | import org.opends.server.replication.common.ChangeNumber; |
| | | import org.opends.server.replication.common.ServerState; |
| | | import org.opends.server.replication.protocol.UpdateMsg; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.Attributes; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.*; |
| | | |
| | | /** |
| | | * This class implements a buffering/producer/consumer mechanism of |
| | |
| | | */ |
| | | protected int replicationServerId; |
| | | /** |
| | | * Specifies the related replication server domain based on serviceId(baseDn). |
| | | * Specifies the related replication server domain based on baseDn. |
| | | */ |
| | | protected ReplicationServerDomain replicationServerDomain = null; |
| | | /** |
| | |
| | | */ |
| | | private ServerState serverState; |
| | | /** |
| | | * Specifies the identifier of the service (usually the baseDn of the domain). |
| | | * Specifies the baseDn of the domain. |
| | | */ |
| | | private String serviceId = null; |
| | | private String baseDN = null; |
| | | /** |
| | | * Specifies whether the consumer is still active or not. |
| | | * If not active, the handler will not return any message. |
| | |
| | | { |
| | | if (replicationServerDomain==null) |
| | | { |
| | | replicationServerDomain = |
| | | replicationServer.getReplicationServerDomain( |
| | | serviceId, createIfNotExist, waitConnections); |
| | | replicationServerDomain = replicationServer.getReplicationServerDomain( |
| | | baseDN, createIfNotExist, waitConnections); |
| | | } |
| | | return replicationServerDomain; |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * Get the name of the serviceId (usually baseDn) for this handler. |
| | | * @return The name of the serviceId. |
| | | * Get the baseDN for this handler. |
| | | * |
| | | * @return The name of the baseDN. |
| | | */ |
| | | protected String getServiceId() |
| | | protected String getBaseDN() |
| | | { |
| | | return serviceId; |
| | | return baseDN; |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | |
| | | /** |
| | | * Set the serviceId (usually baseDn) for this handler. Expected to be done |
| | | * once and never changed during the handler life. |
| | | * Set the baseDN for this handler. Expected to be done once and never changed |
| | | * during the handler life. |
| | | * |
| | | * @param serviceId The provided serviceId. |
| | | * @param isDataServer The handler is a dataServer |
| | | * |
| | | * @exception DirectoryException raised when a problem occurs. |
| | | * @param baseDN |
| | | * The provided baseDN. |
| | | * @param isDataServer |
| | | * The handler is a dataServer |
| | | * @exception DirectoryException |
| | | * raised when a problem occurs. |
| | | */ |
| | | protected void setServiceIdAndDomain(String serviceId, boolean isDataServer) |
| | | protected void setBaseDNAndDomain(String baseDN, boolean isDataServer) |
| | | throws DirectoryException |
| | | { |
| | | if (this.serviceId != null) |
| | | if (this.baseDN != null) |
| | | { |
| | | if (!this.serviceId.equalsIgnoreCase(serviceId)) |
| | | if (!this.baseDN.equalsIgnoreCase(baseDN)) |
| | | { |
| | | Message message = ERR_RS_DN_DOES_NOT_MATCH.get( |
| | | this.serviceId, |
| | | serviceId); |
| | | throw new DirectoryException(ResultCode.OTHER, |
| | | message, null); |
| | | Message message = ERR_RS_DN_DOES_NOT_MATCH.get(this.baseDN, baseDN); |
| | | throw new DirectoryException(ResultCode.OTHER, message, null); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | this.serviceId = serviceId; |
| | | if (!serviceId.equalsIgnoreCase("cn=changelog")) |
| | | this.baseDN = baseDN; |
| | | if (!baseDN.equalsIgnoreCase("cn=changelog")) |
| | | this.replicationServerDomain = getDomain(true, isDataServer); |
| | | } |
| | | } |
| | |
| | | private final Object connectThreadLock = new Object(); |
| | | private long domainTicket = 0L; |
| | | |
| | | /** ServiceIDs excluded for ECL. */ |
| | | private Collection<String> excludedServiceIDs = new ArrayList<String>(); |
| | | /** BaseDNs excluded for ECL. */ |
| | | private Collection<String> excludedBaseDNs = new ArrayList<String>(); |
| | | |
| | | /** |
| | | * The weight affected to the replication server. |
| | |
| | | |
| | | /** |
| | | * Excluded a list of domain from eligibility computation. |
| | | * @param excludedServiceIDs the provided list of serviceIDs excluded from |
| | | * @param excludedBaseDNs the provided list of baseDNs excluded from |
| | | * the computation of eligibleCN. |
| | | */ |
| | | public void disableEligibility(Set<String> excludedServiceIDs) |
| | | public void disableEligibility(Set<String> excludedBaseDNs) |
| | | { |
| | | this.excludedServiceIDs = excludedServiceIDs; |
| | | this.excludedBaseDNs = excludedBaseDNs; |
| | | } |
| | | |
| | | /** |
| | |
| | | ChangeNumber eligibleCN = null; |
| | | for (ReplicationServerDomain domain : getReplicationServerDomains()) |
| | | { |
| | | if ((excludedServiceIDs != null) && |
| | | excludedServiceIDs.contains(domain.getBaseDn())) |
| | | if ((excludedBaseDNs != null) && |
| | | excludedBaseDNs.contains(domain.getBaseDn())) |
| | | continue; |
| | | |
| | | ChangeNumber domainEligibleCN = domain.getEligibleCN(); |
| | |
| | | * |
| | | * @param crossDomainEligibleCN The provided crossDomainEligibleCN used as |
| | | * the upper limit for the lastDraftCN |
| | | * @param excludedServiceIDs The serviceIDs that are excluded from the ECL. |
| | | * @param excludedBaseDNs The baseDNs that are excluded from the ECL. |
| | | * @return The first and last draftCN. |
| | | * @throws DirectoryException When it happens. |
| | | */ |
| | | public int[] getECLDraftCNLimits(ChangeNumber crossDomainEligibleCN, |
| | | Set<String> excludedServiceIDs) throws DirectoryException |
| | | Set<String> excludedBaseDNs) throws DirectoryException |
| | | { |
| | | /* The content of the DraftCNdb depends on the SEARCH operations done before |
| | | * requesting the DraftCN. If no operations, DraftCNdb is empty. |
| | |
| | | changeNumberForLastSeqnum = draftCNDbH.getChangeNumber(lastDraftCN); |
| | | |
| | | // Get the domain associated with the current last DraftCN |
| | | domainForLastSeqnum = draftCNDbH.getServiceID(lastDraftCN); |
| | | domainForLastSeqnum = draftCNDbH.getBaseDN(lastDraftCN); |
| | | } |
| | | |
| | | // Domain by domain |
| | | for (ReplicationServerDomain rsd : getReplicationServerDomains()) |
| | | { |
| | | if (excludedServiceIDs.contains(rsd.getBaseDn())) |
| | | if (excludedBaseDNs.contains(rsd.getBaseDn())) |
| | | continue; |
| | | |
| | | // for this domain, have the state in the replchangelog |
| | |
| | | |
| | | /** |
| | | * Returns the last (newest) cookie value. |
| | | * @param excludedServiceIDs The list of serviceIDs excluded from ECL. |
| | | * @param excludedBaseDNs The list of baseDNs excluded from ECL. |
| | | * @return the last cookie value. |
| | | */ |
| | | public MultiDomainServerState getLastECLCookie(Set<String> excludedServiceIDs) |
| | | public MultiDomainServerState getLastECLCookie(Set<String> excludedBaseDNs) |
| | | { |
| | | disableEligibility(excludedServiceIDs); |
| | | disableEligibility(excludedBaseDNs); |
| | | |
| | | MultiDomainServerState result = new MultiDomainServerState(); |
| | | // Initialize start state for all running domains with empty state |
| | | for (ReplicationServerDomain rsd : getReplicationServerDomains()) |
| | | { |
| | | if ((excludedServiceIDs != null) |
| | | && (excludedServiceIDs.contains(rsd.getBaseDn()))) |
| | | if ((excludedBaseDNs != null) |
| | | && (excludedBaseDNs.contains(rsd.getBaseDn()))) |
| | | continue; |
| | | |
| | | if (rsd.getDbServerState().isEmpty()) |
| | |
| | | public class ReplicationServerHandler extends ServerHandler |
| | | { |
| | | |
| | | /* |
| | | * Properties filled only if remote server is a RS |
| | | /** |
| | | * Properties filled only if remote server is a RS. |
| | | */ |
| | | private String serverAddressURL; |
| | | /** |
| | |
| | | serverAddressURL = |
| | | session.getRemoteAddress() + ":" + serverURL.substring(separator + |
| | | 1); |
| | | setServiceIdAndDomain(inReplServerStartMsg.getBaseDn(), false); |
| | | setBaseDNAndDomain(inReplServerStartMsg.getBaseDn(), false); |
| | | setInitialServerState(inReplServerStartMsg.getServerState()); |
| | | setSendWindowSize(inReplServerStartMsg.getWindowSize()); |
| | | if (protocolVersion > ProtocolVersion.REPLICATION_PROTOCOL_V1) |
| | |
| | | private ReplServerStartMsg sendStartToRemote() throws IOException |
| | | { |
| | | ReplServerStartMsg outReplServerStartMsg = new ReplServerStartMsg( |
| | | replicationServerId, replicationServerURL, getServiceId(), |
| | | replicationServerId, replicationServerURL, getBaseDN(), |
| | | maxRcvWindow, replicationServerDomain.getDbServerState(), |
| | | localGenerationId, sslEncryption, |
| | | getLocalGroupId(), replicationServerDomain.getReplicationServer() |
| | |
| | | /** |
| | | * Connect the hosting RS to the RS represented by THIS handler |
| | | * on an outgoing connection. |
| | | * @param serviceId The serviceId (usually baseDn). |
| | | * @param baseDN The baseDN |
| | | * @param sslEncryption The sslEncryption requested to the remote RS. |
| | | * @throws DirectoryException when an error occurs. |
| | | */ |
| | | public void connect(String serviceId, boolean sslEncryption) |
| | | public void connect(String baseDN, boolean sslEncryption) |
| | | throws DirectoryException |
| | | { |
| | | // we are the initiator and decides of the encryption |
| | | this.sslEncryption = sslEncryption; |
| | | |
| | | setServiceIdAndDomain(serviceId, false); |
| | | setBaseDNAndDomain(baseDN, false); |
| | | |
| | | localGenerationId = replicationServerDomain.getGenerationId(); |
| | | oldGenerationId = localGenerationId; |
| | |
| | | */ |
| | | public void startFromRemoteRS(ReplServerStartMsg inReplServerStartMsg) |
| | | { |
| | | // |
| | | localGenerationId = -1; |
| | | oldGenerationId = -100; |
| | | try |
| | |
| | | */ |
| | | Message message = WARN_BAD_GENERATION_ID_FROM_RS.get( |
| | | serverId, session.getReadableRemoteAddress(), generationId, |
| | | getServiceId(), getReplicationServerId(), localGenerationId); |
| | | getBaseDN(), getReplicationServerId(), localGenerationId); |
| | | logError(message); |
| | | } |
| | | } |
| | |
| | | ArrayList<Attribute> attributes = super.getMonitorData(); |
| | | |
| | | // Add the specific RS ones |
| | | attributes.add(Attributes.create("Replication-Server", |
| | | serverURL)); |
| | | attributes.add(Attributes.create("Replication-Server", serverURL)); |
| | | |
| | | MonitorData md = replicationServerDomain.getDomainMonitorData(); |
| | | |
| | |
| | | package org.opends.server.replication.server; |
| | | |
| | | import static org.opends.messages.ReplicationMessages.*; |
| | | import static org.opends.server.loggers.ErrorLogger.logError; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import static org.opends.server.loggers.ErrorLogger.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | |
| | | * Set the shut down flag to true and returns the previous value of the flag. |
| | | * @return The previous value of the shut down flag |
| | | */ |
| | | @Override |
| | | public boolean engageShutdown() |
| | | { |
| | | // Use thread safe boolean |
| | |
| | | * Get the count of updates received from the server. |
| | | * @return the count of update received from the server. |
| | | */ |
| | | @Override |
| | | public int getInCount() |
| | | { |
| | | return inCount; |
| | |
| | | ArrayList<Attribute> attributes = super.getMonitorData(); |
| | | |
| | | attributes.add(Attributes.create("server-id", String.valueOf(serverId))); |
| | | attributes.add(Attributes.create("domain-name", getServiceId())); |
| | | attributes.add(Attributes.create("domain-name", getBaseDN())); |
| | | |
| | | // Deprecated |
| | | attributes.add(Attributes.create("max-waiting-changes", String |
| | |
| | | * Get the count of updates sent to this server. |
| | | * @return The count of update sent to this server. |
| | | */ |
| | | @Override |
| | | public int getOutCount() |
| | | { |
| | | return outCount; |
| | |
| | | /** |
| | | * Increase the counter of update received from the server. |
| | | */ |
| | | @Override |
| | | public void incrementInCount() |
| | | { |
| | | inCount++; |
| | |
| | | /** |
| | | * Increase the counter of updates sent to the server. |
| | | */ |
| | | @Override |
| | | public void incrementOutCount() |
| | | { |
| | | outCount++; |
| | |
| | | Random random = new Random(); |
| | | int randomTime = random.nextInt(6); // Random from 0 to 5 |
| | | // Wait at least 3 seconds + (0 to 5 seconds) |
| | | long timeout = (long) (3000 + ( randomTime * 1000 ) ); |
| | | long timeout = 3000 + (randomTime * 1000); |
| | | boolean noTimeout = replicationServerDomain.tryLock(timeout); |
| | | if (!noTimeout) |
| | | { |
| | | // Timeout |
| | | Message message = WARN_TIMEOUT_WHEN_CROSS_CONNECTION.get( |
| | | getServiceId(), |
| | | getBaseDN(), |
| | | serverId, |
| | | session.getReadableRemoteAddress(), |
| | | replicationServerId); |
| | |
| | | // while it is not, this means that some problem happened in the |
| | | // window exchange procedure ! |
| | | // lets update the LDAP server with out current window size and hope |
| | | // that everything will work better in the futur. |
| | | // that everything will work better in the future. |
| | | // TODO also log an error message. |
| | | WindowMsg msg = new WindowMsg(rcvWindow); |
| | | session.publish(msg); |
| | |
| | | /** |
| | | * Shutdown This ServerHandler. |
| | | */ |
| | | @Override |
| | | public void shutdown() |
| | | { |
| | | shutdownWriter(); |
| | |
| | | { |
| | | try |
| | | { |
| | | acquired = sendWindow.tryAcquire((long) 500, TimeUnit.MILLISECONDS); |
| | | acquired = sendWindow.tryAcquire(500, TimeUnit.MILLISECONDS); |
| | | interrupted = false; |
| | | } catch (InterruptedException e) |
| | | { |
| | |
| | | package org.opends.server.replication.server; |
| | | |
| | | import static org.opends.messages.ReplicationMessages.*; |
| | | import static org.opends.server.loggers.ErrorLogger.logError; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import static org.opends.server.loggers.debug.DebugLogger.getTracer; |
| | | import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; |
| | | import static org.opends.server.loggers.ErrorLogger.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import java.io.IOException; |
| | | |
| | |
| | | /** |
| | | * Create a loop that reads changes and hands them off to be processed. |
| | | */ |
| | | @Override |
| | | public void run() |
| | | { |
| | | Message errMessage = null; |
| | |
| | | logError(WARN_IGNORING_UPDATE_FROM_DS_BADGENID.get( |
| | | handler.getReplicationServerId(), |
| | | ((UpdateMsg) msg).getChangeNumber().toString(), |
| | | handler.getServiceId(), handler.getServerId(), |
| | | handler.getBaseDN(), handler.getServerId(), |
| | | session.getReadableRemoteAddress(), |
| | | handler.getGenerationId(), |
| | | referenceGenerationId)); |
| | |
| | | logError(WARN_IGNORING_UPDATE_FROM_DS_FULLUP.get( |
| | | handler.getReplicationServerId(), |
| | | ((UpdateMsg) msg).getChangeNumber().toString(), |
| | | handler.getServiceId(), handler.getServerId(), |
| | | handler.getBaseDN(), handler.getServerId(), |
| | | session.getReadableRemoteAddress())); |
| | | filtered = true; |
| | | } |
| | |
| | | WARN_IGNORING_UPDATE_FROM_RS.get( |
| | | handler.getReplicationServerId(), |
| | | ((UpdateMsg) msg).getChangeNumber().toString(), |
| | | handler.getServiceId(), |
| | | handler.getBaseDN(), |
| | | handler.getServerId(), |
| | | session.getReadableRemoteAddress(), |
| | | handler.getGenerationId(), |
| | |
| | | { |
| | | errMessage = |
| | | ERR_RECEIVED_CHANGE_STATUS_NOT_FROM_DS.get( |
| | | handler.getServiceId(), |
| | | handler.getBaseDN(), |
| | | Integer.toString(handler.getServerId()), |
| | | csMsg.toString()); |
| | | logError(errMessage); |
| | |
| | | } else if (msg == null) |
| | | { |
| | | /* |
| | | * The remote server has sent an unknown message, |
| | | * close the conenction. |
| | | * The remote server has sent an unknown message, close the |
| | | * connection. |
| | | */ |
| | | errMessage = NOTE_READER_NULL_MSG.get(handler.toString()); |
| | | logError(errMessage); |
| | |
| | | { |
| | | errMessage = ERR_DS_BADLY_DISCONNECTED.get( |
| | | handler.getReplicationServerId(), handler.getServerId(), |
| | | remoteAddress, handler.getServiceId()); |
| | | remoteAddress, handler.getBaseDN()); |
| | | } |
| | | else |
| | | { |
| | | errMessage = ERR_RS_BADLY_DISCONNECTED.get( |
| | | handler.getReplicationServerId(), handler.getServerId(), |
| | | remoteAddress, handler.getServiceId()); |
| | | remoteAddress, handler.getBaseDN()); |
| | | } |
| | | logError(errMessage); |
| | | } |
| | |
| | | */ |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugInfo("In " + this.getName() |
| | | + " closing the session"); |
| | | TRACER.debugInfo("In " + this.getName() + " closing the session"); |
| | | } |
| | | session.close(); |
| | | handler.doStop(); |
| | |
| | | * Portions Copyright 2011-2013 ForgeRock AS |
| | | */ |
| | | package org.opends.server.replication.server; |
| | | import org.opends.messages.Message; |
| | | |
| | | import static org.opends.server.loggers.ErrorLogger.logError; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import static org.opends.server.loggers.debug.DebugLogger.getTracer; |
| | | import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; |
| | | import static org.opends.messages.ReplicationMessages.*; |
| | | import static org.opends.server.loggers.ErrorLogger.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import java.net.SocketException; |
| | | import java.util.NoSuchElementException; |
| | | |
| | | import org.opends.messages.Message; |
| | | import org.opends.server.api.DirectoryThread; |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import org.opends.server.replication.common.ServerStatus; |
| | |
| | | * Loops waiting for changes from the ReplicationServerDomain and forward them |
| | | * to the other servers |
| | | */ |
| | | @Override |
| | | public void run() |
| | | { |
| | | Message errMessage = null; |
| | |
| | | logError(WARN_IGNORING_UPDATE_TO_DS_BADGENID.get( |
| | | handler.getReplicationServerId(), |
| | | update.getChangeNumber().toString(), |
| | | handler.getServiceId(), handler.getServerId(), |
| | | handler.getBaseDN(), handler.getServerId(), |
| | | session.getReadableRemoteAddress(), |
| | | handler.getGenerationId(), |
| | | referenceGenerationId)); |
| | |
| | | logError(WARN_IGNORING_UPDATE_TO_DS_FULLUP.get( |
| | | handler.getReplicationServerId(), |
| | | update.getChangeNumber().toString(), |
| | | handler.getServiceId(), handler.getServerId(), |
| | | handler.getBaseDN(), handler.getServerId(), |
| | | session.getReadableRemoteAddress())); |
| | | continue; |
| | | } |
| | |
| | | WARN_IGNORING_UPDATE_TO_RS.get( |
| | | handler.getReplicationServerId(), |
| | | update.getChangeNumber().toString(), |
| | | handler.getServiceId(), |
| | | handler.getBaseDN(), |
| | | handler.getServerId(), |
| | | session.getReadableRemoteAddress(), |
| | | handler.getGenerationId(), |
| | |
| | | { |
| | | errMessage = ERR_DS_BADLY_DISCONNECTED.get( |
| | | handler.getReplicationServerId(), handler.getServerId(), |
| | | session.getReadableRemoteAddress(), handler.getServiceId()); |
| | | session.getReadableRemoteAddress(), handler.getBaseDN()); |
| | | } |
| | | else |
| | | { |
| | | errMessage = ERR_RS_BADLY_DISCONNECTED.get( |
| | | handler.getReplicationServerId(), handler.getServerId(), |
| | | session.getReadableRemoteAddress(), handler.getServiceId()); |
| | | session.getReadableRemoteAddress(), handler.getBaseDN()); |
| | | } |
| | | |
| | | logError(errMessage); |
| | |
| | | { |
| | | errMessage = ERR_DS_BADLY_DISCONNECTED.get( |
| | | handler.getReplicationServerId(), handler.getServerId(), |
| | | session.getReadableRemoteAddress(), handler.getServiceId()); |
| | | session.getReadableRemoteAddress(), handler.getBaseDN()); |
| | | } |
| | | else |
| | | { |
| | | errMessage = ERR_RS_BADLY_DISCONNECTED.get( |
| | | handler.getReplicationServerId(), handler.getServerId(), |
| | | session.getReadableRemoteAddress(), handler.getServiceId()); |
| | | session.getReadableRemoteAddress(), handler.getBaseDN()); |
| | | } |
| | | logError(errMessage); |
| | | } |
| | |
| | | ServerConstants.OID_VLV_REQUEST_CONTROL)); |
| | | |
| | | /** The set of objectclasses that will be used in ECL root entry. */ |
| | | private static final HashMap<ObjectClass, String> |
| | | private static final Map<ObjectClass, String> |
| | | CHANGELOG_ROOT_OBJECT_CLASSES = new LinkedHashMap<ObjectClass, String>(2); |
| | | static |
| | | { |
| | |
| | | } |
| | | |
| | | /** The set of objectclasses that will be used in ECL entries. */ |
| | | private static final HashMap<ObjectClass, String> |
| | | private static final Map<ObjectClass, String> |
| | | CHANGELOG_ENTRY_OBJECT_CLASSES = new LinkedHashMap<ObjectClass, String>(2); |
| | | static |
| | | { |
| | |
| | | + e.getMessage())); |
| | | } |
| | | |
| | | ArrayList<RawAttribute> eclAttributes = addMsg.getEclIncludes(); |
| | | List<RawAttribute> eclAttributes = addMsg.getEclIncludes(); |
| | | |
| | | clEntry = createChangelogEntry(eclmsg.getServiceId(), eclmsg |
| | | clEntry = createChangelogEntry(eclmsg.getBaseDN(), eclmsg |
| | | .getCookie().toString(), DN.decode(addMsg.getDn()), |
| | | addMsg.getChangeNumber(), ldifChanges, // entry as created (in LDIF |
| | | // format) |
| | | addMsg.getEntryUUID(), |
| | | eclAttributes, // entry attributes |
| | | eclmsg.getDraftChangeNumber(), "add", changeInitiatorsName); |
| | | |
| | | } |
| | | else if (msg instanceof ModifyCommonMsg) |
| | | { |
| | |
| | | String changeType = (modifyMsg instanceof ModifyDNMsg) ? "modrdn" |
| | | : "modify"; |
| | | |
| | | clEntry = createChangelogEntry(eclmsg.getServiceId(), eclmsg |
| | | clEntry = createChangelogEntry(eclmsg.getBaseDN(), eclmsg |
| | | .getCookie().toString(), DN.decode(modifyMsg.getDn()), |
| | | modifyMsg.getChangeNumber(), ldifChanges, |
| | | modifyMsg.getEntryUUID(), |
| | |
| | | { |
| | | ModifyDNMsg modDNMsg = (ModifyDNMsg) modifyMsg; |
| | | |
| | | Attribute a = Attributes.create("newrdn", |
| | | modDNMsg.getNewRDN()); |
| | | Attribute a = Attributes.create("newrdn", modDNMsg.getNewRDN()); |
| | | clEntry.addAttribute(a, null); |
| | | |
| | | if (modDNMsg.getNewSuperior() != null) |
| | |
| | | { |
| | | DeleteMsg delMsg = (DeleteMsg) msg; |
| | | |
| | | clEntry = createChangelogEntry(eclmsg.getServiceId(), eclmsg |
| | | clEntry = createChangelogEntry(eclmsg.getBaseDN(), eclmsg |
| | | .getCookie().toString(), DN.decode(delMsg.getDn()), |
| | | delMsg.getChangeNumber(), |
| | | null, // no changes |
| | |
| | | * Create an ECL entry from a set of provided information. This is the part |
| | | * of entry creation common to all types of msgs (ADD, DEL, MOD, MODDN). |
| | | * |
| | | * @param serviceID The provided cookie value. |
| | | * @param baseDN The provided baseDN value. |
| | | * @param cookie The provided cookie value. |
| | | * @param targetDN The provided targetDN. |
| | | * @param changeNumber The provided replication changeNumber. |
| | |
| | | * When any error occurs. |
| | | */ |
| | | private static Entry createChangelogEntry( |
| | | String serviceID, |
| | | String baseDN, |
| | | String cookie, |
| | | DN targetDN, |
| | | ChangeNumber changeNumber, |
| | |
| | | if (draftChangenumber == 0) |
| | | { |
| | | // Draft uncompat mode |
| | | dnString = "replicationCSN=" + changeNumber + "," + serviceID + "," |
| | | dnString = "replicationCSN=" + changeNumber + "," + baseDN + "," |
| | | + ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT; |
| | | } |
| | | else |
| | |
| | | // Objectclass |
| | | Map<AttributeType, List<Attribute>> uAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(); |
| | | |
| | | Map<AttributeType, List<Attribute>> operationalAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(); |
| | | |
| | | // Operational standard attributes |
| | | |
| | | addAttributeByType(ATTR_SUBSCHEMA_SUBENTRY_LC, ATTR_SUBSCHEMA_SUBENTRY_LC, |
| | | ConfigConstants.DN_DEFAULT_SCHEMA_ROOT, uAttrs, operationalAttrs); |
| | | |
| | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | /** |
| | | * Test the constructors, encoders and decoders of the replication protocol |
| | | * PDUs classes (message classes) |
| | | */ |
| | | @SuppressWarnings("javadoc") |
| | | public class SynchronizationMsgTest extends ReplicationTestCase |
| | | { |
| | | /** |
| | |
| | | mods2.add(mod2); |
| | | |
| | | AttributeBuilder builder = new AttributeBuilder(type); |
| | | List<Modification> mods3 = new ArrayList<Modification>(); |
| | | builder.add("string"); |
| | | builder.add("value"); |
| | | builder.add("again"); |
| | | Attribute attr3 = builder.toAttribute(); |
| | | Modification mod3 = new Modification(ModificationType.ADD, attr3); |
| | | List<Modification> mods3 = new ArrayList<Modification>(); |
| | | mods3.add(mod3); |
| | | |
| | | List<Modification> mods4 = new ArrayList<Modification>(); |
| | |
| | | DeleteMsg delmsg = new DeleteMsg(op); |
| | | int draftcn = 21; |
| | | |
| | | String serviceId = "serviceid"; |
| | | String baseDN = "dc=example,dc=com"; |
| | | |
| | | // create a cookie |
| | | MultiDomainServerState cookie = |
| | |
| | | "o=test2:000001210b6f21e904b100000002 000001210b6f21e904b200000002;"); |
| | | |
| | | // Constructor test |
| | | ECLUpdateMsg msg1 = new ECLUpdateMsg(delmsg, cookie, serviceId, draftcn); |
| | | ECLUpdateMsg msg1 = new ECLUpdateMsg(delmsg, cookie, baseDN, draftcn); |
| | | assertTrue(msg1.getCookie().equalsTo(cookie)); |
| | | assertTrue(msg1.getServiceId().equalsIgnoreCase(serviceId)); |
| | | assertTrue((msg1.getDraftChangeNumber()==draftcn)); |
| | | assertTrue(msg1.getBaseDN().equalsIgnoreCase(baseDN)); |
| | | assertEquals(msg1.getDraftChangeNumber(), draftcn); |
| | | DeleteMsg delmsg2 = (DeleteMsg)msg1.getUpdateMsg(); |
| | | assertTrue(delmsg.compareTo(delmsg2)==0); |
| | | assertEquals(delmsg.compareTo(delmsg2), 0); |
| | | |
| | | // Constructor test (with byte[]) |
| | | ECLUpdateMsg msg2 = new ECLUpdateMsg(msg1.getBytes(getCurrentVersion())); |
| | | assertTrue(msg2.getCookie().equalsTo(msg2.getCookie())); |
| | | assertTrue(msg2.getCookie().equalsTo(cookie)); |
| | | assertTrue(msg2.getServiceId().equalsIgnoreCase(msg1.getServiceId())); |
| | | assertTrue(msg2.getServiceId().equalsIgnoreCase(serviceId)); |
| | | assertTrue(msg2.getDraftChangeNumber()==(msg1.getDraftChangeNumber())); |
| | | assertTrue(msg2.getDraftChangeNumber()==draftcn); |
| | | assertTrue(msg2.getBaseDN().equalsIgnoreCase(msg1.getBaseDN())); |
| | | assertTrue(msg2.getBaseDN().equalsIgnoreCase(baseDN)); |
| | | assertEquals(msg2.getDraftChangeNumber(), msg1.getDraftChangeNumber()); |
| | | assertEquals(msg2.getDraftChangeNumber(), draftcn); |
| | | |
| | | DeleteMsg delmsg1 = (DeleteMsg)msg1.getUpdateMsg(); |
| | | delmsg2 = (DeleteMsg)msg2.getUpdateMsg(); |
| | | assertTrue(delmsg2.compareTo(delmsg)==0); |
| | | assertTrue(delmsg2.compareTo(delmsg1)==0); |
| | | assertEquals(delmsg2.compareTo(delmsg), 0); |
| | | assertEquals(delmsg2.compareTo(delmsg1), 0); |
| | | } |
| | | |
| | | @DataProvider(name="createServerStartData") |
| | |
| | | public void stopMsgTest() throws Exception |
| | | { |
| | | StopMsg msg = new StopMsg(); |
| | | StopMsg newMsg = new StopMsg(msg.getBytes(getCurrentVersion())); |
| | | new StopMsg(msg.getBytes(getCurrentVersion())); |
| | | } |
| | | |
| | | /** |
| | |
| | | assertEquals(msg.getGenerationId(), newMsg.getGenerationId()); |
| | | assertTrue(msg.getGroupId() == newMsg.getGroupId()); |
| | | } |
| | | |
| | | /** |
| | | * Test StartSessionMsg encoding and decoding. |
| | | */ |
| | |
| | | msg.setLastDraftChangeNumber(lastDraftChangeNumber); |
| | | msg.setECLRequestType(mode); |
| | | msg.setOperationId(myopid); |
| | | Set<String> dns = new HashSet<String>(); |
| | | String dn1 = "cn=admin data"; |
| | | String dn2 = "cn=config"; |
| | | Set<String> dns = new HashSet<String>(); |
| | | dns.add(dn1); |
| | | dns.add(dn2); |
| | | msg.setExcludedDNs(dns); |
| | |
| | | StartECLSessionMsg newMsg = new StartECLSessionMsg(msg.getBytes(getCurrentVersion())); |
| | | // test equality between the two copies |
| | | assertEquals(msg.getChangeNumber(), newMsg.getChangeNumber()); |
| | | assertTrue(msg.isPersistent() == newMsg.isPersistent()); |
| | | assertTrue(msg.getFirstDraftChangeNumber() == newMsg.getFirstDraftChangeNumber()); |
| | | assertEquals(msg.isPersistent(), newMsg.isPersistent()); |
| | | assertEquals(msg.getFirstDraftChangeNumber(), newMsg |
| | | .getFirstDraftChangeNumber()); |
| | | assertEquals(msg.getECLRequestType(), newMsg.getECLRequestType()); |
| | | assertEquals(msg.getLastDraftChangeNumber(), newMsg.getLastDraftChangeNumber()); |
| | | assertTrue( |
| | | msg.getCrossDomainServerState().equalsIgnoreCase(newMsg.getCrossDomainServerState())); |
| | | assertTrue( |
| | | msg.getOperationId().equalsIgnoreCase(newMsg.getOperationId())); |
| | | Set<String> dns2 = newMsg.getExcludedServiceIDs(); |
| | | assertTrue(dns2.size()==2); |
| | | Set<String> dns2 = newMsg.getExcludedBaseDNs(); |
| | | assertEquals(dns2.size(), 2); |
| | | boolean dn1found=false,dn2found=false; |
| | | for (String dn : dns2) |
| | | { |
| | |
| | | assertTrue(dn2found); |
| | | } |
| | | |
| | | int perfRep = 100000; |
| | | private int perfRep = 100000; |
| | | |
| | | |
| | | @Test(enabled=false,dataProvider = "createAddData") |
| | |
| | | long createmsgfromop = 0; |
| | | long encodemsg = 0; |
| | | long getbytes = 0; |
| | | long alld = 0; |
| | | long setentryattr = 0; |
| | | long buildnew = 0; |
| | | long t1,t2,t3,t31,t4,t5,t6 = 0; |
| | |
| | | new AddMsg(bytes); |
| | | t6 = System.nanoTime(); |
| | | buildnew += (t6 - t5); |
| | | |
| | | alld += (t6 - t1); |
| | | } |
| | | |
| | | System.out.println( |
| | |
| | | long createmsgfromop = 0; |
| | | long encodemsg = 0; |
| | | long getbytes = 0; |
| | | long alld = 0; |
| | | long setentryattr = 0; |
| | | long buildnew = 0; |
| | | long t1,t2,t3,t31,t4,t5,t6 = 0; |
| | |
| | | new ModifyMsg(bytes); |
| | | t6 = System.nanoTime(); |
| | | buildnew += (t6 - t5); |
| | | |
| | | alld += (t6 - t1); |
| | | } |
| | | |
| | | System.out.println( |
| | |
| | | long createmsgfromop = 0; |
| | | long encodemsg = 0; |
| | | long getbytes = 0; |
| | | long alld = 0; |
| | | long setentryattr = 0; |
| | | long buildnew = 0; |
| | | long t1,t2,t3,t31,t4,t5,t6 = 0; |
| | |
| | | new DeleteMsg(bytes); |
| | | t6 = System.nanoTime(); |
| | | buildnew += (t6 - t5); |
| | | |
| | | alld += (t6 - t1); |
| | | } |
| | | |
| | | System.out.println( |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011 ForgeRock AS |
| | | * Portions Copyright 2011-2013 ForgeRock AS |
| | | */ |
| | | package org.opends.server.replication.server; |
| | | |
| | | import static org.testng.Assert.assertEquals; |
| | | import static org.testng.Assert.assertFalse; |
| | | import static org.testng.Assert.assertTrue; |
| | | import static org.testng.Assert.*; |
| | | |
| | | import java.io.File; |
| | | import java.net.ServerSocket; |
| | |
| | | String value2 = "value2"; |
| | | String value3 = "value3"; |
| | | |
| | | String serviceID1 = "serviceID1"; |
| | | String serviceID2 = "serviceID2"; |
| | | String serviceID3 = "serviceID3"; |
| | | String baseDN1 = "baseDN1"; |
| | | String baseDN2 = "baseDN2"; |
| | | String baseDN3 = "baseDN3"; |
| | | |
| | | ChangeNumberGenerator gen = new ChangeNumberGenerator( 1, 0); |
| | | ChangeNumber changeNumber1 = gen.newChangeNumber(); |
| | |
| | | ChangeNumber changeNumber3 = gen.newChangeNumber(); |
| | | |
| | | // Add records |
| | | handler.add(sn1, value1, serviceID1, changeNumber1); |
| | | handler.add(sn2, value2, serviceID2, changeNumber2); |
| | | handler.add(sn3, value3, serviceID3, changeNumber3); |
| | | handler.add(sn1, value1, baseDN1, changeNumber1); |
| | | handler.add(sn2, value2, baseDN2, changeNumber2); |
| | | handler.add(sn3, value3, baseDN3, changeNumber3); |
| | | |
| | | // The ChangeNumber should not get purged |
| | | int firstkey = handler.getFirstKey(); |
| | |
| | | try |
| | | { |
| | | assertEquals(dbc.currentChangeNumber(), changeNumber1); |
| | | assertEquals(dbc.currentServiceID(), serviceID1); |
| | | assertEquals(dbc.currentBaseDN(), baseDN1); |
| | | assertEquals(dbc.currentValue(), value1); |
| | | assertTrue(dbc.toString().length() != 0); |
| | | |
| | | assertTrue(dbc.next()); |
| | | |
| | | assertEquals(dbc.currentChangeNumber(), changeNumber2); |
| | | assertEquals(dbc.currentServiceID(), serviceID2); |
| | | assertEquals(dbc.currentBaseDN(), baseDN2); |
| | | assertEquals(dbc.currentValue(), value2); |
| | | |
| | | assertTrue(dbc.next()); |
| | | |
| | | assertEquals(dbc.currentChangeNumber(), changeNumber3); |
| | | assertEquals(dbc.currentServiceID(), serviceID3); |
| | | assertEquals(dbc.currentBaseDN(), baseDN3); |
| | | assertEquals(dbc.currentValue(), value3); |
| | | |
| | | assertFalse(dbc.next()); |
| | |
| | | String value2 = "value2"; |
| | | String value3 = "value3"; |
| | | |
| | | String serviceID1 = "serviceID1"; |
| | | String serviceID2 = "serviceID2"; |
| | | String serviceID3 = "serviceID3"; |
| | | String baseDN1 = "baseDN1"; |
| | | String baseDN2 = "baseDN2"; |
| | | String baseDN3 = "baseDN3"; |
| | | |
| | | ChangeNumberGenerator gen = new ChangeNumberGenerator( 1, 0); |
| | | ChangeNumber changeNumber1 = gen.newChangeNumber(); |
| | |
| | | ChangeNumber changeNumber3 = gen.newChangeNumber(); |
| | | |
| | | // Add records |
| | | handler.add(sn1, value1, serviceID1, changeNumber1); |
| | | handler.add(sn2, value2, serviceID2, changeNumber2); |
| | | handler.add(sn3, value3, serviceID3, changeNumber3); |
| | | handler.add(sn1, value1, baseDN1, changeNumber1); |
| | | handler.add(sn2, value2, baseDN2, changeNumber2); |
| | | handler.add(sn3, value3, baseDN3, changeNumber3); |
| | | Thread.sleep(500); |
| | | |
| | | // Checks |
| | |
| | | // Check the db is cleared. |
| | | assertEquals(handler.getFirstKey(), 0); |
| | | assertEquals(handler.getLastKey(), 0); |
| | | assertTrue(handler.count()==0); |
| | | assertEquals(handler.count(), 0); |
| | | |
| | | } finally |
| | | { |