View Javadoc

1   package org.apache.jcs.auxiliary.remote;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.Serializable;
24  import java.net.UnknownHostException;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.jcs.access.exception.CacheException;
29  import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheAttributes;
30  import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheListener;
31  import org.apache.jcs.engine.behavior.ICacheElement;
32  import org.apache.jcs.engine.behavior.ICacheElementSerialized;
33  import org.apache.jcs.engine.behavior.ICompositeCacheManager;
34  import org.apache.jcs.engine.behavior.IElementSerializer;
35  import org.apache.jcs.engine.control.CompositeCache;
36  import org.apache.jcs.engine.control.CompositeCacheManager;
37  import org.apache.jcs.utils.net.HostNameUtil;
38  import org.apache.jcs.utils.serialization.SerializationConversionUtil;
39  import org.apache.jcs.utils.serialization.StandardSerializer;
40  
41  /** Shared listener base. */
42  public abstract class AbsractRemoteCacheListener
43      implements IRemoteCacheListener, Serializable
44  {
45      /** Don't change */
46      private static final long serialVersionUID = 32442324243243L;
47  
48      /** The logger */
49      private final static Log log = LogFactory.getLog( AbsractRemoteCacheListener.class );
50  
51      /** The cached name of the local host. The remote server gets this for logging purposes. */
52      private static String localHostName = null;
53  
54      /** Has this client been shutdown. */
55      boolean disposed = false;
56  
57      /**
58       * The cache manager used to put items in different regions. This is set lazily and should not
59       * be sent to the remote server.
60       */
61      protected transient ICompositeCacheManager cacheMgr;
62  
63      /** The remote cache configuration object. */
64      protected IRemoteCacheAttributes irca;
65  
66      /** Number of put requests received. For debugging only. */
67      protected int puts = 0;
68  
69      /** Number of remove requests received. For debugging only. */
70      protected int removes = 0;
71  
72      /** This is set by the remote cache server. */
73      protected long listenerId = 0;
74  
75      /** Custom serializer. Standard by default. */
76      private transient IElementSerializer elementSerializer = new StandardSerializer();
77  
78      /**
79       * Only need one since it does work for all regions, just reference by multiple region names.
80       * <p>
81       * The constructor exports this object, making it available to receive incoming calls. The
82       * callback port is anonymous unless a local port value was specified in the configuration.
83       * <p>
84       * @param irca
85       * @param cacheMgr
86       */
87      public AbsractRemoteCacheListener( IRemoteCacheAttributes irca, ICompositeCacheManager cacheMgr )
88      {
89          this.irca = irca;
90          this.cacheMgr = cacheMgr;
91      }
92  
93      /**
94       * Let the remote cache set a listener_id. Since there is only one listener for all the regions
95       * and every region gets registered? the id shouldn't be set if it isn't zero. If it is we
96       * assume that it is a reconnect.
97       * <p>
98       * @param id The new listenerId value
99       * @throws IOException
100      */
101     public void setListenerId( long id )
102         throws IOException
103     {
104         listenerId = id;
105         if ( log.isInfoEnabled() )
106         {
107             log.info( "set listenerId = [" + id + "]" );
108         }
109     }
110 
111     /**
112      * Gets the listenerId attribute of the RemoteCacheListener object. This is stored in the
113      * object. The RemoteCache object contains a reference to the listener and get the id this way.
114      * <p>
115      * @return The listenerId value
116      * @throws IOException
117      */
118     public long getListenerId()
119         throws IOException
120     {
121         if ( log.isDebugEnabled() )
122         {
123             log.debug( "get listenerId = [" + listenerId + "]" );
124         }
125         return listenerId;
126 
127     }
128 
129     /**
130      * Gets the remoteType attribute of the RemoteCacheListener object <p.
131      * @return The remoteType value
132      * @throws IOException
133      */
134     public int getRemoteType()
135         throws IOException
136     {
137         if ( log.isDebugEnabled() )
138         {
139             log.debug( "getRemoteType = [" + irca.getRemoteType() + "]" );
140         }
141         return irca.getRemoteType();
142     }
143 
144     /**
145      * If this is configured to remove on put, then remove the element since it has been updated
146      * elsewhere. cd should be incomplete for faster transmission. We don't want to pass data only
147      * invalidation. The next time it is used the local cache will get the new version from the
148      * remote store.
149      * <p>
150      * If remove on put is not configured, then update the item.
151      * @param cb
152      * @throws IOException
153      */
154     public void handlePut( ICacheElement cb )
155         throws IOException
156     {
157         if ( irca.getRemoveUponRemotePut() )
158         {
159             if ( log.isDebugEnabled() )
160             {
161                 log.debug( "PUTTING ELEMENT FROM REMOTE, (  invalidating ) " );
162             }
163             handleRemove( cb.getCacheName(), cb.getKey() );
164         }
165         else
166         {
167             puts++;
168             if ( log.isDebugEnabled() )
169             {
170                 log.debug( "PUTTING ELEMENT FROM REMOTE, ( updating ) " );
171                 log.debug( "cb = " + cb );
172 
173                 if ( puts % 100 == 0 )
174                 {
175                     log.debug( "puts = " + puts );
176                 }
177             }
178 
179             CompositeCache cache = getCacheManager().getCache( cb.getCacheName() );
180 
181             // Eventually the instance of will not be necessary.
182             if ( cb instanceof ICacheElementSerialized )
183             {
184                 if ( log.isDebugEnabled() )
185                 {
186                     log.debug( "Object needs to be deserialized." );
187                 }
188                 try
189                 {
190                     cb = SerializationConversionUtil.getDeSerializedCacheElement( (ICacheElementSerialized) cb,
191                                                                                   this.elementSerializer );
192                     if ( log.isDebugEnabled() )
193                     {
194                         log.debug( "Deserialized result = " + cb );
195                     }
196                 }
197                 catch ( IOException e )
198                 {
199                     throw e;
200                 }
201                 catch ( ClassNotFoundException e )
202                 {
203                     log.error( "Received a serialized version of a class that we don't know about.", e );
204                 }
205             }
206 
207             cache.localUpdate( cb );
208         }
209     }
210 
211     /**
212      * Calls localRemove on the CompositeCache.
213      * <p>
214      * @param cacheName
215      * @param key
216      * @throws IOException
217      */
218     public void handleRemove( String cacheName, Serializable key )
219         throws IOException
220     {
221         removes++;
222         if ( log.isDebugEnabled() )
223         {
224             if ( removes % 100 == 0 )
225             {
226                 log.debug( "removes = " + removes );
227             }
228 
229             log.debug( "handleRemove> cacheName=" + cacheName + ", key=" + key );
230         }
231 
232         CompositeCache cache = getCacheManager().getCache( cacheName );
233 
234         cache.localRemove( key );
235     }
236 
237     /**
238      * Calls localRemoveAll on the CompositeCache.
239      * <p>
240      * @param cacheName
241      * @throws IOException
242      */
243     public void handleRemoveAll( String cacheName )
244         throws IOException
245     {
246         if ( log.isDebugEnabled() )
247         {
248             log.debug( "handleRemoveAll> cacheName=" + cacheName );
249         }
250 
251         CompositeCache cache = getCacheManager().getCache( cacheName );
252         cache.localRemoveAll();
253     }
254 
255     /**
256      * @param cacheName
257      * @throws IOException
258      */
259     public void handleDispose( String cacheName )
260         throws IOException
261     {
262         if ( log.isDebugEnabled() )
263         {
264             log.debug( "handleDispose> cacheName=" + cacheName );
265         }
266         // TODO consider what to do here, we really don't want to
267         // dispose, we just want to disconnect.
268         // just allow the cache to go into error recovery mode.
269         // getCacheManager().freeCache( cacheName, true );
270     }
271 
272     /**
273      * Gets the cacheManager attribute of the RemoteCacheListener object. This is one of the few
274      * places that force the cache to be a singleton.
275      */
276     protected ICompositeCacheManager getCacheManager()
277     {
278         if ( cacheMgr == null )
279         {
280             try
281             {
282                 cacheMgr = CompositeCacheManager.getInstance();
283 
284                 if ( log.isDebugEnabled() )
285                 {
286                     log.debug( "had to get cacheMgr" );
287                     log.debug( "cacheMgr = " + cacheMgr );
288                 }
289             }
290             catch (CacheException e)
291             {
292                 log.error( "Could not get cacheMgr", e );
293             }
294         }
295         else
296         {
297             if ( log.isDebugEnabled() )
298             {
299                 log.debug( "already got cacheMgr = " + cacheMgr );
300             }
301         }
302 
303         return cacheMgr;
304     }
305 
306     /**
307      * This is for debugging. It allows the remote server to log the address of clients.
308      * <p>
309      * @return String
310      * @throws IOException
311      */
312     public synchronized String getLocalHostAddress()
313         throws IOException
314     {
315         if ( localHostName == null )
316         {
317             try
318             {
319                 localHostName = HostNameUtil.getLocalHostAddress();
320             }
321             catch ( UnknownHostException uhe )
322             {
323                 localHostName = "unknown";
324             }
325         }
326         return localHostName;
327     }
328 
329     /**
330      * For easier debugging.
331      * <p>
332      * @return Basic info on this listener.
333      */
334     @Override
335     public String toString()
336     {
337         StringBuffer buf = new StringBuffer();
338         buf.append( "\n AbstractRemoteCacheListener: " );
339         buf.append( "\n RemoteHost = " + irca.getRemoteHost() );
340         buf.append( "\n RemotePort = " + irca.getRemotePort() );
341         buf.append( "\n ListenerId = " + listenerId );
342         return buf.toString();
343     }
344 }