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 }