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 2013-2016 ForgeRock AS.
015 */
016package org.opends.server.replication.server.changelog.api;
017
018import java.util.Set;
019
020import org.opends.server.replication.common.CSN;
021import org.opends.server.replication.common.MultiDomainServerState;
022import org.opends.server.replication.common.ServerState;
023import org.opends.server.replication.protocol.UpdateMsg;
024import org.opends.server.replication.server.changelog.api.DBCursor.CursorOptions;
025import org.opends.server.replication.server.changelog.file.MultiDomainDBCursor;
026import org.forgerock.opendj.ldap.DN;
027
028/**
029 * This interface allows to query or control the replication domain database(s)
030 * (composed of one or more ReplicaDBs) and query/update each ReplicaDB.
031 * <p>
032 * In particular, the {@code getCursorFom()} methods allow to obtain a cursor at any level:
033 * <ul>
034 *  <li>Across all the domains, provided a {@link MultiDomainServerState}</li>
035 *  <li>Across all replicaDBs of a domain, provided a {@link ServerState}</li>
036 *  <li>On one replica DB for a domain and serverId, provided a CSN</li>
037 * </ul>
038 * The cursor starting point is specified by providing a key,
039 * a {@link org.opends.server.replication.server.changelog.api.DBCursor.KeyMatchingStrategy} and
040 * a {@link org.opends.server.replication.server.changelog.api.DBCursor.PositionStrategy}.
041 */
042public interface ReplicationDomainDB
043{
044
045  /**
046   * Returns the oldest {@link CSN}s from the replicaDBs for each serverId in
047   * the specified replication domain.
048   *
049   * @param baseDN
050   *          the replication domain baseDN
051   * @return a new ServerState object holding the {serverId => oldest CSN}
052   *         mapping. If a replica DB is empty or closed, the oldest CSN will be
053   *         null for that replica. The caller owns the generated ServerState.
054   */
055  ServerState getDomainOldestCSNs(DN baseDN);
056
057  /**
058   * Returns the newest {@link CSN}s from the replicaDBs for each serverId in
059   * the specified replication domain.
060   *
061   * @param baseDN
062   *          the replication domain baseDN
063   * @return a new ServerState object holding the {serverId => newest CSN} Map.
064   *         If a replica DB is empty or closed, the newest CSN will be null for
065   *         that replica. The caller owns the generated ServerState.
066   */
067  ServerState getDomainNewestCSNs(DN baseDN);
068
069  /**
070   * Removes all the data relating to the specified replication domain and
071   * shutdown all its replica databases. In particular, it will:
072   * <ol>
073   * <li>remove all the changes from the replica databases</li>
074   * <li>remove all knowledge of the serverIds in this domain</li>
075   * <li>remove any knowledge of the current generationId for this domain</li>
076   * </ol>
077   *
078   * @param baseDN
079   *          the replication domain baseDN
080   * @throws ChangelogException
081   *           If a database problem happened
082   */
083  void removeDomain(DN baseDN) throws ChangelogException;
084
085  /**
086   * Generates a {@link DBCursor} across all the domains starting before, at or
087   * after the provided {@link MultiDomainServerState} for each domain,
088   * depending on the provided matching and positioning strategies.
089   * <p>
090   * When the cursor is not used anymore, client code MUST call the
091   * {@link DBCursor#close()} method to free the resources and locks used by the
092   * cursor.
093   *
094   * @param startState
095   *          Starting point for each domain cursor. If any {@link ServerState}
096   *          for a domain is null, then start from the oldest CSN for each
097   *          replicaDBs
098   * @param options The cursor options
099   * @return a non null {@link DBCursor}
100   * @throws ChangelogException
101   *           If a database problem happened
102   * @see #getCursorFrom(DN, ServerState, CursorOptions)
103   */
104  MultiDomainDBCursor getCursorFrom(MultiDomainServerState startState, CursorOptions options) throws ChangelogException;
105
106  /**
107   * Generates a {@link DBCursor} across all the domains starting before, at or
108   * after the provided {@link MultiDomainServerState} for each domain,
109   * excluding a provided set of domain DNs.
110   * <p>
111   * When the cursor is not used anymore, client code MUST call the
112   * {@link DBCursor#close()} method to free the resources and locks used by the
113   * cursor.
114   *
115   * @param startState
116   *          Starting point for each domain cursor. If any {@link ServerState}
117   *          for a domain is null, then start from the oldest CSN for each
118   *          replicaDBs
119   * @param options The cursor options
120   * @param excludedDomainDns
121   *          Every domain appearing in this set is excluded from the cursor
122   * @return a non null {@link DBCursor}
123   * @throws ChangelogException
124   *           If a database problem happened
125   * @see #getCursorFrom(DN, ServerState, CursorOptions)
126   */
127  MultiDomainDBCursor getCursorFrom(MultiDomainServerState startState, CursorOptions options, Set<DN> excludedDomainDns)
128      throws ChangelogException;
129
130  /**
131   * Generates a {@link DBCursor} across all the replicaDBs for the specified
132   * replication domain starting before, at or after the provided
133   * {@link ServerState} for each replicaDB, depending on the provided matching
134   * and positioning strategies.
135   * <p>
136   * When the cursor is not used anymore, client code MUST call the
137   * {@link DBCursor#close()} method to free the resources and locks used by the
138   * cursor.
139   *
140   * @param baseDN
141   *          the replication domain baseDN
142   * @param startState
143   *          Starting point for each ReplicaDB cursor. If any CSN for a
144   *          replicaDB is null, then start from the oldest CSN for this
145   *          replicaDB
146   * @param options The cursor options
147   * @return a non null {@link DBCursor}
148   * @throws ChangelogException
149   *           If a database problem happened
150   * @see #getCursorFrom(DN, int, CSN, CursorOptions)
151   */
152  DBCursor<UpdateMsg> getCursorFrom(DN baseDN, ServerState startState, CursorOptions options) throws ChangelogException;
153
154  /**
155   * Generates a {@link DBCursor} for one replicaDB for the specified
156   * replication domain and serverId starting before, at or after the provided
157   * {@link CSN}, depending on the provided matching and positioning strategies.
158   * <p>
159   * When the cursor is not used anymore, client code MUST call the
160   * {@link DBCursor#close()} method to free the resources and locks used by the
161   * cursor.
162   *
163   * @param baseDN
164   *          the replication domain baseDN of the replicaDB
165   * @param serverId
166   *          the serverId of the replicaDB
167   * @param startCSN
168   *          Starting point for the ReplicaDB cursor. If the CSN is null, then
169   *          start from the oldest CSN for this replicaDB
170   * @param options The cursor options
171   * @return a non null {@link DBCursor}
172   * @throws ChangelogException
173   *           If a database problem happened
174   */
175  DBCursor<UpdateMsg> getCursorFrom(DN baseDN, int serverId, CSN startCSN, CursorOptions options)
176      throws ChangelogException;
177
178  /**
179   * Unregisters the provided cursor from this replication domain.
180   *
181   * @param cursor
182   *          the cursor to unregister.
183   */
184  void unregisterCursor(DBCursor<?> cursor);
185
186  /**
187   * Publishes the provided change to the changelog DB for the specified
188   * serverId and replication domain. After a change has been successfully
189   * published, it becomes available to be returned by the External ChangeLog.
190   *
191   * @param baseDN
192   *          the replication domain baseDN
193   * @param updateMsg
194   *          the update message to publish to the replicaDB
195   * @return true if a db had to be created to publish this message
196   * @throws ChangelogException
197   *           If a database problem happened
198   */
199  boolean publishUpdateMsg(DN baseDN, UpdateMsg updateMsg)
200      throws ChangelogException;
201
202  /**
203   * Let the DB know this replica is alive.
204   * <p>
205   * This method allows the medium consistency point to move forward in case
206   * this replica did not publish new changes.
207   *
208   * @param baseDN
209   *          the replication domain baseDN
210   * @param heartbeatCSN
211   *          The CSN heartbeat sent by this replica (contains the serverId and
212   *          timestamp of the heartbeat)
213   * @throws ChangelogException
214   *            If a database problem happened
215   */
216  void replicaHeartbeat(DN baseDN, CSN heartbeatCSN) throws ChangelogException;
217
218  /**
219   * Let the DB know this replica is going down.
220   * <p>
221   * This method allows to let the medium consistency point move forward while
222   * this replica is offline.
223   * <p>
224   * Note: This method must not be called to let the DB know the replica is not
225   * sending heartbeats anymore, i.e. it must not be used in case of suspected
226   * network partition.
227   *
228   * @param baseDN
229   *          the replication domain baseDN
230   * @param offlineCSN
231   *          The CSN (serverId and timestamp) for the replica's going offline
232   * @throws ChangelogException
233   *           If a database problem happened
234   */
235  void notifyReplicaOffline(DN baseDN, CSN offlineCSN) throws ChangelogException;
236}