001
014
015 package com.liferay.portal.cache.ehcache;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019
020 import java.rmi.RemoteException;
021
022 import java.util.ArrayList;
023 import java.util.List;
024 import java.util.Random;
025
026 import net.sf.ehcache.Ehcache;
027 import net.sf.ehcache.distribution.RemoteCacheException;
028 import net.sf.ehcache.distribution.jgroups.JGroupEventMessage;
029 import net.sf.ehcache.distribution.jgroups.JGroupManager;
030
031 import org.jgroups.Address;
032
033
040 public class JGroupsBootstrapCacheLoader
041 extends net.sf.ehcache.distribution.jgroups.JGroupsBootstrapCacheLoader {
042
043 public JGroupsBootstrapCacheLoader(
044 boolean asynchronous, int maximumChunkSize) {
045
046 super(asynchronous, maximumChunkSize);
047 }
048
049 public Object clone() {
050 return new JGroupsBootstrapCacheLoader(
051 asynchronous, maximumChunkSizeBytes);
052 }
053
054 public void doLoad(Ehcache cache) throws RemoteCacheException {
055 List<JGroupManager> cachePeers = acquireCachePeers(cache);
056
057 if ((cachePeers == null) || cachePeers.isEmpty()) {
058 if (_log.isInfoEnabled()) {
059 _log.info(
060 "Empty list of cache peers for cache " + cache.getName() +
061 ". No cache peer to bootstrap from.");
062 }
063
064 return;
065 }
066
067 JGroupManager jGroupManager = cachePeers.get(0);
068
069 Address localAddress = jGroupManager.getBusLocalAddress();
070
071 if (_log.isInfoEnabled()) {
072 _log.info(
073 "(" + cache.getName() + ") local address: " + localAddress);
074 }
075
076 List<Address> addresses = _buildCachePeerAddressList(
077 cache, jGroupManager, localAddress);
078
079 if ((addresses == null) || addresses.isEmpty()) {
080 if (_log.isInfoEnabled()) {
081 _log.info(
082 "This is the first node to start. No cache bootstrap for " +
083 cache.getName() + ".");
084 }
085
086 return;
087 }
088
089 Address address = null;
090 Random random = new Random();
091
092 while (!addresses.isEmpty() &&
093 ((address == null) || (cache.getSize() == 0))) {
094
095 int randomPeerNumber = random.nextInt(addresses.size());
096
097 address = addresses.get(randomPeerNumber);
098
099 addresses.remove(randomPeerNumber);
100
101 JGroupEventMessage event = new JGroupEventMessage(
102 JGroupEventMessage.ASK_FOR_BOOTSTRAP,
103 localAddress, null, cache, cache.getName());
104
105 if (_log.isInfoEnabled()) {
106 _log.info(
107 "Contact " + address + " to boot cache " + cache.getName());
108 }
109
110 List<JGroupEventMessage> events =
111 new ArrayList<JGroupEventMessage>();
112
113 events.add(event);
114
115 try {
116 jGroupManager.send(address, events);
117
118 try {
119 Thread.sleep(3000);
120 }
121 catch (InterruptedException ie) {
122 _log.error(ie, ie);
123 }
124 }
125 catch (RemoteException re) {
126 _log.error(re, re);
127 }
128 }
129
130 if (cache.getSize() == 0) {
131 if (_log.isInfoEnabled()) {
132 _log.info(
133 "Cache failed to bootstrap from its peers " +
134 cache.getName());
135 }
136 }
137 else {
138 if (_log.isInfoEnabled()) {
139 _log.info(
140 "Bootstrap for cache " + cache.getName() + " has loaded " +
141 cache.getSize() + " elements");
142 }
143 }
144 }
145
146 private List<Address> _buildCachePeerAddressList(
147 Ehcache cache, JGroupManager jGroupManager, Address localAddress) {
148
149 List<Address> addresses = new ArrayList<Address>();
150
151 List<Address> members = jGroupManager.getBusMembership();
152
153 for (int i = 0; i < members.size(); i++) {
154 Address member = members.get(i);
155
156 if (_log.isInfoEnabled()) {
157 _log.info(
158 "(" + cache.getName() + ") member " + i + ": " + member +
159 (member.equals(localAddress) ? " ***" : ""));
160 }
161
162 if (!member.equals(localAddress)) {
163 addresses.add(member);
164 }
165 }
166
167 return addresses;
168 }
169
170 private static Log _log = LogFactoryUtil.getLog(
171 JGroupsBootstrapCacheLoader.class);
172
173 }