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
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.replication.server;
028
029 import org.opends.server.replication.common.ChangeNumber;
030 import org.opends.server.replication.protocol.UpdateMessage;
031 import org.opends.server.replication.server.ReplicationDB.ReplServerDBCursor;
032
033 import com.sleepycat.je.DatabaseException;
034
035 /**
036 * This class allows to iterate through the changes received from a given
037 * LDAP Server Identifier.
038 */
039 public class ReplicationIterator
040 {
041 private UpdateMessage currentChange = null;
042 private ReplServerDBCursor cursor = null;
043
044 /**
045 * Creates a new ReplicationIterator.
046 * All created iterator must be released by the caller using the
047 * releaseCursor() method.
048 *
049 * @param id the Identifier of the server on which the iterator applies.
050 * @param db The db where the iterator must be created.
051 * @param changeNumber The ChangeNumber after which the iterator must start.
052 * @throws Exception If there is no other change to push after change
053 * with changeNumber number.
054 * @throws DatabaseException if a database problem happened.
055 */
056 public ReplicationIterator(
057 short id, ReplicationDB db, ChangeNumber changeNumber)
058 throws Exception, DatabaseException
059 {
060 cursor = db.openReadCursor(changeNumber);
061 if (cursor == null)
062 {
063 throw new Exception("no new change");
064 }
065 if (this.next() == false)
066 {
067 cursor.close();
068 cursor = null;
069 throw new Exception("no new change");
070 }
071 }
072
073 /**
074 * Get the UpdateMessage where the iterator is currently set.
075 * @return The UpdateMessage where the iterator is currently set.
076 */
077 public UpdateMessage getChange()
078 {
079 return currentChange;
080 }
081
082 /**
083 * Go to the next change in the ReplicationDB or in the server Queue.
084 * @return false if the iterator is already on the last change before
085 * this call.
086 */
087 public boolean next()
088 {
089 currentChange = cursor.next();
090
091 if (currentChange != null)
092 return true;
093 else
094 {
095 // TODO : should check here if some changes are still in the
096 // dbHandler message queue and not yet saved to the backing database
097 // if yes should get change from there from now on.
098 return false;
099 }
100
101 }
102
103 /**
104 * Release the resources and locks used by this Iterator.
105 * This method must be called when the iterator is no longer used.
106 * Failure to do it could cause DB deadlock.
107 */
108 public void releaseCursor()
109 {
110 synchronized (this)
111 {
112 if (cursor != null)
113 {
114 cursor.close();
115 cursor = null;
116 }
117 }
118 }
119
120 /**
121 * Called by the Gc when the object is garbage collected
122 * Release the cursor in case the iterator was badly used and releaseCursor
123 * was never called.
124 */
125 protected void finalize()
126 {
127 releaseCursor();
128 }
129 }