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