init
This commit is contained in:
34
java/org/apache/catalina/tribes/membership/Constants.java
Normal file
34
java/org/apache/catalina/tribes/membership/Constants.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.catalina.tribes.membership;
|
||||
|
||||
import org.apache.catalina.tribes.util.Arrays;
|
||||
|
||||
/**
|
||||
* Manifest constants for the <code>org.apache.catalina.tribes.membership</code>
|
||||
* package.
|
||||
*
|
||||
* @author Peter Rossbach
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
public static final String Package = "org.apache.catalina.tribes.membership";
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println(Arrays.toString("TRIBES-B".getBytes()));
|
||||
System.out.println(Arrays.toString("TRIBES-E".getBytes()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
McastService.domain=Unable to send domain update
|
||||
McastService.parseSoTimeout=Unable to parse SoTimeout: [{0}]
|
||||
McastService.parseTTL=Unable to parse TTL: [{0}]
|
||||
McastService.payload=Unable to send payload update
|
||||
McastService.stopFail=Unable to stop the mcast service, level: [{0}]
|
||||
|
||||
mcastService.exceed.maxPacketSize=Packet length[{0}] exceeds max packet size of [{1}] bytes.
|
||||
mcastService.missing.property=McastService:Required property [{0}] is missing.
|
||||
mcastService.noStart=Multicast send is not started or enabled.
|
||||
|
||||
mcastServiceImpl.bind=Attempting to bind the multicast socket to [{0}:{1}]
|
||||
mcastServiceImpl.bind.failed=Binding to multicast address, failed. Binding to port only.
|
||||
mcastServiceImpl.error.receiving=Error receiving mcast package. Sleeping 500ms
|
||||
mcastServiceImpl.invalid.startLevel=Invalid start level. Only acceptable levels are Channel.MBR_RX_SEQ and Channel.MBR_TX_SEQ
|
||||
mcastServiceImpl.invalid.stopLevel=Invalid stop level. Only acceptable levels are Channel.MBR_RX_SEQ and Channel.MBR_TX_SEQ
|
||||
mcastServiceImpl.memberDisappeared.failed=Unable to process member disappeared message.
|
||||
mcastServiceImpl.packet.tooLong=Multicast packet received was too long, dropping package:[{0}]
|
||||
mcastServiceImpl.receive.running=McastService.receive already running.
|
||||
mcastServiceImpl.recovery=Tribes membership, running recovery thread, multicasting is not functional.
|
||||
mcastServiceImpl.recovery.failed=Recovery attempt number [{0}] failed, trying again in [{1}] seconds
|
||||
mcastServiceImpl.recovery.startFailed=Recovery thread failed to start membership service.
|
||||
mcastServiceImpl.recovery.stopFailed=Recovery thread failed to stop membership service.
|
||||
mcastServiceImpl.recovery.successful=Membership recovery was successful.
|
||||
mcastServiceImpl.send.failed=Unable to send mcast message.
|
||||
mcastServiceImpl.send.running=McastService.send already running.
|
||||
mcastServiceImpl.setInterface=Setting multihome multicast interface to:[{0}]
|
||||
mcastServiceImpl.setSoTimeout=Setting cluster mcast soTimeout to [{0}]
|
||||
mcastServiceImpl.setTTL=Setting cluster mcast TTL to [{0}]
|
||||
mcastServiceImpl.unable.join=Unable to join multicast group, make sure your system has multicasting enabled.
|
||||
mcastServiceImpl.unableReceive.broadcastMessage=Unable to receive broadcast message.
|
||||
mcastServiceImpl.waitForMembers.done=Done sleeping, membership established, start level:[{0}]
|
||||
mcastServiceImpl.waitForMembers.start=Sleeping for [{0}] milliseconds to establish cluster membership, start level:[{1}]
|
||||
|
||||
memberImpl.invalid.package.begin=Invalid package, should start with:[{0}]
|
||||
memberImpl.invalid.package.end=Invalid package, should end with:[{0}]
|
||||
memberImpl.large.payload=Payload is too large for tribes to handle.
|
||||
memberImpl.notEnough.bytes=Not enough bytes in member package.
|
||||
memberImpl.package.small=Member package too small to validate.
|
||||
memberImpl.unableParse.hostname=Unable to parse hostname.
|
||||
|
||||
staticMember.invalid.uuidLength=UUID must be exactly 16 bytes, not:[{0}]
|
||||
@@ -0,0 +1,24 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
mcastServiceImpl.bind=Versuche Multicast Socket an [{0}:{1}] zu binden
|
||||
mcastServiceImpl.recovery.failed=Wiederherstellungsversuch Nummer [{0}] ist fehlgeschlagen, versuche es in [{1}] Sekunden erneut
|
||||
mcastServiceImpl.send.failed=Eine mcast-Nachricht kann nicht gesendet werden.
|
||||
mcastServiceImpl.send.running=McastService.send läuft bereits
|
||||
mcastServiceImpl.setSoTimeout=Setze Cluster mcast soTimeout auf [{0}]
|
||||
mcastServiceImpl.setTTL=Setze Cluster mcast TTL auf [{0}]
|
||||
mcastServiceImpl.unableReceive.broadcastMessage=Konnte Broadcast-Nachricht nicht empfangen.
|
||||
|
||||
memberImpl.notEnough.bytes=Nicht genug bytes im Mitgliederpaket
|
||||
@@ -0,0 +1,24 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
mcastServiceImpl.bind=Tratando de atar el socket multicast a [{0}:{1}]\n
|
||||
mcastServiceImpl.recovery=Membresía Tribes ejecutando hilo de recuperación, multicasting no esta operativo.
|
||||
mcastServiceImpl.send.running=McastService.send aún esta corriendo.
|
||||
mcastServiceImpl.setInterface=Fijando interfaz multicase multihme a:[{0}]\n
|
||||
mcastServiceImpl.setSoTimeout=Fijando cluster mcast para tiempo de espera gotado en [{0}]
|
||||
mcastServiceImpl.setTTL=Fijando cluster cluster mcast TTL a [{0}]\n
|
||||
mcastServiceImpl.unableReceive.broadcastMessage=Incapaz de recibir el mensaje de broadcast
|
||||
|
||||
memberImpl.notEnough.bytes=No hay suficientes bytes en el paquete miembro
|
||||
@@ -0,0 +1,56 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
McastService.domain=Impossible d'envoyer la mise à jour du domaine
|
||||
McastService.parseSoTimeout=Impossible de lire SoTimeout: [{0}]
|
||||
McastService.parseTTL=Impossible d''analyser le TTL: [{0}]
|
||||
McastService.payload=Impossible d'envoyer les données de mise à jour
|
||||
McastService.stopFail=Impossible d''arrêter le service mcast, niveau [{0}]
|
||||
|
||||
mcastService.exceed.maxPacketSize=La taille du paquet [{0}] excède la taille maximale qui est de [{1}] octets
|
||||
mcastService.missing.property=McastService:La propriété obligatoire [{0}] manque.
|
||||
mcastService.noStart=L'envoi multicast n'est pas démarré ou activé
|
||||
|
||||
mcastServiceImpl.bind=Tentive d'associer le socket multicast à [{0}:{1}]
|
||||
mcastServiceImpl.bind.failed=Echec de l'association à l’adresse multicast, association uniquement sur le port
|
||||
mcastServiceImpl.error.receiving=Erreur en recevant un paquet multicast, attente de 500ms
|
||||
mcastServiceImpl.invalid.startLevel=Niveau de départ invalide. Les seuls niveaux acceptables sont Channel.MBR_RX_SEQ et Channel.MBR_TX_SEQ
|
||||
mcastServiceImpl.invalid.stopLevel=Niveau de stop invalide, les seuls niveaux valides sont Channel.MBR_RX_SEQ et Channel.MBR_TX_SEQ
|
||||
mcastServiceImpl.memberDisappeared.failed=Impossible de traiter le message indiquant un membre disparu
|
||||
mcastServiceImpl.packet.tooLong=Le paquet multicast reçu est trop long, il est abandonné: [{0}]
|
||||
mcastServiceImpl.receive.running=McastService.receive est déjà en cours d'exécution
|
||||
mcastServiceImpl.recovery=Le multicast est non fonctionnel, le registre de membres de Tribes exécute le processus de récupération
|
||||
mcastServiceImpl.recovery.failed=La tentative de récupération numéro [{0}] échouée, nouvel essai dans [{1}] secondes
|
||||
mcastServiceImpl.recovery.startFailed=Le thread de récupération n'a pas pu démarrer le registre de membres
|
||||
mcastServiceImpl.recovery.stopFailed=Le thread de récupération n'a pu arrêter le registre de membres
|
||||
mcastServiceImpl.recovery.successful=Succès de récupération du registre de membres
|
||||
mcastServiceImpl.send.failed=Impossible d'envoyer le message mcast.
|
||||
mcastServiceImpl.send.running=McastService.send est déjà en cours d'exécution.
|
||||
mcastServiceImpl.setInterface=Définition de l''interface multicast multi réseaux comme [{0}]
|
||||
mcastServiceImpl.setSoTimeout=Réglage du mcast soTimeout du cluster à [{0}]
|
||||
mcastServiceImpl.setTTL=Le multicast TTL du cluster est fixé à [{0}]
|
||||
mcastServiceImpl.unable.join=Incapable de rejoindre le le groupe de multidiffusion ("multicast"). Assurez-vous que la multidiffusion est activée sur votre système.
|
||||
mcastServiceImpl.unableReceive.broadcastMessage=N'a pas pu recevoir de message général (broadcast)
|
||||
mcastServiceImpl.waitForMembers.done=Fin de l''attente, le registre de membres est établi, démarrage de niveau: [{0}]
|
||||
mcastServiceImpl.waitForMembers.start=Attente de [{0}] millisecondes pour établir le registre de membres du cluster, démarrage au niveau [{1}]
|
||||
|
||||
memberImpl.invalid.package.begin=Le paquet est invalide, il devrait démarrer par [{0}]
|
||||
memberImpl.invalid.package.end=le paquet est invalide, il devrait se terminer par: [{0}]
|
||||
memberImpl.large.payload=Le contenu est trop gros pour être géré par Tribes
|
||||
memberImpl.notEnough.bytes=Pas assez d'octets dans le paquet membre
|
||||
memberImpl.package.small=Le paquet du membre est trop petit pour être validé
|
||||
memberImpl.unableParse.hostname=Incapable d'analyser le nom d'hôte (hostname)
|
||||
|
||||
staticMember.invalid.uuidLength=Un UUID doit faire exactement 16 octets et non [{0}]
|
||||
@@ -0,0 +1,56 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
McastService.domain=ドメイン更新の送信が出来ません。
|
||||
McastService.parseSoTimeout=SoTimeoutを解析できません:[{0}]
|
||||
McastService.parseTTL=TTL 値を解釈できません: [{0}]
|
||||
McastService.payload=Payload更新の送信が出来ません。
|
||||
McastService.stopFail=マルチキャストサービスを停止できません。レベル:[{0}]
|
||||
|
||||
mcastService.exceed.maxPacketSize=パケット長[{0}]は[{1}]バイトの最大パケットサイズを超えています。
|
||||
mcastService.missing.property=McastService: 必須プロパティ [{0}] がありません。
|
||||
mcastService.noStart=マルチキャスト送信が開始または有効になっていません。
|
||||
|
||||
mcastServiceImpl.bind=[{0}:{1}] にマルチキャストソケットを束縛します。
|
||||
mcastServiceImpl.bind.failed=マルチキャストアドレスへのバインドに失敗しました。 ポートのみにバインドします。
|
||||
mcastServiceImpl.error.receiving=マルチキャストパッケージを受信中にエラーが発生しました。 500msスリープします。
|
||||
mcastServiceImpl.invalid.startLevel=不正な開始レベルです。受け付けられるのは Channel.MBR_RX_SEQ と Channel.MBR_TX_SEQ です。
|
||||
mcastServiceImpl.invalid.stopLevel=無効な停止レベルです。 受け入れ可能なレベルはChannel.MBR_RX_SEQとChannel.MBR_TX_SEQのみです。
|
||||
mcastServiceImpl.memberDisappeared.failed=メンバー消失メッセージを処理できません。
|
||||
mcastServiceImpl.packet.tooLong=受信したマルチキャストパケットが大きすぎるためパッケージを破棄します。受信したパケットサイズは [{0}] です。
|
||||
mcastServiceImpl.receive.running=McastService.receive は既に実行中です。
|
||||
mcastServiceImpl.recovery=リカバリスレッドがメンバーシップを復旧するため、マルチキャストできなくなります。
|
||||
mcastServiceImpl.recovery.failed=リカバリの試み[{0}]が失敗しました。[{1}]秒後に再試行します。
|
||||
mcastServiceImpl.recovery.startFailed=リカバリースレッドはメンバーシップサービスを開始できません。
|
||||
mcastServiceImpl.recovery.stopFailed=リカバリースレッドはメンバーシップサービスを停止できません。
|
||||
mcastServiceImpl.recovery.successful=メンバーシップの回復に成功しました。
|
||||
mcastServiceImpl.send.failed=マルチキャストメッセージを送信出来ません。
|
||||
mcastServiceImpl.send.running=McastService.sendはすでに実行中です。
|
||||
mcastServiceImpl.setInterface=マルチホームマルチキャストインターフェイスを構成しました。 : [{0}]
|
||||
mcastServiceImpl.setSoTimeout=クラスタ マルチキャスト soTimeoutを[{0}]に設定します
|
||||
mcastServiceImpl.setTTL=クラスターのマルチキャスト TTL を [{0}] に設定しました。
|
||||
mcastServiceImpl.unable.join=マルチキャストグループに参加できません、システムでマルチキャストが有効になっていることを確認してください。
|
||||
mcastServiceImpl.unableReceive.broadcastMessage=ブロードキャストメッセージを受信できません。
|
||||
mcastServiceImpl.waitForMembers.done=sleep完了、メンバーシップを確立し、開始レベル:[{0}]
|
||||
mcastServiceImpl.waitForMembers.start=クラスタメンバシップを確立するために[{0}]ミリ秒スリープ、開始レベル:[{1}]
|
||||
|
||||
memberImpl.invalid.package.begin=パッケージが不正です。[{0}] から開始しなければなりません。
|
||||
memberImpl.invalid.package.end=不正なパッケージです。[{0}] で終端しなければなりません。
|
||||
memberImpl.large.payload=ペイロードはtribes が処理するには大きすぎます。
|
||||
memberImpl.notEnough.bytes=メンバーパッケージのバイト長が不足しています。
|
||||
memberImpl.package.small=メンバーパッケージが小さすぎて検証できません。
|
||||
memberImpl.unableParse.hostname=ホスト名を解析できません。
|
||||
|
||||
staticMember.invalid.uuidLength=UUIDは正確に16バイトでなければなりません。[{0}]
|
||||
@@ -0,0 +1,56 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
McastService.domain=도메인 변경 메시지를 보낼 수 없습니다.
|
||||
McastService.parseSoTimeout=SoTimeout을 파싱할 수 없습니다: [{0}]
|
||||
McastService.parseTTL=TTL을 파싱할 수 없습니다: [{0}]
|
||||
McastService.payload=Payload 변경 메시지를 보낼 수 없습니다.
|
||||
McastService.stopFail=멀티캐스트 서비스를 중단시킬 수 없습니다. 레벨: [{0}]
|
||||
|
||||
mcastService.exceed.maxPacketSize=패킷 길이 [{0}]이(가), 최대 패킷 크기인 [{1}] 바이트를 초과합니다.
|
||||
mcastService.missing.property=McastService: 필수 프로퍼티 [{0}]이(가) 없습니다.
|
||||
mcastService.noStart=멀티캐스트 전송이 시작되지 않았거나 사용가능 상태가 아닙니다.
|
||||
|
||||
mcastServiceImpl.bind=멀티캐스트 소켓을 [{0}:{1}](으)로 바인딩하려 시도 중
|
||||
mcastServiceImpl.bind.failed=멀티캐스트 주소로 바인딩하지 못했습니다. 포트로만 바인딩합니다.
|
||||
mcastServiceImpl.error.receiving=멀티캐스트 패키지를 받는 중 오류 발생. 500 밀리초 동안 잠에 들겠습니다.
|
||||
mcastServiceImpl.invalid.startLevel=유효하지 않은 시작 레벨. 허용되는 레벨들은 Channel.MBR_RX_SEQ와 Channel.MBR_TX_SEQ 뿐입니다.
|
||||
mcastServiceImpl.invalid.stopLevel=유효하지 않은 중지 레벨. 허용 레벨들은 Channel.MBR_RX_SEQ와 Channel.MBR_TX_SEQ입니다.
|
||||
mcastServiceImpl.memberDisappeared.failed=멤버 사라짐 메시지를 처리할 수 없습니다.
|
||||
mcastServiceImpl.packet.tooLong=수신된 멀티캐스트 패킷이 너무 깁니다. 패키지를 무시합니다: [{0}]
|
||||
mcastServiceImpl.receive.running=McastService.receive가 이미 실행 중입니다.
|
||||
mcastServiceImpl.recovery=Tribes 멤버십을 복구하려고, 별도의 쓰레드에서 멀티캐스팅을 시도하고 있습니다.
|
||||
mcastServiceImpl.recovery.failed=복구 시도가 [{0}]회 실패했습니다. [{1}] 초 후에 다시 시도 하겠습니다.
|
||||
mcastServiceImpl.recovery.startFailed=복구 쓰레드가 멤버십 서비스를 시작하지 못했습니다.
|
||||
mcastServiceImpl.recovery.stopFailed=복구 쓰레드가 멤버십 서비스를 중지시키지 못했습니다.
|
||||
mcastServiceImpl.recovery.successful=멤버십 복구가 성공적이었습니다.
|
||||
mcastServiceImpl.send.failed=멀티캐스트 메시지를 보낼 수 없습니다.
|
||||
mcastServiceImpl.send.running=McastService.send가 이미 실행 중입니다.
|
||||
mcastServiceImpl.setInterface=멀티홈 멀티캐스트 인터페이스를 [{0}]에 설정합니다.
|
||||
mcastServiceImpl.setSoTimeout=클러스터 멀티캐스트의 soTimeout을 [{0}](으)로 설정합니다.
|
||||
mcastServiceImpl.setTTL=클러스터 멀티캐스트 TTL을 [{0}](으)로 설정합니다.
|
||||
mcastServiceImpl.unable.join=멀티캐스트 그룹에 참가할 수 없습니다. 귀하의 시스템이 멀티캐스팅을 사용 가능하도록 설정되었는지 확인하십시오.
|
||||
mcastServiceImpl.unableReceive.broadcastMessage=브로드캐스트 메시지를 수신할 수 없습니다.
|
||||
mcastServiceImpl.waitForMembers.done=잠들기가 끝났습니다. 멤버십이 확립되었고, 시작 레벨은 [{0}]입니다.
|
||||
mcastServiceImpl.waitForMembers.start=클러스터 멤버십을 확립하기 위해, [{0}] 밀리초 동안 잠에 듭니다. 시작 레벨: [{1}]
|
||||
|
||||
memberImpl.invalid.package.begin=유효하지 않은 패키지입니다. [{0}](으)로 시작해야 합니다.
|
||||
memberImpl.invalid.package.end=유효하지 않은 패키지. [{0}](으)로 끝나야 합니다.
|
||||
memberImpl.large.payload=Payload가 너무 커서 tribe들이 처리할 수 없습니다.
|
||||
memberImpl.notEnough.bytes=멤버 데이터 바이트 배열에 충분한 데이터가 존재하지 않습니다.
|
||||
memberImpl.package.small=멤버 패키지가 너무 작아서, 유효한지 확인할 수 없습니다.
|
||||
memberImpl.unableParse.hostname=호스트 이름을 파싱할 수 없습니다.
|
||||
|
||||
staticMember.invalid.uuidLength=UUID는 정확히 16 바이트여야만 합니다. [{0}]이어서는 안됩니다.
|
||||
@@ -0,0 +1,41 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
McastService.parseSoTimeout=无法解析SoTimeout:[{0}]
|
||||
McastService.payload=无法发送负载更新
|
||||
|
||||
mcastService.missing.property=McastService:缺少必需属性 [{0}]。
|
||||
|
||||
mcastServiceImpl.bind=尝试将多播套接字绑定到 [{0}:{1}]
|
||||
mcastServiceImpl.bind.failed=绑定到多播地址失败。仅绑定到端口。
|
||||
mcastServiceImpl.error.receiving=接收mcast包时出错。睡眠500毫秒
|
||||
mcastServiceImpl.invalid.startLevel=无效的启动级别。只接受以下级别:Channel.MBR_RX_SEQ或 Channel.MBR_TX_SEQ
|
||||
mcastServiceImpl.invalid.stopLevel=无效的停止级别。只有Channel.MBR_RX_SEQ和Channel.MBR_TX_SEQ是可接受的级别
|
||||
mcastServiceImpl.recovery=家族成员,运行恢复线程,广播不是功能。
|
||||
mcastServiceImpl.recovery.stopFailed=恢复线程未能停止成员服务。
|
||||
mcastServiceImpl.recovery.successful=成员身份恢复成功。
|
||||
mcastServiceImpl.send.failed=无法发送多播信息
|
||||
mcastServiceImpl.send.running=McastService.send已经运行
|
||||
mcastServiceImpl.setInterface=设置多宿主多播接口为:[{0}]
|
||||
mcastServiceImpl.setSoTimeout=设置集群多播超时时间:[{0}]
|
||||
mcastServiceImpl.setTTL=设置集群多播TTL:[{0}]
|
||||
mcastServiceImpl.unable.join=无法加入多播组,请确保你的系统已启用多播。
|
||||
mcastServiceImpl.unableReceive.broadcastMessage=无法接收广播消息。
|
||||
|
||||
memberImpl.large.payload=负载太大以至于难以处理
|
||||
memberImpl.notEnough.bytes=成员包中的字节不够。
|
||||
memberImpl.package.small=成员包太小以至于不能校验。
|
||||
|
||||
staticMember.invalid.uuidLength=UUID必须正好是16个字节,而不是:[{0}]
|
||||
653
java/org/apache/catalina/tribes/membership/McastService.java
Normal file
653
java/org/apache/catalina/tribes/membership/McastService.java
Normal file
@@ -0,0 +1,653 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.catalina.tribes.membership;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.catalina.tribes.Channel;
|
||||
import org.apache.catalina.tribes.ChannelException;
|
||||
import org.apache.catalina.tribes.ChannelMessage;
|
||||
import org.apache.catalina.tribes.Member;
|
||||
import org.apache.catalina.tribes.MembershipListener;
|
||||
import org.apache.catalina.tribes.MembershipService;
|
||||
import org.apache.catalina.tribes.MessageListener;
|
||||
import org.apache.catalina.tribes.io.ChannelData;
|
||||
import org.apache.catalina.tribes.io.XByteBuffer;
|
||||
import org.apache.catalina.tribes.jmx.JmxRegistry;
|
||||
import org.apache.catalina.tribes.util.Arrays;
|
||||
import org.apache.catalina.tribes.util.StringManager;
|
||||
import org.apache.catalina.tribes.util.UUIDGenerator;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A <b>membership</b> implementation using simple multicast.
|
||||
* This is the representation of a multicast membership service.
|
||||
* This class is responsible for maintaining a list of active cluster nodes in the cluster.
|
||||
* If a node fails to send out a heartbeat, the node will be dismissed.
|
||||
*/
|
||||
public class McastService
|
||||
implements MembershipService,MembershipListener,MessageListener, McastServiceMBean {
|
||||
|
||||
private static final Log log = LogFactory.getLog(McastService.class);
|
||||
|
||||
/**
|
||||
* The string manager for this package.
|
||||
*/
|
||||
protected static final StringManager sm = StringManager.getManager(Constants.Package);
|
||||
|
||||
/**
|
||||
* The implementation specific properties
|
||||
*/
|
||||
protected Properties properties = new Properties();
|
||||
/**
|
||||
* A handle to the actual low level implementation
|
||||
*/
|
||||
protected McastServiceImpl impl;
|
||||
/**
|
||||
* A membership listener delegate (should be the cluster :)
|
||||
*/
|
||||
protected volatile MembershipListener listener;
|
||||
/**
|
||||
* A message listener delegate for broadcasts
|
||||
*/
|
||||
protected MessageListener msglistener;
|
||||
/**
|
||||
* The local member
|
||||
*/
|
||||
protected MemberImpl localMember ;
|
||||
private int mcastSoTimeout;
|
||||
private int mcastTTL;
|
||||
|
||||
protected byte[] payload;
|
||||
|
||||
protected byte[] domain;
|
||||
|
||||
private Channel channel;
|
||||
|
||||
/**
|
||||
* the ObjectName of this McastService.
|
||||
*/
|
||||
private ObjectName oname = null;
|
||||
|
||||
/**
|
||||
* Create a membership service.
|
||||
*/
|
||||
public McastService() {
|
||||
//default values
|
||||
setDefaults(this.properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the properties for the membership service.
|
||||
* @param properties
|
||||
* <br>All are required<br>
|
||||
* 1. mcastPort - the port to listen to<BR>
|
||||
* 2. mcastAddress - the mcast group address<BR>
|
||||
* 4. bindAddress - the bind address if any - only one that can be null<BR>
|
||||
* 5. memberDropTime - the time a member is gone before it is considered gone.<BR>
|
||||
* 6. mcastFrequency - the frequency of sending messages<BR>
|
||||
* 7. tcpListenPort - the port this member listens to<BR>
|
||||
* 8. tcpListenHost - the bind address of this member<BR>
|
||||
* @exception java.lang.IllegalArgumentException if a property is missing.
|
||||
*/
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
hasProperty(properties,"mcastPort");
|
||||
hasProperty(properties,"mcastAddress");
|
||||
hasProperty(properties,"memberDropTime");
|
||||
hasProperty(properties,"mcastFrequency");
|
||||
hasProperty(properties,"tcpListenPort");
|
||||
hasProperty(properties,"tcpListenHost");
|
||||
setDefaults(properties);
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the local member name
|
||||
*/
|
||||
@Override
|
||||
public String getLocalMemberName() {
|
||||
return localMember.toString() ;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Member getLocalMember(boolean alive) {
|
||||
if ( alive && localMember != null && impl != null) localMember.setMemberAliveTime(System.currentTimeMillis()-impl.getServiceStartTime());
|
||||
return localMember;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setLocalMemberProperties(String listenHost, int listenPort, int securePort, int udpPort) {
|
||||
properties.setProperty("tcpListenHost",listenHost);
|
||||
properties.setProperty("tcpListenPort",String.valueOf(listenPort));
|
||||
properties.setProperty("udpListenPort",String.valueOf(udpPort));
|
||||
properties.setProperty("tcpSecurePort",String.valueOf(securePort));
|
||||
try {
|
||||
if (localMember != null) {
|
||||
localMember.setHostname(listenHost);
|
||||
localMember.setPort(listenPort);
|
||||
} else {
|
||||
localMember = new MemberImpl(listenHost, listenPort, 0);
|
||||
localMember.setUniqueId(UUIDGenerator.randomUUID(true));
|
||||
localMember.setPayload(getPayload());
|
||||
localMember.setDomain(getDomain());
|
||||
localMember.setLocal(true);
|
||||
}
|
||||
localMember.setSecurePort(securePort);
|
||||
localMember.setUdpPort(udpPort);
|
||||
localMember.getData(true, true);
|
||||
}catch ( IOException x ) {
|
||||
throw new IllegalArgumentException(x);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAddress(String addr) {
|
||||
properties.setProperty("mcastAddress", addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAddress() {
|
||||
return properties.getProperty("mcastAddress");
|
||||
}
|
||||
|
||||
public void setMcastBindAddress(String bindaddr) {
|
||||
setBind(bindaddr);
|
||||
}
|
||||
|
||||
public void setBind(String bindaddr) {
|
||||
properties.setProperty("mcastBindAddress", bindaddr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBind() {
|
||||
return properties.getProperty("mcastBindAddress");
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
properties.setProperty("mcastPort", String.valueOf(port));
|
||||
}
|
||||
|
||||
public void setRecoveryCounter(int recoveryCounter) {
|
||||
properties.setProperty("recoveryCounter", String.valueOf(recoveryCounter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRecoveryCounter(){
|
||||
String p = properties.getProperty("recoveryCounter");
|
||||
if(p != null){
|
||||
return Integer.parseInt(p);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setRecoveryEnabled(boolean recoveryEnabled) {
|
||||
properties.setProperty("recoveryEnabled", String.valueOf(recoveryEnabled));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getRecoveryEnabled() {
|
||||
String p = properties.getProperty("recoveryEnabled");
|
||||
if(p != null){
|
||||
return Boolean.parseBoolean(p);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setRecoverySleepTime(long recoverySleepTime) {
|
||||
properties.setProperty("recoverySleepTime", String.valueOf(recoverySleepTime));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRecoverySleepTime(){
|
||||
String p = properties.getProperty("recoverySleepTime");
|
||||
if(p != null){
|
||||
return Long.parseLong(p);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setLocalLoopbackDisabled(boolean localLoopbackDisabled) {
|
||||
properties.setProperty("localLoopbackDisabled",String.valueOf(localLoopbackDisabled));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getLocalLoopbackDisabled() {
|
||||
String p = properties.getProperty("localLoopbackDisabled");
|
||||
if(p != null){
|
||||
return Boolean.parseBoolean(p);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
String p = properties.getProperty("mcastPort");
|
||||
return Integer.parseInt(p);
|
||||
}
|
||||
|
||||
public void setFrequency(long time) {
|
||||
properties.setProperty("mcastFrequency", String.valueOf(time));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrequency() {
|
||||
String p = properties.getProperty("mcastFrequency");
|
||||
return Long.parseLong(p);
|
||||
}
|
||||
|
||||
public void setMcastDropTime(long time) {
|
||||
setDropTime(time);
|
||||
}
|
||||
public void setDropTime(long time) {
|
||||
properties.setProperty("memberDropTime", String.valueOf(time));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDropTime() {
|
||||
String p = properties.getProperty("memberDropTime");
|
||||
return Long.parseLong(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a required property is available.
|
||||
* @param properties The set of properties
|
||||
* @param name The property to check for
|
||||
*/
|
||||
protected void hasProperty(Properties properties, String name){
|
||||
if ( properties.getProperty(name)==null) throw new IllegalArgumentException(sm.getString("mcastService.missing.property", name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Start broadcasting and listening to membership pings
|
||||
* @throws java.lang.Exception if a IO error occurs
|
||||
*/
|
||||
@Override
|
||||
public void start() throws java.lang.Exception {
|
||||
start(MembershipService.MBR_RX);
|
||||
start(MembershipService.MBR_TX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(int level) throws java.lang.Exception {
|
||||
hasProperty(properties,"mcastPort");
|
||||
hasProperty(properties,"mcastAddress");
|
||||
hasProperty(properties,"memberDropTime");
|
||||
hasProperty(properties,"mcastFrequency");
|
||||
hasProperty(properties,"tcpListenPort");
|
||||
hasProperty(properties,"tcpListenHost");
|
||||
hasProperty(properties,"tcpSecurePort");
|
||||
hasProperty(properties,"udpListenPort");
|
||||
|
||||
|
||||
if ( impl != null ) {
|
||||
impl.start(level);
|
||||
return;
|
||||
}
|
||||
String host = getProperties().getProperty("tcpListenHost");
|
||||
int port = Integer.parseInt(getProperties().getProperty("tcpListenPort"));
|
||||
int securePort = Integer.parseInt(getProperties().getProperty("tcpSecurePort"));
|
||||
int udpPort = Integer.parseInt(getProperties().getProperty("udpListenPort"));
|
||||
|
||||
if ( localMember == null ) {
|
||||
localMember = new MemberImpl(host, port, 100);
|
||||
localMember.setUniqueId(UUIDGenerator.randomUUID(true));
|
||||
localMember.setLocal(true);
|
||||
} else {
|
||||
localMember.setHostname(host);
|
||||
localMember.setPort(port);
|
||||
localMember.setMemberAliveTime(100);
|
||||
}
|
||||
localMember.setSecurePort(securePort);
|
||||
localMember.setUdpPort(udpPort);
|
||||
if ( this.payload != null ) localMember.setPayload(payload);
|
||||
if ( this.domain != null ) localMember.setDomain(domain);
|
||||
localMember.setServiceStartTime(System.currentTimeMillis());
|
||||
java.net.InetAddress bind = null;
|
||||
if ( properties.getProperty("mcastBindAddress")!= null ) {
|
||||
bind = java.net.InetAddress.getByName(properties.getProperty("mcastBindAddress"));
|
||||
}
|
||||
int ttl = -1;
|
||||
int soTimeout = -1;
|
||||
if ( properties.getProperty("mcastTTL") != null ) {
|
||||
try {
|
||||
ttl = Integer.parseInt(properties.getProperty("mcastTTL"));
|
||||
} catch ( Exception x ) {
|
||||
log.error(sm.getString("McastService.parseTTL",
|
||||
properties.getProperty("mcastTTL")), x);
|
||||
}
|
||||
}
|
||||
if ( properties.getProperty("mcastSoTimeout") != null ) {
|
||||
try {
|
||||
soTimeout = Integer.parseInt(properties.getProperty("mcastSoTimeout"));
|
||||
} catch ( Exception x ) {
|
||||
log.error(sm.getString("McastService.parseSoTimeout",
|
||||
properties.getProperty("mcastSoTimeout")), x);
|
||||
}
|
||||
}
|
||||
|
||||
impl = new McastServiceImpl(localMember,Long.parseLong(properties.getProperty("mcastFrequency")),
|
||||
Long.parseLong(properties.getProperty("memberDropTime")),
|
||||
Integer.parseInt(properties.getProperty("mcastPort")),
|
||||
bind,
|
||||
java.net.InetAddress.getByName(properties.getProperty("mcastAddress")),
|
||||
ttl,
|
||||
soTimeout,
|
||||
this,
|
||||
this,
|
||||
Boolean.parseBoolean(properties.getProperty("localLoopbackDisabled")));
|
||||
String value = properties.getProperty("recoveryEnabled");
|
||||
boolean recEnabled = Boolean.parseBoolean(value);
|
||||
impl.setRecoveryEnabled(recEnabled);
|
||||
int recCnt = Integer.parseInt(properties.getProperty("recoveryCounter"));
|
||||
impl.setRecoveryCounter(recCnt);
|
||||
long recSlpTime = Long.parseLong(properties.getProperty("recoverySleepTime"));
|
||||
impl.setRecoverySleepTime(recSlpTime);
|
||||
impl.setChannel(channel);
|
||||
|
||||
impl.start(level);
|
||||
// register jmx
|
||||
JmxRegistry jmxRegistry = JmxRegistry.getRegistry(channel);
|
||||
if (jmxRegistry != null) {
|
||||
this.oname = jmxRegistry.registerJmx(",component=Membership", this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stop broadcasting and listening to membership pings
|
||||
*/
|
||||
@Override
|
||||
public void stop(int svc) {
|
||||
try {
|
||||
if ( impl != null && impl.stop(svc) ) {
|
||||
if (oname != null) {
|
||||
JmxRegistry.getRegistry(channel).unregisterJmx(oname);
|
||||
oname = null;
|
||||
}
|
||||
impl.setChannel(null);
|
||||
impl = null;
|
||||
channel = null;
|
||||
}
|
||||
} catch ( Exception x) {
|
||||
log.error(sm.getString(
|
||||
"McastService.stopFail", Integer.valueOf(svc)), x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return all the members by name
|
||||
*/
|
||||
@Override
|
||||
public String[] getMembersByName() {
|
||||
Member[] currentMembers = getMembers();
|
||||
String [] membernames ;
|
||||
if(currentMembers != null) {
|
||||
membernames = new String[currentMembers.length];
|
||||
for (int i = 0; i < currentMembers.length; i++) {
|
||||
membernames[i] = currentMembers[i].toString() ;
|
||||
}
|
||||
} else
|
||||
membernames = new String[0] ;
|
||||
return membernames ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the member by name
|
||||
*/
|
||||
@Override
|
||||
public Member findMemberByName(String name) {
|
||||
Member[] currentMembers = getMembers();
|
||||
for (int i = 0; i < currentMembers.length; i++) {
|
||||
if (name.equals(currentMembers[i].toString()))
|
||||
return currentMembers[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* has members?
|
||||
*/
|
||||
@Override
|
||||
public boolean hasMembers() {
|
||||
if ( impl == null || impl.membership == null ) return false;
|
||||
return impl.membership.hasMembers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getMember(Member mbr) {
|
||||
if ( impl == null || impl.membership == null ) return null;
|
||||
return impl.membership.getMember(mbr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the members
|
||||
*/
|
||||
protected static final Member[]EMPTY_MEMBERS = new Member[0];
|
||||
@Override
|
||||
public Member[] getMembers() {
|
||||
if ( impl == null || impl.membership == null ) return EMPTY_MEMBERS;
|
||||
return impl.membership.getMembers();
|
||||
}
|
||||
/**
|
||||
* Add a membership listener, this version only supports one listener per service,
|
||||
* so calling this method twice will result in only the second listener being active.
|
||||
* @param listener The listener
|
||||
*/
|
||||
@Override
|
||||
public void setMembershipListener(MembershipListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setMessageListener(MessageListener listener) {
|
||||
this.msglistener = listener;
|
||||
}
|
||||
|
||||
public void removeMessageListener() {
|
||||
this.msglistener = null;
|
||||
}
|
||||
/**
|
||||
* Remove the membership listener
|
||||
*/
|
||||
@Override
|
||||
public void removeMembershipListener(){
|
||||
listener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void memberAdded(Member member) {
|
||||
MembershipListener listener = this.listener;
|
||||
if (listener != null) {
|
||||
listener.memberAdded(member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from the impl when a new member has been received
|
||||
* @param member The member
|
||||
*/
|
||||
@Override
|
||||
public void memberDisappeared(Member member) {
|
||||
MembershipListener listener = this.listener;
|
||||
if (listener != null) {
|
||||
listener.memberDisappeared(member);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelMessage msg) {
|
||||
if (msglistener!=null && msglistener.accept(msg)) msglistener.messageReceived(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(ChannelMessage msg) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void broadcast(ChannelMessage message) throws ChannelException {
|
||||
if (impl==null || (impl.startLevel & Channel.MBR_TX_SEQ)!=Channel.MBR_TX_SEQ )
|
||||
throw new ChannelException(sm.getString("mcastService.noStart"));
|
||||
|
||||
byte[] data = XByteBuffer.createDataPackage((ChannelData)message);
|
||||
if (data.length>McastServiceImpl.MAX_PACKET_SIZE) {
|
||||
throw new ChannelException(sm.getString("mcastService.exceed.maxPacketSize",
|
||||
Integer.toString(data.length) ,
|
||||
Integer.toString(McastServiceImpl.MAX_PACKET_SIZE)));
|
||||
}
|
||||
DatagramPacket packet = new DatagramPacket(data,0,data.length);
|
||||
try {
|
||||
impl.send(false, packet);
|
||||
} catch (Exception x) {
|
||||
throw new ChannelException(x);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSoTimeout() {
|
||||
return mcastSoTimeout;
|
||||
}
|
||||
|
||||
public void setSoTimeout(int mcastSoTimeout) {
|
||||
this.mcastSoTimeout = mcastSoTimeout;
|
||||
properties.setProperty("mcastSoTimeout", String.valueOf(mcastSoTimeout));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTtl() {
|
||||
return mcastTTL;
|
||||
}
|
||||
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public void setTtl(int mcastTTL) {
|
||||
this.mcastTTL = mcastTTL;
|
||||
properties.setProperty("mcastTTL", String.valueOf(mcastTTL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPayload(byte[] payload) {
|
||||
this.payload = payload;
|
||||
if ( localMember != null ) {
|
||||
localMember.setPayload(payload);
|
||||
try {
|
||||
if (impl != null) impl.send(false);
|
||||
}catch ( Exception x ) {
|
||||
log.error(sm.getString("McastService.payload"), x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDomain(byte[] domain) {
|
||||
this.domain = domain;
|
||||
if ( localMember != null ) {
|
||||
localMember.setDomain(domain);
|
||||
try {
|
||||
if (impl != null) impl.send(false);
|
||||
}catch ( Exception x ) {
|
||||
log.error(sm.getString("McastService.domain"), x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setDomain(String domain) {
|
||||
if ( domain == null ) return;
|
||||
if ( domain.startsWith("{") ) setDomain(Arrays.fromString(domain));
|
||||
else setDomain(Arrays.convert(domain));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChannel(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
protected void setDefaults(Properties properties) {
|
||||
// default values
|
||||
if (properties.getProperty("mcastPort") == null)
|
||||
properties.setProperty("mcastPort","45564");
|
||||
if (properties.getProperty("mcastAddress") == null)
|
||||
properties.setProperty("mcastAddress","228.0.0.4");
|
||||
if (properties.getProperty("memberDropTime") == null)
|
||||
properties.setProperty("memberDropTime","3000");
|
||||
if (properties.getProperty("mcastFrequency") == null)
|
||||
properties.setProperty("mcastFrequency","500");
|
||||
if (properties.getProperty("recoveryCounter") == null)
|
||||
properties.setProperty("recoveryCounter", "10");
|
||||
if (properties.getProperty("recoveryEnabled") == null)
|
||||
properties.setProperty("recoveryEnabled", "true");
|
||||
if (properties.getProperty("recoverySleepTime") == null)
|
||||
properties.setProperty("recoverySleepTime", "5000");
|
||||
if (properties.getProperty("localLoopbackDisabled") == null)
|
||||
properties.setProperty("localLoopbackDisabled", "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple test program
|
||||
* @param args Command-line arguments
|
||||
* @throws Exception If an error occurs
|
||||
*/
|
||||
public static void main(String args[]) throws Exception {
|
||||
McastService service = new McastService();
|
||||
java.util.Properties p = new java.util.Properties();
|
||||
p.setProperty("mcastPort","5555");
|
||||
p.setProperty("mcastAddress","224.10.10.10");
|
||||
p.setProperty("mcastClusterDomain","catalina");
|
||||
p.setProperty("bindAddress","localhost");
|
||||
p.setProperty("memberDropTime","3000");
|
||||
p.setProperty("mcastFrequency","500");
|
||||
p.setProperty("tcpListenPort","4000");
|
||||
p.setProperty("tcpListenHost","127.0.0.1");
|
||||
p.setProperty("tcpSecurePort","4100");
|
||||
p.setProperty("udpListenPort","4200");
|
||||
service.setProperties(p);
|
||||
service.start();
|
||||
Thread.sleep(60*1000*60);
|
||||
}
|
||||
}
|
||||
695
java/org/apache/catalina/tribes/membership/McastServiceImpl.java
Normal file
695
java/org/apache/catalina/tribes/membership/McastServiceImpl.java
Normal file
@@ -0,0 +1,695 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.catalina.tribes.membership;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.BindException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.catalina.tribes.Channel;
|
||||
import org.apache.catalina.tribes.Member;
|
||||
import org.apache.catalina.tribes.MembershipListener;
|
||||
import org.apache.catalina.tribes.MessageListener;
|
||||
import org.apache.catalina.tribes.io.ChannelData;
|
||||
import org.apache.catalina.tribes.io.XByteBuffer;
|
||||
import org.apache.catalina.tribes.util.ExecutorFactory;
|
||||
import org.apache.catalina.tribes.util.StringManager;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A <b>membership</b> implementation using simple multicast.
|
||||
* This is the representation of a multicast membership service.
|
||||
* This class is responsible for maintaining a list of active cluster nodes in the cluster.
|
||||
* If a node fails to send out a heartbeat, the node will be dismissed.
|
||||
* This is the low level implementation that handles the multicasting sockets.
|
||||
* Need to fix this, could use java.nio and only need one thread to send and receive, or
|
||||
* just use a timeout on the receive
|
||||
*/
|
||||
public class McastServiceImpl {
|
||||
|
||||
private static final Log log = LogFactory.getLog(McastService.class);
|
||||
|
||||
protected static final int MAX_PACKET_SIZE = 65535;
|
||||
|
||||
protected static final StringManager sm = StringManager.getManager(Constants.Package);
|
||||
/**
|
||||
* Internal flag used for the listen thread that listens to the multicasting socket.
|
||||
*/
|
||||
protected volatile boolean doRunSender = false;
|
||||
protected volatile boolean doRunReceiver = false;
|
||||
protected volatile int startLevel = 0;
|
||||
/**
|
||||
* Socket that we intend to listen to
|
||||
*/
|
||||
protected MulticastSocket socket;
|
||||
/**
|
||||
* The local member that we intend to broad cast over and over again
|
||||
*/
|
||||
protected final MemberImpl member;
|
||||
/**
|
||||
* The multicast address
|
||||
*/
|
||||
protected final InetAddress address;
|
||||
/**
|
||||
* The multicast port
|
||||
*/
|
||||
protected final int port;
|
||||
/**
|
||||
* The time it takes for a member to expire.
|
||||
*/
|
||||
protected final long timeToExpiration;
|
||||
/**
|
||||
* How often to we send out a broadcast saying we are alive, must be smaller than timeToExpiration
|
||||
*/
|
||||
protected final long sendFrequency;
|
||||
/**
|
||||
* Reuse the sendPacket, no need to create a new one everytime
|
||||
*/
|
||||
protected DatagramPacket sendPacket;
|
||||
/**
|
||||
* Reuse the receivePacket, no need to create a new one everytime
|
||||
*/
|
||||
protected DatagramPacket receivePacket;
|
||||
/**
|
||||
* The membership, used so that we calculate memberships when they arrive or don't arrive
|
||||
*/
|
||||
protected Membership membership;
|
||||
/**
|
||||
* The actual listener, for callback when stuff goes down
|
||||
*/
|
||||
protected final MembershipListener service;
|
||||
/**
|
||||
* The actual listener for broadcast callbacks
|
||||
*/
|
||||
protected final MessageListener msgservice;
|
||||
/**
|
||||
* Thread to listen for pings
|
||||
*/
|
||||
protected ReceiverThread receiver;
|
||||
/**
|
||||
* Thread to send pings
|
||||
*/
|
||||
protected SenderThread sender;
|
||||
|
||||
/**
|
||||
* Time to live for the multicast packets that are being sent out
|
||||
*/
|
||||
protected final int mcastTTL;
|
||||
/**
|
||||
* Read timeout on the mcast socket
|
||||
*/
|
||||
protected int mcastSoTimeout = -1;
|
||||
/**
|
||||
* bind address
|
||||
*/
|
||||
protected final InetAddress mcastBindAddress;
|
||||
|
||||
/**
|
||||
* nr of times the system has to fail before a recovery is initiated
|
||||
*/
|
||||
protected int recoveryCounter = 10;
|
||||
|
||||
/**
|
||||
* The time the recovery thread sleeps between recovery attempts
|
||||
*/
|
||||
protected long recoverySleepTime = 5000;
|
||||
|
||||
/**
|
||||
* Add the ability to turn on/off recovery
|
||||
*/
|
||||
protected boolean recoveryEnabled = true;
|
||||
|
||||
/**
|
||||
* Dont interrupt the sender/receiver thread, but pass off to an executor
|
||||
*/
|
||||
protected final ExecutorService executor =
|
||||
ExecutorFactory.newThreadPool(0, 2, 2, TimeUnit.SECONDS);
|
||||
|
||||
/**
|
||||
* disable/enable local loopback message
|
||||
*/
|
||||
protected final boolean localLoopbackDisabled;
|
||||
|
||||
private Channel channel;
|
||||
|
||||
/**
|
||||
* Create a new mcast service instance.
|
||||
* @param member - the local member
|
||||
* @param sendFrequency - the time (ms) in between pings sent out
|
||||
* @param expireTime - the time (ms) for a member to expire
|
||||
* @param port - the mcast port
|
||||
* @param bind - the bind address (not sure this is used yet)
|
||||
* @param mcastAddress - the mcast address
|
||||
* @param ttl multicast ttl that will be set on the socket
|
||||
* @param soTimeout Socket timeout
|
||||
* @param service - the callback service
|
||||
* @param msgservice Message listener
|
||||
* @param localLoopbackDisabled - disable loopbackMode
|
||||
* @throws IOException Init error
|
||||
*/
|
||||
public McastServiceImpl(
|
||||
MemberImpl member,
|
||||
long sendFrequency,
|
||||
long expireTime,
|
||||
int port,
|
||||
InetAddress bind,
|
||||
InetAddress mcastAddress,
|
||||
int ttl,
|
||||
int soTimeout,
|
||||
MembershipListener service,
|
||||
MessageListener msgservice,
|
||||
boolean localLoopbackDisabled)
|
||||
throws IOException {
|
||||
this.member = member;
|
||||
this.address = mcastAddress;
|
||||
this.port = port;
|
||||
this.mcastSoTimeout = soTimeout;
|
||||
this.mcastTTL = ttl;
|
||||
this.mcastBindAddress = bind;
|
||||
this.timeToExpiration = expireTime;
|
||||
this.service = service;
|
||||
this.msgservice = msgservice;
|
||||
this.sendFrequency = sendFrequency;
|
||||
this.localLoopbackDisabled = localLoopbackDisabled;
|
||||
init();
|
||||
}
|
||||
|
||||
public void init() throws IOException {
|
||||
setupSocket();
|
||||
sendPacket = new DatagramPacket(new byte[MAX_PACKET_SIZE],MAX_PACKET_SIZE);
|
||||
sendPacket.setAddress(address);
|
||||
sendPacket.setPort(port);
|
||||
receivePacket = new DatagramPacket(new byte[MAX_PACKET_SIZE],MAX_PACKET_SIZE);
|
||||
receivePacket.setAddress(address);
|
||||
receivePacket.setPort(port);
|
||||
member.setCommand(new byte[0]);
|
||||
if ( membership == null ) membership = new Membership(member);
|
||||
}
|
||||
|
||||
protected void setupSocket() throws IOException {
|
||||
if (mcastBindAddress != null) {
|
||||
try {
|
||||
log.info(sm.getString("mcastServiceImpl.bind", address, Integer.toString(port)));
|
||||
socket = new MulticastSocket(new InetSocketAddress(address,port));
|
||||
} catch (BindException e) {
|
||||
/*
|
||||
* On some platforms (e.g. Linux) it is not possible to bind
|
||||
* to the multicast address. In this case only bind to the
|
||||
* port.
|
||||
*/
|
||||
log.info(sm.getString("mcastServiceImpl.bind.failed"));
|
||||
socket = new MulticastSocket(port);
|
||||
}
|
||||
} else {
|
||||
socket = new MulticastSocket(port);
|
||||
}
|
||||
socket.setLoopbackMode(localLoopbackDisabled); //hint if we want disable loop back(local machine) messages
|
||||
if (mcastBindAddress != null) {
|
||||
if(log.isInfoEnabled())
|
||||
log.info(sm.getString("mcastServiceImpl.setInterface", mcastBindAddress));
|
||||
socket.setInterface(mcastBindAddress);
|
||||
} //end if
|
||||
//force a so timeout so that we don't block forever
|
||||
if (mcastSoTimeout <= 0) mcastSoTimeout = (int)sendFrequency;
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info(sm.getString("mcastServiceImpl.setSoTimeout",
|
||||
Integer.toString(mcastSoTimeout)));
|
||||
}
|
||||
socket.setSoTimeout(mcastSoTimeout);
|
||||
|
||||
if ( mcastTTL >= 0 ) {
|
||||
if(log.isInfoEnabled())
|
||||
log.info(sm.getString("mcastServiceImpl.setTTL", Integer.toString(mcastTTL)));
|
||||
socket.setTimeToLive(mcastTTL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start the service
|
||||
* @param level 1 starts the receiver, level 2 starts the sender
|
||||
* @throws IOException if the service fails to start
|
||||
* @throws IllegalStateException if the service is already started
|
||||
*/
|
||||
public synchronized void start(int level) throws IOException {
|
||||
boolean valid = false;
|
||||
if ( (level & Channel.MBR_RX_SEQ)==Channel.MBR_RX_SEQ ) {
|
||||
if ( receiver != null ) throw new IllegalStateException(sm.getString("mcastServiceImpl.receive.running"));
|
||||
try {
|
||||
if ( sender == null ) socket.joinGroup(address);
|
||||
}catch (IOException iox) {
|
||||
log.error(sm.getString("mcastServiceImpl.unable.join"));
|
||||
throw iox;
|
||||
}
|
||||
doRunReceiver = true;
|
||||
receiver = new ReceiverThread();
|
||||
receiver.setDaemon(true);
|
||||
receiver.start();
|
||||
valid = true;
|
||||
}
|
||||
if ( (level & Channel.MBR_TX_SEQ)==Channel.MBR_TX_SEQ ) {
|
||||
if ( sender != null ) throw new IllegalStateException(sm.getString("mcastServiceImpl.send.running"));
|
||||
if ( receiver == null ) socket.joinGroup(address);
|
||||
//make sure at least one packet gets out there
|
||||
send(false);
|
||||
doRunSender = true;
|
||||
sender = new SenderThread(sendFrequency);
|
||||
sender.setDaemon(true);
|
||||
sender.start();
|
||||
//we have started the receiver, but not yet waited for membership to establish
|
||||
valid = true;
|
||||
}
|
||||
if (!valid) {
|
||||
throw new IllegalArgumentException(sm.getString("mcastServiceImpl.invalid.startLevel"));
|
||||
}
|
||||
//pause, once or twice
|
||||
waitForMembers(level);
|
||||
startLevel = (startLevel | level);
|
||||
}
|
||||
|
||||
private void waitForMembers(int level) {
|
||||
long memberwait = sendFrequency*2;
|
||||
if(log.isInfoEnabled())
|
||||
log.info(sm.getString("mcastServiceImpl.waitForMembers.start",
|
||||
Long.toString(memberwait), Integer.toString(level)));
|
||||
try {Thread.sleep(memberwait);}catch (InterruptedException ignore){}
|
||||
if(log.isInfoEnabled())
|
||||
log.info(sm.getString("mcastServiceImpl.waitForMembers.done", Integer.toString(level)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the service.
|
||||
* @param level Stop status
|
||||
* @return <code>true</code> if the stop is complete
|
||||
* @throws IOException if the service fails to disconnect from the sockets
|
||||
*/
|
||||
public synchronized boolean stop(int level) throws IOException {
|
||||
boolean valid = false;
|
||||
|
||||
if ( (level & Channel.MBR_RX_SEQ)==Channel.MBR_RX_SEQ ) {
|
||||
valid = true;
|
||||
doRunReceiver = false;
|
||||
if ( receiver !=null ) receiver.interrupt();
|
||||
receiver = null;
|
||||
}
|
||||
if ( (level & Channel.MBR_TX_SEQ)==Channel.MBR_TX_SEQ ) {
|
||||
valid = true;
|
||||
doRunSender = false;
|
||||
if ( sender != null )sender.interrupt();
|
||||
sender = null;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
throw new IllegalArgumentException(sm.getString("mcastServiceImpl.invalid.stopLevel"));
|
||||
}
|
||||
startLevel = (startLevel & (~level));
|
||||
//we're shutting down, send a shutdown message and close the socket
|
||||
if ( startLevel == 0 ) {
|
||||
//send a stop message
|
||||
member.setCommand(Member.SHUTDOWN_PAYLOAD);
|
||||
send(false);
|
||||
//leave mcast group
|
||||
try {socket.leaveGroup(address);}catch ( Exception ignore){}
|
||||
try {socket.close();}catch ( Exception ignore){}
|
||||
member.setServiceStartTime(-1);
|
||||
}
|
||||
return (startLevel == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive a datagram packet, locking wait
|
||||
* @throws IOException Received failed
|
||||
*/
|
||||
public void receive() throws IOException {
|
||||
boolean checkexpired = true;
|
||||
try {
|
||||
|
||||
socket.receive(receivePacket);
|
||||
if(receivePacket.getLength() > MAX_PACKET_SIZE) {
|
||||
log.error(sm.getString("mcastServiceImpl.packet.tooLong",
|
||||
Integer.toString(receivePacket.getLength())));
|
||||
} else {
|
||||
byte[] data = new byte[receivePacket.getLength()];
|
||||
System.arraycopy(receivePacket.getData(), receivePacket.getOffset(), data, 0, data.length);
|
||||
if (XByteBuffer.firstIndexOf(data,0,MemberImpl.TRIBES_MBR_BEGIN)==0) {
|
||||
memberDataReceived(data);
|
||||
} else {
|
||||
memberBroadcastsReceived(data);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (SocketTimeoutException x ) {
|
||||
//do nothing, this is normal, we don't want to block forever
|
||||
//since the receive thread is the same thread
|
||||
//that does membership expiration
|
||||
}
|
||||
if (checkexpired) checkExpired();
|
||||
}
|
||||
|
||||
private void memberDataReceived(byte[] data) {
|
||||
final Member m = MemberImpl.getMember(data);
|
||||
if (log.isTraceEnabled()) log.trace("Mcast receive ping from member " + m);
|
||||
Runnable t = null;
|
||||
if (Arrays.equals(m.getCommand(), Member.SHUTDOWN_PAYLOAD)) {
|
||||
if (log.isDebugEnabled()) log.debug("Member has shutdown:" + m);
|
||||
membership.removeMember(m);
|
||||
t = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String name = Thread.currentThread().getName();
|
||||
try {
|
||||
Thread.currentThread().setName("Membership-MemberDisappeared.");
|
||||
service.memberDisappeared(m);
|
||||
}finally {
|
||||
Thread.currentThread().setName(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
} else if (membership.memberAlive(m)) {
|
||||
if (log.isDebugEnabled()) log.debug("Mcast add member " + m);
|
||||
t = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String name = Thread.currentThread().getName();
|
||||
try {
|
||||
Thread.currentThread().setName("Membership-MemberAdded.");
|
||||
service.memberAdded(m);
|
||||
}finally {
|
||||
Thread.currentThread().setName(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
} //end if
|
||||
if ( t != null ) {
|
||||
executor.execute(t);
|
||||
}
|
||||
}
|
||||
|
||||
private void memberBroadcastsReceived(final byte[] b) {
|
||||
if (log.isTraceEnabled()) log.trace("Mcast received broadcasts.");
|
||||
XByteBuffer buffer = new XByteBuffer(b,true);
|
||||
if (buffer.countPackages(true)>0) {
|
||||
int count = buffer.countPackages();
|
||||
final ChannelData[] data = new ChannelData[count];
|
||||
for (int i=0; i<count; i++) {
|
||||
try {
|
||||
data[i] = buffer.extractPackage(true);
|
||||
}catch (IllegalStateException ise) {
|
||||
log.debug("Unable to decode message.",ise);
|
||||
}
|
||||
}
|
||||
Runnable t = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String name = Thread.currentThread().getName();
|
||||
try {
|
||||
Thread.currentThread().setName("Membership-MemberAdded.");
|
||||
for (int i=0; i<data.length; i++ ) {
|
||||
try {
|
||||
if (data[i]!=null && !member.equals(data[i].getAddress())) {
|
||||
msgservice.messageReceived(data[i]);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (t instanceof ThreadDeath) {
|
||||
throw (ThreadDeath) t;
|
||||
}
|
||||
if (t instanceof VirtualMachineError) {
|
||||
throw (VirtualMachineError) t;
|
||||
}
|
||||
log.error(sm.getString("mcastServiceImpl.unableReceive.broadcastMessage"),t);
|
||||
}
|
||||
}
|
||||
}finally {
|
||||
Thread.currentThread().setName(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
executor.execute(t);
|
||||
}
|
||||
}
|
||||
|
||||
protected final Object expiredMutex = new Object();
|
||||
protected void checkExpired() {
|
||||
synchronized (expiredMutex) {
|
||||
Member[] expired = membership.expire(timeToExpiration);
|
||||
for (int i = 0; i < expired.length; i++) {
|
||||
final Member member = expired[i];
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Mcast expire member " + expired[i]);
|
||||
try {
|
||||
Runnable t = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String name = Thread.currentThread().getName();
|
||||
try {
|
||||
Thread.currentThread().setName("Membership-MemberExpired.");
|
||||
service.memberDisappeared(member);
|
||||
}finally {
|
||||
Thread.currentThread().setName(name);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
executor.execute(t);
|
||||
} catch (Exception x) {
|
||||
log.error(sm.getString("mcastServiceImpl.memberDisappeared.failed"), x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a ping.
|
||||
* @param checkexpired <code>true</code> to check for expiration
|
||||
* @throws IOException Send error
|
||||
*/
|
||||
public void send(boolean checkexpired) throws IOException {
|
||||
send(checkexpired,null);
|
||||
}
|
||||
|
||||
private final Object sendLock = new Object();
|
||||
|
||||
public void send(boolean checkexpired, DatagramPacket packet) throws IOException {
|
||||
checkexpired = (checkexpired && (packet==null));
|
||||
//ignore if we haven't started the sender
|
||||
//if ( (startLevel&Channel.MBR_TX_SEQ) != Channel.MBR_TX_SEQ ) return;
|
||||
if (packet==null) {
|
||||
member.inc();
|
||||
if(log.isTraceEnabled()) {
|
||||
log.trace("Mcast send ping from member " + member);
|
||||
}
|
||||
byte[] data = member.getData();
|
||||
packet = new DatagramPacket(data,data.length);
|
||||
} else if (log.isTraceEnabled()) {
|
||||
log.trace("Sending message broadcast "+packet.getLength()+ " bytes from "+ member);
|
||||
}
|
||||
packet.setAddress(address);
|
||||
packet.setPort(port);
|
||||
//TODO this operation is not thread safe
|
||||
synchronized (sendLock) {
|
||||
socket.send(packet);
|
||||
}
|
||||
if ( checkexpired ) checkExpired();
|
||||
}
|
||||
|
||||
public long getServiceStartTime() {
|
||||
return (member!=null) ? member.getServiceStartTime() : -1l;
|
||||
}
|
||||
|
||||
public int getRecoveryCounter() {
|
||||
return recoveryCounter;
|
||||
}
|
||||
|
||||
public boolean isRecoveryEnabled() {
|
||||
return recoveryEnabled;
|
||||
}
|
||||
|
||||
public long getRecoverySleepTime() {
|
||||
return recoverySleepTime;
|
||||
}
|
||||
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public class ReceiverThread extends Thread {
|
||||
int errorCounter = 0;
|
||||
public ReceiverThread() {
|
||||
super();
|
||||
String channelName = "";
|
||||
if (channel.getName() != null) channelName = "[" + channel.getName() + "]";
|
||||
setName("Tribes-MembershipReceiver" + channelName);
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
while ( doRunReceiver ) {
|
||||
try {
|
||||
receive();
|
||||
errorCounter=0;
|
||||
} catch ( ArrayIndexOutOfBoundsException ax ) {
|
||||
//we can ignore this, as it means we have an invalid package
|
||||
//but we will log it to debug
|
||||
if ( log.isDebugEnabled() )
|
||||
log.debug("Invalid member mcast package.",ax);
|
||||
} catch ( Exception x ) {
|
||||
if (errorCounter==0 && doRunReceiver) log.warn(sm.getString("mcastServiceImpl.error.receiving"),x);
|
||||
else if (log.isDebugEnabled()) log.debug("Error receiving mcast package"+(doRunReceiver?". Sleeping 500ms":"."),x);
|
||||
if (doRunReceiver) {
|
||||
try { Thread.sleep(500); } catch ( Exception ignore ){}
|
||||
if ( (++errorCounter)>=recoveryCounter ) {
|
||||
errorCounter=0;
|
||||
RecoveryThread.recover(McastServiceImpl.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}//class ReceiverThread
|
||||
|
||||
public class SenderThread extends Thread {
|
||||
final long time;
|
||||
int errorCounter=0;
|
||||
public SenderThread(long time) {
|
||||
this.time = time;
|
||||
String channelName = "";
|
||||
if (channel.getName() != null) channelName = "[" + channel.getName() + "]";
|
||||
setName("Tribes-MembershipSender" + channelName);
|
||||
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
while ( doRunSender ) {
|
||||
try {
|
||||
send(true);
|
||||
errorCounter = 0;
|
||||
} catch ( Exception x ) {
|
||||
if (errorCounter==0) log.warn(sm.getString("mcastServiceImpl.send.failed"),x);
|
||||
else log.debug("Unable to send mcast message.",x);
|
||||
if ( (++errorCounter)>=recoveryCounter ) {
|
||||
errorCounter=0;
|
||||
RecoveryThread.recover(McastServiceImpl.this);
|
||||
}
|
||||
}
|
||||
try { Thread.sleep(time); } catch ( Exception ignore ) {}
|
||||
}
|
||||
}
|
||||
}//class SenderThread
|
||||
|
||||
protected static class RecoveryThread extends Thread {
|
||||
|
||||
private static final AtomicBoolean running = new AtomicBoolean(false);
|
||||
|
||||
public static synchronized void recover(McastServiceImpl parent) {
|
||||
|
||||
if (!parent.isRecoveryEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!running.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Thread t = new RecoveryThread(parent);
|
||||
String channelName = "";
|
||||
if (parent.channel.getName() != null) channelName = "[" + parent.channel.getName() + "]";
|
||||
t.setName("Tribes-MembershipRecovery" + channelName);
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
}
|
||||
|
||||
|
||||
final McastServiceImpl parent;
|
||||
public RecoveryThread(McastServiceImpl parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public boolean stopService() {
|
||||
try {
|
||||
parent.stop(Channel.MBR_RX_SEQ | Channel.MBR_TX_SEQ);
|
||||
return true;
|
||||
} catch (Exception x) {
|
||||
log.warn(sm.getString("mcastServiceImpl.recovery.stopFailed"), x);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean startService() {
|
||||
try {
|
||||
parent.init();
|
||||
parent.start(Channel.MBR_RX_SEQ | Channel.MBR_TX_SEQ);
|
||||
return true;
|
||||
} catch (Exception x) {
|
||||
log.warn(sm.getString("mcastServiceImpl.recovery.startFailed"), x);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
boolean success = false;
|
||||
int attempt = 0;
|
||||
try {
|
||||
while (!success) {
|
||||
if(log.isInfoEnabled())
|
||||
log.info(sm.getString("mcastServiceImpl.recovery"));
|
||||
if (stopService() & startService()) {
|
||||
success = true;
|
||||
if(log.isInfoEnabled())
|
||||
log.info(sm.getString("mcastServiceImpl.recovery.successful"));
|
||||
}
|
||||
try {
|
||||
if (!success) {
|
||||
if(log.isInfoEnabled())
|
||||
log.info(sm.getString("mcastServiceImpl.recovery.failed",
|
||||
Integer.toString(++attempt),
|
||||
Long.toString(parent.recoverySleepTime)));
|
||||
Thread.sleep(parent.recoverySleepTime);
|
||||
}
|
||||
}catch (InterruptedException ignore) {
|
||||
}
|
||||
}
|
||||
}finally {
|
||||
running.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setRecoveryCounter(int recoveryCounter) {
|
||||
this.recoveryCounter = recoveryCounter;
|
||||
}
|
||||
|
||||
public void setRecoveryEnabled(boolean recoveryEnabled) {
|
||||
this.recoveryEnabled = recoveryEnabled;
|
||||
}
|
||||
|
||||
public void setRecoverySleepTime(long recoverySleepTime) {
|
||||
this.recoverySleepTime = recoverySleepTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.catalina.tribes.membership;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.catalina.tribes.Member;
|
||||
|
||||
public interface McastServiceMBean {
|
||||
|
||||
// Attributes
|
||||
public String getAddress();
|
||||
|
||||
public int getPort();
|
||||
|
||||
public long getFrequency();
|
||||
|
||||
public long getDropTime();
|
||||
|
||||
public String getBind();
|
||||
|
||||
public int getTtl();
|
||||
|
||||
public byte[] getDomain();
|
||||
|
||||
public int getSoTimeout();
|
||||
|
||||
public boolean getRecoveryEnabled();
|
||||
|
||||
public int getRecoveryCounter();
|
||||
|
||||
public long getRecoverySleepTime();
|
||||
|
||||
public boolean getLocalLoopbackDisabled();
|
||||
|
||||
public String getLocalMemberName();
|
||||
|
||||
// Operation
|
||||
public Properties getProperties();
|
||||
|
||||
public boolean hasMembers();
|
||||
|
||||
public String[] getMembersByName();
|
||||
|
||||
public Member findMemberByName(String name);
|
||||
}
|
||||
687
java/org/apache/catalina/tribes/membership/MemberImpl.java
Normal file
687
java/org/apache/catalina/tribes/membership/MemberImpl.java
Normal file
@@ -0,0 +1,687 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.catalina.tribes.membership;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.catalina.tribes.Member;
|
||||
import org.apache.catalina.tribes.io.XByteBuffer;
|
||||
import org.apache.catalina.tribes.transport.SenderState;
|
||||
import org.apache.catalina.tribes.util.StringManager;
|
||||
|
||||
/**
|
||||
* A <b>membership</b> implementation using simple multicast.
|
||||
* This is the representation of a multicast member.
|
||||
* Carries the host, and port of the this or other cluster nodes.
|
||||
*/
|
||||
public class MemberImpl implements Member, java.io.Externalizable {
|
||||
|
||||
/**
|
||||
* Should a call to getName or getHostName try to do a DNS lookup?
|
||||
* default is false
|
||||
*/
|
||||
public static final boolean DO_DNS_LOOKUPS = Boolean.parseBoolean(System.getProperty("org.apache.catalina.tribes.dns_lookups","false"));
|
||||
|
||||
public static final transient byte[] TRIBES_MBR_BEGIN = new byte[] {84, 82, 73, 66, 69, 83, 45, 66, 1, 0};
|
||||
public static final transient byte[] TRIBES_MBR_END = new byte[] {84, 82, 73, 66, 69, 83, 45, 69, 1, 0};
|
||||
protected static final StringManager sm = StringManager.getManager(Constants.Package);
|
||||
|
||||
/**
|
||||
* The listen host for this member
|
||||
*/
|
||||
protected volatile byte[] host = new byte[0];
|
||||
protected transient volatile String hostname;
|
||||
/**
|
||||
* The tcp listen port for this member
|
||||
*/
|
||||
protected volatile int port;
|
||||
/**
|
||||
* The udp listen port for this member
|
||||
*/
|
||||
protected volatile int udpPort = -1;
|
||||
|
||||
/**
|
||||
* The tcp/SSL listen port for this member
|
||||
*/
|
||||
protected volatile int securePort = -1;
|
||||
|
||||
/**
|
||||
* Counter for how many broadcast messages have been sent from this member
|
||||
*/
|
||||
protected AtomicInteger msgCount = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* The number of milliseconds since this member was
|
||||
* created, is kept track of using the start time
|
||||
*/
|
||||
protected volatile long memberAliveTime = 0;
|
||||
|
||||
/**
|
||||
* For the local member only
|
||||
*/
|
||||
protected transient long serviceStartTime;
|
||||
|
||||
/**
|
||||
* To avoid serialization over and over again, once the local dataPkg
|
||||
* has been set, we use that to transmit data
|
||||
*/
|
||||
protected transient byte[] dataPkg = null;
|
||||
|
||||
/**
|
||||
* Unique session Id for this member
|
||||
*/
|
||||
protected volatile byte[] uniqueId = new byte[16];
|
||||
|
||||
/**
|
||||
* Custom payload that an app framework can broadcast
|
||||
* Also used to transport stop command.
|
||||
*/
|
||||
protected volatile byte[] payload = new byte[0];
|
||||
|
||||
/**
|
||||
* Command, so that the custom payload doesn't have to be used
|
||||
* This is for internal tribes use, such as SHUTDOWN_COMMAND
|
||||
*/
|
||||
protected volatile byte[] command = new byte[0];
|
||||
|
||||
/**
|
||||
* Domain if we want to filter based on domain.
|
||||
*/
|
||||
protected volatile byte[] domain = new byte[0];
|
||||
|
||||
/**
|
||||
* The flag indicating that this member is a local member.
|
||||
*/
|
||||
protected volatile boolean local = false;
|
||||
|
||||
/**
|
||||
* Empty constructor for serialization
|
||||
*/
|
||||
public MemberImpl() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new member object.
|
||||
*
|
||||
* @param host - the tcp listen host
|
||||
* @param port - the tcp listen port
|
||||
* @param aliveTime - the number of milliseconds since this member was created
|
||||
*
|
||||
* @throws IOException If there is an error converting the host name to an
|
||||
* IP address
|
||||
*/
|
||||
public MemberImpl(String host,
|
||||
int port,
|
||||
long aliveTime) throws IOException {
|
||||
setHostname(host);
|
||||
this.port = port;
|
||||
this.memberAliveTime=aliveTime;
|
||||
}
|
||||
|
||||
public MemberImpl(String host,
|
||||
int port,
|
||||
long aliveTime,
|
||||
byte[] payload) throws IOException {
|
||||
this(host,port,aliveTime);
|
||||
setPayload(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return SenderState.getSenderState(this).isReady();
|
||||
}
|
||||
@Override
|
||||
public boolean isSuspect() {
|
||||
return SenderState.getSenderState(this).isSuspect();
|
||||
}
|
||||
@Override
|
||||
public boolean isFailing() {
|
||||
return SenderState.getSenderState(this).isFailing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the message count.
|
||||
*/
|
||||
protected void inc() {
|
||||
msgCount.incrementAndGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a data package to send over the wire representing this member.
|
||||
* This is faster than serialization.
|
||||
* @return - the bytes for this member deserialized
|
||||
*/
|
||||
public byte[] getData() {
|
||||
return getData(true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] getData(boolean getalive) {
|
||||
return getData(getalive,false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized int getDataLength() {
|
||||
return TRIBES_MBR_BEGIN.length+ //start pkg
|
||||
4+ //data length
|
||||
8+ //alive time
|
||||
4+ //port
|
||||
4+ //secure port
|
||||
4+ //udp port
|
||||
1+ //host length
|
||||
host.length+ //host
|
||||
4+ //command length
|
||||
command.length+ //command
|
||||
4+ //domain length
|
||||
domain.length+ //domain
|
||||
16+ //unique id
|
||||
4+ //payload length
|
||||
payload.length+ //payload
|
||||
TRIBES_MBR_END.length; //end pkg
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized byte[] getData(boolean getalive, boolean reset) {
|
||||
if (reset) {
|
||||
dataPkg = null;
|
||||
}
|
||||
// Look in cache first
|
||||
if (dataPkg != null) {
|
||||
if (getalive) {
|
||||
// You'd be surprised, but System.currentTimeMillis
|
||||
// shows up on the profiler
|
||||
long alive = System.currentTimeMillis() - getServiceStartTime();
|
||||
byte[] result = dataPkg.clone();
|
||||
XByteBuffer.toBytes(alive, result, TRIBES_MBR_BEGIN.length + 4);
|
||||
dataPkg = result;
|
||||
}
|
||||
return dataPkg;
|
||||
}
|
||||
|
||||
//package looks like
|
||||
//start package TRIBES_MBR_BEGIN.length
|
||||
//package length - 4 bytes
|
||||
//alive - 8 bytes
|
||||
//port - 4 bytes
|
||||
//secure port - 4 bytes
|
||||
//udp port - 4 bytes
|
||||
//host length - 1 byte
|
||||
//host - hl bytes
|
||||
//clen - 4 bytes
|
||||
//command - clen bytes
|
||||
//dlen - 4 bytes
|
||||
//domain - dlen bytes
|
||||
//uniqueId - 16 bytes
|
||||
//payload length - 4 bytes
|
||||
//payload plen bytes
|
||||
//end package TRIBES_MBR_END.length
|
||||
long alive=System.currentTimeMillis()-getServiceStartTime();
|
||||
byte[] data = new byte[getDataLength()];
|
||||
|
||||
int bodylength = (getDataLength() - TRIBES_MBR_BEGIN.length - TRIBES_MBR_END.length - 4);
|
||||
|
||||
int pos = 0;
|
||||
|
||||
//TRIBES_MBR_BEGIN
|
||||
System.arraycopy(TRIBES_MBR_BEGIN,0,data,pos,TRIBES_MBR_BEGIN.length);
|
||||
pos += TRIBES_MBR_BEGIN.length;
|
||||
|
||||
//body length
|
||||
XByteBuffer.toBytes(bodylength,data,pos);
|
||||
pos += 4;
|
||||
|
||||
//alive data
|
||||
XByteBuffer.toBytes(alive,data,pos);
|
||||
pos += 8;
|
||||
//port
|
||||
XByteBuffer.toBytes(port,data,pos);
|
||||
pos += 4;
|
||||
//secure port
|
||||
XByteBuffer.toBytes(securePort,data,pos);
|
||||
pos += 4;
|
||||
//udp port
|
||||
XByteBuffer.toBytes(udpPort,data,pos);
|
||||
pos += 4;
|
||||
//host length
|
||||
data[pos++] = (byte) host.length;
|
||||
//host
|
||||
System.arraycopy(host,0,data,pos,host.length);
|
||||
pos+=host.length;
|
||||
//clen - 4 bytes
|
||||
XByteBuffer.toBytes(command.length,data,pos);
|
||||
pos+=4;
|
||||
//command - clen bytes
|
||||
System.arraycopy(command,0,data,pos,command.length);
|
||||
pos+=command.length;
|
||||
//dlen - 4 bytes
|
||||
XByteBuffer.toBytes(domain.length,data,pos);
|
||||
pos+=4;
|
||||
//domain - dlen bytes
|
||||
System.arraycopy(domain,0,data,pos,domain.length);
|
||||
pos+=domain.length;
|
||||
//unique Id
|
||||
System.arraycopy(uniqueId,0,data,pos,uniqueId.length);
|
||||
pos+=uniqueId.length;
|
||||
//payload
|
||||
XByteBuffer.toBytes(payload.length,data,pos);
|
||||
pos+=4;
|
||||
System.arraycopy(payload,0,data,pos,payload.length);
|
||||
pos+=payload.length;
|
||||
|
||||
//TRIBES_MBR_END
|
||||
System.arraycopy(TRIBES_MBR_END,0,data,pos,TRIBES_MBR_END.length);
|
||||
pos += TRIBES_MBR_END.length;
|
||||
|
||||
//create local data
|
||||
dataPkg = data;
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* Deserializes a member from data sent over the wire.
|
||||
*
|
||||
* @param data The bytes received
|
||||
* @param member The member object to populate
|
||||
*
|
||||
* @return The populated member object.
|
||||
*/
|
||||
public static Member getMember(byte[] data, MemberImpl member) {
|
||||
return getMember(data,0,data.length,member);
|
||||
}
|
||||
|
||||
public static Member getMember(byte[] data, int offset, int length, MemberImpl member) {
|
||||
//package looks like
|
||||
//start package TRIBES_MBR_BEGIN.length
|
||||
//package length - 4 bytes
|
||||
//alive - 8 bytes
|
||||
//port - 4 bytes
|
||||
//secure port - 4 bytes
|
||||
//udp port - 4 bytes
|
||||
//host length - 1 byte
|
||||
//host - hl bytes
|
||||
//clen - 4 bytes
|
||||
//command - clen bytes
|
||||
//dlen - 4 bytes
|
||||
//domain - dlen bytes
|
||||
//uniqueId - 16 bytes
|
||||
//payload length - 4 bytes
|
||||
//payload plen bytes
|
||||
//end package TRIBES_MBR_END.length
|
||||
|
||||
int pos = offset;
|
||||
|
||||
if (XByteBuffer.firstIndexOf(data,offset,TRIBES_MBR_BEGIN)!=pos) {
|
||||
throw new IllegalArgumentException(sm.getString("memberImpl.invalid.package.begin", org.apache.catalina.tribes.util.Arrays.toString(TRIBES_MBR_BEGIN)));
|
||||
}
|
||||
|
||||
if ( length < (TRIBES_MBR_BEGIN.length+4) ) {
|
||||
throw new ArrayIndexOutOfBoundsException(sm.getString("memberImpl.package.small"));
|
||||
}
|
||||
|
||||
pos += TRIBES_MBR_BEGIN.length;
|
||||
|
||||
int bodylength = XByteBuffer.toInt(data,pos);
|
||||
pos += 4;
|
||||
|
||||
if ( length < (bodylength+4+TRIBES_MBR_BEGIN.length+TRIBES_MBR_END.length) ) {
|
||||
throw new ArrayIndexOutOfBoundsException(sm.getString("memberImpl.notEnough.bytes"));
|
||||
}
|
||||
|
||||
int endpos = pos+bodylength;
|
||||
if (XByteBuffer.firstIndexOf(data,endpos,TRIBES_MBR_END)!=endpos) {
|
||||
throw new IllegalArgumentException(sm.getString("memberImpl.invalid.package.end", org.apache.catalina.tribes.util.Arrays.toString(TRIBES_MBR_END)));
|
||||
}
|
||||
|
||||
|
||||
byte[] alived = new byte[8];
|
||||
System.arraycopy(data, pos, alived, 0, 8);
|
||||
pos += 8;
|
||||
byte[] portd = new byte[4];
|
||||
System.arraycopy(data, pos, portd, 0, 4);
|
||||
pos += 4;
|
||||
|
||||
byte[] sportd = new byte[4];
|
||||
System.arraycopy(data, pos, sportd, 0, 4);
|
||||
pos += 4;
|
||||
|
||||
byte[] uportd = new byte[4];
|
||||
System.arraycopy(data, pos, uportd, 0, 4);
|
||||
pos += 4;
|
||||
|
||||
|
||||
byte hl = data[pos++];
|
||||
byte[] addr = new byte[hl];
|
||||
System.arraycopy(data, pos, addr, 0, hl);
|
||||
pos += hl;
|
||||
|
||||
int cl = XByteBuffer.toInt(data, pos);
|
||||
pos += 4;
|
||||
|
||||
byte[] command = new byte[cl];
|
||||
System.arraycopy(data, pos, command, 0, command.length);
|
||||
pos += command.length;
|
||||
|
||||
int dl = XByteBuffer.toInt(data, pos);
|
||||
pos += 4;
|
||||
|
||||
byte[] domain = new byte[dl];
|
||||
System.arraycopy(data, pos, domain, 0, domain.length);
|
||||
pos += domain.length;
|
||||
|
||||
byte[] uniqueId = new byte[16];
|
||||
System.arraycopy(data, pos, uniqueId, 0, 16);
|
||||
pos += 16;
|
||||
|
||||
int pl = XByteBuffer.toInt(data, pos);
|
||||
pos += 4;
|
||||
|
||||
byte[] payload = new byte[pl];
|
||||
System.arraycopy(data, pos, payload, 0, payload.length);
|
||||
pos += payload.length;
|
||||
|
||||
member.setHost(addr);
|
||||
member.setPort(XByteBuffer.toInt(portd, 0));
|
||||
member.setSecurePort(XByteBuffer.toInt(sportd, 0));
|
||||
member.setUdpPort(XByteBuffer.toInt(uportd, 0));
|
||||
member.setMemberAliveTime(XByteBuffer.toLong(alived, 0));
|
||||
member.setUniqueId(uniqueId);
|
||||
member.payload = payload;
|
||||
member.domain = domain;
|
||||
member.command = command;
|
||||
|
||||
member.dataPkg = new byte[length];
|
||||
System.arraycopy(data, offset, member.dataPkg, 0, length);
|
||||
|
||||
return member;
|
||||
}
|
||||
|
||||
public static Member getMember(byte[] data) {
|
||||
return getMember(data,new MemberImpl());
|
||||
}
|
||||
|
||||
public static Member getMember(byte[] data, int offset, int length) {
|
||||
return getMember(data,offset,length,new MemberImpl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of this object
|
||||
* @return a unique name to the cluster
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "tcp://"+getHostname()+":"+getPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the listen port of this member
|
||||
* @return - tcp listen port
|
||||
*/
|
||||
@Override
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the TCP listen host for this member
|
||||
* @return IP address or host name
|
||||
*/
|
||||
@Override
|
||||
public byte[] getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
if ( this.hostname != null ) return hostname;
|
||||
else {
|
||||
try {
|
||||
byte[] host = this.host;
|
||||
if (DO_DNS_LOOKUPS)
|
||||
this.hostname = java.net.InetAddress.getByAddress(host).getHostName();
|
||||
else
|
||||
this.hostname = org.apache.catalina.tribes.util.Arrays.toString(host,0,host.length,true);
|
||||
return this.hostname;
|
||||
}catch ( IOException x ) {
|
||||
throw new RuntimeException(sm.getString("memberImpl.unableParse.hostname"),x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getMsgCount() {
|
||||
return msgCount.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains information on how long this member has been online.
|
||||
* The result is the number of milli seconds this member has been
|
||||
* broadcasting its membership to the cluster.
|
||||
* @return nr of milliseconds since this member started.
|
||||
*/
|
||||
@Override
|
||||
public long getMemberAliveTime() {
|
||||
return memberAliveTime;
|
||||
}
|
||||
|
||||
public long getServiceStartTime() {
|
||||
return serviceStartTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getUniqueId() {
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSecurePort() {
|
||||
return securePort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUdpPort() {
|
||||
return udpPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMemberAliveTime(long time) {
|
||||
memberAliveTime=time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* String representation of this object
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(getClass().getName());
|
||||
buf.append("[");
|
||||
buf.append(getName()).append(",");
|
||||
buf.append(getHostname()).append(",");
|
||||
buf.append(port).append(", alive=");
|
||||
buf.append(memberAliveTime).append(", ");
|
||||
buf.append("securePort=").append(securePort).append(", ");
|
||||
buf.append("UDP Port=").append(udpPort).append(", ");
|
||||
buf.append("id=").append(bToS(this.uniqueId)).append(", ");
|
||||
buf.append("payload=").append(bToS(this.payload,8)).append(", ");
|
||||
buf.append("command=").append(bToS(this.command,8)).append(", ");
|
||||
buf.append("domain=").append(bToS(this.domain,8));
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
public static String bToS(byte[] data) {
|
||||
return bToS(data,data.length);
|
||||
}
|
||||
public static String bToS(byte[] data, int max) {
|
||||
StringBuilder buf = new StringBuilder(4*16);
|
||||
buf.append("{");
|
||||
for (int i=0; data!=null && i<data.length; i++ ) {
|
||||
buf.append(String.valueOf(data[i])).append(" ");
|
||||
if ( i==max ) {
|
||||
buf.append("...("+data.length+")");
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf.append("}");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
* @return The hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getHost()[0]+getHost()[1]+getHost()[2]+getHost()[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the param o is a McastMember with the same name
|
||||
*
|
||||
* @param o The object to test for equality
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( o instanceof MemberImpl ) {
|
||||
return Arrays.equals(this.getHost(),((MemberImpl)o).getHost()) &&
|
||||
this.getPort() == ((MemberImpl)o).getPort() &&
|
||||
Arrays.equals(this.getUniqueId(),((MemberImpl)o).getUniqueId());
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized void setHost(byte[] host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public void setHostname(String host) throws IOException {
|
||||
hostname = host;
|
||||
synchronized (this) {
|
||||
this.host = java.net.InetAddress.getByName(host).getAddress();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMsgCount(int msgCount) {
|
||||
this.msgCount.set(msgCount);
|
||||
}
|
||||
|
||||
public synchronized void setPort(int port) {
|
||||
this.port = port;
|
||||
this.dataPkg = null;
|
||||
}
|
||||
|
||||
public void setServiceStartTime(long serviceStartTime) {
|
||||
this.serviceStartTime = serviceStartTime;
|
||||
}
|
||||
|
||||
public synchronized void setUniqueId(byte[] uniqueId) {
|
||||
this.uniqueId = uniqueId!=null?uniqueId:new byte[16];
|
||||
getData(true,true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setPayload(byte[] payload) {
|
||||
// longs to avoid any possibility of overflow
|
||||
long oldPayloadLength = 0;
|
||||
if (this.payload != null) {
|
||||
oldPayloadLength = this.payload.length;
|
||||
}
|
||||
long newPayloadLength = 0;
|
||||
if (payload != null) {
|
||||
newPayloadLength = payload.length;
|
||||
}
|
||||
if (newPayloadLength > oldPayloadLength) {
|
||||
// It is possible that the max packet size will be exceeded
|
||||
if ((newPayloadLength - oldPayloadLength + getData(false, false).length) >
|
||||
McastServiceImpl.MAX_PACKET_SIZE) {
|
||||
throw new IllegalArgumentException(sm.getString("memberImpl.large.payload"));
|
||||
}
|
||||
}
|
||||
this.payload = payload != null ? payload : new byte[0];
|
||||
getData(true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setCommand(byte[] command) {
|
||||
this.command = command!=null?command:new byte[0];
|
||||
getData(true,true);
|
||||
}
|
||||
|
||||
public synchronized void setDomain(byte[] domain) {
|
||||
this.domain = domain!=null?domain:new byte[0];
|
||||
getData(true,true);
|
||||
}
|
||||
|
||||
public synchronized void setSecurePort(int securePort) {
|
||||
this.securePort = securePort;
|
||||
this.dataPkg = null;
|
||||
}
|
||||
|
||||
public synchronized void setUdpPort(int port) {
|
||||
this.udpPort = port;
|
||||
this.dataPkg = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return local;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocal(boolean local) {
|
||||
this.local = local;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
int length = in.readInt();
|
||||
byte[] message = new byte[length];
|
||||
in.readFully(message);
|
||||
getMember(message,this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
byte[] data = this.getData();
|
||||
out.writeInt(data.length);
|
||||
out.write(data);
|
||||
}
|
||||
|
||||
}
|
||||
350
java/org/apache/catalina/tribes/membership/Membership.java
Normal file
350
java/org/apache/catalina/tribes/membership/Membership.java
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.catalina.tribes.membership;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.catalina.tribes.Member;
|
||||
|
||||
/**
|
||||
* A <b>membership</b> implementation using simple multicast.
|
||||
* This is the representation of a multicast membership.
|
||||
* This class is responsible for maintaining a list of active cluster nodes in the cluster.
|
||||
* If a node fails to send out a heartbeat, the node will be dismissed.
|
||||
*
|
||||
* @author Peter Rossbach
|
||||
*/
|
||||
public class Membership implements Cloneable {
|
||||
|
||||
protected static final Member[] EMPTY_MEMBERS = new Member[0];
|
||||
|
||||
// Non-final to support clone()
|
||||
private Object membersLock = new Object();
|
||||
|
||||
/**
|
||||
* The local member.
|
||||
*/
|
||||
protected final Member local;
|
||||
|
||||
/**
|
||||
* A map of all the members in the cluster.
|
||||
*/
|
||||
protected HashMap<Member, MbrEntry> map = new HashMap<>(); // Guarded by membersLock
|
||||
|
||||
/**
|
||||
* A list of all the members in the cluster.
|
||||
*/
|
||||
protected volatile Member[] members = EMPTY_MEMBERS; // Guarded by membersLock
|
||||
|
||||
/**
|
||||
* Comparator for sorting members by alive time.
|
||||
*/
|
||||
protected final Comparator<Member> memberComparator;
|
||||
|
||||
@Override
|
||||
public Membership clone() {
|
||||
synchronized (membersLock) {
|
||||
Membership clone;
|
||||
try {
|
||||
clone = (Membership) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// Can't happen
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
// Standard clone() method will copy the map object. Replace that
|
||||
// with a new map but with the same contents.
|
||||
@SuppressWarnings("unchecked")
|
||||
final HashMap<Member, MbrEntry> tmpclone = (HashMap<Member, MbrEntry>) map.clone();
|
||||
clone.map = tmpclone;
|
||||
|
||||
// Standard clone() method will copy the array object. Replace that
|
||||
// with a new array but with the same contents.
|
||||
clone.members = members.clone();
|
||||
|
||||
// Standard clone() method will copy the lock object. Replace that
|
||||
// with a new object.
|
||||
clone.membersLock = new Object();
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new membership
|
||||
* @param local - has to be the name of the local member. Used to filter the local member from the cluster membership
|
||||
* @param includeLocal - TBA
|
||||
*/
|
||||
public Membership(Member local, boolean includeLocal) {
|
||||
this(local, new MemberComparator(), includeLocal);
|
||||
}
|
||||
|
||||
public Membership(Member local) {
|
||||
this(local, false);
|
||||
}
|
||||
|
||||
public Membership(Member local, Comparator<Member> comp) {
|
||||
this(local, comp, false);
|
||||
}
|
||||
|
||||
public Membership(Member local, Comparator<Member> comp, boolean includeLocal) {
|
||||
this.local = local;
|
||||
this.memberComparator = comp;
|
||||
if (includeLocal) {
|
||||
addMember(local);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the membership and start over fresh. i.e., delete all the members
|
||||
* and wait for them to ping again and join this membership.
|
||||
*/
|
||||
public void reset() {
|
||||
synchronized (membersLock) {
|
||||
map.clear();
|
||||
members = EMPTY_MEMBERS ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the membership that this member has announced itself.
|
||||
*
|
||||
* @param member - the member that just pinged us
|
||||
* @return - true if this member is new to the cluster, false otherwise.<br>
|
||||
* - false if this member is the local member or updated.
|
||||
*/
|
||||
public boolean memberAlive(Member member) {
|
||||
// Ignore ourselves
|
||||
if (member.equals(local)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = false;
|
||||
synchronized (membersLock) {
|
||||
MbrEntry entry = map.get(member);
|
||||
if (entry == null) {
|
||||
entry = addMember(member);
|
||||
result = true;
|
||||
} else {
|
||||
// Update the member alive time
|
||||
Member updateMember = entry.getMember();
|
||||
if (updateMember.getMemberAliveTime() != member.getMemberAliveTime()) {
|
||||
// Update fields that can change
|
||||
updateMember.setMemberAliveTime(member.getMemberAliveTime());
|
||||
updateMember.setPayload(member.getPayload());
|
||||
updateMember.setCommand(member.getCommand());
|
||||
// Re-order. Can't sort in place since a call to
|
||||
// getMembers() may then receive an intermediate result.
|
||||
Member[] newMembers = members.clone();
|
||||
Arrays.sort(newMembers, memberComparator);
|
||||
members = newMembers;
|
||||
}
|
||||
}
|
||||
entry.accessed();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a member to this component and sort array with memberComparator
|
||||
*
|
||||
* @param member The member to add
|
||||
*
|
||||
* @return The member entry created for this new member.
|
||||
*/
|
||||
public MbrEntry addMember(Member member) {
|
||||
MbrEntry entry = new MbrEntry(member);
|
||||
synchronized (membersLock) {
|
||||
if (!map.containsKey(member) ) {
|
||||
map.put(member, entry);
|
||||
Member results[] = new Member[members.length + 1];
|
||||
System.arraycopy(members, 0, results, 0, members.length);
|
||||
results[members.length] = member;
|
||||
Arrays.sort(results, memberComparator);
|
||||
members = results;
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a member from this component.
|
||||
*
|
||||
* @param member The member to remove
|
||||
*/
|
||||
public void removeMember(Member member) {
|
||||
synchronized (membersLock) {
|
||||
map.remove(member);
|
||||
int n = -1;
|
||||
for (int i = 0; i < members.length; i++) {
|
||||
if (members[i] == member || members[i].equals(member)) {
|
||||
n = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n < 0) return;
|
||||
Member results[] = new Member[members.length - 1];
|
||||
int j = 0;
|
||||
for (int i = 0; i < members.length; i++) {
|
||||
if (i != n) {
|
||||
results[j++] = members[i];
|
||||
}
|
||||
}
|
||||
members = results;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a refresh cycle and returns a list of members that has expired.
|
||||
* This also removes the members from the membership, in such a way that
|
||||
* getMembers() = getMembers() - expire()
|
||||
* @param maxtime - the max time a member can remain unannounced before it is considered dead.
|
||||
* @return the list of expired members
|
||||
*/
|
||||
public Member[] expire(long maxtime) {
|
||||
synchronized (membersLock) {
|
||||
if (!hasMembers()) {
|
||||
return EMPTY_MEMBERS;
|
||||
}
|
||||
|
||||
ArrayList<Member> list = null;
|
||||
for (MbrEntry entry : map.values()) {
|
||||
if (entry.hasExpired(maxtime)) {
|
||||
if (list == null) {
|
||||
// Only need a list when members are expired (smaller gc)
|
||||
list = new java.util.ArrayList<>();
|
||||
}
|
||||
list.add(entry.getMember());
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null) {
|
||||
Member[] result = new Member[list.size()];
|
||||
list.toArray(result);
|
||||
for (int j=0; j<result.length; j++) {
|
||||
removeMember(result[j]);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return EMPTY_MEMBERS ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returning that service has members or not.
|
||||
*
|
||||
* @return <code>true</code> if there are one or more members, otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean hasMembers() {
|
||||
return members.length > 0;
|
||||
}
|
||||
|
||||
|
||||
public Member getMember(Member mbr) {
|
||||
Member[] members = this.members;
|
||||
if (members.length > 0) {
|
||||
for (int i = 0; i < members.length; i++) {
|
||||
if (members[i].equals(mbr)) {
|
||||
return members[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean contains(Member mbr) {
|
||||
return getMember(mbr) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returning a list of all the members in the membership.
|
||||
* We not need a copy: add and remove generate new arrays.
|
||||
*
|
||||
* @return An array of the current members
|
||||
*/
|
||||
public Member[] getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------- Inner Class
|
||||
|
||||
private static class MemberComparator implements Comparator<Member>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public int compare(Member m1, Member m2) {
|
||||
// Longer alive time, means sort first
|
||||
long result = m2.getMemberAliveTime() - m1.getMemberAliveTime();
|
||||
if (result < 0) {
|
||||
return -1;
|
||||
} else if (result == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class that represents a member entry
|
||||
*/
|
||||
protected static class MbrEntry {
|
||||
|
||||
protected final Member mbr;
|
||||
protected long lastHeardFrom;
|
||||
|
||||
public MbrEntry(Member mbr) {
|
||||
this.mbr = mbr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that this member has been accessed.
|
||||
*/
|
||||
public void accessed(){
|
||||
lastHeardFrom = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the member associated with this entry.
|
||||
*
|
||||
* @return The member for this entry.
|
||||
*/
|
||||
public Member getMember() {
|
||||
return mbr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this member has expired.
|
||||
*
|
||||
* @param maxtime The time threshold
|
||||
*
|
||||
* @return <code>true</code> if the member has expired, otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean hasExpired(long maxtime) {
|
||||
long delta = System.currentTimeMillis() - lastHeardFrom;
|
||||
return delta > maxtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
java/org/apache/catalina/tribes/membership/StaticMember.java
Normal file
67
java/org/apache/catalina/tribes/membership/StaticMember.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.catalina.tribes.membership;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.catalina.tribes.util.Arrays;
|
||||
|
||||
public class StaticMember extends MemberImpl {
|
||||
public StaticMember() {
|
||||
super();
|
||||
}
|
||||
|
||||
public StaticMember(String host, int port, long aliveTime) throws IOException {
|
||||
super(host, port, aliveTime);
|
||||
}
|
||||
|
||||
public StaticMember(String host, int port, long aliveTime, byte[] payload) throws IOException {
|
||||
super(host, port, aliveTime, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param host String, either in byte array string format, like {214,116,1,3}
|
||||
* or as a regular hostname, 127.0.0.1 or tomcat01.mydomain.com
|
||||
*/
|
||||
public void setHost(String host) {
|
||||
if ( host == null ) return;
|
||||
if ( host.startsWith("{") ) setHost(Arrays.fromString(host));
|
||||
else try { setHostname(host); }catch (IOException x) { throw new RuntimeException(x);}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param domain String, either in byte array string format, like {214,116,1,3}
|
||||
* or as a regular string value like 'mydomain'. The latter will be converted using ISO-8859-1 encoding
|
||||
*/
|
||||
public void setDomain(String domain) {
|
||||
if ( domain == null ) return;
|
||||
if ( domain.startsWith("{") ) setDomain(Arrays.fromString(domain));
|
||||
else setDomain(Arrays.convert(domain));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id String, must be in byte array string format, like {214,116,1,3} and exactly 16 bytes long
|
||||
*/
|
||||
public void setUniqueId(String id) {
|
||||
byte[] uuid = Arrays.fromString(id);
|
||||
if ( uuid==null || uuid.length != 16 ) throw new RuntimeException(sm.getString("staticMember.invalid.uuidLength", id));
|
||||
setUniqueId(uuid);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!DOCTYPE mbeans-descriptors PUBLIC
|
||||
"-//Apache Software Foundation//DTD Model MBeans Configuration File"
|
||||
"http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">
|
||||
<mbeans-descriptors>
|
||||
<mbean
|
||||
name="McastService"
|
||||
description="Cluster Membership service implementation"
|
||||
domain="Catalina"
|
||||
group="Cluster"
|
||||
type="org.apache.catalina.tribes.membership.McastService">
|
||||
<attribute
|
||||
name="address"
|
||||
description="Multicast IP Address"
|
||||
type="java.lang.String"/>
|
||||
<attribute
|
||||
name="bind"
|
||||
description="Multicast IP Interface address (default auto)"
|
||||
type="java.lang.String"/>
|
||||
<attribute
|
||||
name="dropTime"
|
||||
description="Timeout from frequency ping after member disappear notify"
|
||||
type="long"/>
|
||||
<attribute
|
||||
name="frequency"
|
||||
description="Ping Frequency at msec"
|
||||
type="long"/>
|
||||
<attribute
|
||||
name="localLoopbackDisabled"
|
||||
description="Is local loopback disabled?"
|
||||
is="true"
|
||||
type="boolean"/>
|
||||
<attribute
|
||||
name="localMemberName"
|
||||
description="Complete local receiver information"
|
||||
type="java.lang.String"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="membersByName"
|
||||
description="Complete remote sender information"
|
||||
type="[Ljava.lang.String;"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="port"
|
||||
description="Multicast UDP Port"
|
||||
type="int"/>
|
||||
<attribute
|
||||
name="recoveryCounter"
|
||||
description="Counter after membership failure socket restarted"
|
||||
type="int"/>
|
||||
<attribute
|
||||
name="recoveryEnabled"
|
||||
description="Membership recovery enabled"
|
||||
is="true"
|
||||
type="boolean"/>
|
||||
<attribute
|
||||
name="recoverySleepTime"
|
||||
description="Sleep time between next socket recovery (5000 msec)"
|
||||
type="long"/>
|
||||
<attribute
|
||||
name="soTimeout"
|
||||
description="Multicast Socket Timeout"
|
||||
type="int"/>
|
||||
<attribute
|
||||
name="Ttl"
|
||||
description=""
|
||||
type="int"/>
|
||||
<operation
|
||||
name="start"
|
||||
description="Start the cluster membership"
|
||||
impact="ACTION"
|
||||
returnType="void"/>
|
||||
<operation
|
||||
name="stop"
|
||||
description="Stop the cluster membership"
|
||||
impact="ACTION"
|
||||
returnType="void"/>
|
||||
</mbean>
|
||||
<mbean
|
||||
name="MemberImpl"
|
||||
description="Cluster member"
|
||||
domain="Catalina"
|
||||
group="Cluster"
|
||||
type="org.apache.catalina.tribes.membership.MemberImpl">
|
||||
<attribute
|
||||
name="failing"
|
||||
description="Has a problem been observed with this member (failing is worse than suspect)"
|
||||
type="boolean"
|
||||
is="true"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="hostname"
|
||||
description="The name of the host where this member is located"
|
||||
type="String"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="memberAliveTime"
|
||||
description="The number of milliseconds since this member was created"
|
||||
type="long"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="msgCount"
|
||||
description="The number of messages sent by this member"
|
||||
type="int"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="name"
|
||||
description="The unique name of this member within the cluster"
|
||||
type="String"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="port"
|
||||
description="The tcp port the member is listening on"
|
||||
type="int"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="ready"
|
||||
description="Is this member ready to send messages"
|
||||
type="boolean"
|
||||
is="true"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="securePort"
|
||||
description="The tcp(SSL) port the member is listening on"
|
||||
type="int"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="serviceStartTime"
|
||||
description="The time the member was started"
|
||||
type="long"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="suspect"
|
||||
description="Has a potential problem been observed with this member (failing is worse than suspect)"
|
||||
type="boolean"
|
||||
is="true"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="udpPort"
|
||||
description="The upd port the member is listening on"
|
||||
type="int"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="local"
|
||||
description="The flag indicating that this member is a local member"
|
||||
type="boolean"
|
||||
is="true"
|
||||
writeable="false"/>
|
||||
</mbean>
|
||||
<mbean
|
||||
name="StaticMember"
|
||||
description="Cluster static member"
|
||||
domain="Catalina"
|
||||
group="Cluster"
|
||||
type="org.apache.catalina.tribes.membership.StaticMember">
|
||||
<attribute
|
||||
name="failing"
|
||||
description="Has a problem been observed with this member (failing is worse than suspect)"
|
||||
type="boolean"
|
||||
is="true"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="hostname"
|
||||
description="The name of the host where this member is located"
|
||||
type="String"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="memberAliveTime"
|
||||
description="The number of milliseconds since this member was created"
|
||||
type="long"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="msgCount"
|
||||
description="The number of messages sent by this member"
|
||||
type="int"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="name"
|
||||
description="The unique name of this member within the cluster"
|
||||
type="String"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="port"
|
||||
description="The tcp port the member is listening on"
|
||||
type="int"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="ready"
|
||||
description="Is this member ready to send messages"
|
||||
type="boolean"
|
||||
is="true"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="securePort"
|
||||
description="The tcp(SSL) port the member is listening on"
|
||||
type="int"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="serviceStartTime"
|
||||
description="The time the member was started"
|
||||
type="long"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="suspect"
|
||||
description="Has a potential problem been observed with this member (failing is worse than suspect)"
|
||||
type="boolean"
|
||||
is="true"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="udpPort"
|
||||
description="The upd port the member is listening on"
|
||||
type="int"
|
||||
writeable="false"/>
|
||||
<attribute
|
||||
name="local"
|
||||
description="The flag indicating that this member is a local member"
|
||||
type="boolean"
|
||||
is="true"
|
||||
writeable="false"/>
|
||||
</mbean>
|
||||
</mbeans-descriptors>
|
||||
Reference in New Issue
Block a user