001: /*
002: Copyright (C) 2003 Know Gate S.L. All rights reserved.
003: C/Oña, 107 1º2 28050 Madrid (Spain)
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions
007: are met:
008:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011:
012: 2. The end-user documentation included with the redistribution,
013: if any, must include the following acknowledgment:
014: "This product includes software parts from hipergate
015: (http://www.hipergate.org/)."
016: Alternately, this acknowledgment may appear in the software itself,
017: if and wherever such third-party acknowledgments normally appear.
018:
019: 3. The name hipergate must not be used to endorse or promote products
020: derived from this software without prior written permission.
021: Products derived from this software may not be called hipergate,
022: nor may hipergate appear in their name, without prior written
023: permission.
024:
025: This library is distributed in the hope that it will be useful,
026: but WITHOUT ANY WARRANTY; without even the implied warranty of
027: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
028:
029: You should have received a copy of hipergate License with this code;
030: if not, visit http://www.hipergate.org or mail to info@hipergate.org
031: */
032:
033: package com.knowgate.cache;
034:
035: import java.rmi.RemoteException;
036:
037: import java.io.ByteArrayOutputStream;
038: import java.io.IOException;
039:
040: import java.util.Date;
041: import java.util.Properties;
042: import java.util.Iterator;
043:
044: import java.net.URL;
045: import java.net.MalformedURLException;
046:
047: import com.knowgate.debug.DebugFile;
048: import com.knowgate.misc.Environment;
049: import com.knowgate.dataobjs.DBSubset;
050:
051: /**
052: * <p>Distributed Cache Local Peer</p>
053: * <p>Each distributed cache peer holds its own local copy of cached data.</p>
054: * <p>On the simplest scenenario there is only one client cache peer witch
055: * stores data localy for faster access and reduce network bandwitch consumption.</p>
056: * <p>As data is kept localy at each peer, when more than one client peer concurrently
057: * access the same data, a cache coordinator becomes necessary.</p>
058: * <p>The cache coordinator is an EJB that must be installed at an application server
059: * such as JBoss or BEA Weblogic. See cache.DistributedCacheCoordinatorBean for more
060: * information about the cache coordinator.</p>
061: * <br>
062: * <p><b>Distributed Cache Tokens and Policies</b></p>
063: * <p>A cache peer is essentially a named set of objects. Each object name is called
064: * a "cache token". Cache Token associate a String (the object name) with the actual cached object.</p>
065: * <p>Token have an usage count and a last usage date, each time a token is requested its usage count
066: * and last usage dates are updated at the cache peer.</p>
067: * <p>The cache peer the applies a customizable Policy for discarding objects as cache becomes full.</p>
068: * <p>Currently only a Least Recently Used Cache Policy is provided.</p>
069: * <p>By default the cache has a maximum of 400 objects slots.</p>
070: * <p>There is no checking of memory consumption for the cache peer, it is the programmer's responsability
071: * not to cache objects that are too large.</p>
072: * <p>It is also the programmer's task to remove tokens from the cache peer when the cached data has been changed.</p>
073: * <p><b>Comunnication between client cache peers and the cache coordinator</b></p>
074: * <p>The cache coordinator is a single object instance that coordinates data cached by multiple cache peers,
075: * at a given time a cache peer may change data that is already cache at another peer. When doing so the last usage date
076: * for the token of cached data will be updated and the cache coordinator will be notified of this last usage change.</p>
077: * <p>Each cache peer holds its own copy of data, and the cache coordinator keeps a record of all
078: * last usage timestamp for every object at every cache peer. In this way, cached data is not be shared among peers,
079: * but it is kept synchronized by discarding all tokens witch timestamp at the peer is older than the one at the cache coordinator.</p>
080: * <p><b>UML</b></p>
081: * <img src="doc-files/DistributedCache-1.gif">
082: * @author Sergio Montoro Ten
083: * @version 1.1
084: * <br>
085: */
086:
087: public final class DistributedCachePeer {
088:
089: private Object oCtx; // javax.naming.Context
090: private Object oDCC; // cache.DistributedCacheCoordinator
091: private Object oHome; // cache.DistributedCacheCoordinatorHome
092:
093: private LRUCachePolicy oCacheStore;
094: private Properties oEnvProps;
095: private int iProviderProtocol;
096:
097: final private int PROTOCOL_NONE = -1;
098: final private int PROTOCOL_UNKNOWN = 0;
099: final private int PROTOCOL_HTTP = 1;
100: final private int PROTOCOL_HTTPS = 2;
101: final private int PROTOCOL_JNP = 3;
102:
103: /**
104: * <p>Create a local cache peer.</p>
105: * <p>The cache peer may be initialized to work in single-peer mode or in
106: * multi-peer mode with a cache coordinator.</p>
107: * <p>Initializacion properties for connecting with the cache coordinator
108: * when working in multi-peer mode are passed in appserver.cnf properties file.
109: * The appserver.cnf file is read using the singleton Environment object at
110: * com.knowgate.misc package.</p>
111: * <p>An example of a configuration file for JBoss may be as follows:</p>
112: * #DistributedCachePeer JBoss configuration file<br><br>
113: * #set this entry to "disabled" is working in single-peer mode<br>
114: * threetiers=enabled<br><br>
115: * java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory<br>
116: * java.naming.provider.url=jnp://127.1.0.0:1099/<br>
117: * java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces<br>
118: * jnp.socketFactory=org.jnp.interfaces.TimedSocketFactory<br>
119: * <p>An example of a configuration file for Tomcat may be as follows:</p>
120: * #DistributedCachePeer Tomcat configuration file<br><br>
121: * #set this entry to "disabled" is working in single-peer mode<br>
122: * threetiers=enabled<br><br>
123: * java.naming.factory.initial=<br>
124: * java.naming.provider.url=http://www.remotehost.com:1099/cache/server.jsp<br>
125: * java.naming.factory.url.pkgs=<br>
126: * jnp.socketFactory=<br>
127: * @throws InstantiationException
128: * @throws RemoteException
129: * @see Environment
130: */
131:
132: public DistributedCachePeer() throws InstantiationException,
133: RemoteException {
134:
135: long lServerTime, lClientTime;
136: String s3Tiers;
137:
138: if (DebugFile.trace) {
139: DebugFile.writeln("Begin DistributedCachePeer()");
140: DebugFile.incIdent();
141: }
142:
143: oCacheStore = new LRUCachePolicy(200, 400);
144:
145: oEnvProps = Environment.getProfile("appserver");
146: s3Tiers = oEnvProps.getProperty("threetiers", "disabled");
147:
148: /* Only test and debugging purposes ****************************************
149:
150: oEnvProps = new Properties();
151: oEnvProps.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
152: oEnvProps.put("java.naming.provider.url", "jnp://server:1099/");
153: oEnvProps.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
154: oEnvProps.put("jnp.socketFactory", "org.jnp.interfaces.TimedSocketFactory");
155:
156: ***************************************************************************/
157:
158: if (DebugFile.trace) {
159: DebugFile.writeln("java.naming.factory.initial="
160: + oEnvProps.getProperty(
161: "java.naming.factory.initial", ""));
162: DebugFile.writeln("java.naming.provider.url="
163: + oEnvProps.getProperty("java.naming.provider.url",
164: ""));
165: DebugFile.writeln("java.naming.factory.url.pkgs="
166: + oEnvProps.getProperty(
167: "java.naming.factory.url.pkgs", ""));
168: DebugFile.writeln("jnp.socketFactory="
169: + oEnvProps.getProperty("jnp.socketFactory", ""));
170: }
171:
172: if (s3Tiers.equalsIgnoreCase("enabled")
173: || s3Tiers.equalsIgnoreCase("yes")
174: || s3Tiers.equalsIgnoreCase("true")
175: || s3Tiers.equalsIgnoreCase("on")
176: || s3Tiers.equals("1")) {
177:
178: String sProviderURL = oEnvProps.getProperty(
179: "java.naming.provider.url", "").toLowerCase();
180:
181: if (sProviderURL.startsWith("http://"))
182: iProviderProtocol = PROTOCOL_HTTP;
183: else if (sProviderURL.startsWith("https://"))
184: iProviderProtocol = PROTOCOL_HTTPS;
185: else if (sProviderURL.startsWith("jnp://"))
186: iProviderProtocol = PROTOCOL_JNP;
187: else
188: iProviderProtocol = PROTOCOL_UNKNOWN;
189:
190: if (PROTOCOL_HTTP != iProviderProtocol
191: && PROTOCOL_HTTPS != iProviderProtocol) {
192:
193: try {
194:
195: if (DebugFile.trace)
196: DebugFile
197: .writeln("Context oCtx = new InitialContext(Properties)");
198:
199: oCtx = new javax.naming.InitialContext(oEnvProps);
200:
201: if (DebugFile.trace)
202: DebugFile
203: .writeln("oHome = (DistributedCacheCoordinatorHome) oCtx.lookup(\"DistributedCacheCoordinator\")");
204:
205: oHome = ((javax.naming.Context) oCtx)
206: .lookup("DistributedCacheCoordinator");
207:
208: if (DebugFile.trace)
209: DebugFile
210: .writeln("DistributedCacheCoordinator = DistributedCacheCoordinatorHome.create()");
211:
212: oDCC = ((com.knowgate.cache.server.DistributedCacheCoordinatorHome) oHome)
213: .create();
214:
215: // Sincronizar la fecha del cliente con la del servidor
216: lServerTime = ((com.knowgate.cache.server.DistributedCacheCoordinator) oDCC)
217: .now();
218:
219: lClientTime = new Date().getTime();
220:
221: if (lClientTime < lServerTime) {
222: lServerTime = ((com.knowgate.cache.server.DistributedCacheCoordinator) oDCC)
223: .now() + 1000;
224: Environment.updateSystemTime(lServerTime);
225: } // fi (lClientTime < lServerTime)
226: } catch (javax.naming.NamingException ne) {
227: throw new java.lang.InstantiationException(
228: "javax.naming.NamingException "
229: + ne.getMessage() + " "
230: + ne.getExplanation());
231: } catch (javax.ejb.CreateException ce) {
232: throw new java.lang.InstantiationException(
233: "javax.ejb.CreateException "
234: + ce.getMessage());
235: }
236: } // fi (iProviderProtocol)
237: else
238: oDCC = null;
239: } // fi (threetiers)
240: else {
241: iProviderProtocol = PROTOCOL_NONE;
242: }
243:
244: if (DebugFile.trace) {
245: DebugFile.decIdent();
246: DebugFile.writeln("End new DistributedCachePeer()");
247: }
248:
249: } // DistributedCachePeer
250:
251: // ----------------------------------------------------------
252:
253: private static String trim(String s) {
254: if (null == s)
255: return null;
256: else
257: return (s.replace('\n', ' ').replace('\r', ' ').replace(
258: '\t', ' ')).trim();
259: }
260:
261: // ----------------------------------------------------------
262:
263: /**
264: * Get an object from the cache peer.
265: * @param sTokenKey Token of object to be retrieved
266: * @return Reference to the requested object or <b>null</b> if object is not present at the local cache or it was modified by another cache peer.
267: * @throws RemoteException
268: */
269:
270: public Object get(String sTokenKey) throws RemoteException,
271: NullPointerException {
272:
273: long lLastMod;
274: long lLastLocal;
275: Object oRetSet = null;
276:
277: if (DebugFile.trace) {
278: DebugFile.writeln("Begin DistributedCachePeer.get("
279: + sTokenKey + ")");
280: DebugFile.incIdent();
281: }
282:
283: if (PROTOCOL_NONE == iProviderProtocol)
284: // Si no existe ningún coordinador de cache distribuido configurado,
285: // tener en cuenta sólo el cache local.
286: oRetSet = oCacheStore.get(sTokenKey);
287: else {
288: // Recuperar la entrada del cache local
289: oRetSet = oCacheStore.get(sTokenKey);
290:
291: if (null != oRetSet) {
292: // Obtener la fecha de última modificación del coordinador de caches
293: if (PROTOCOL_HTTP == iProviderProtocol
294: || PROTOCOL_HTTPS == iProviderProtocol) {
295:
296: String sProviderURL = oEnvProps
297: .getProperty("java.naming.provider.url");
298:
299: if (null == sProviderURL)
300: throw new NullPointerException(
301: "Property java.naming.provider.url not set at appserver.cnf");
302:
303: else {
304: String sLastMod = "";
305:
306: try {
307: if (DebugFile.trace)
308: DebugFile
309: .writeln("new javax.activation.DataHandler(new URL("
310: + sProviderURL
311: + "?method=get&key="
312: + sTokenKey + "))");
313:
314: javax.activation.DataHandler oDataHndlr = new javax.activation.DataHandler(
315: new URL(sProviderURL
316: + "?method=get&key="
317: + sTokenKey));
318:
319: ByteArrayOutputStream oURLBytes = new ByteArrayOutputStream(
320: 128);
321: oDataHndlr.writeTo(oURLBytes);
322: sLastMod = trim(oURLBytes.toString());
323: oURLBytes.close();
324: oURLBytes = null;
325:
326: if (DebugFile.trace)
327: DebugFile.writeln("lLastMod="
328: + sLastMod);
329:
330: lLastMod = Long.parseLong(sLastMod);
331: } catch (MalformedURLException badurl) {
332: if (DebugFile.trace)
333: DebugFile
334: .writeln("MalformedURLException "
335: + sProviderURL
336: + "?method=get&key="
337: + sTokenKey);
338:
339: throw new RemoteException(
340: "MalformedURLException "
341: + sProviderURL
342: + "?method=get&key="
343: + sTokenKey);
344: } catch (IOException badurl) {
345: if (DebugFile.trace)
346: DebugFile.writeln("IOException "
347: + sProviderURL
348: + "?method=get&key="
349: + sTokenKey);
350:
351: throw new RemoteException("IOException "
352: + sProviderURL + "?method=get&key="
353: + sTokenKey);
354: } catch (NumberFormatException nume) {
355: if (DebugFile.trace)
356: DebugFile
357: .writeln("NumberFormatException "
358: + sLastMod);
359:
360: throw new RemoteException(
361: "NumberFormatException " + sLastMod);
362: }
363: }
364: } else {
365: if (DebugFile.trace)
366: DebugFile
367: .writeln("DistributedCacheCoordinator.lastModified("
368: + sTokenKey + ")");
369:
370: lLastMod = ((com.knowgate.cache.server.DistributedCacheCoordinator) oDCC)
371: .lastModified(sTokenKey);
372:
373: if (DebugFile.trace)
374: DebugFile.writeln("lLastMod="
375: + String.valueOf(lLastMod));
376: }
377:
378: lLastLocal = oCacheStore.last(sTokenKey);
379:
380: if (DebugFile.trace) {
381: if (lLastMod == 0)
382: DebugFile.writeln(sTokenKey
383: + " not found at distributed cache");
384: else
385: DebugFile.writeln(sTokenKey + " has timestamp "
386: + new Date(lLastMod).toString()
387: + " at distributed cache");
388:
389: DebugFile.writeln(sTokenKey + " has timestamp "
390: + new Date(lLastLocal).toString()
391: + " at local cache");
392: }
393:
394: if (lLastLocal >= lLastMod) {
395: // Si la fecha local es mayor o igual que la del coordinador, devolver la entrada local
396: if (DebugFile.trace)
397: DebugFile.writeln("cache hit for " + sTokenKey);
398: } else {
399: // Si la fecha local es anterior a la del coordinador, la entrada local ya no es válida
400: if (DebugFile.trace)
401: DebugFile.writeln("cache outdated for "
402: + sTokenKey);
403: oCacheStore.remove(sTokenKey);
404: oRetSet = null;
405: }
406: } // fi(oEntry)
407: else {
408: if (DebugFile.trace)
409: DebugFile.writeln("cache miss for " + sTokenKey);
410: }
411: } // fi(oDCC)
412:
413: if (DebugFile.trace) {
414: DebugFile.decIdent();
415: DebugFile.writeln("End DistributedCachePeer.get()");
416: }
417:
418: return oRetSet;
419: } // getDBSubset
420:
421: // ----------------------------------------------------------
422:
423: /**
424: * @return Same as DistributedCachePeer.get() but cast returned object to a {@link DBSubset}.
425: * @throws ClassCastException
426: */
427: public DBSubset getDBSubset(String sTokenKey)
428: throws RemoteException, ClassCastException {
429: Object oObj = get(sTokenKey);
430:
431: if (null == oObj)
432: return null;
433: else
434: return (DBSubset) get(sTokenKey);
435: } // getDBSubset
436:
437: // ----------------------------------------------------------
438:
439: /**
440: * @param sTokenKey Token of object to be retrieved
441: * @return Same as DistributedCachePeer.get() but cast returned object to a String.
442: * @throws ClassCastException
443: */
444: public String getString(String sTokenKey) throws RemoteException,
445: ClassCastException {
446: Object oObj = get(sTokenKey);
447: if (null == oObj)
448: return null;
449: else
450: return (String) oObj;
451: } // getString
452:
453: // ----------------------------------------------------------
454:
455: /**
456: * @param sTokenKey Token of object to be retrieved
457: * @throws ClassCastException
458: */
459: public Boolean getBoolean(String sTokenKey) throws RemoteException,
460: ClassCastException {
461: Object oObj = get(sTokenKey);
462: if (null == oObj)
463: return null;
464: else
465: return (Boolean) oObj;
466: } // getBoolean
467:
468: // ----------------------------------------------------------
469:
470: /**
471: * Return keys for entries in cache
472: * @return Set of keys (Strings)
473: */
474:
475: public java.util.Set keySet() {
476:
477: return oCacheStore.keySet();
478: }
479:
480: // ----------------------------------------------------------
481:
482: /**
483: * <p>Puts an Object into local cache.</p>
484: * @param sTokenKey Token for object
485: * @param oObj Object to be stored.
486: * @throws RemoteException
487: * @throws IllegalArgumentException If either sTokenKey or oObj is <b>null</b>.
488: * @throws IllegalStateException If object with given token is already present at local cache.
489: */
490: public void put(String sTokenKey, Object oObj)
491: throws IllegalStateException, IllegalArgumentException,
492: RemoteException {
493: long lDtServerModified;
494:
495: if (DebugFile.trace) {
496: DebugFile.writeln("Begin DistributedCachePeer.put("
497: + sTokenKey + ", ...)");
498: DebugFile.incIdent();
499: }
500:
501: if (PROTOCOL_NONE == iProviderProtocol)
502:
503: lDtServerModified = System.currentTimeMillis();
504:
505: else if (PROTOCOL_HTTP == iProviderProtocol
506: || PROTOCOL_HTTPS == iProviderProtocol) {
507:
508: String sProviderURL = oEnvProps
509: .getProperty("java.naming.provider.url");
510:
511: if (null == sProviderURL)
512: throw new NullPointerException(
513: "Property java.naming.provider.url not set at appserver.cnf");
514:
515: else {
516: String sServerMod = "";
517:
518: try {
519: if (DebugFile.trace)
520: DebugFile
521: .writeln("new javax.activation.DataHandler(new URL("
522: + sProviderURL
523: + "?method=put&key="
524: + sTokenKey + "))");
525:
526: javax.activation.DataHandler oDataHndlr = new javax.activation.DataHandler(
527: new URL(sProviderURL + "?method=put&key="
528: + sTokenKey));
529:
530: ByteArrayOutputStream oURLBytes = new ByteArrayOutputStream(
531: 128);
532: oDataHndlr.writeTo(oURLBytes);
533: sServerMod = trim(oURLBytes.toString());
534: oURLBytes.close();
535: oURLBytes = null;
536:
537: if (DebugFile.trace)
538: DebugFile.writeln("lDtServerModified="
539: + sServerMod);
540:
541: lDtServerModified = Long.parseLong(sServerMod);
542: } catch (MalformedURLException badurl) {
543: if (DebugFile.trace)
544: DebugFile.writeln("MalformedURLException "
545: + sProviderURL + "?method=get&put="
546: + sTokenKey);
547:
548: throw new RemoteException("MalformedURLException "
549: + sProviderURL + "?method=put&key="
550: + sTokenKey);
551: } catch (IOException badurl) {
552: if (DebugFile.trace)
553: DebugFile.writeln("IOException " + sProviderURL
554: + "?method=get&put=" + sTokenKey);
555:
556: throw new RemoteException("IOException "
557: + sProviderURL + "?method=get&put="
558: + sTokenKey);
559: } catch (NumberFormatException nume) {
560: if (DebugFile.trace)
561: DebugFile.writeln("NumberFormatException "
562: + sServerMod);
563:
564: throw new RemoteException("NumberFormatException "
565: + sServerMod);
566: }
567: }
568: } else {
569:
570: if (DebugFile.trace)
571: DebugFile.writeln("DistributedCacheCoordinator.modify("
572: + sTokenKey + ")");
573:
574: lDtServerModified = ((com.knowgate.cache.server.DistributedCacheCoordinator) oDCC)
575: .modify(sTokenKey);
576:
577: if (DebugFile.trace)
578: DebugFile.writeln("lDtServerModified="
579: + String.valueOf(lDtServerModified));
580:
581: }
582:
583: if (DebugFile.trace)
584: DebugFile.writeln("LRUCachePolicy.insert(" + sTokenKey
585: + ", [Object], "
586: + String.valueOf(lDtServerModified));
587:
588: oCacheStore.insert(sTokenKey, oObj, lDtServerModified);
589:
590: if (DebugFile.trace) {
591: DebugFile.decIdent();
592: DebugFile.writeln("End DistributedCachePeer.put()");
593: }
594: } // put
595:
596: // ----------------------------------------------------------
597:
598: /**
599: * <p>Puts a DBSubset into local cache.</p>
600: * @param sTokenKey Token for object
601: * @param oObj Object to be stored.
602: * @throws RemoteException
603: * @throws IllegalArgumentException If either sTokenKey or oObj is <b>null</b>.
604: * @throws IllegalStateException If object with given token is already present at local cache.
605: */
606: public void putDBSubset(String sTableName, String sTokenKey,
607: DBSubset oDBSS) throws RemoteException {
608: if (DebugFile.trace) {
609: DebugFile.writeln("Begin DistributedCachePeer.putDBSubset("
610: + sTokenKey + ", ...)");
611: DebugFile.incIdent();
612: }
613:
614: put(sTokenKey, oDBSS);
615:
616: if (DebugFile.trace) {
617: DebugFile.decIdent();
618: DebugFile.writeln("End DistributedCachePeer.putDBSubset()");
619: }
620: } // putDBSubset
621:
622: // ----------------------------------------------------------
623:
624: /**
625: * <b>Removes an Object from the cache and notify other cache peers that
626: * the objects with the given token should no longer be considered valid.</p>
627: * If Object with given token was not present at cache no error is raised.
628: * @param sTokenKey Token of object to be removed from local cache.
629: * @throws RemoteException
630: * @throws IllegalArgumentException If sTkeney is <b>null</b>.
631: * @throws IllegalStateException If local cache is empty.
632: */
633: public void expire(String sTokenKey)
634: throws IllegalArgumentException, RemoteException {
635: if (DebugFile.trace) {
636: DebugFile.writeln("Begin DistributedCachePeer.expire("
637: + sTokenKey + ")");
638: DebugFile.incIdent();
639: }
640: if (PROTOCOL_NONE != iProviderProtocol) {
641:
642: if (PROTOCOL_HTTP == iProviderProtocol
643: || PROTOCOL_HTTPS == iProviderProtocol) {
644:
645: String sProviderURL = oEnvProps
646: .getProperty("java.naming.provider.url");
647:
648: if (null == sProviderURL)
649: throw new NullPointerException(
650: "Property java.naming.provider.url not set at appserver.cnf");
651:
652: else {
653:
654: try {
655:
656: if (DebugFile.trace)
657: DebugFile
658: .writeln("new javax.activation.DataHandler(new URL("
659: + sProviderURL
660: + "?method=expire&key="
661: + sTokenKey + "))");
662:
663: javax.activation.DataHandler oDataHndlr = new javax.activation.DataHandler(
664: new URL(sProviderURL
665: + "?method=expire&key="
666: + sTokenKey));
667:
668: ByteArrayOutputStream oURLBytes = new ByteArrayOutputStream(
669: 128);
670: oDataHndlr.writeTo(oURLBytes);
671: oURLBytes.close();
672: oURLBytes = null;
673:
674: } catch (MalformedURLException badurl) {
675: throw new RemoteException(
676: "MalformedURLException " + sProviderURL
677: + "?method=expire&key="
678: + sTokenKey);
679: } catch (IOException badurl) {
680: throw new RemoteException("IOException "
681: + sProviderURL + "?method=get&key="
682: + sTokenKey);
683: }
684: } // fi (null!=sProviderURL)
685: } else {
686: if (DebugFile.trace)
687: DebugFile
688: .writeln("DistributedCacheCoordinator.expire("
689: + sTokenKey + ")");
690:
691: ((com.knowgate.cache.server.DistributedCacheCoordinator) oDCC)
692: .expire(sTokenKey);
693: }
694: }
695: oCacheStore.remove(sTokenKey);
696:
697: if (DebugFile.trace) {
698: DebugFile.decIdent();
699: DebugFile.writeln("End DistributedCachePeer.expire()");
700: }
701: } // expire
702:
703: // ----------------------------------------------------------
704:
705: /**
706: * <p>Remove all objects from local cache and expire then and cache coordinator.</p>
707: * @throws RemoteException
708: */
709: public void expireAll() throws RemoteException {
710: if (DebugFile.trace) {
711: DebugFile.writeln("Begin DistributedCachePeer.expireAll()");
712: DebugFile.incIdent();
713: }
714: Iterator oKeys;
715:
716: if (PROTOCOL_NONE != iProviderProtocol) {
717:
718: oKeys = oCacheStore.m_map.keySet().iterator();
719:
720: while (oKeys.hasNext())
721: expire((String) oKeys.next());
722:
723: } // fi (oDCC)
724:
725: oCacheStore.flush();
726:
727: if (DebugFile.trace) {
728: DebugFile.decIdent();
729: DebugFile.writeln("End DistributedCachePeer.expireAll()");
730: }
731: } // expireAll
732:
733: // ----------------------------------------------------------
734:
735: /**
736: * <p>Number of entries in cache</p>
737: */
738: public int size() {
739: return oCacheStore.size();
740: }
741: } // DistributedCachePeer
|