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