001
014
015 package com.liferay.portal.cluster;
016
017 import com.liferay.portal.kernel.cluster.Address;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.util.CharPool;
021 import com.liferay.portal.kernel.util.GetterUtil;
022 import com.liferay.portal.kernel.util.IPDetector;
023 import com.liferay.portal.kernel.util.OSDetector;
024 import com.liferay.portal.kernel.util.SocketUtil;
025 import com.liferay.portal.kernel.util.StringBundler;
026 import com.liferay.portal.kernel.util.Validator;
027 import com.liferay.portal.util.PropsValues;
028
029 import java.io.IOException;
030
031 import java.net.InetAddress;
032 import java.net.NetworkInterface;
033
034 import java.util.ArrayList;
035 import java.util.Collections;
036 import java.util.List;
037 import java.util.Vector;
038
039 import org.jgroups.ChannelException;
040 import org.jgroups.JChannel;
041 import org.jgroups.Receiver;
042 import org.jgroups.View;
043
044
047 public abstract class ClusterBase {
048
049 public void afterPropertiesSet() {
050 if (!isEnabled()) {
051 return;
052 }
053
054 if (!_initialized) {
055 if (OSDetector.isUnix() && IPDetector.isSupportsV6() &&
056 !IPDetector.isPrefersV4() && _log.isWarnEnabled()) {
057
058 StringBundler sb = new StringBundler(4);
059
060 sb.append(
061 "You are on an Unix server with IPv6 enabled. JGroups ");
062 sb.append("may not work with IPv6. If you see a multicast ");
063 sb.append("error, try adding java.net.preferIPv4Stack=true ");
064 sb.append("as a JVM startup parameter.");
065
066 _log.warn(sb.toString());
067 }
068
069 initSystemProperties();
070
071 try {
072 initBindAddress();
073 }
074 catch (IOException ioe) {
075 if (_log.isWarnEnabled()) {
076 _log.warn("Failed to initialize outgoing IP address", ioe);
077 }
078 }
079
080 _initialized = true;
081 }
082
083 try {
084 initChannels();
085 }
086 catch (Exception e) {
087 if (_log.isErrorEnabled()) {
088 _log.error("Unable to initialize channels", e);
089 }
090
091 throw new IllegalStateException(e);
092 }
093 }
094
095 public abstract void destroy();
096
097 public boolean isEnabled() {
098 return PropsValues.CLUSTER_LINK_ENABLED;
099 }
100
101 protected JChannel createJChannel(
102 String properties, Receiver receiver, String clusterName)
103 throws ChannelException {
104
105 JChannel jChannel = new JChannel(properties);
106
107 jChannel.setReceiver(receiver);
108
109 jChannel.connect(clusterName);
110
111 if (_log.isInfoEnabled()) {
112 _log.info(
113 "Create a new channel with properties " +
114 jChannel.getProperties());
115 }
116
117 return jChannel;
118 }
119
120 protected List<Address> getAddresses(JChannel channel) {
121 BaseReceiver baseReceiver = (BaseReceiver)channel.getReceiver();
122
123 View view = baseReceiver.getView();
124
125 Vector<org.jgroups.Address> jGroupsAddresses = view.getMembers();
126
127 if (jGroupsAddresses == null) {
128 return Collections.emptyList();
129 }
130
131 List<Address> addresses = new ArrayList<Address>(
132 jGroupsAddresses.size());
133
134 for (org.jgroups.Address jgroupsAddress : jGroupsAddresses) {
135 addresses.add(new AddressImpl(jgroupsAddress));
136 }
137
138 return addresses;
139 }
140
141 protected void initBindAddress() throws IOException {
142 String autodetectAddress = PropsValues.CLUSTER_LINK_AUTODETECT_ADDRESS;
143
144 if (Validator.isNull(autodetectAddress)) {
145 return;
146 }
147
148 String host = autodetectAddress;
149 int port = 80;
150
151 int index = autodetectAddress.indexOf(CharPool.COLON);
152
153 if (index != -1) {
154 host = autodetectAddress.substring(0, index);
155 port = GetterUtil.getInteger(
156 autodetectAddress.substring(index + 1), port);
157 }
158
159 if (_log.isInfoEnabled()) {
160 _log.info(
161 "Autodetecting JGroups outgoing IP address and interface for " +
162 host + ":" + port);
163 }
164
165 SocketUtil.BindInfo bindInfo = SocketUtil.getBindInfo(host, port);
166
167 bindInetAddress = bindInfo.getInetAddress();
168 NetworkInterface networkInterface = bindInfo.getNetworkInterface();
169
170 System.setProperty(
171 "jgroups.bind_addr", bindInetAddress.getHostAddress());
172 System.setProperty(
173 "jgroups.bind_interface", networkInterface.getName());
174
175 if (_log.isInfoEnabled()) {
176 _log.info(
177 "Setting JGroups outgoing IP address to " +
178 bindInetAddress.getHostAddress() + " and interface to " +
179 networkInterface.getName());
180 }
181 }
182
183 protected abstract void initChannels() throws ChannelException;
184
185 protected void initSystemProperties() {
186 for (String systemProperty :
187 PropsValues.CLUSTER_LINK_CHANNEL_SYSTEM_PROPERTIES) {
188
189 int index = systemProperty.indexOf(CharPool.COLON);
190
191 if (index == -1) {
192 continue;
193 }
194
195 String key = systemProperty.substring(0, index);
196 String value = systemProperty.substring(index + 1);
197
198 System.setProperty(key, value);
199
200 if (_log.isDebugEnabled()) {
201 _log.debug(
202 "Setting system property {key=" + key + ", value=" + value +
203 "}");
204 }
205 }
206 }
207
208 protected static InetAddress bindInetAddress;
209
210 private static Log _log = LogFactoryUtil.getLog(ClusterBase.class);
211
212 private static boolean _initialized;
213
214 }