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-2017 ForgeRock AS. 015 */ 016package org.opends.server.replication.server.changelog.file; 017 018import java.util.Iterator; 019import java.util.Map.Entry; 020import java.util.concurrent.ConcurrentSkipListMap; 021 022import net.jcip.annotations.NotThreadSafe; 023 024import org.opends.server.replication.common.ServerState; 025import org.opends.server.replication.protocol.UpdateMsg; 026import org.opends.server.replication.server.changelog.api.ChangelogException; 027import org.opends.server.replication.server.changelog.api.DBCursor; 028import org.opends.server.replication.server.changelog.api.ReplicationDomainDB; 029import org.forgerock.opendj.ldap.DN; 030 031/** Cursor iterating over all the replication domains known to the changelog DB. */ 032@NotThreadSafe 033public class MultiDomainDBCursor extends CompositeDBCursor<DN> 034{ 035 private final ReplicationDomainDB domainDB; 036 private final ConcurrentSkipListMap<DN, ServerState> newDomains = new ConcurrentSkipListMap<>(); 037 private final CursorOptions options; 038 039 /** 040 * Builds a MultiDomainDBCursor instance. 041 * 042 * @param domainDB 043 * the replication domain management DB 044 * @param options The cursor options 045 */ 046 public MultiDomainDBCursor(final ReplicationDomainDB domainDB, CursorOptions options) 047 { 048 this.domainDB = domainDB; 049 this.options = options; 050 } 051 052 /** 053 * Adds a replication domain for this cursor to iterate over. Added cursors 054 * will be created and iterated over on the next call to {@link #next()}. 055 * 056 * @param baseDN 057 * the replication domain's baseDN 058 * @param startAfterState 059 * the {@link ServerState} after which to start iterating 060 */ 061 public void addDomain(DN baseDN, ServerState startAfterState) 062 { 063 newDomains.put(baseDN, startAfterState != null ? startAfterState : new ServerState()); 064 } 065 066 /** {@inheritDoc} */ 067 @Override 068 protected void incorporateNewCursors() throws ChangelogException 069 { 070 for (Iterator<Entry<DN, ServerState>> iter = newDomains.entrySet().iterator(); 071 iter.hasNext();) 072 { 073 final Entry<DN, ServerState> entry = iter.next(); 074 final DN baseDN = entry.getKey(); 075 final ServerState serverState = entry.getValue(); 076 final DBCursor<UpdateMsg> domainDBCursor = domainDB.getCursorFrom(baseDN, serverState, options); 077 addCursor(domainDBCursor, baseDN); 078 iter.remove(); 079 } 080 } 081 082 /** 083 * Removes a replication domain from this cursor and stops iterating over it. 084 * Removed cursors will be effectively removed on the next call to 085 * {@link #next()}. 086 * 087 * @param baseDN 088 * the replication domain's baseDN 089 */ 090 public void removeDomain(DN baseDN) 091 { 092 removeCursor(baseDN); 093 } 094 095 /** {@inheritDoc} */ 096 @Override 097 public void close() 098 { 099 super.close(); 100 domainDB.unregisterCursor(this); 101 newDomains.clear(); 102 } 103 104}