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 *      Copyright 2014-2015 ForgeRock AS
024 */
025package org.opends.server.replication.server.changelog.file;
026
027import org.opends.server.replication.protocol.UpdateMsg;
028import org.opends.server.replication.server.changelog.api.ChangelogException;
029import org.opends.server.replication.server.changelog.api.DBCursor;
030import org.opends.server.types.DN;
031
032import java.util.ArrayList;
033import java.util.List;
034
035/**
036 * Multi domain DB cursor that only returns updates for the domains which have
037 * been enabled for the external changelog.
038 */
039public final class ECLMultiDomainDBCursor implements DBCursor<UpdateMsg>
040{
041  private final ECLEnabledDomainPredicate predicate;
042  private final MultiDomainDBCursor cursor;
043  private final List<DN> eclDisabledDomains = new ArrayList<>();
044
045  /**
046   * Builds an instance of this class filtering updates from the provided cursor.
047   *
048   * @param predicate
049   *          tells whether a domain is enabled for the external changelog
050   * @param cursor
051   *          the cursor whose updates will be filtered
052   */
053  public ECLMultiDomainDBCursor(ECLEnabledDomainPredicate predicate, MultiDomainDBCursor cursor)
054  {
055    this.predicate = predicate;
056    this.cursor = cursor;
057  }
058
059  /** {@inheritDoc} */
060  @Override
061  public UpdateMsg getRecord()
062  {
063    return cursor.getRecord();
064  }
065
066  /**
067   * Returns the data associated to the cursor that returned the current record.
068   *
069   * @return the data associated to the cursor that returned the current record.
070   */
071  public DN getData()
072  {
073    return cursor.getData();
074  }
075
076  /**
077   * Removes a replication domain from this cursor and stops iterating over it.
078   * Removed cursors will be effectively removed on the next call to
079   * {@link #next()}.
080   *
081   * @param baseDN
082   *          the replication domain's baseDN
083   */
084  public void removeDomain(DN baseDN)
085  {
086    cursor.removeDomain(baseDN);
087  }
088
089  /**
090   * Returns whether the cursor should be reinitialized because a domain became re-enabled.
091   *
092   * @return whether the cursor should be reinitialized
093   */
094  public boolean shouldReInitialize()
095  {
096    for (DN domainDN : eclDisabledDomains)
097    {
098      if (predicate.isECLEnabledDomain(domainDN))
099      {
100        eclDisabledDomains.clear();
101        return true;
102      }
103    }
104    return false;
105  }
106
107  @Override
108  public boolean next() throws ChangelogException
109  {
110    if (!cursor.next())
111    {
112      return false;
113    }
114    // discard updates from non ECL enabled domains by removing the disabled domains from the cursor
115    DN domain = cursor.getData();
116    while (domain != null && !predicate.isECLEnabledDomain(domain))
117    {
118      cursor.removeDomain(domain);
119      eclDisabledDomains.add(domain);
120      domain = cursor.getData();
121    }
122    return domain != null;
123  }
124
125  @Override
126  public void close()
127  {
128    cursor.close();
129  }
130
131  @Override
132  public String toString()
133  {
134    return getClass().getSimpleName() + " cursor=[" + cursor + ']';
135  }
136}