001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.server.ldap.replication; 021 022 023 import org.apache.directory.server.i18n.I18n; 024 import org.apache.directory.server.ldap.LdapSession; 025 import org.apache.directory.shared.ldap.codec.controls.replication.syncDoneValue.SyncDoneValueControl; 026 import org.apache.directory.shared.ldap.codec.search.SearchResultDoneCodec; 027 import org.apache.directory.shared.ldap.message.control.Control; 028 import org.apache.directory.shared.ldap.message.internal.InternalSearchResponseDone; 029 import org.apache.directory.shared.ldap.util.StringTools; 030 import org.slf4j.Logger; 031 import org.slf4j.LoggerFactory; 032 033 034 /** 035 * Handle the SearchResultDone response, received from a producer server, when 036 * replication is set. 037 * 038 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 039 * @version $Rev$, $Date$ 040 */ 041 public class SearchResultDoneResponseHandler<T extends InternalSearchResponseDone> 042 { 043 private static final Logger LOG = LoggerFactory.getLogger( SearchResultDoneResponseHandler.class ); 044 045 /** Speedup for logs */ 046 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 047 048 049 public final void handle( LdapSession session, T response ) throws Exception 050 { 051 LOG.debug( "Handling single searchResultDone response: {}", response ); 052 053 SearchResultDoneCodec searchResult = (SearchResultDoneCodec)response; 054 055 // Get the control 056 Control control = searchResult.getCurrentControl(); 057 SyncDoneValueControl syncDoneCtrl = ( SyncDoneValueControl ) control; 058 059 /** the sync cookie sent by the server */ 060 byte[] syncCookie; 061 062 if ( syncDoneCtrl.getCookie() != null ) 063 { 064 syncCookie = syncDoneCtrl.getCookie(); 065 LOG.debug( "assigning cookie from sync done value control: {}", StringTools.utf8ToString( syncCookie ) ); 066 } 067 else 068 { 069 LOG.info( "cookie in syncdone message is null" ); 070 } 071 072 SyncreplConfiguration config = (SyncreplConfiguration)session.getIoSession().getAttribute( "SYNC_COOKIE" ); 073 074 if ( !config.isRefreshPersist() ) 075 { 076 // Now, switch to refreshAndPresist 077 config.setRefreshPersist( true ); 078 LOG.debug( "Swithing to RefreshAndPersist" ); 079 080 try 081 { 082 // the below call is required to send the updated cookie 083 // and refresh mode change (i.e to refreshAndPersist stage) 084 // cause while the startSync() method sleeps even after the 'sync done' 085 // message arrives as part of initial searchRequest with 'refreshOnly' mode. 086 // During this sleep time any 'modifications' happened on the server 087 // to already fetched entries will be sent as SearchResultEntries with 088 // SyncState value as 'ADD' which will conflict with the DNs of initially received entries 089 090 // TODO thinking of alternative ways to implement this in case of large DITs 091 // where the modification to entry(ies) can happen before the initial sync is done 092 //doSyncSearch(); 093 } 094 catch( Exception e ) 095 { 096 LOG.error( I18n.err( I18n.ERR_170 ), e ); 097 } 098 } 099 } 100 }