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