From b6b4ffda44ae8fbda08fe5324f9914ea514de8d1 Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Tue, 13 Oct 2009 13:39:08 +0000 Subject: [PATCH] Merged V3.2 to HEAD 15590: Merged V3.1 to V3.2 (JGroups) 15110: Upgraded JGroups (potential fix for ETHREEOH-1497: JGroups UDP stack is not working) 15141: Close existing Channel before starting a new one 15142: Reduced pings' num_initial_members to 2 15143: More succint logging to make DEBUG more useful 15144: Fixed JGroups jar path in classpath 15150: Fixed SDK classpath 15174: JGroups default configuration changes: FD_SIMPLE 15205: Minor JGroups-EHCache tweaks (Real dummy channel, etc) 15592: Merged V3.1 to V3.2 15591: Use Channel.connect without state transfer 15747: (record only) Added beta warning in footer 15786: (record ony) Merge 3.1 to 3.2: 15861: Merged V3.1 to V3.2 15858: (record-only) Fix for ETHREEOH-2698: CLONE -Enterprise 3.x / Searching with Speech Marks ("") for a User ID causes an Error 15881: (record only) ALFCOM-3300: Document move when already exists makes alfresco enter an infinite loop 15889: Cleanup of old static declarations 15890: (record only) Undid accidental offshort commit 15951: (record only) Removed mobile.war from war bundles. Added oracle & mssql config. 15968: (record only) Updated readme 16241: (record only) Fix typos in installer ___________________________________________________________________ Modified: svn:mergeinfo Reverse-merged /alfresco/BRANCHES/V3.2:r15888 Merged /alfresco/BRANCHES/V3.1:r15110,15141-15144,15150,15174,15205,15591,15779,15858 Merged /alfresco/BRANCHES/V3.2:r15590,15592,15747,15780,15786,15861,15881,15889-15890,15951,15968,16241 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16866 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/bootstrap-context.xml | 7 +- config/alfresco/jgroups-default.xml | 116 - config/alfresco/jgroups/JGroups-2.8.xsd | 2000 +++++++++++++++++ .../alfresco/jgroups/alfresco-jgroups-TCP.xml | 64 + .../alfresco/jgroups/alfresco-jgroups-UDP.xml | 67 + config/alfresco/repository.properties | 12 +- .../AlfrescoJGroupsChannelFactory.java | 423 ++-- .../AlfrescoJGroupsChannelFactoryTest.java | 3 + 8 files changed, 2369 insertions(+), 323 deletions(-) delete mode 100644 config/alfresco/jgroups-default.xml create mode 100644 config/alfresco/jgroups/JGroups-2.8.xsd create mode 100644 config/alfresco/jgroups/alfresco-jgroups-TCP.xml create mode 100644 config/alfresco/jgroups/alfresco-jgroups-UDP.xml diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index e6cd3c8720..261a80f8dc 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -127,16 +127,13 @@ ${alfresco.cluster.name} - + - ${alfresco.jgroups.defaultProtocol} + ${alfresco.jgroups.configLocation} - - ${alfresco.jgroups.configLocation} - diff --git a/config/alfresco/jgroups-default.xml b/config/alfresco/jgroups-default.xml deleted file mode 100644 index 4ea0e87e69..0000000000 --- a/config/alfresco/jgroups-default.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config/alfresco/jgroups/JGroups-2.8.xsd b/config/alfresco/jgroups/JGroups-2.8.xsd new file mode 100644 index 0000000000..82585ccb74 --- /dev/null +++ b/config/alfresco/jgroups/JGroups-2.8.xsd @@ -0,0 +1,2000 @@ + + + + + + + + + +The NIC on which the ServerSocket should listen on + + + + +Timeout for getting socket cache from coordinator. Default is 1000 msec + + + + +Interval for broadcasting suspect messages. Default is 5000 msec + + + + +Number of attempts coordinator is solicited for socket cache until we give up. Default is 3 + + + + +Start port for server socket. Default value of 0 picks a random port + + + + +Whether to use KEEP_ALIVE on the ping socket or not. Default is true + + + + +Max time in millis to wait for ping Socket.connect() to return + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Number of ports to be probed for initial membership. Default is 1 + + + + +Comma delimeted list of hosts to be contacted for initial membership + + + + +Timeout to wait for the initial members. Default is 3000 msec + + + + +Minimum number of initial members to get a response from. Default is 2 + + + + +Minimum number of server responses (PingData.isServer()=true). If this value is greater than 0, we'll ignore num_initial_members + + + + +Return from the discovery phase as soon as we have 1 coordinator response + + + + +Number of discovery requests to be sent distributed over timeout. Default is 2 + + + + +Whether or not to return the entire logical-physical address cache mappings on a discovery request, or not. Default is false, except for TCPPING + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +The interface (NIC) which should be used by this transport + + + + +Ignores all bind address parameters and let's the OS return the local host address. Default is false + + + + + If true, the transport should use all available interfaces to receive multicast messages. Default is false + + + + +Comma delimited list of interfaces (IP addresses or interface names) to receive multicasts on + + + + +The port to which the transport binds. Default of 0 binds to any (ephemeral) port + + + + + + + + + +tries to make sure ephemeral ports are used + + + + +Messages to self are looped back immediately if true. Default is false + + + + +Discard packets with a different version if true. Default is false + + + + +Thread naming pattern for threads in this channel. Default is cl + + + + +Switch for enabling thread pool for OOB messages. Default true + + + + +Minimum thread pool size for OOB messages. Default is 2 + + + + +Maximum thread pool size for OOB messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from OOB pool. Default is 30000 + + + + +Use queue to enqueue incoming OOB messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run. Default is Run + + + + +Minimum thread pool size for regular messages. Default is 2 + + + + +Maximum thread pool size for regular messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from regular pool. Default is 30000 + + + + +Switch for enabling thread pool for regular messages. Default true + + + + +Use queue to enqueue incoming regular messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run Default is Run + + + + +Number of threads to be used by the timer thread pool. Default is 4 + + + + +Enable bundling of smaller messages into bigger ones. Default is true + + + + +Enable bundling of smaller messages into bigger ones for unicast messages. Default is false + + + + +Switch to enable diagnostic probing. Default is true + + + + +Address for diagnostic probing. Default is 224.0.75.75 + + + + +Port for diagnostic probing. Default is 7500 + + + + +If assigned enable this transport to be a singleton (shared) transport + + + + +Path to a file to store currently used ports on this machine + + + + +Timeout to expire ports used with PortManager. Default is 30000 msec + + + + +Switch to enable tracking of currently used ports on this machine. Default is false + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + + + +Max time barrier can be closed. Default is 60000 msec + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Interval in which a HEARTBEAT is sent to the cluster. Default is 3000 msec + + + + +Timeout after which a node P is suspected if neither a heartbeat nor data were received from P. Default is 5000 msec + + + + +Treat messages received from members as heartbeats. Note that this means we're updating a value in a hashmap every time a message is passing up the stack through FD_ALL, which is costly. Default is false + + + + +Shun switch. Default is true + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Rate of continious refresh registering of underlying gossip client with gossip server. Default is 20000 msec + + + + +Max time for socket creation. Default is 1000 msec + + + + +Max time in milliseconds to block on a read. 0 blocks forever + + + + +Timeout to wait for the initial members. Default is 3000 msec + + + + +Minimum number of initial members to get a response from. Default is 2 + + + + +Minimum number of server responses (PingData.isServer()=true). If this value is greater than 0, we'll ignore num_initial_members + + + + +Return from the discovery phase as soon as we have 1 coordinator response + + + + +Number of discovery requests to be sent distributed over timeout. Default is 2 + + + + +Whether or not to return the entire logical-physical address cache mappings on a discovery request, or not. Default is false, except for TCPPING + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + + +Whether to loop back messages sent to self. Default is false + + + + +Max number of milliseconds we try to retransmit a message to any given member. After that, the connection is removed. Any new connection to that member will start with seqno #1 again. 0 disables this + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + + +The max number of bytes in a message. Larger messages will be fragmented. Default is 8192 bytes + + + + +The max size in bytes for the byte array output buffer + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Should unicast messages to suspected members be dropped. Default is false + + + + +If cannot send a message to P (on an exception), should SUSPECT message be raised. Default is false + + + + +Reaper interval in msec. Default is 0 (no reaping) + + + + +Max time connection can be idle before being reaped + + + + +Should separate send queues be used for each connection. Default is true + + + + +Max number of messages in a send queue. Default is 10000 messages + + + + +Receiver buffer size in bytes. Default is 150000 bytes + + + + +Send buffer size in bytes. Default is 150000 bytes + + + + +Max time allowed for a socket creation in ConnectionTable. Default is 2000 msec + + + + +Max time to block on reading of peer address. Default is 1000 msec + + + + +Should TCP no delay flag be turned on. Default is false + + + + +SO_LINGER in msec. Default of -1 disables it + + + + +The interface (NIC) which should be used by this transport + + + + +Ignores all bind address parameters and let's the OS return the local host address. Default is false + + + + + If true, the transport should use all available interfaces to receive multicast messages. Default is false + + + + +Comma delimited list of interfaces (IP addresses or interface names) to receive multicasts on + + + + +The port to which the transport binds. Default of 0 binds to any (ephemeral) port + + + + + + + + + +tries to make sure ephemeral ports are used + + + + +Messages to self are looped back immediately if true. Default is false + + + + +Discard packets with a different version if true. Default is false + + + + +Thread naming pattern for threads in this channel. Default is cl + + + + +Switch for enabling thread pool for OOB messages. Default true + + + + +Minimum thread pool size for OOB messages. Default is 2 + + + + +Maximum thread pool size for OOB messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from OOB pool. Default is 30000 + + + + +Use queue to enqueue incoming OOB messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run. Default is Run + + + + +Minimum thread pool size for regular messages. Default is 2 + + + + +Maximum thread pool size for regular messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from regular pool. Default is 30000 + + + + +Switch for enabling thread pool for regular messages. Default true + + + + +Use queue to enqueue incoming regular messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run Default is Run + + + + +Number of threads to be used by the timer thread pool. Default is 4 + + + + +Enable bundling of smaller messages into bigger ones. Default is true + + + + +Enable bundling of smaller messages into bigger ones for unicast messages. Default is false + + + + +Switch to enable diagnostic probing. Default is true + + + + +Address for diagnostic probing. Default is 224.0.75.75 + + + + +Port for diagnostic probing. Default is 7500 + + + + +If assigned enable this transport to be a singleton (shared) transport + + + + +Path to a file to store currently used ports on this machine + + + + +Timeout to expire ports used with PortManager. Default is 30000 msec + + + + +Switch to enable tracking of currently used ports on this machine. Default is false + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + +Use "external_addr" if you have hosts on different networks, behind firewalls. On each firewall, set up a port forwarding rule (sometimes called "virtual server") to the local IP (e.g. 192.168.1.100) of the host then on each host, set "external_addr" TCP transport parameter to the external (public IP) address of the firewall. + + + + + + + + + + +Number of millisecs to wait for a response from a suspected member + + + + +Number of verify heartbeats sent to a suspected member + + + + +Use InetAddress.isReachable() to verify suspected member instead of regular messages + + + + +Interface for ICMP pings. Used if use_icmp is true + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Gossip host + + + + +Gossip port + + + + +Time in msecs after which the entry in GossipRouter will be refreshed. Default is 20000 msec + + + + +Number of ports to be probed for initial membership. Default is 1 + + + + +If socket is used for discovery, time in msecs to wait until socket is connected. Default is 1000 msec + + + + +Max to block on the socket on a read (in ms). 0 means block forever + + + + +Time (in ms) to wait for our own discovery message to be received. 0 means don't wait. If the discovery message is not received within discovery_timeout ms, a warning will be logged + + + + +Timeout to wait for the initial members. Default is 3000 msec + + + + +Minimum number of initial members to get a response from. Default is 2 + + + + +Minimum number of server responses (PingData.isServer()=true). If this value is greater than 0, we'll ignore num_initial_members + + + + +Return from the discovery phase as soon as we have 1 coordinator response + + + + +Number of discovery requests to be sent distributed over timeout. Default is 2 + + + + +Whether or not to return the entire logical-physical address cache mappings on a discovery request, or not. Default is false, except for TCPPING + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + + + + + +Router host address + + + + +Router port + + + + +Interval in msec to attempt connecting back to router in case of torn connection. Default is 5000 msec + + + + +The interface (NIC) which should be used by this transport + + + + +Ignores all bind address parameters and let's the OS return the local host address. Default is false + + + + + If true, the transport should use all available interfaces to receive multicast messages. Default is false + + + + +Comma delimited list of interfaces (IP addresses or interface names) to receive multicasts on + + + + +The port to which the transport binds. Default of 0 binds to any (ephemeral) port + + + + + + + + + +tries to make sure ephemeral ports are used + + + + +Messages to self are looped back immediately if true. Default is false + + + + +Discard packets with a different version if true. Default is false + + + + +Thread naming pattern for threads in this channel. Default is cl + + + + +Switch for enabling thread pool for OOB messages. Default true + + + + +Minimum thread pool size for OOB messages. Default is 2 + + + + +Maximum thread pool size for OOB messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from OOB pool. Default is 30000 + + + + +Use queue to enqueue incoming OOB messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run. Default is Run + + + + +Minimum thread pool size for regular messages. Default is 2 + + + + +Maximum thread pool size for regular messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from regular pool. Default is 30000 + + + + +Switch for enabling thread pool for regular messages. Default true + + + + +Use queue to enqueue incoming regular messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run Default is Run + + + + +Number of threads to be used by the timer thread pool. Default is 4 + + + + +Enable bundling of smaller messages into bigger ones. Default is true + + + + +Enable bundling of smaller messages into bigger ones for unicast messages. Default is false + + + + +Switch to enable diagnostic probing. Default is true + + + + +Address for diagnostic probing. Default is 224.0.75.75 + + + + +Port for diagnostic probing. Default is 7500 + + + + +If assigned enable this transport to be a singleton (shared) transport + + + + +Path to a file to store currently used ports on this machine + + + + +Timeout to expire ports used with PortManager. Default is 30000 msec + + + + +Switch to enable tracking of currently used ports on this machine. Default is false + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + + + + +The interface (NIC) which should be used by this transport + + + + +Ignores all bind address parameters and let's the OS return the local host address. Default is false + + + + + If true, the transport should use all available interfaces to receive multicast messages. Default is false + + + + +Comma delimited list of interfaces (IP addresses or interface names) to receive multicasts on + + + + +The port to which the transport binds. Default of 0 binds to any (ephemeral) port + + + + + + + + + +tries to make sure ephemeral ports are used + + + + +Messages to self are looped back immediately if true. Default is false + + + + +Discard packets with a different version if true. Default is false + + + + +Thread naming pattern for threads in this channel. Default is cl + + + + +Switch for enabling thread pool for OOB messages. Default true + + + + +Minimum thread pool size for OOB messages. Default is 2 + + + + +Maximum thread pool size for OOB messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from OOB pool. Default is 30000 + + + + +Use queue to enqueue incoming OOB messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run. Default is Run + + + + +Minimum thread pool size for regular messages. Default is 2 + + + + +Maximum thread pool size for regular messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from regular pool. Default is 30000 + + + + +Switch for enabling thread pool for regular messages. Default true + + + + +Use queue to enqueue incoming regular messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run Default is Run + + + + +Number of threads to be used by the timer thread pool. Default is 4 + + + + +Enable bundling of smaller messages into bigger ones. Default is true + + + + +Enable bundling of smaller messages into bigger ones for unicast messages. Default is false + + + + +Switch to enable diagnostic probing. Default is true + + + + +Address for diagnostic probing. Default is 224.0.75.75 + + + + +Port for diagnostic probing. Default is 7500 + + + + +If assigned enable this transport to be a singleton (shared) transport + + + + +Path to a file to store currently used ports on this machine + + + + +Timeout to expire ports used with PortManager. Default is 30000 msec + + + + +Switch to enable tracking of currently used ports on this machine. Default is false + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + + + +Max number of bytes to send per receiver until an ack must be received to proceed. Default is 2000000 bytes + + + + +Max time (in milliseconds) to block. Default is 5000 msec + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Max number of bytes to send per receiver until an ack must be received to proceed. Default is 500000 bytes + + + + +Max time (in milliseconds) to block. Default is 5000 msec + + + + +If credits fall below this limit, we send more credits to the sender. Default is 0.25 + + + + +Computed as max_credits x min_theshold unless explicitely set + + + + +Does not block a down message if it is a result of handling an up message in thesame thread. Fixes JGRP-928 + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + +Max times to block for the listed messages sizes (Message.getLength()) + + + + + + + + +Cryptographic Service Provider. Default is Bouncy Castle Provider + + + + +Cipher engine transformation for asymmetric algorithm. Default is RSA + + + + +Cipher engine transformation for symmetric algorithm. Default is AES + + + + +Initial public/private key length. Default is 512 + + + + +Initial key length for matching symmetric algorithm. Default is 128 + + + + +File on classpath that contains keystore repository + + + + +Password used to check the integrity/unlock the keystore. Change the default + + + + +Password for recovering the key. Change the default + + + + +Alias used for recovering the key. Change the default + + + + + + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Lower bound in msec to run merge protocol. Default is 5000 msec + + + + +Upper bound in msec to run merge protocol. Default is 20000 msec + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Traffic class for sending unicast and multicast datagrams. Default is 8 + + + + +The multicast address used for sending and receiving packets. Default is 228.8.8.8 + + + + +The multicast port used for sending and receiving packets. Default is 7600 + + + + +Multicast toggle. If false multiple unicast datagrams are sent instead of one multicast. Default is true + + + + +The time-to-live (TTL) for multicast datagram packets. Default is 8 + + + + +Send buffer size of the multicast datagram socket. Default is 100'000 bytes + + + + +Receive buffer size of the multicast datagram socket. Default is 500'000 bytes + + + + +Send buffer size of the unicast datagram socket. Default is 100'000 bytes + + + + +Receive buffer size of the unicast datagram socket. Default is 64'000 bytes + + + + +The interface (NIC) which should be used by this transport + + + + +Ignores all bind address parameters and let's the OS return the local host address. Default is false + + + + + If true, the transport should use all available interfaces to receive multicast messages. Default is false + + + + +Comma delimited list of interfaces (IP addresses or interface names) to receive multicasts on + + + + +The port to which the transport binds. Default of 0 binds to any (ephemeral) port + + + + + + + + + +tries to make sure ephemeral ports are used + + + + +Messages to self are looped back immediately if true. Default is false + + + + +Discard packets with a different version if true. Default is false + + + + +Thread naming pattern for threads in this channel. Default is cl + + + + +Switch for enabling thread pool for OOB messages. Default true + + + + +Minimum thread pool size for OOB messages. Default is 2 + + + + +Maximum thread pool size for OOB messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from OOB pool. Default is 30000 + + + + +Use queue to enqueue incoming OOB messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run. Default is Run + + + + +Minimum thread pool size for regular messages. Default is 2 + + + + +Maximum thread pool size for regular messages. Default is 10 + + + + +Timeout in milliseconds to remove idle thread from regular pool. Default is 30000 + + + + +Switch for enabling thread pool for regular messages. Default true + + + + +Use queue to enqueue incoming regular messages. Default is true + + + + +Maximum queue size for incoming OOB messages. Default is 500 + + + + +Thread rejection policy. Possible values are Abort, Discard, DiscardOldest and Run Default is Run + + + + +Number of threads to be used by the timer thread pool. Default is 4 + + + + +Enable bundling of smaller messages into bigger ones. Default is true + + + + +Enable bundling of smaller messages into bigger ones for unicast messages. Default is false + + + + +Switch to enable diagnostic probing. Default is true + + + + +Address for diagnostic probing. Default is 224.0.75.75 + + + + +Port for diagnostic probing. Default is 7500 + + + + +If assigned enable this transport to be a singleton (shared) transport + + + + +Path to a file to store currently used ports on this machine + + + + +Timeout to expire ports used with PortManager. Default is 30000 msec + + + + +Switch to enable tracking of currently used ports on this machine. Default is false + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + + + +Timeout to suspect a node P if neither a heartbeat nor data were received from P. Default is 3000 msec + + + + +Shun switch. Default is true + + + + +Number of times to send heartbeat. Default is 2 + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Bind address for multicast socket + + + + +Time to live for discovery packets. Default is 8 + + + + +Multicast port for discovery packets. Default is 7555 + + + + +If true, the transport should use all available interfaces to receive multicast messages. Default is false + + + + +List of interfaces to receive multicasts on + + + + +Whether send messages are sent on all interfaces. Default is false + + + + +List of interfaces to send multicasts on + + + + +Gossip host + + + + +Gossip port + + + + +Time in msecs after which the entry in GossipRouter will be refreshed. Default is 20000 msec + + + + +Number of ports to be probed for initial membership. Default is 1 + + + + +If socket is used for discovery, time in msecs to wait until socket is connected. Default is 1000 msec + + + + +Max to block on the socket on a read (in ms). 0 means block forever + + + + +Time (in ms) to wait for our own discovery message to be received. 0 means don't wait. If the discovery message is not received within discovery_timeout ms, a warning will be logged + + + + +Timeout to wait for the initial members. Default is 3000 msec + + + + +Minimum number of initial members to get a response from. Default is 2 + + + + +Minimum number of server responses (PingData.isServer()=true). If this value is greater than 0, we'll ignore num_initial_members + + + + +Return from the discovery phase as soon as we have 1 coordinator response + + + + +Number of discovery requests to be sent distributed over timeout. Default is 2 + + + + +Whether or not to return the entire logical-physical address cache mappings on a discovery request, or not. Default is false, except for TCPPING + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + + + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Compression level 0-9 (0=no compression, 9=best compression). Default is 9 + + + + +Minimal payload size of a message (in bytes) for compression to kick in. Default is 500 bytes + + + + +Number of inflaters/deflaters for concurrent processing. Default is 2 + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +View synchronization interval. Default is 60 sec + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +The max number of bytes in a message. Larger messages will be fragmented. Default is 1500 bytes + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Join timeout. Default is 5000 msec + + + + +Leave timeout. Default is 5000 msec + + + + +Timeout to complete merge. Default is 10000 msec + + + + +Shunning toggle. Default is false + + + + +If true this member is a designated merge leader. Default is false + + + + +Print local address of this member after connect. Default is true + + + + +If true this member can never become coordinator. Default is false + + + + +Temporary switch. Default is true and should not be changed + + + + +Should views be bundled? Default is true + + + + +Max view bundling timeout if view bundling is turned on. Default is 50 msec + + + + +Max number of old members to keep in history. Default is 50 + + + + +Time in ms to wait for all VIEW acks (0 == wait forever. Default is 2000 msec + + + + +Timeout to resume ViewHandler. Default is 20000 msec + + + + +Use flush for view changes. Default is true + + + + + + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +The interface (NIC) used to accept state requests + + + + +The port listening for state requests. Default value of 0 binds to any (ephemeral) port + + + + +Maximum number of pool threads serving state requests. Default is 5 + + + + +Keep alive for pool threads serving state requests. Default is 20000 msec + + + + +Buffer size for state transfer. Default is 8192 bytes + + + + +If default transport is used the total state buffer size before state producer is blocked. Default is 81920 bytes + + + + +If true default transport is used for state transfer rather than seperate TCP sockets. Default is false + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Timeout before requesting retransmissions. Default is 600, 1200, 2400, 4800 + + + + +If true, retransmissions stats will be captured. Default is false + + + + +Garbage collection lag. Default is 20 msec + + + + +Retransmit messages using multicast rather than unicast. Default is true + + + + +Use a multicast to request retransmission of missing messages. Default is false + + + + +Ask a random member for retransmission of a missing message. Default is false + + + + +The first value (in milliseconds) to use in the exponential backoff. Enabled if greater than 0. Default is 0 + + + + +Use statistics gathered from actual retransmission times to compute new retransmission times. Default is false + + + + +Should messages delivered to application be discarded. Default is false + + + + +See http://jira.jboss.com/jira/browse/JGRP-656. Default is true + + + + +If value is > 0, the retransmit buffer is bounded. If value <= 0 unbounded buffers are used. Default is 0 + + + + +Size of retransmission history. Default is 50 entries + + + + +Timeout to rebroadcast messages. Default is 2000 msec + + + + +Should stability history be printed if we fail in retransmission. Default is false + + + + +Size of send and receive history. Default is 20 entries + + + + +discards warnings about promiscuous traffic + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Max time to keep channel blocked in flush. Default is 8000 msec + + + + +Timeout (per atttempt) to quiet the cluster during the first flush phase. Default is 2500 msec + + + + +Retry timeout after an unsuccessful attempt to quiet the cluster (first flush phase). Default is 3000 msec + + + + +Reconcilliation phase toggle. Default is true + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + +Average time to send a STABLE message. Default is 20000 msec + + + + +Delay before stability message is sent. Default is 6000 msec + + + + +Maximum number of bytes received in all messages before sending a STABLE message is triggered. Default is 0 (disabled) + + + + +Determines whether to collect statistics (and expose them via JMX). Default is true + + + + + + + + diff --git a/config/alfresco/jgroups/alfresco-jgroups-TCP.xml b/config/alfresco/jgroups/alfresco-jgroups-TCP.xml new file mode 100644 index 0000000000..a74ec1f82a --- /dev/null +++ b/config/alfresco/jgroups/alfresco-jgroups-TCP.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/alfresco/jgroups/alfresco-jgroups-UDP.xml b/config/alfresco/jgroups/alfresco-jgroups-UDP.xml new file mode 100644 index 0000000000..37b76982ff --- /dev/null +++ b/config/alfresco/jgroups/alfresco-jgroups-UDP.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index cad431893d..ae3e2c2a00 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -66,14 +66,14 @@ system.bootstrap.config_check.strict=true # Leave this empty to disable cluster entry alfresco.cluster.name= +# The protocol stack to use from the JGroups configuration file +# Use this property to select which communication method should be used. +# The JGroups configuration file is build up using the protocol string +alfresco.jgroups.defaultProtocol=UDP # JGroups configuration (http://www.jgroups.org) # The location of the JGroups configuration file -# It is also possible to override this by just dropping a file in classpath:alfresco/extension/jgroups-custom.xml -alfresco.jgroups.configLocation=classpath:alfresco/jgroups-default.xml -# The protocol stack to use from the JGroups configuration file -# The JGroups configuration files are divided into protocol stacks. -# Use this property to select which communication method should be used. -alfresco.jgroups.defaultProtocol=UDP +alfresco.jgroups.configLocation=classpath:alfresco/jgroups/alfresco-jgroups-${alfresco.jgroups.defaultProtocol}.xml +#alfresco.jgroups.configLocation=alfresco/jgroups/alfresco-jgroups-${alfresco.jgroups.defaultProtocol}.xml # # How long should shutdown wait to complete normally before diff --git a/source/java/org/alfresco/repo/jgroups/AlfrescoJGroupsChannelFactory.java b/source/java/org/alfresco/repo/jgroups/AlfrescoJGroupsChannelFactory.java index 2a10d7bc4a..ca4851ac10 100644 --- a/source/java/org/alfresco/repo/jgroups/AlfrescoJGroupsChannelFactory.java +++ b/source/java/org/alfresco/repo/jgroups/AlfrescoJGroupsChannelFactory.java @@ -24,7 +24,6 @@ */ package org.alfresco.repo.jgroups; -import java.io.FileNotFoundException; import java.io.Serializable; import java.net.URL; import java.util.HashMap; @@ -50,12 +49,13 @@ import org.jgroups.ChannelListener; import org.jgroups.ChannelNotConnectedException; import org.jgroups.Event; import org.jgroups.JChannel; -import org.jgroups.JChannelFactory; import org.jgroups.Message; import org.jgroups.Receiver; import org.jgroups.TimeoutException; import org.jgroups.UpHandler; import org.jgroups.View; +import org.jgroups.protocols.LOOPBACK; +import org.jgroups.stack.ProtocolStack; import org.springframework.context.ApplicationEvent; import org.springframework.util.ResourceUtils; @@ -63,23 +63,12 @@ import org.springframework.util.ResourceUtils; * A cache peer provider that does heartbeat sending and receiving using JGroups. *

* The cluster name needs to be set before any communication is possible. This can be done using the - * system property
- * {@link #PROP_CLUSTER_NAME_PREFIX -Dalfresco.cluster-name-prefix}=MyCluster - * or by declaring a bean - *

- *    
- *       
- *          MyCluster
- *       
- *    
- * 
+ * property {@link #setClusterName(String)}. *

* The channels provided to the callers will be proxies to underlying channels that will be hot-swappable. * This means that the client code can continue to use the channel references while the actual * implementation can be switched in and out as required. * - * @see #PROP_CLUSTER_NAME_PREFIX - * * @author Derek Hulley * @since 2.1.3 */ @@ -89,15 +78,10 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean public static final String APP_REGION_DEFAULT = "DEFAULT"; /** The application region used by the EHCache heartbeat implementation over JGroups. */ public static final String APP_REGION_EHCACHE_HEARTBEAT = "EHCACHE_HEARTBEAT"; - /** The UDP protocol stack (default) */ - public static final String PROTOCOL_STACK_UDP = "UDP"; - /** The TCP protocol stack */ - public static final String PROTOCOL_STACK_TCP = "TCP"; - - - public static final String PROP_CLUSTER_NAME_PREFIX = "alfresco.cluster-name-prefix"; - public static final String CUSTOM_CONFIGURATION_FILE = "classpath:alfresco/extension/jgroups-custom.xml"; - public static final String DEFAULT_CONFIGURATION_FILE = "classpath:alfresco/jgroups-default.xml"; + /** The UDP protocol config (default) */ + public static final String DEFAULT_CONFIG_UDP = "classpath:alfresco/jgroups/alfresco-jgroups-UDP.xml"; + /** The TCP protocol config */ + public static final String DEFAULT_CONFIG_TCP = "classpath:alfresco/jgroups/alfresco-jgroups-TCP.xml"; private static Log logger = LogFactory.getLog(AlfrescoJGroupsChannelFactory.class); @@ -107,13 +91,11 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean // Values that are modified by the bean implementation private static String clusterNamePrefix; - private static URL configUrl; - private static Map stacksByAppRegion; + private static Map configUrlsByAppRegion; // Derived data /** A map that stores channel information by the application region. */ - private static final Map channels; - private static JChannelFactory channelFactory; + private static final Map channelsByAppRegion; static { @@ -121,17 +103,13 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean readLock = readWriteLock.readLock(); writeLock = readWriteLock.writeLock(); - channels = new HashMap(5); + channelsByAppRegion = new HashMap(5); clusterNamePrefix = null; - configUrl = null; - stacksByAppRegion = new HashMap(5); - stacksByAppRegion.put( - AlfrescoJGroupsChannelFactory.APP_REGION_EHCACHE_HEARTBEAT, - AlfrescoJGroupsChannelFactory.PROTOCOL_STACK_UDP); - stacksByAppRegion.put( + configUrlsByAppRegion = new HashMap(5); + configUrlsByAppRegion.put( AlfrescoJGroupsChannelFactory.APP_REGION_DEFAULT, - AlfrescoJGroupsChannelFactory.PROTOCOL_STACK_UDP); + AlfrescoJGroupsChannelFactory.DEFAULT_CONFIG_UDP); } /** @@ -158,7 +136,7 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean */ private static void closeChannels() { - for (Map.Entry entry : channels.entrySet()) + for (Map.Entry entry : channelsByAppRegion.entrySet()) { ChannelProxy channelProxy = entry.getValue(); @@ -166,7 +144,6 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean try { channelProxy.close(); - channelProxy.shutdown(); if (logger.isDebugEnabled()) { logger.debug("\n" + @@ -183,12 +160,44 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean } } + /** + * Returns the configuration URL to use for the given application region. This might default to the + * {@link #APP_REGION_DEFAULT default app region}. + */ + private static String getConfigUrl(String appRegion) + { + readLock.lock(); + try + { + // Get the configuration to use + String configUrlStr = configUrlsByAppRegion.get(appRegion); + if (!PropertyCheck.isValidPropertyString(configUrlStr)) + { + configUrlStr = configUrlsByAppRegion.get(AlfrescoJGroupsChannelFactory.APP_REGION_DEFAULT); + } + if (configUrlStr == null) + { + throw new AlfrescoRuntimeException( + "No protocol configuration was found for application region: \n" + + " Cluster prefix: " + clusterNamePrefix + "\n" + + " App region: " + appRegion + "\n" + + " Regions defined: " + configUrlsByAppRegion); + } + return configUrlStr; + } + finally + { + readLock.unlock(); + } + } + + /** /** * Creates a channel for the cluster. This method should not be heavily used - * as the checks and synchronizations will slow the calls. Returns channels can be + * as the checks and synchronizations will slow the calls. Returned channels can be * kept and will be modified directly using the factory-held references, if necessary. *

- * The application region is used to determine the protocol stack to apply. + * The application region is used to determine the protocol configuration to apply. *

* This method returns a dummy channel if no cluster name has been provided. * @@ -200,7 +209,7 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean readLock.lock(); try { - ChannelProxy channelProxy = channels.get(appRegion); + ChannelProxy channelProxy = channelsByAppRegion.get(appRegion); if (channelProxy != null) { // This will do @@ -216,8 +225,7 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean writeLock.lock(); try { - // Double check - ChannelProxy channelProxy = channels.get(appRegion); + ChannelProxy channelProxy = channelsByAppRegion.get(appRegion); if (channelProxy != null) { // This will do @@ -228,7 +236,7 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean // Proxy the channel channelProxy = new ChannelProxy(channel); // Store the channel to the map - channels.put(appRegion, channelProxy); + channelsByAppRegion.put(appRegion, channelProxy); // Done return channelProxy; } @@ -240,7 +248,7 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean /** * Creates a channel for the given cluster. The application region is used - * to determine the protocol stack to apply. + * to determine the protocol configuration to apply. * * @param appRegion the application region identifier. * @return Returns a channel @@ -249,6 +257,7 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean private static /*synchronized*/ Channel getChannelInternal(String appRegion) { Channel channel; + URL configUrl = null; // If there is no cluster defined (yet) then we define a dummy channel if (AlfrescoJGroupsChannelFactory.clusterNamePrefix == null) { @@ -267,26 +276,13 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean } else // Create real channel { - JChannelFactory channelFactory = getChannelFactory(); - // Get the protocol stack to use - String stack = stacksByAppRegion.get(appRegion); - if (!PropertyCheck.isValidPropertyString(stack)) - { - stack = stacksByAppRegion.get(AlfrescoJGroupsChannelFactory.APP_REGION_DEFAULT); - } - if (stack == null) - { - throw new AlfrescoRuntimeException( - "No protocol stack was found for application region: \n" + - " Cluster prefix: " + clusterNamePrefix + "\n" + - " App region: " + appRegion + "\n" + - " Regions defined: " + stacksByAppRegion); - } + // Get the protocol configuration to use + String configUrlStr = getConfigUrl(appRegion); try { - // Get the stack config from the factory (we are not using MUX) - String config = channelFactory.getConfig(stack); - channel = new JChannel(config); + // Construct the JChannel directly + configUrl = ResourceUtils.getURL(configUrlStr); + channel = new JChannel(configUrl); } catch (Throwable e) { @@ -294,8 +290,8 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean "Failed to create JGroups channel: \n" + " Cluster prefix: " + clusterNamePrefix + "\n" + " App region: " + appRegion + "\n" + - " Protocol stack: " + stack + "\n" + - " Configuration URL: " + AlfrescoJGroupsChannelFactory.configUrl, + " Regions defined: " + configUrlsByAppRegion + "\n" + + " Configuration URL: " + configUrlStr, e); } } @@ -303,14 +299,10 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean try { String clusterName = clusterNamePrefix + ":" + appRegion; - // Set reconnect property - channel.setOpt(Channel.AUTO_RECONNECT, Boolean.TRUE); // Don't accept messages from self channel.setOpt(Channel.LOCAL, Boolean.FALSE); - // No state transfer - channel.setOpt(Channel.AUTO_GETSTATE, Boolean.FALSE); // Connect - channel.connect(clusterName, null, null, 5000L); + channel.connect(clusterName); // Done if (logger.isDebugEnabled()) { @@ -318,8 +310,9 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean "Created JGroups channel: \n" + " Cluster prefix: " + clusterNamePrefix + "\n" + " App region: " + appRegion + "\n" + + " Regions defined: " + configUrlsByAppRegion + "\n" + " Channel: " + channel + "\n" + - " Configuration URL: " + AlfrescoJGroupsChannelFactory.configUrl); + " Configuration URL: " + configUrl); } } catch (Throwable e) @@ -329,65 +322,26 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean " Cluster prefix: " + clusterNamePrefix + "\n" + " App region: " + appRegion + "\n" + " Channel: " + channel + "\n" + - " Configuration URL: " + AlfrescoJGroupsChannelFactory.configUrl, + " Configuration URL: " + configUrl, e); } return channel; } /** - * Builds and initializes a JChannelFactory + * Rebuild all the channels using the current cluster name and configuration mappings. */ - /* All calls to this are ultimately wrapped in the writeLock. */ - private static /*synchronized*/ JChannelFactory getChannelFactory() + public static void rebuildChannels() { - if (AlfrescoJGroupsChannelFactory.channelFactory != null) - { - return AlfrescoJGroupsChannelFactory.channelFactory; - } - // Set the config location to use - if (AlfrescoJGroupsChannelFactory.configUrl == null) - { - // This was not set by the bean so set it using the default mechanism - try - { - AlfrescoJGroupsChannelFactory.configUrl = ResourceUtils.getURL(CUSTOM_CONFIGURATION_FILE); - } - catch (FileNotFoundException e) - { - // try the alfresco default - try - { - AlfrescoJGroupsChannelFactory.configUrl = ResourceUtils.getURL(DEFAULT_CONFIGURATION_FILE); - } - catch (FileNotFoundException ee) - { - throw new AlfrescoRuntimeException("Missing default JGroups config: " + DEFAULT_CONFIGURATION_FILE); - } - } - } + writeLock.lock(); try { - // Construct factory - AlfrescoJGroupsChannelFactory.channelFactory = new JChannelFactory(); - channelFactory.setMultiplexerConfig(AlfrescoJGroupsChannelFactory.configUrl); + rebuildChannelsInternal(); } - catch (Throwable e) + finally { - throw new AlfrescoRuntimeException( - "Failed to construct JChannelFactory using config: " + AlfrescoJGroupsChannelFactory.configUrl, - e); + writeLock.unlock(); } - // done - if (logger.isInfoEnabled()) - { - logger.info("\n" + - "Created JChannelFactory: \n" + - " Cluster Name: " + (AlfrescoJGroupsChannelFactory.clusterNamePrefix == null ? "" : AlfrescoJGroupsChannelFactory.clusterNamePrefix) + "\n" + - " Stack Mapping: " + AlfrescoJGroupsChannelFactory.stacksByAppRegion + "\n" + - " Configuration: " + AlfrescoJGroupsChannelFactory.configUrl); - } - return AlfrescoJGroupsChannelFactory.channelFactory; } /** @@ -395,29 +349,25 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean * be reconstructed from scratch. All the channels are reconstructed - but this will not * affect any references to channels held outside this class as the values returned are proxies * on top of hot swappable implementations. + *

+ * The old channel is closed before the new one is created, so it is possible for a channel + * held by client code to be rendered unusable during the switch-over. */ /* All calls to this are ultimately wrapped in the writeLock. */ - private static /*synchronized*/ void rebuildChannels() + private static /*synchronized*/ void rebuildChannelsInternal() { - // First throw away the channel factory. It will be fetched lazily. - AlfrescoJGroupsChannelFactory.channelFactory = null; - // Reprocess all the application regions with the new data - for (Map.Entry entry : channels.entrySet()) + for (Map.Entry entry : channelsByAppRegion.entrySet()) { String appRegion = entry.getKey(); ChannelProxy channelProxy = entry.getValue(); - // Create the new channel - Channel newChannel = getChannelInternal(appRegion); - - // Now do the hot-swap - Channel oldChannel = channelProxy.swap(newChannel); - // Close the old channel + // Get the old channel + Channel oldChannel = channelProxy.getDelegate(); + // Close the old channel. try { oldChannel.close(); - oldChannel.shutdown(); if (logger.isDebugEnabled()) { logger.debug("\n" + @@ -432,6 +382,12 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean " Old channel: " + oldChannel, e); } + + // Create the new channel + Channel newChannel = getChannelInternal(appRegion); + + // Now do the hot-swap + channelProxy.swap(newChannel); } } @@ -442,6 +398,8 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean * clusterNamePrefix:appRegion * * If no cluster name prefix is declared, the cluster is effectively disabled. + *

+ * NOTE: The channels must be {@link #rebuildChannels() rebuilt}. * * @param clusterNamePrefix a prefix to append to the cluster names used */ @@ -467,22 +425,24 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean } /** - * Configure a mapping between the application regions and the available JGroup protocol stacks. + * Configure a mapping between the application regions and the available JGroup protocol configurations. * The map must contain a mapping for application region 'DEFAULT'. + *

+ * NOTE: The channels must be {@link #rebuildChannels() rebuilt}. * - * @param protocolMap a mapping from application region (keys) to protocol stacks (values) + * @param configUrlsByAppRegion a mapping from application region (keys) to protocol configuration URLs (values) */ - public static void changeProtocolStackMapping(Map protocolMap) + private static void changeConfigUrlsMapping(Map configUrlsByAppRegion) { writeLock.lock(); try { // Check that there is a mapping for default - if (!protocolMap.containsKey(AlfrescoJGroupsChannelFactory.APP_REGION_DEFAULT)) + if (!configUrlsByAppRegion.containsKey(AlfrescoJGroupsChannelFactory.APP_REGION_DEFAULT)) { - throw new AlfrescoRuntimeException("A protocol stack must be defined for 'DEFAULT'"); + throw new AlfrescoRuntimeException("A configuration URL must be defined for 'DEFAULT'"); } - stacksByAppRegion = protocolMap; + AlfrescoJGroupsChannelFactory.configUrlsByAppRegion = configUrlsByAppRegion; } finally { @@ -490,38 +450,6 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean } } - /** - * Set the URL location of the JGroups configuration file. This must refer to a MUX-compatible - * configuration file. - * - * @param configUrl a url of the form file:... or classpath: - */ - public static void changeJgroupsConfigurationUrl(String configUrl) - { - writeLock.lock(); - if (!PropertyCheck.isValidPropertyString(configUrl)) - { - // It's not really being set - AlfrescoJGroupsChannelFactory.configUrl = null; - return; - } - // It's a real attempt to set it - try - { - AlfrescoJGroupsChannelFactory.configUrl = ResourceUtils.getURL(configUrl); - } - catch (FileNotFoundException e) - { - throw new AlfrescoRuntimeException( - "Failed to set property 'jgroupsConfigurationUrl'. The url is invalid: " + configUrl, - e); - } - finally - { - writeLock.unlock(); - } - } - /** * Bean-enabling constructor */ @@ -538,31 +466,31 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean } /** - * @see AlfrescoJGroupsChannelFactory#changeProtocolStackMapping(Map) + * @see AlfrescoJGroupsChannelFactory#changeConfigUrlsMapping(Map) */ - public void setProtocolStackMapping(Map protocolMap) + public void setConfigUrlsByAppRegion(Map configUrlsByAppRegion) { - AlfrescoJGroupsChannelFactory.changeProtocolStackMapping(protocolMap); + AlfrescoJGroupsChannelFactory.changeConfigUrlsMapping(configUrlsByAppRegion); } /** - * Set the URL location of the JGroups configuration file. This must refer to a MUX-compatible - * configuration file. - * - * @param configUrl a url of the form file:... or classpath: + * @deprecated Use {@link #setConfigUrlsByAppRegion(Map)} + */ + public void setProtocolStackMapping(Map unused) + { + throw new AlfrescoRuntimeException( + "Properties 'protocolStackMapping' and 'jgroupsConfigurationUrl'" + + " have been deprecated in favour of 'configUrlsByAppRegion'."); + } + + /** + * @deprecated Use {@link #setConfigUrlsByAppRegion(Map)} */ public void setJgroupsConfigurationUrl(String configUrl) { - try - { - AlfrescoJGroupsChannelFactory.configUrl = ResourceUtils.getURL(configUrl); - } - catch (FileNotFoundException e) - { - throw new AlfrescoRuntimeException( - "Failed to set property 'jgroupsConfigurationUrl'. The url is invalid: " + configUrl, - e); - } + throw new AlfrescoRuntimeException( + "Properties 'protocolStackMapping' and 'jgroupsConfigurationUrl'" + + " have been deprecated in favour of 'configUrlsByAppRegion'."); } @Override @@ -587,7 +515,28 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean { public DummyJChannel() throws ChannelException { - super("DUMMY_TP:UDP(mcast_addr=224.10.10.200;mcast_port=5679)"); + super("org.alfresco.repo.jgroups.AlfrescoJGroupsChannelFactory$DummyProtocol"); + } + } + + public static class DummyProtocol extends LOOPBACK + { + @Override + public String getName() + { + return "ALF_DUMMY"; + } + + @Override + public Object down(Event evt) + { + return null; + } + + @Override + public Object up(Event evt) + { + return null; } } @@ -609,13 +558,24 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean private UpHandler delegateUpHandler; private Set delegateChannelListeners; private Receiver delegateReceiver; - + + /** + * @param delegate the real channel that will do the work + */ public ChannelProxy(Channel delegate) { this.delegate = delegate; this.delegateChannelListeners = new HashSet(7); } + /** + * @return Returns the channel to which the implementation will delegate + */ + public Channel getDelegate() + { + return delegate; + } + /** * Swap the channel. The old delegate will be disconnected before the swap occurs. * This guarantees data consistency, assuming that any failures will be handled. @@ -625,7 +585,7 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean * @param the new delegate * @return the old, disconnected delegate */ - public Channel swap(Channel channel) + public synchronized Channel swap(Channel channel) { // Remove the listeners from the old channel delegate.setReceiver(null); @@ -635,7 +595,7 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean } delegate.setUpHandler(null); - Channel oldDelegage = delegate; + Channel oldDelegate = delegate; // Assign the new delegate and carry the listeners over delegate = channel; @@ -646,22 +606,42 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean } delegate.setUpHandler(delegateUpHandler); // Done - return oldDelegage; + return oldDelegate; } @Override - protected Log getLog() + protected org.jgroups.logging.Log getLog() { throw new UnsupportedOperationException(); } - public void setReceiver(Receiver r) + @Override + public Address getAddress() + { + return delegate.getAddress(); + } + + @Override + public String getName() + { + return delegate.getName(); + } + + @Override + public ProtocolStack getProtocolStack() + { + return delegate.getProtocolStack(); + } + + @Override + public synchronized void setReceiver(Receiver r) { delegateReceiver = r; delegate.setReceiver(r); } - public void addChannelListener(ChannelListener listener) + @Override + public synchronized void addChannelListener(ChannelListener listener) { if (listener == null) { @@ -671,7 +651,8 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean delegate.addChannelListener(listener); } - public void removeChannelListener(ChannelListener listener) + @Override + public synchronized void removeChannelListener(ChannelListener listener) { if (listener != null) { @@ -680,223 +661,273 @@ public class AlfrescoJGroupsChannelFactory extends AbstractLifecycleBean delegate.removeChannelListener(listener); } - public void clearChannelListeners() + @Override + public synchronized void clearChannelListeners() { delegateChannelListeners.clear(); delegate.clearChannelListeners(); } - public void setUpHandler(UpHandler up_handler) + @Override + public synchronized void setUpHandler(UpHandler up_handler) { delegateUpHandler = up_handler; delegate.setUpHandler(up_handler); } + @Override public void blockOk() { delegate.blockOk(); } + @Override public void close() { delegate.close(); } + @Override public void connect(String cluster_name, Address target, String state_id, long timeout) throws ChannelException { delegate.connect(cluster_name, target, state_id, timeout); } + @Override public void connect(String cluster_name) throws ChannelException { delegate.connect(cluster_name); } + @Override public void disconnect() { delegate.disconnect(); } + @Override public void down(Event evt) { delegate.down(evt); } + @Override public Object downcall(Event evt) { return delegate.downcall(evt); } + @Override public String dumpQueue() { return delegate.dumpQueue(); } + @Override @SuppressWarnings("unchecked") public Map dumpStats() { return delegate.dumpStats(); } + @Override public boolean equals(Object obj) { return delegate.equals(obj); } + @Override public boolean flushSupported() { return delegate.flushSupported(); } + @Override @SuppressWarnings("unchecked") public boolean getAllStates(Vector targets, long timeout) throws ChannelNotConnectedException, ChannelClosedException { return delegate.getAllStates(targets, timeout); } + @Override public String getChannelName() { return delegate.getChannelName(); } + @Override public String getClusterName() { return delegate.getClusterName(); } + @Override public Map getInfo() { return delegate.getInfo(); } + @Override public Address getLocalAddress() { return delegate.getLocalAddress(); } + @Override public int getNumMessages() { return delegate.getNumMessages(); } + @Override public Object getOpt(int option) { return delegate.getOpt(option); } + @Override public boolean getState(Address target, long timeout) throws ChannelNotConnectedException, ChannelClosedException { return delegate.getState(target, timeout); } + @Override public boolean getState(Address target, String state_id, long timeout) throws ChannelNotConnectedException, ChannelClosedException { return delegate.getState(target, state_id, timeout); } + @Override public View getView() { return delegate.getView(); } + @Override public int hashCode() { return delegate.hashCode(); } + @Override public boolean isConnected() { return delegate.isConnected(); } + @Override public boolean isOpen() { return delegate.isOpen(); } + @Override public void open() throws ChannelException { delegate.open(); } + @Override public Object peek(long timeout) throws ChannelNotConnectedException, ChannelClosedException, TimeoutException { return delegate.peek(timeout); } + @Override public Object receive(long timeout) throws ChannelNotConnectedException, ChannelClosedException, TimeoutException { return delegate.receive(timeout); } + @Override public void returnState(byte[] state, String state_id) { delegate.returnState(state, state_id); } + @Override public void returnState(byte[] state) { delegate.returnState(state); } + @Override public void send(Address dst, Address src, Serializable obj) throws ChannelNotConnectedException, ChannelClosedException { delegate.send(dst, src, obj); } + @Override public void send(Message msg) throws ChannelNotConnectedException, ChannelClosedException { delegate.send(msg); } + @Override public void setChannelListener(ChannelListener channel_listener) { delegate.setChannelListener(channel_listener); } + @Override public void setInfo(String key, Object value) { delegate.setInfo(key, value); } + @Override public void setOpt(int option, Object value) { delegate.setOpt(option, value); } + @Override public void shutdown() { delegate.shutdown(); } + @Override public boolean startFlush(boolean automatic_resume) { return delegate.startFlush(automatic_resume); } + @Override public boolean startFlush(List

flushParticipants, boolean automatic_resume) { return delegate.startFlush(flushParticipants, automatic_resume); } + @Override public boolean startFlush(long timeout, boolean automatic_resume) { return delegate.startFlush(timeout, automatic_resume); } + @Override public void stopFlush() { delegate.stopFlush(); } + @Override public void stopFlush(List
flushParticipants) { delegate.stopFlush(flushParticipants); } - public String toString() + @Override + public synchronized String toString() { - return delegate.toString(); + if (delegate instanceof DummyJChannel) + { + return delegate.toString() + "(dummy)"; + } + else + { + return delegate.toString(); + } } } } diff --git a/source/java/org/alfresco/repo/jgroups/AlfrescoJGroupsChannelFactoryTest.java b/source/java/org/alfresco/repo/jgroups/AlfrescoJGroupsChannelFactoryTest.java index 2c35095e94..2551fe4f24 100644 --- a/source/java/org/alfresco/repo/jgroups/AlfrescoJGroupsChannelFactoryTest.java +++ b/source/java/org/alfresco/repo/jgroups/AlfrescoJGroupsChannelFactoryTest.java @@ -75,6 +75,7 @@ public class AlfrescoJGroupsChannelFactoryTest extends TestCase public void testBasicCluster() throws Exception { AlfrescoJGroupsChannelFactory.changeClusterNamePrefix("blah"); + AlfrescoJGroupsChannelFactory.rebuildChannels(); Channel channel = AlfrescoJGroupsChannelFactory.getChannel(appRegion); stressChannel(channel); } @@ -82,9 +83,11 @@ public class AlfrescoJGroupsChannelFactoryTest extends TestCase public void testHotSwapCluster() throws Exception { AlfrescoJGroupsChannelFactory.changeClusterNamePrefix("ONE"); + AlfrescoJGroupsChannelFactory.rebuildChannels(); Channel channel1 = AlfrescoJGroupsChannelFactory.getChannel(appRegion); stressChannel(channel1); AlfrescoJGroupsChannelFactory.changeClusterNamePrefix("TWO"); + AlfrescoJGroupsChannelFactory.rebuildChannels(); Channel channel2 = AlfrescoJGroupsChannelFactory.getChannel(appRegion); stressChannel(channel1); assertTrue("Channel reference must be the same", channel1 == channel2);