001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.server.cluster;
031:
032: import com.caucho.config.program.ConfigProgram;
033: import com.caucho.config.program.ContainerProgram;
034: import com.caucho.config.ConfigException;
035: import com.caucho.config.types.Period;
036: import com.caucho.lifecycle.StartLifecycleException;
037: import com.caucho.log.Log;
038: import com.caucho.server.http.HttpProtocol;
039: import com.caucho.server.port.Port;
040: import com.caucho.util.L10N;
041: import com.caucho.vfs.QServerSocket;
042:
043: import javax.management.ObjectName;
044: import java.net.UnknownHostException;
045: import java.util.ArrayList;
046: import java.util.logging.Logger;
047:
048: /**
049: * Defines a member of the cluster, corresponds to <server> in the conf file.
050: *
051: * A {@link ServerConnector} obtained with {@link #getServerConnector} is used to actually
052: * communicate with this ClusterServer when it is active in another instance of
053: * Resin .
054: */
055: public class ClusterServer {
056: private static final Logger log = Log.open(ClusterServer.class);
057: private static final L10N L = new L10N(ClusterServer.class);
058:
059: private static final long DEFAULT = 0xcafebabe;
060:
061: private Cluster _cluster;
062: private Machine _machine;
063: private String _id = "";
064:
065: private int _index;
066:
067: private ClusterPort _clusterPort;
068: private ServerConnector _serverConnector;
069:
070: private long _socketTimeout = 65000L;
071: private long _keepaliveTimeout = 15000L;
072:
073: private long _loadBalanceIdleTime = DEFAULT;
074: private long _loadBalanceRecoverTime = 15000L;
075: private long _loadBalanceSocketTimeout = DEFAULT;
076: private long _loadBalanceWarmupTime = 60000L;
077:
078: private long _loadBalanceConnectTimeout = 5000L;
079:
080: private int _loadBalanceWeight = 100;
081:
082: private ContainerProgram _serverProgram = new ContainerProgram();
083:
084: private ArrayList<Port> _ports = new ArrayList<Port>();
085:
086: public ClusterServer(Cluster cluster) {
087: this (new Machine(cluster));
088: }
089:
090: public ClusterServer(Machine machine) {
091: _machine = machine;
092:
093: _cluster = machine.getCluster();
094:
095: _clusterPort = new ClusterPort(this );
096: _ports.add(_clusterPort);
097:
098: _serverConnector = new ServerConnector(this );
099: }
100:
101: public ClusterServer(Cluster cluster, boolean test) {
102: _cluster = cluster;
103: _clusterPort = new ClusterPort(this );
104: _serverConnector = new ServerConnector(this );
105: }
106:
107: /**
108: * Gets the server identifier.
109: */
110: public String getId() {
111: return _id;
112: }
113:
114: /**
115: * Sets the server identifier.
116: */
117: public void setId(String id) {
118: _id = id;
119: }
120:
121: /**
122: * Returns the cluster.
123: */
124: public Cluster getCluster() {
125: return _cluster;
126: }
127:
128: /**
129: * Returns the machine.
130: */
131: public Machine getMachine() {
132: return _machine;
133: }
134:
135: /**
136: * Returns the server index.
137: */
138: void setIndex(int index) {
139: _index = index;
140: }
141:
142: /**
143: * Returns the server index.
144: */
145: public int getIndex() {
146: return _index;
147: }
148:
149: /**
150: * Sets the keepalive timeout.
151: */
152: public void setKeepaliveTimeout(Period timeout) {
153: _keepaliveTimeout = timeout.getPeriod();
154: }
155:
156: /**
157: * Gets the keepalive timeout.
158: */
159: public long getKeepaliveTimeout() {
160: return _keepaliveTimeout;
161: }
162:
163: /**
164: * Sets the address
165: */
166: public void setAddress(String address) throws UnknownHostException {
167: _clusterPort.setAddress(address);
168: }
169:
170: /**
171: * Sets true for backups
172: */
173: public void setBackup(boolean isBackup) {
174: if (isBackup)
175: setLoadBalanceWeight(1);
176: }
177:
178: /**
179: * Sets the loadBalance connection time.
180: */
181: public void setLoadBalanceConnectTimeout(Period period) {
182: _loadBalanceConnectTimeout = period.getPeriod();
183: }
184:
185: /**
186: * Gets the loadBalance connection time.
187: */
188: public long getLoadBalanceConnectTimeout() {
189: return _loadBalanceConnectTimeout;
190: }
191:
192: /**
193: * Sets the loadBalance socket time.
194: */
195: public void setLoadBalanceSocketTimeout(Period period) {
196: _loadBalanceSocketTimeout = period.getPeriod();
197: }
198:
199: /**
200: * Gets the loadBalance socket time.
201: */
202: public long getLoadBalanceSocketTimeout() {
203: if (_loadBalanceSocketTimeout != DEFAULT)
204: return _loadBalanceSocketTimeout;
205: else
206: return _socketTimeout;
207: }
208:
209: /**
210: * Sets the loadBalance max-idle-time.
211: */
212: public void setLoadBalanceIdleTime(Period period) {
213: _loadBalanceIdleTime = period.getPeriod();
214: }
215:
216: /**
217: * Sets the loadBalance idle-time.
218: */
219: public long getLoadBalanceIdleTime() {
220: if (_loadBalanceIdleTime != DEFAULT)
221: return _loadBalanceIdleTime;
222: else if (_keepaliveTimeout < 10000L)
223: return _keepaliveTimeout - 2000L;
224: else
225: return _keepaliveTimeout - 5000L;
226: }
227:
228: /**
229: * Sets the loadBalance fail-recover-time.
230: */
231: public void setLoadBalanceRecoverTime(Period period) {
232: _loadBalanceRecoverTime = period.getPeriod();
233: }
234:
235: /**
236: * Gets the loadBalance fail-recover-time.
237: */
238: public long getLoadBalanceRecoverTime() {
239: return _loadBalanceRecoverTime;
240: }
241:
242: /**
243: * Sets the loadBalance read/write timeout
244: */
245: public void setSocketTimeout(Period period) {
246: _socketTimeout = period.getPeriod();
247: }
248:
249: /**
250: * Gets the loadBalance read/write timeout
251: */
252: public long getSocketTimeout() {
253: return _socketTimeout;
254: }
255:
256: /**
257: * Sets the loadBalance warmup time
258: */
259: public void setLoadBalanceWarmupTime(Period period) {
260: _loadBalanceWarmupTime = period.getPeriod();
261: }
262:
263: /**
264: * Gets the loadBalance warmup time
265: */
266: public long getLoadBalanceWarmupTime() {
267: return _loadBalanceWarmupTime;
268: }
269:
270: /**
271: * Sets the loadBalance weight
272: */
273: public void setLoadBalanceWeight(int weight) {
274: _loadBalanceWeight = weight;
275: }
276:
277: /**
278: * Gets the loadBalance weight
279: */
280: public int getLoadBalanceWeight() {
281: return _loadBalanceWeight;
282: }
283:
284: /**
285: * Arguments on boot
286: */
287: public void addJavaExe(String args) {
288: }
289:
290: /**
291: * Arguments on boot
292: */
293: public void addJvmArg(String args) {
294: }
295:
296: /**
297: * Arguments on boot
298: */
299: public void addWatchdogArg(String args) {
300: }
301:
302: /**
303: * Arguments on boot
304: */
305: public void addWatchdogJvmArg(String args) {
306: }
307:
308: /**
309: * Arguments on boot
310: */
311: public void addWatchdogPassword(String args) {
312: }
313:
314: /**
315: * Arguments on boot
316: */
317: public void addWatchdogPort(int port) {
318: }
319:
320: /**
321: * Sets a port.
322: */
323: public void setPort(int port) {
324: _clusterPort.setPort(port);
325: }
326:
327: /**
328: * Gets the port.
329: */
330: public int getPort() {
331: return _clusterPort.getPort();
332: }
333:
334: /**
335: * Adds a http.
336: */
337: public Port createHttp() throws ConfigException {
338: Port port = new Port(this );
339:
340: HttpProtocol protocol = new HttpProtocol();
341: protocol.setParent(port);
342: port.setProtocol(protocol);
343:
344: addProtocolPort(port);
345:
346: return port;
347: }
348:
349: /**
350: * Adds a custom-protocol port.
351: */
352: public Port createProtocol() throws ConfigException {
353: Port port = new Port(this );
354:
355: _ports.add(port);
356:
357: return port;
358: }
359:
360: void addProtocolPort(Port port) {
361: _ports.add(port);
362: }
363:
364: /**
365: * Pre-binding of ports.
366: */
367: public void bind(String address, int port, QServerSocket ss)
368: throws Exception {
369: if ("null".equals(address))
370: address = null;
371:
372: for (int i = 0; i < _ports.size(); i++) {
373: Port serverPort = _ports.get(i);
374:
375: if (port != serverPort.getPort())
376: continue;
377:
378: if ((address == null) != (serverPort.getAddress() == null))
379: continue;
380: else if (address == null
381: || address.equals(serverPort.getAddress())) {
382: serverPort.bind(ss);
383:
384: return;
385: }
386: }
387:
388: throw new IllegalStateException(L.l(
389: "No matching port for {0}:{1}", address, port));
390: }
391:
392: /**
393: * Sets the user name.
394: */
395: public void setUserName(String userName) {
396: }
397:
398: /**
399: * Sets the group name.
400: */
401: public void setGroupName(String groupName) {
402: }
403:
404: /**
405: * Returns the ports.
406: */
407: public ArrayList<Port> getPorts() {
408: return _ports;
409: }
410:
411: /**
412: * Sets the ClusterPort.
413: */
414: public ClusterPort createClusterPort() {
415: return _clusterPort;
416: }
417:
418: /**
419: * Sets the ClusterPort.
420: */
421: public ClusterPort getClusterPort() {
422: return _clusterPort;
423: }
424:
425: /**
426: * Returns true for secure.
427: */
428: public boolean isSSL() {
429: return getClusterPort().isSSL();
430: }
431:
432: /**
433: * Returns the server connector.
434: */
435: public ServerConnector getServerConnector() {
436: if (_cluster.getSelfServer() != this )
437: return _serverConnector;
438: else
439: return null;
440: }
441:
442: /**
443: * Adds a program.
444: */
445: public void addBuilderProgram(ConfigProgram program) {
446: _serverProgram.addProgram(program);
447: }
448:
449: /**
450: * Adds a program.
451: */
452: public ConfigProgram getServerProgram() {
453: return _serverProgram;
454: }
455:
456: /**
457: * Initialize
458: */
459: public void init() throws Exception {
460: _clusterPort.init();
461:
462: if (_cluster != null) {
463: _serverConnector.init();
464: _serverConnector.register();
465: }
466: }
467:
468: /**
469: * Starts the server.
470: */
471: public Server startServer() throws StartLifecycleException {
472: return _cluster.startServer(this );
473: }
474:
475: /**
476: * Generate the primary, secondary, tertiary, returning the value encoded
477: * in a long.
478: */
479: public long generateBackupCode() {
480: return _cluster.generateBackupCode(_index);
481: }
482:
483: /**
484: * Adds the primary/backup/third digits to the id.
485: */
486: public void generateBackupCode(StringBuilder cb) {
487: _cluster.generateBackupCode(cb, generateBackupCode());
488: }
489:
490: /**
491: * Close any ports.
492: */
493: public void close() {
494: if (_serverConnector != null)
495: _serverConnector.close();
496: }
497:
498: @Override
499: public String toString() {
500: return getClass().getSimpleName() + "[id=" + getId() + "]";
501: }
502: }
|