Author: echatellier Date: 2010-06-02 11:46:04 +0200 (Wed, 02 Jun 2010) New Revision: 77 Url: http://nuiton.org/repositories/revision/wikitty/77 Log: Add properties parameters on cached service. Add jgroups synchronization. Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java Modified: trunk/wikitty-api/pom.xml trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyCache.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceCached.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceImpl.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyUtil.java Modified: trunk/wikitty-api/pom.xml =================================================================== --- trunk/wikitty-api/pom.xml 2010-06-01 16:01:43 UTC (rev 76) +++ trunk/wikitty-api/pom.xml 2010-06-02 09:46:04 UTC (rev 77) @@ -97,6 +97,14 @@ <version>1.1</version> </dependency> + <!-- Cache --> + <dependency> + <groupId>jgroups</groupId> + <artifactId>jgroups</artifactId> + <version>2.9.0.GA</version> + <scope>compile</scope> + </dependency> + </dependencies> <!-- ************************************************************* --> Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java (rev 0) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java 2010-06-02 09:46:04 UTC (rev 77) @@ -0,0 +1,255 @@ +/* *##% + * Copyright (C) 2010 Code Lutin, Chatellier Eric + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.nuiton.wikitty; + +import java.io.Serializable; + +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter.DEFAULT; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jgroups.Channel; +import org.jgroups.ChannelClosedException; +import org.jgroups.ChannelException; +import org.jgroups.ChannelNotConnectedException; +import org.jgroups.JChannel; +import org.jgroups.Message; +import org.jgroups.ReceiverAdapter; +import org.nuiton.wikitty.WikittyCache.WikittyCacheListener; + +/** + * JGroups notifier. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class JGroupsCacheNotifier extends ReceiverAdapter implements WikittyCacheListener { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(JGroupsCacheNotifier.class); + + /** Cache reference. */ + protected WikittyCache cache; + + /** Message type (put, remove, clear...). */ + static enum WikittyJGroupType { + PUT_WIKITTY, + REMOVE_WIKITTY, + CLEAR_WIKITTY, + PUT_EXTENSION, + REMOVE_EXTENSION, + CLEAR_EXTENSION + } + + static class WikittyJGroupMessage implements Serializable { + /** serialVersionUID. */ + private static final long serialVersionUID = 1914969328584238081L; + + public WikittyJGroupType type; + public String wikittyId; + public String wikittyVersion; + + private WikittyJGroupMessage(WikittyJGroupType type, String wikittyId, String wikittyVersion) { + this.type = type; + this.wikittyId = wikittyId; + this.wikittyVersion = wikittyVersion; + } + + public String toString() { + String toString = type + " " + wikittyId + "[" + wikittyVersion + "]"; + return toString; + } + } + + /** + * Indique si les objects sont propages (true) vers les autres caches ou + * simplement supprimes des autres caches (false). + * + * @see WikittyServiceCached#WIKITTY_PROPAGATE_CACHE_OPTION + */ + protected boolean propagateCache = false; + + /** JGroup channel. */ + protected JChannel channel; + + public JGroupsCacheNotifier(WikittyCache cache, boolean propagateCache) { + this.cache = cache; + this.propagateCache = propagateCache; + initChannel(); + } + + /** + * Init jgroup channel. + */ + protected void initChannel() { + if (log.isDebugEnabled()) { + log.debug("Init jgroup communication channel..."); + } + + try { + // use default udp.xml in classpath + channel = new JChannel(); + channel.connect("wikitty"); + channel.setReceiver(this); + + // don't receive messages sent by myself + channel.setOpt(Channel.LOCAL, false); + + if (log.isDebugEnabled()) { + log.debug("JGroup communication channel initialized to " + channel.getAddressAsString()); + } + } + catch (ChannelException eee) { + if (log.isErrorEnabled()) { + log.error("Can't init jgroup channel"); + } + } + } + + /** + * Send a jgroup message to all other channel member. + * + * @param wikittyMessage message to send + */ + protected void sendJGroupMessage(WikittyJGroupMessage wikittyMessage) { + if (log.isInfoEnabled()) { + log.info("Send message : " + wikittyMessage); + } + Message msg = new Message(null, null, wikittyMessage); + try { + channel.send(msg); + } catch (ChannelNotConnectedException eee) { + if (log.isErrorEnabled()) { + log.error("Can't send jgroup message", eee); + } + } catch (ChannelClosedException eee) { + if (log.isErrorEnabled()) { + log.error("Can't send jgroup message", eee); + } + } + } + + /* + * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#putWikitty(org.nuiton.wikitty.Wikitty[]) + */ + @Override + public void putWikitty(Wikitty... ws) { + if (propagateCache) { + // TODO EC20100602 maybe send only one message for all wikitties + for (Wikitty wikitty : ws) { + WikittyJGroupMessage wikittyMessage = new WikittyJGroupMessage( + WikittyJGroupType.PUT_WIKITTY, wikitty.getId(), wikitty.getVersion()); + sendJGroupMessage(wikittyMessage); + } + } + } + + /* + * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#removeWikitty(java.lang.String[]) + */ + @Override + public void removeWikitty(String... ids) { + if (propagateCache) { + // TODO EC20100602 maybe send only one message for all wikitties + for (String id : ids) { + WikittyJGroupMessage wikittyMessage = new WikittyJGroupMessage( + WikittyJGroupType.REMOVE_WIKITTY, id, null); + sendJGroupMessage(wikittyMessage); + } + } + } + + /* + * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#clearWikitty() + */ + @Override + public void clearWikitty() { + if (propagateCache) { + WikittyJGroupMessage wikittyMessage = new WikittyJGroupMessage( + WikittyJGroupType.CLEAR_WIKITTY, null, null); + sendJGroupMessage(wikittyMessage); + } + } + + /* + * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#putExtension(org.nuiton.wikitty.WikittyExtension[]) + */ + @Override + public void putExtension(WikittyExtension... es) { + + } + + /* + * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#removeExtension(java.lang.String[]) + */ + @Override + public void removeExtension(String... ids) { + + } + + /* + * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#clearExtension() + */ + @Override + public void clearExtension() { + + } + + /* + * @see org.jgroups.ReceiverAdapter#receive(org.jgroups.Message) + */ + @Override + public void receive(Message msg) { + + Object message = msg.getObject(); + + if (log.isInfoEnabled()) { + log.info("Receive message : " + msg.getObject()); + } + + if (message instanceof WikittyJGroupMessage) { + WikittyJGroupMessage wikittyMessage = (WikittyJGroupMessage)message; + + switch(wikittyMessage.type) { + case PUT_WIKITTY: + // put on server, remove it from local cache + Wikitty currentWikitty = cache.getWikitty(wikittyMessage.wikittyId); + if (currentWikitty != null + && WikittyUtil.versionGreaterThan(wikittyMessage.wikittyVersion, currentWikitty.getVersion())) { + cache.removeWikitty(wikittyMessage.wikittyId); + } + + break; + case REMOVE_WIKITTY: + cache.removeWikitty(wikittyMessage.wikittyId); + break; + case CLEAR_WIKITTY: + cache.clearWikitty(); + break; + default: + if (log.isDebugEnabled()) { + log.debug("Not managed jgroup message " + wikittyMessage.type); + } + } + } + } +} Property changes on: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyCache.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyCache.java 2010-06-01 16:01:43 UTC (rev 76) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyCache.java 2010-06-02 09:46:04 UTC (rev 77) @@ -20,10 +20,12 @@ import java.util.Collection; import java.util.HashSet; import java.util.Map; +import java.util.Properties; import java.util.Set; + +import org.apache.commons.collections.map.ReferenceMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.commons.collections.map.ReferenceMap; /** * Cette classe sert a introduire du cache dans wikitty. Elle sert a centraliser @@ -55,23 +57,34 @@ /** * indique si les objects sont propages (true) vers les autres caches ou - * simplement supprimes des autres caches (false) + * simplement supprimes des autres caches (false). + * + * @see WikittyServiceCached#WIKITTY_PROPAGATE_CACHE_OPTION */ - // TODO poussin 20100520 rendre configurable cette variable propagateCache protected boolean propagateCache = false; + protected Map<String, Wikitty> wikittyCache; + protected Set<WikittyCacheListener> listeners; - protected WikittyCache() { - wikittyCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT); + protected WikittyCache(Properties props) { + + // get propagate cache property + String propagateCacheOption = props.getProperty(WikittyServiceCached.WIKITTY_PROPAGATE_CACHE_OPTION, "false"); + propagateCache = "true".equalsIgnoreCase(propagateCacheOption); + if (log.isDebugEnabled()) { + log.debug("Set propagateCache option to " + propagateCache); + } + + wikittyCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT); listeners = new HashSet<WikittyCacheListener>(); - // FIXME poussin 20100520 add jgroups listener to send message to other cache - // addListener(new JGroupsCacheNotifier(propagateCache)); + addListener(new JGroupsCacheNotifier(this, propagateCache)); + } - public static synchronized WikittyCache getInstance() { + public static synchronized WikittyCache getInstance(Properties props) { if (instance == null) { - instance = new WikittyCache(); + instance = new WikittyCache(props); } return instance; } @@ -183,7 +196,4 @@ public void removeListener(WikittyCacheListener l) { listeners.remove(l); } - - - } Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceCached.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceCached.java 2010-06-01 16:01:43 UTC (rev 76) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceCached.java 2010-06-02 09:46:04 UTC (rev 77) @@ -24,7 +24,9 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Properties; import java.util.Set; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -42,14 +44,25 @@ /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(WikittyServiceCached.class); - WikittyCache cache = null; - WikittyService ws; + /** + * Indique si les objects sont propages (true) vers les autres caches ou + * simplement supprimes des autres caches (false). Default to {@code false}. + */ + static public final String WIKITTY_PROPAGATE_CACHE_OPTION = "wikitty.service.cache.propagateCache"; - public WikittyServiceCached(WikittyService ws) { - cache = WikittyCache.getInstance(); + protected WikittyCache cache = null; + + protected WikittyService ws; + + public WikittyServiceCached(WikittyService ws, Properties props) { + cache = WikittyCache.getInstance(props); this.ws = ws; } + public WikittyServiceCached(WikittyService ws) { + this(ws, new Properties()); + } + @Override public void clear() { ws.clear(); Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceImpl.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceImpl.java 2010-06-01 16:01:43 UTC (rev 76) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceImpl.java 2010-06-02 09:46:04 UTC (rev 77) @@ -17,7 +17,6 @@ package org.nuiton.wikitty; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyUtil.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyUtil.java 2010-06-01 16:01:43 UTC (rev 76) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyUtil.java 2010-06-02 09:46:04 UTC (rev 77) @@ -20,11 +20,9 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.math.BigDecimal; -import java.text.CharacterIterator; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.text.StringCharacterIterator; import java.util.Arrays; import java.util.Collection; import java.util.Collections;