This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
# 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.
nioReceiver.alreadyStarted=ServerSocketChannel already started
nioReceiver.cleanup.fail=Unable to cleanup on selector close
nioReceiver.clientDisconnect=Replication client disconnected, error when polling key. Ignoring client.
nioReceiver.requestError=Unable to process request in NioReceiver
nioReceiver.run.fail=Unable to run replication listener
nioReceiver.start.fail=Unable to start cluster receiver
nioReceiver.stop.fail=Unable to close cluster receiver selector
nioReceiver.stop.threadRunning=The NioReceiver thread did not stop in a timely manner. Errors may be observed when the selector is closed.
nioReceiver.threadpool.fail=ThreadPool cannot be initialized. Listener not started.
nioReceiver.threadsExhausted=Channel key is registered, but has had no interest ops for the last [{0}] ms. (cancelled: [{1}]):[{2}] last access:[{3}] Possible cause: all threads used, perform thread dump
nioReplicationTask.error.register.key=Error registering key for read:[{0}]
nioReplicationTask.exception.drainChannel=Exception caught in TcpReplicationThread.drainChannel.
nioReplicationTask.process.clusterMsg.failed=Processing of cluster message failed.
nioReplicationTask.unable.ack=Unable to send ACK back through channel, channel disconnected?: [{0}]
nioReplicationTask.unable.drainChannel.ioe=IOException in replication worker, unable to drain channel. Probable cause: Keep alive socket closed[{0}].
nioSender.already.connected=NioSender is already in connected state.
nioSender.datagram.already.established=Datagram channel has already been established. Connection might be in progress.
nioSender.key.inValid=Key is not valid, it must have been cancelled.
nioSender.not.connected=NioSender is not connected, this should not occur.
nioSender.receive.failedAck=Received a failed ack:org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA
nioSender.sender.disconnected=Sender has been disconnected, can't process selection key.
nioSender.socketChannel.already.established=Socket channel has already been established. Connection might be in progress.
nioSender.unable.disconnect=Unable to disconnect NioSender. msg=[{0}]
nioSender.unable.receive.ack=Unable to receive an ack message. EOF on socket channel has been reached.
nioSender.unknown.state=Data is in unknown state. readyOps=[{0}]
parallelNioSender.error.keepalive=Error during keepalive test for sender:[{0}]
parallelNioSender.operation.timedout=Operation has timed out([{0}] ms.).
parallelNioSender.send.fail=Member send is failing for:[{0}] ; Setting to suspect.
parallelNioSender.send.fail.retrying=Member send is failing for:[{0}] ; Setting to suspect and retrying.
parallelNioSender.send.failed=Parallel NIO send failed.
parallelNioSender.sendFailed.attempt=Send failed, attempt:[{0}] max:[{1}]
parallelNioSender.sender.disconnected.notRetry=Not retrying send for:[{0}]; Sender is disconnected.
parallelNioSender.sender.disconnected.sendFailed=Send failed, and sender is disconnected. Not retrying.
parallelNioSender.unable.setup.NioSender=Unable to setup NioSender.
pooledParallelSender.sender.disconnected=Sender not connected.
pooledParallelSender.unable.open=Unable to open NIO selector.
pooledParallelSender.unable.retrieveSender=Unable to retrieve a sender from the sender pool
pooledParallelSender.unable.retrieveSender.timeout=Unable to retrieve a data sender, time out([{0}] ms) error.

View File

@@ -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.
nioReceiver.start.fail=Cluster-Empfänger konnte nicht gestartet werden
nioReceiver.stop.fail=Kann den Cluster Receiver Selektor nicht schliessen
nioReceiver.threadpool.fail=ThreadPool kann nicht initialisiert werden. Der Listener wird nicht gestartet.
nioReplicationTask.process.clusterMsg.failed=Verarbeitung der Cluster Nachricht fehlgeschlagen.
nioSender.unknown.state=Daten sind in unbekanntem Zustand. readyOps=[{0}]
pooledParallelSender.sender.disconnected=Sender nicht verbunden

View 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.
nioReceiver.cleanup.fail=Imposible hacer limpieza en el cierre del selector
nioReceiver.start.fail=Incapaz de iniciar el recividor del cluster
nioReceiver.stop.fail=No fue posible cerrar el selector de recepción del cluster
nioReceiver.threadpool.fail=ThreadPool no pudo ser inicializado. Escuchador no iniciado.\n
nioReplicationTask.error.register.key=Error al registrar la llave para lectura:[{0}]
nioReplicationTask.process.clusterMsg.failed=Fallo al procesar el mensaje del cluster
nioReplicationTask.unable.ack=No se pudo devolver el ACK a travez del canal. Esta el canal desconectado?: [{0}]\n
nioSender.not.connected=El NioSender no esta conectado, esto no deberia ocurrir.\n
nioSender.unknown.state=Los Datos estan en un estado desconocido. readyOps=[{0}]
parallelNioSender.send.fail.retrying=El envió de miembro esta fallando por:[{0}] ; Fijándolo como sospechoso y reintentando.
parallelNioSender.send.failed=Fallo al enviar NIO paralelo.
parallelNioSender.sendFailed.attempt=Fallo de envío, intento:[{0}] máximo:[{1}]\n
parallelNioSender.sender.disconnected.sendFailed=Envio fallido, y el remitente esta desconctado. No intentando nuevamente.\n
pooledParallelSender.sender.disconnected=El remitente no esta conectado
pooledParallelSender.unable.retrieveSender=Incapaz de recuperar el enviador desde el pool de enviadores

View File

@@ -0,0 +1,57 @@
# 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.
nioReceiver.alreadyStarted=ServerSocketChannel est déjà démarré
nioReceiver.cleanup.fail=Impossible de nettoyer lors de la fermeture du sélecteur
nioReceiver.clientDisconnect=Le client de réplication est déconnecté, erreur lors du "polling" de clé. Le client est ignoré.
nioReceiver.requestError=Impossible de traiter la requête dans NioReceiver
nioReceiver.run.fail=Impossible d'exécuter l'écouteur de réplication
nioReceiver.start.fail=Incapable de démarrer le récepteur de cluster
nioReceiver.stop.fail=Incapable de femer le sélecteur de récepteur de cluster ("cluster receiver selector")
nioReceiver.stop.threadRunning=Le thread NioReceiver ne s'est pas arrêté suffisamment rapidement, des erreurs peuvent se produire lorsque le sélecteur sera fermé
nioReceiver.threadpool.fail=Le ThreadPool n'a pas pu être initialisé. Le Listener n'a pas démarré.
nioReceiver.threadsExhausted=La clé du canal est enregistrée mais n''a pas reçue d''opérations qui l''intéressaient depuis [{0}] ms (annulé: [{1}]):[{2}] dernier accès: [{3}] cause possible: tous les threads sont utilisés, effectuez un dump des threads
nioReplicationTask.error.register.key=Erreur lors de l''enregistrement de la clé en lecture: [{0}]
nioReplicationTask.exception.drainChannel=Erreur rencontrée dans TcpReplicationThread.drainChannel
nioReplicationTask.process.clusterMsg.failed=Le traitement du message du cluster a échoué
nioReplicationTask.unable.ack=Impossible d''envoyer un ACK réponse par le canal, le canal peut avoir été déconnecté: [{0}]
nioReplicationTask.unable.drainChannel.ioe=IOException pendant le traitement de la réplication, impossible de drainer le canal, cause probable: le socket gardé actif a été fermé [{0}]
nioSender.already.connected=NioSender est déjà dans l'état connecté
nioSender.datagram.already.established=Le canal de datagramme a déjà été établi, une connection peut être déjà en cours
nioSender.key.inValid=La clé est invalide, elle doit avoir été annulée
nioSender.not.connected=NioSender n'est pas connecté, cela ne devrait jamais arriver
nioSender.receive.failedAck=Réception d'un échec de confirmation:org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA
nioSender.sender.disconnected=L'envoyeur s'est déconnecté, impossible d'envoyer la clé de sélection
nioSender.socketChannel.already.established=Le canal du socket a déjà été établi, la connection est peut-être déjà en cours
nioSender.unable.disconnect=Impossible de déconnecter le NioSender, msg=[{0}]
nioSender.unable.receive.ack=Impossible de recevoir un message de confirmation, le canal a rencontré l'EOF
nioSender.unknown.state=Les données sont dans un état inconnu. readyOps=[{0}]
parallelNioSender.error.keepalive=Erreur lors du test de temps d''attente pour l''expéditeur [{0}]
parallelNioSender.operation.timedout=L''opération a dépassé le temps imparti ([{0}] ms)
parallelNioSender.send.fail=L''envoi d''un membre a échoué pour [{0}], le membre est considéré suspect
parallelNioSender.send.fail.retrying=L''envoi au membre[{0}] ne fonctionne pas ; Marqué comme suspect et nouvel essai.
parallelNioSender.send.failed=L'envoi NIO en parallèle a échoué
parallelNioSender.sendFailed.attempt=Echec de l''envoi, tentative: [{0}] maximum:[{1}]
parallelNioSender.sender.disconnected.notRetry=Pas de réessai d''envoi de [{0}], l''expéditeur s''est déconnecté
parallelNioSender.sender.disconnected.sendFailed=L'envoi a échoué et l'envoyeur est déconnecté, pas de nouvel essai
parallelNioSender.unable.setup.NioSender=Impossible d'installer un NioSender
pooledParallelSender.sender.disconnected=Emetteur non connecté
pooledParallelSender.unable.open=Impossible d'ouvrir le sélecteur NIO
pooledParallelSender.unable.retrieveSender=Impossible d'obtenir un envoyeur depuis le pool
pooledParallelSender.unable.retrieveSender.timeout=Impossible d''obtenir un expéditeur de données, temps d''attente dépassé ([{0}] ms)

View File

@@ -0,0 +1,57 @@
# 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.
nioReceiver.alreadyStarted=ServerSocketChannel は既に開始しています。
nioReceiver.cleanup.fail=セレクターの切断と後始末が失敗しました。
nioReceiver.clientDisconnect=レプリケーションクライアントが切断されました。ポーリングキーでエラーが発生しました。 クライアントを無視します。
nioReceiver.requestError=NioReceiverでリクエストを処理できません
nioReceiver.run.fail=レプリケーションリスナーを実行できません。
nioReceiver.start.fail=クラスタレシーバを起動出来ません
nioReceiver.stop.fail=クラスターレシーバーのセレクタを切断できませんでした。
nioReceiver.stop.threadRunning=NioReceiver スレッドは時間内に停止できませんでした。Selectorを切断するときに異常を検出した可能性があります。
nioReceiver.threadpool.fail=ThreadPool を初期化できません。リスナーを開始しませんでした。
nioReceiver.threadsExhausted=チャネルキーは登録されていますが、最後の[{0}]ミリ秒間はinterest ops がありませんでした。 (キャンセル {1}][{2}]最終アクセス:[{3}]考えられる原因:すべてのスレッドが使用され、スレッドダンプを実行します。
nioReplicationTask.error.register.key=読み取り用のキーを登録するときに異常が発生しました: [{0}]
nioReplicationTask.exception.drainChannel=TcpReplicationThread.drainChannelで例外をキャッチしました。
nioReplicationTask.process.clusterMsg.failed=クラスターメッセージを処理できませんでした。
nioReplicationTask.unable.ack=チャンネルから ACK を送信できません。切断されている可能性があります。: [{0}]
nioReplicationTask.unable.drainChannel.ioe=レプリケーションワーカーのIOException、チャネルを排除できません。 考えられる原因:キープアライブソケットが切断[{0}]。
nioSender.already.connected=NioSenderはすでに接続された状態です。
nioSender.datagram.already.established=データグラムチャネルはすでに確立されています。 コネクションが進行中である可能性があります。
nioSender.key.inValid=キーは無効です。キャンセルされている必要があります。
nioSender.not.connected=NioSender は接続していません。これは発生するべきではない事象です。
nioSender.receive.failedAck=失敗したackを受け取りましたorg.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA
nioSender.sender.disconnected=Sender が切断されました。Selectキーを処理できません。
nioSender.socketChannel.already.established=ソケットチャネルはすでに確立されています。 接続が進行中である可能性があります。
nioSender.unable.disconnect=NioSenderを切断できません。 msg = [{0}]
nioSender.unable.receive.ack=レスポンスメッセージを受信できません。ソケットチャンネルは終端に達しています。
nioSender.unknown.state=不明な状態です。実行可能操作セット=[{0}]
parallelNioSender.error.keepalive=Sender[{0}]のキープアライブテスト中にエラーが発生しました。
parallelNioSender.operation.timedout=操作がタイムアウトしました([{0}]ミリ秒)。
parallelNioSender.send.fail=メンバーの送信に失敗しました:[{0}]; Settingに設定します。
parallelNioSender.send.fail.retrying=[{0}] へのメッセージ送信が失敗しました。状態を SUSPECT へ変更して再送します。
parallelNioSender.send.failed=パラレル NIO 送信の失敗
parallelNioSender.sendFailed.attempt=送信に失敗しました:試行[{0}] 最大:[{1}]
parallelNioSender.sender.disconnected.notRetry=再試行していません:[{0}]; Sender が切断されました。
parallelNioSender.sender.disconnected.sendFailed=送信が失敗しました。送信先との接続も失われています。再送信を行いません。
parallelNioSender.unable.setup.NioSender=NioSenderのセットアップが出来ません。
pooledParallelSender.sender.disconnected=Sender 接続されていません。
pooledParallelSender.unable.open=NIO selectorをオープン出来ません。
pooledParallelSender.unable.retrieveSender=SenderプールからSenderを取得できません
pooledParallelSender.unable.retrieveSender.timeout=データSenderを取得できません。タイムアウト[{0}] msエラー。

View File

@@ -0,0 +1,57 @@
# 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.
nioReceiver.alreadyStarted=ServerSocketChannel이 이미 시작되었습니다.
nioReceiver.cleanup.fail=selector close 시에 cleanup을 할 수 없습니다.
nioReceiver.clientDisconnect=복제 클라이언트가 연결이 끊겼습니다. 키를 poll할 때, 오류가 발생했습니다. 해당 클라이언트는 무시됩니다.
nioReceiver.requestError=NioReceiver에서 요청을 처리할 수 없습니다.
nioReceiver.run.fail=복제 리스너를 실행할 수 없습니다.
nioReceiver.start.fail=클러스터 receiver를 시작 할 수 없습니다.
nioReceiver.stop.fail=클러스터 receiver selector를 닫을 수 없습니다.
nioReceiver.stop.threadRunning=NioReceiver 쓰레드가 적절한 시간 내에 중지되지 않았습니다. Selector가 닫힐 때에 오류들이 발견될 수 있습니다.
nioReceiver.threadpool.fail=쓰레드풀을 초기화할 수 없습니다. 리스너가 시작되지 못했습니다.
nioReceiver.threadsExhausted=채널 키가 등록되지만, 마지막 [{0}] 밀리초 동안에 어떠한 interest 오퍼레이션도 없었습니다 (취소 여부: [{1}]). 키:[{2}], 최종 접근 시간:[{3}], 있을 법한 사유: 모든 쓰레드들이 사용 중이고, 쓰레드 덤프 수행.
nioReplicationTask.error.register.key=읽기를 위한 키 등록 중 오류 발생: [{0}]
nioReplicationTask.exception.drainChannel=TcpReplicationThread.drainChannel에서 예외 발생
nioReplicationTask.process.clusterMsg.failed=클러스터 메시지 처리가 실패했습니다.
nioReplicationTask.unable.ack=채널을 통해 ACK을 되돌려 전송할 수 없습니다. 채널이 단절되었나요?: [{0}]
nioReplicationTask.unable.drainChannel.ioe=복제 worker에서 IOException이 발생했으며, 채널을 깨끗이 비울 수 없습니다. 있음직한 사유: Keep alive 소켓이 닫히는 경우. [{0}]
nioSender.already.connected=NioSender가 이미 연결된 상태에 있습니다.
nioSender.datagram.already.established=데이터그램 채널이 이미 확립되어 있습니다. 연결이 진행 중인 상태일 수 있습니다.
nioSender.key.inValid=키가 유효하지 않습니다. 이는 필시 이미 취소되었던 키일 것입니다.
nioSender.not.connected=NioSender가 연결되어 있지 않습니다. 이는 일어나서는 안될 일입니다.
nioSender.receive.failedAck=실패한 ACK: org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA를 받았습니다.
nioSender.sender.disconnected=Sender가 연결이 끊어진 상태입니다. SelectionKey를 처리할 수 없습니다.
nioSender.socketChannel.already.established=소켓 채널이 이미 확립되어 있습니다. 혹시 연결이 진행 중일 수 있습니다.
nioSender.unable.disconnect=NioSender의 연결을 끊을 수 없습니다. 메시지=[{0}]
nioSender.unable.receive.ack=Ack 메시지를 받을 수 없습니다. 소켓 채널에서 EOF에 도달했습니다.
nioSender.unknown.state=데이터가 알 수 없는 상태에 있습니다. readyOps=[{0}]
parallelNioSender.error.keepalive=Sender [{0}]을(를) 위해 keepalive 검사 중 오류 발생
parallelNioSender.operation.timedout=오퍼레이션이 제한 시간 초과되었습니다 (제한 시간: [{0}] 밀리초).
parallelNioSender.send.fail=멤버에 대한 전송이 실패하고 있습니다: [{0}]; 의심 멤버로 설정합니다.
parallelNioSender.send.fail.retrying=멤버로 전송이 실패했습니다: [{0}]. 의심 멤버로 설정하고 다시 시도합니다.
parallelNioSender.send.failed=병렬 NIO 전송 실패.
parallelNioSender.sendFailed.attempt=전송 실패, 총시도회수:[{0}] 최대시도회수:[{1}]
parallelNioSender.sender.disconnected.notRetry=[{0}]을(를) 위해 다시 전송 시도를 하지 않습니다. Sender가 연결이 끊겼습니다.
parallelNioSender.sender.disconnected.sendFailed=전송이 실패했으며 sender가 연결이 끊겼습니다. 재시도는 하지 않습니다.
parallelNioSender.unable.setup.NioSender=NioSender를 셋업할 수 없습니다.
pooledParallelSender.sender.disconnected=Sender가 연결되어 있지 않습니다.
pooledParallelSender.unable.open=NIO selector를 열 수 없습니다.
pooledParallelSender.unable.retrieveSender=Sender를 해당 sender 풀로부터 얻을 수 없습니다.
pooledParallelSender.unable.retrieveSender.timeout=데이터 sender를 조회할 수 없습니다. 제한 시간 초과 ([{0}] 밀리초) 오류.

View File

@@ -0,0 +1,43 @@
# 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.
nioReceiver.alreadyStarted=ServerSocketChannel已经被启动
nioReceiver.cleanup.fail=无法清除关闭的选择器
nioReceiver.clientDisconnect=复制客户端已断开连接,轮询密钥时出错。忽略客户端。
nioReceiver.requestError=NioReceiver无法处理请求
nioReceiver.run.fail=不能允许复制监听器
nioReceiver.start.fail=无法启动集群接收器
nioReceiver.stop.fail=无法关闭集群接收的选择器
nioReceiver.stop.threadRunning=NioReceiver线程没有及时停止。关闭选择器时可能会观察到错误。
nioReceiver.threadpool.fail=ThreadPool 无法初始化。 监听器未启动。
nioReplicationTask.error.register.key=错误的注册key被读取:[{0}]
nioReplicationTask.process.clusterMsg.failed=处理集群消息失败
nioReplicationTask.unable.ack=不能通过channel发送ackchannel已经断开?[{0}]
nioSender.datagram.already.established=数据报通道已经建立。连接可能正在进行中。
nioSender.not.connected=NioSender未连接这是不应该发生的。
nioSender.sender.disconnected=发件人已断开连接,无法处理选择密钥。
nioSender.unable.receive.ack=无法接收确认消息。已到达套接字通道上的EOF。
nioSender.unknown.state=数据处于未知状态。readyOps = [{0}]
parallelNioSender.send.fail.retrying=成员发送失败:[{0}]; 设置为怀疑并重试。
parallelNioSender.send.failed=并行的NIO.发送失败。
parallelNioSender.sendFailed.attempt=发送失败,尝试: [{0}] 最大: [{1}]
parallelNioSender.sender.disconnected.sendFailed=发送失败且sender已断开连接不再重试。
pooledParallelSender.sender.disconnected=sender 未连接。
pooledParallelSender.unable.open=无法打开nio选择器。
pooledParallelSender.unable.retrieveSender=无法从sender池中获取一个sender

View File

@@ -0,0 +1,459 @@
/*
* 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.transport.nio;
import java.io.IOException;
import java.net.ServerSocket;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Deque;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.catalina.tribes.io.ObjectReader;
import org.apache.catalina.tribes.transport.AbstractRxTask;
import org.apache.catalina.tribes.transport.ReceiverBase;
import org.apache.catalina.tribes.transport.RxTaskPool;
import org.apache.catalina.tribes.util.ExceptionUtils;
import org.apache.catalina.tribes.util.StringManager;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
public class NioReceiver extends ReceiverBase implements Runnable, NioReceiverMBean {
private static final Log log = LogFactory.getLog(NioReceiver.class);
/**
* The string manager for this package.
*/
protected static final StringManager sm = StringManager.getManager(NioReceiver.class);
private volatile boolean running = false;
private AtomicReference<Selector> selector = new AtomicReference<>();
private ServerSocketChannel serverChannel = null;
private DatagramChannel datagramChannel = null;
protected final Deque<Runnable> events = new ConcurrentLinkedDeque<>();
public NioReceiver() {
}
@Override
public void stop() {
this.stopListening();
super.stop();
}
/**
* Start cluster receiver.
*
* @throws IOException If the receiver fails to start
*
* @see org.apache.catalina.tribes.ChannelReceiver#start()
*/
@Override
public void start() throws IOException {
super.start();
try {
setPool(new RxTaskPool(getMaxThreads(),getMinThreads(),this));
} catch (Exception x) {
log.fatal(sm.getString("nioReceiver.threadpool.fail"), x);
if ( x instanceof IOException ) throw (IOException)x;
else throw new IOException(x.getMessage());
}
try {
getBind();
bind();
String channelName = "";
if (getChannel().getName() != null) channelName = "[" + getChannel().getName() + "]";
Thread t = new Thread(this, "NioReceiver" + channelName);
t.setDaemon(true);
t.start();
} catch (Exception x) {
log.fatal(sm.getString("nioReceiver.start.fail"), x);
if ( x instanceof IOException ) throw (IOException)x;
else throw new IOException(x.getMessage());
}
}
@Override
public AbstractRxTask createRxTask() {
NioReplicationTask thread = new NioReplicationTask(this,this);
thread.setUseBufferPool(this.getUseBufferPool());
thread.setRxBufSize(getRxBufSize());
thread.setOptions(getWorkerThreadOptions());
return thread;
}
protected void bind() throws IOException {
// allocate an unbound server socket channel
serverChannel = ServerSocketChannel.open();
// Get the associated ServerSocket to bind it with
ServerSocket serverSocket = serverChannel.socket();
// create a new Selector for use below
this.selector.set(Selector.open());
// set the port the server channel will listen to
//serverSocket.bind(new InetSocketAddress(getBind(), getTcpListenPort()));
bind(serverSocket,getPort(),getAutoBind());
// set non-blocking mode for the listening socket
serverChannel.configureBlocking(false);
// register the ServerSocketChannel with the Selector
serverChannel.register(this.selector.get(), SelectionKey.OP_ACCEPT);
//set up the datagram channel
if (this.getUdpPort()>0) {
datagramChannel = DatagramChannel.open();
configureDatagraChannel();
//bind to the address to avoid security checks
bindUdp(datagramChannel.socket(),getUdpPort(),getAutoBind());
}
}
private void configureDatagraChannel() throws IOException {
datagramChannel.configureBlocking(false);
datagramChannel.socket().setSendBufferSize(getUdpTxBufSize());
datagramChannel.socket().setReceiveBufferSize(getUdpRxBufSize());
datagramChannel.socket().setReuseAddress(getSoReuseAddress());
datagramChannel.socket().setSoTimeout(getTimeout());
datagramChannel.socket().setTrafficClass(getSoTrafficClass());
}
public void addEvent(Runnable event) {
Selector selector = this.selector.get();
if (selector != null) {
events.add(event);
if (log.isTraceEnabled()) {
log.trace("Adding event to selector:" + event);
}
if (isListening()) {
selector.wakeup();
}
}
}
public void events() {
if (events.isEmpty()) {
return;
}
Runnable r = null;
while ((r = events.pollFirst()) != null ) {
try {
if (log.isTraceEnabled()) {
log.trace("Processing event in selector:" + r);
}
r.run();
} catch (Exception x) {
log.error("", x);
}
}
}
public static void cancelledKey(SelectionKey key) {
ObjectReader reader = (ObjectReader)key.attachment();
if ( reader != null ) {
reader.setCancelled(true);
reader.finish();
}
key.cancel();
key.attach(null);
if (key.channel() instanceof SocketChannel)
try { ((SocketChannel)key.channel()).socket().close(); } catch (IOException e) { if (log.isDebugEnabled()) log.debug("", e); }
if (key.channel() instanceof DatagramChannel)
try { ((DatagramChannel)key.channel()).socket().close(); } catch (Exception e) { if (log.isDebugEnabled()) log.debug("", e); }
try { key.channel().close(); } catch (IOException e) { if (log.isDebugEnabled()) log.debug("", e); }
}
protected long lastCheck = System.currentTimeMillis();
protected void socketTimeouts() {
long now = System.currentTimeMillis();
if ( (now-lastCheck) < getSelectorTimeout() ) return;
//timeout
Selector tmpsel = this.selector.get();
Set<SelectionKey> keys = (isListening()&&tmpsel!=null)?tmpsel.keys():null;
if ( keys == null ) return;
for (Iterator<SelectionKey> iter = keys.iterator(); iter.hasNext();) {
SelectionKey key = iter.next();
try {
// if (key.interestOps() == SelectionKey.OP_READ) {
// //only timeout sockets that we are waiting for a read from
// ObjectReader ka = (ObjectReader) key.attachment();
// long delta = now - ka.getLastAccess();
// if (delta > (long) getTimeout()) {
// cancelledKey(key);
// }
// }
// else
if ( key.interestOps() == 0 ) {
//check for keys that didn't make it in.
ObjectReader ka = (ObjectReader) key.attachment();
if ( ka != null ) {
long delta = now - ka.getLastAccess();
if (delta > getTimeout() && (!ka.isAccessed())) {
if (log.isWarnEnabled())
log.warn(sm.getString(
"nioReceiver.threadsExhausted",
Integer.valueOf(getTimeout()),
Boolean.valueOf(ka.isCancelled()),
key,
new java.sql.Timestamp(ka.getLastAccess())));
ka.setLastAccess(now);
//key.interestOps(SelectionKey.OP_READ);
}//end if
} else {
cancelledKey(key);
}//end if
}//end if
}catch ( CancelledKeyException ckx ) {
cancelledKey(key);
}
}
lastCheck = System.currentTimeMillis();
}
/**
* Get data from channel and store in byte array
* send it to cluster
* @throws IOException IO error
*/
protected void listen() throws Exception {
if (doListen()) {
log.warn(sm.getString("nioReceiver.alreadyStarted"));
return;
}
setListen(true);
// Avoid NPEs if selector is set to null on stop.
Selector selector = this.selector.get();
if (selector!=null && datagramChannel!=null) {
ObjectReader oreader = new ObjectReader(MAX_UDP_SIZE); //max size for a datagram packet
registerChannel(selector,datagramChannel,SelectionKey.OP_READ,oreader);
}
while (doListen() && selector != null) {
// this may block for a long time, upon return the
// selected set contains keys of the ready channels
try {
events();
socketTimeouts();
int n = selector.select(getSelectorTimeout());
if (n == 0) {
//there is a good chance that we got here
//because the TcpReplicationThread called
//selector wakeup().
//if that happens, we must ensure that that
//thread has enough time to call interestOps
// synchronized (interestOpsMutex) {
//if we got the lock, means there are no
//keys trying to register for the
//interestOps method
// }
continue; // nothing to do
}
// get an iterator over the set of selected keys
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
// look at each key in the selected set
while (it!=null && it.hasNext()) {
SelectionKey key = it.next();
// Is a new connection coming in?
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel channel = server.accept();
channel.socket().setReceiveBufferSize(getRxBufSize());
channel.socket().setSendBufferSize(getTxBufSize());
channel.socket().setTcpNoDelay(getTcpNoDelay());
channel.socket().setKeepAlive(getSoKeepAlive());
channel.socket().setOOBInline(getOoBInline());
channel.socket().setReuseAddress(getSoReuseAddress());
channel.socket().setSoLinger(getSoLingerOn(),getSoLingerTime());
channel.socket().setSoTimeout(getTimeout());
Object attach = new ObjectReader(channel);
registerChannel(selector,
channel,
SelectionKey.OP_READ,
attach);
}
// is there data to read on this channel?
if (key.isReadable()) {
readDataFromSocket(key);
} else {
key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
}
// remove key from selected set, it's been handled
it.remove();
}
} catch (java.nio.channels.ClosedSelectorException cse) {
// ignore is normal at shutdown or stop listen socket
} catch (java.nio.channels.CancelledKeyException nx) {
log.warn(sm.getString("nioReceiver.clientDisconnect"));
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("nioReceiver.requestError"), t);
}
}
serverChannel.close();
if (datagramChannel!=null) {
try {
datagramChannel.close();
}catch (Exception iox) {
if (log.isDebugEnabled()) log.debug("Unable to close datagram channel.",iox);
}
datagramChannel=null;
}
closeSelector();
}
/**
* Close Selector.
*
* @see org.apache.catalina.tribes.transport.ReceiverBase#stop()
*/
protected void stopListening() {
setListen(false);
Selector selector = this.selector.get();
if (selector != null) {
try {
// Unlock the thread if is is blocked waiting for input
selector.wakeup();
// Wait for the receiver thread to finish
int count = 0;
while (running && count < 50) {
Thread.sleep(100);
count ++;
}
if (running) {
log.warn(sm.getString("nioReceiver.stop.threadRunning"));
}
closeSelector();
} catch (Exception x) {
log.error(sm.getString("nioReceiver.stop.fail"), x);
} finally {
this.selector.set(null);
}
}
}
private void closeSelector() throws IOException {
Selector selector = this.selector.getAndSet(null);
if (selector == null) return;
try {
// look at each key in the selected set
for (SelectionKey key : selector.keys()) {
key.channel().close();
key.attach(null);
key.cancel();
}
} catch (IOException ignore){
if (log.isWarnEnabled()) {
log.warn(sm.getString("nioReceiver.cleanup.fail"), ignore);
}
} catch (ClosedSelectorException ignore){
// Ignore
}
try {
selector.selectNow();
} catch (Throwable t){
ExceptionUtils.handleThrowable(t);
// Ignore everything else
}
selector.close();
}
// ----------------------------------------------------------
/**
* Register the given channel with the given selector for
* the given operations of interest
* @param selector The selector to use
* @param channel The channel
* @param ops The operations to register
* @param attach Attachment object
* @throws Exception IO error with channel
*/
protected void registerChannel(Selector selector,
SelectableChannel channel,
int ops,
Object attach) throws Exception {
if (channel == null)return; // could happen
// set the new channel non-blocking
channel.configureBlocking(false);
// register it with the selector
channel.register(selector, ops, attach);
}
/**
* Start thread and listen
*/
@Override
public void run() {
running = true;
try {
listen();
} catch (Exception x) {
log.error(sm.getString("nioReceiver.run.fail"), x);
} finally {
running = false;
}
}
// ----------------------------------------------------------
/**
* Sample data handler method for a channel with data ready to read.
* @param key A SelectionKey object associated with a channel
* determined by the selector to be ready for reading. If the
* channel returns an EOF condition, it is closed here, which
* automatically invalidates the associated key. The selector
* will then de-register the channel on the next select call.
* @throws Exception IO error with channel
*/
protected void readDataFromSocket(SelectionKey key) throws Exception {
NioReplicationTask task = (NioReplicationTask) getTaskPool().getRxTask();
if (task == null) {
// No threads/tasks available, do nothing, the selection
// loop will keep calling this method until a
// thread becomes available, the thread pool itself has a waiting mechanism
// so we will not wait here.
if (log.isDebugEnabled()) log.debug("No TcpReplicationThread available");
} else {
// invoking this wakes up the worker thread then returns
//add task to thread pool
task.serviceChannel(key);
getExecutor().execute(task);
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* 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.transport.nio;
public interface NioReceiverMBean {
// Receiver Attributes
public String getAddress();
public boolean getDirect();
public int getPort();
public int getAutoBind();
public int getSecurePort();
public int getUdpPort();
public long getSelectorTimeout();
public int getMaxThreads();
public int getMinThreads();
public long getMaxIdleTime();
public boolean getOoBInline();
public int getRxBufSize();
public int getTxBufSize();
public int getUdpRxBufSize();
public int getUdpTxBufSize();
public boolean getSoKeepAlive();
public boolean getSoLingerOn();
public int getSoLingerTime();
public boolean getSoReuseAddress();
public boolean getTcpNoDelay();
public int getTimeout();
public boolean getUseBufferPool();
public boolean isListening();
// pool stats
public int getPoolSize();
public int getActiveCount();
public long getTaskCount();
public long getCompletedTaskCount();
}

View File

@@ -0,0 +1,341 @@
/*
* 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.transport.nio;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
import org.apache.catalina.tribes.ChannelMessage;
import org.apache.catalina.tribes.ChannelReceiver;
import org.apache.catalina.tribes.RemoteProcessException;
import org.apache.catalina.tribes.UniqueId;
import org.apache.catalina.tribes.io.BufferPool;
import org.apache.catalina.tribes.io.ChannelData;
import org.apache.catalina.tribes.io.ListenCallback;
import org.apache.catalina.tribes.io.ObjectReader;
import org.apache.catalina.tribes.transport.AbstractRxTask;
import org.apache.catalina.tribes.transport.Constants;
import org.apache.catalina.tribes.util.Logs;
import org.apache.catalina.tribes.util.StringManager;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
/**
* A worker thread class which can drain channels and echo-back the input. Each
* instance is constructed with a reference to the owning thread pool object.
* When started, the thread loops forever waiting to be awakened to service the
* channel associated with a SelectionKey object. The worker is tasked by
* calling its serviceChannel() method with a SelectionKey object. The
* serviceChannel() method stores the key reference in the thread object then
* calls notify() to wake it up. When the channel has been drained, the worker
* thread returns itself to its parent pool.
*/
public class NioReplicationTask extends AbstractRxTask {
private static final Log log = LogFactory.getLog(NioReplicationTask.class);
protected static final StringManager sm = StringManager.getManager(NioReplicationTask.class);
private ByteBuffer buffer = null;
private SelectionKey key;
private int rxBufSize;
private final NioReceiver receiver;
public NioReplicationTask (ListenCallback callback, NioReceiver receiver) {
super(callback);
this.receiver = receiver;
}
// loop forever waiting for work to do
@Override
public synchronized void run() {
if ( buffer == null ) {
int size = getRxBufSize();
if (key.channel() instanceof DatagramChannel) {
size = ChannelReceiver.MAX_UDP_SIZE;
}
if ( (getOptions() & OPTION_DIRECT_BUFFER) == OPTION_DIRECT_BUFFER) {
buffer = ByteBuffer.allocateDirect(size);
} else {
buffer = ByteBuffer.allocate(size);
}
} else {
buffer.clear();
}
if (key == null) {
return; // just in case
}
if ( log.isTraceEnabled() )
log.trace("Servicing key:"+key);
try {
ObjectReader reader = (ObjectReader)key.attachment();
if ( reader == null ) {
if ( log.isTraceEnabled() )
log.trace("No object reader, cancelling:"+key);
cancelKey(key);
} else {
if ( log.isTraceEnabled() )
log.trace("Draining channel:"+key);
drainChannel(key, reader);
}
} catch (Exception e) {
//this is common, since the sockets on the other
//end expire after a certain time.
if ( e instanceof CancelledKeyException ) {
//do nothing
} else if ( e instanceof IOException ) {
//dont spew out stack traces for IO exceptions unless debug is enabled.
if (log.isDebugEnabled()) log.debug ("IOException in replication worker, unable to drain channel. Probable cause: Keep alive socket closed["+e.getMessage()+"].", e);
else log.warn (sm.getString("nioReplicationTask.unable.drainChannel.ioe", e.getMessage()));
} else if ( log.isErrorEnabled() ) {
//this is a real error, log it.
log.error(sm.getString("nioReplicationTask.exception.drainChannel"),e);
}
cancelKey(key);
}
key = null;
// done, ready for more, return to pool
getTaskPool().returnWorker (this);
}
/**
* Called to initiate a unit of work by this worker thread
* on the provided SelectionKey object. This method is
* synchronized, as is the run() method, so only one key
* can be serviced at a given time.
* Before waking the worker thread, and before returning
* to the main selection loop, this key's interest set is
* updated to remove OP_READ. This will cause the selector
* to ignore read-readiness for this channel while the
* worker thread is servicing it.
* @param key The key to process
*/
public synchronized void serviceChannel (SelectionKey key) {
if ( log.isTraceEnabled() ) log.trace("About to service key:"+key);
ObjectReader reader = (ObjectReader)key.attachment();
if ( reader != null ) reader.setLastAccess(System.currentTimeMillis());
this.key = key;
key.interestOps (key.interestOps() & (~SelectionKey.OP_READ));
key.interestOps (key.interestOps() & (~SelectionKey.OP_WRITE));
}
/**
* The actual code which drains the channel associated with
* the given key. This method assumes the key has been
* modified prior to invocation to turn off selection
* interest in OP_READ. When this method completes it
* re-enables OP_READ and calls wakeup() on the selector
* so the selector will resume watching this channel.
* @param key The key to process
* @param reader The reader
* @throws Exception IO error
*/
protected void drainChannel (final SelectionKey key, ObjectReader reader) throws Exception {
reader.access();
ReadableByteChannel channel = (ReadableByteChannel) key.channel();
int count=-1;
buffer.clear(); // make buffer empty
SocketAddress saddr = null;
if (channel instanceof SocketChannel) {
// loop while data available, channel is non-blocking
while ((count = channel.read (buffer)) > 0) {
buffer.flip(); // make buffer readable
if ( buffer.hasArray() )
reader.append(buffer.array(),0,count,false);
else
reader.append(buffer,count,false);
buffer.clear(); // make buffer empty
//do we have at least one package?
if ( reader.hasPackage() ) break;
}
} else if (channel instanceof DatagramChannel) {
DatagramChannel dchannel = (DatagramChannel)channel;
saddr = dchannel.receive(buffer);
buffer.flip(); // make buffer readable
if ( buffer.hasArray() )
reader.append(buffer.array(),0,buffer.limit()-buffer.position(),false);
else
reader.append(buffer,buffer.limit()-buffer.position(),false);
buffer.clear(); // make buffer empty
//did we get a package
count = reader.hasPackage()?1:-1;
}
int pkgcnt = reader.count();
if (count < 0 && pkgcnt == 0 ) {
//end of stream, and no more packages to process
remoteEof(key);
return;
}
ChannelMessage[] msgs = pkgcnt == 0? ChannelData.EMPTY_DATA_ARRAY : reader.execute();
registerForRead(key,reader);//register to read new data, before we send it off to avoid dead locks
for ( int i=0; i<msgs.length; i++ ) {
/**
* Use send ack here if you want to ack the request to the remote
* server before completing the request
* This is considered an asynchronous request
*/
if (ChannelData.sendAckAsync(msgs[i].getOptions())) sendAck(key,(WritableByteChannel)channel,Constants.ACK_COMMAND,saddr);
try {
if ( Logs.MESSAGES.isTraceEnabled() ) {
try {
Logs.MESSAGES.trace("NioReplicationThread - Received msg:" + new UniqueId(msgs[i].getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis()));
}catch ( Throwable t ) {}
}
//process the message
getCallback().messageDataReceived(msgs[i]);
/**
* Use send ack here if you want the request to complete on this
* server before sending the ack to the remote server
* This is considered a synchronized request
*/
if (ChannelData.sendAckSync(msgs[i].getOptions())) sendAck(key,(WritableByteChannel)channel,Constants.ACK_COMMAND,saddr);
}catch ( RemoteProcessException e ) {
if ( log.isDebugEnabled() ) log.error(sm.getString("nioReplicationTask.process.clusterMsg.failed"),e);
if (ChannelData.sendAckSync(msgs[i].getOptions())) sendAck(key,(WritableByteChannel)channel,Constants.FAIL_ACK_COMMAND,saddr);
}catch ( Exception e ) {
log.error(sm.getString("nioReplicationTask.process.clusterMsg.failed"),e);
if (ChannelData.sendAckSync(msgs[i].getOptions())) sendAck(key,(WritableByteChannel)channel,Constants.FAIL_ACK_COMMAND,saddr);
}
if ( getUseBufferPool() ) {
BufferPool.getBufferPool().returnBuffer(msgs[i].getMessage());
msgs[i].setMessage(null);
}
}
if (count < 0) {
remoteEof(key);
return;
}
}
private void remoteEof(SelectionKey key) {
// close channel on EOF, invalidates the key
if ( log.isDebugEnabled() ) log.debug("Channel closed on the remote end, disconnecting");
cancelKey(key);
}
protected void registerForRead(final SelectionKey key, ObjectReader reader) {
if ( log.isTraceEnabled() )
log.trace("Adding key for read event:"+key);
reader.finish();
//register our OP_READ interest
Runnable r = new Runnable() {
@Override
public void run() {
try {
if (key.isValid()) {
// cycle the selector so this key is active again
key.selector().wakeup();
// resume interest in OP_READ, OP_WRITE
int resumeOps = key.interestOps() | SelectionKey.OP_READ;
key.interestOps(resumeOps);
if ( log.isTraceEnabled() )
log.trace("Registering key for read:"+key);
}
} catch (CancelledKeyException ckx ) {
NioReceiver.cancelledKey(key);
if ( log.isTraceEnabled() )
log.trace("CKX Cancelling key:"+key);
} catch (Exception x) {
log.error(sm.getString("nioReplicationTask.error.register.key", key),x);
}
}
};
receiver.addEvent(r);
}
private void cancelKey(final SelectionKey key) {
if ( log.isTraceEnabled() )
log.trace("Adding key for cancel event:"+key);
ObjectReader reader = (ObjectReader)key.attachment();
if ( reader != null ) {
reader.setCancelled(true);
reader.finish();
}
Runnable cx = new Runnable() {
@Override
public void run() {
if ( log.isTraceEnabled() )
log.trace("Cancelling key:"+key);
NioReceiver.cancelledKey(key);
}
};
receiver.addEvent(cx);
}
/**
* Send a reply-acknowledgement (6,2,3), sends it doing a busy write, the ACK is so small
* that it should always go to the buffer.
* @param key The key to use
* @param channel The channel
* @param command The command to write
* @param udpaddr Target address
*/
protected void sendAck(SelectionKey key, WritableByteChannel channel, byte[] command, SocketAddress udpaddr) {
try {
ByteBuffer buf = ByteBuffer.wrap(command);
int total = 0;
if (channel instanceof DatagramChannel) {
DatagramChannel dchannel = (DatagramChannel)channel;
//were using a shared channel, document says its thread safe
//TODO check optimization, one channel per thread?
while ( total < command.length ) {
total += dchannel.send(buf, udpaddr);
}
} else {
while ( total < command.length ) {
total += channel.write(buf);
}
}
if (log.isTraceEnabled()) {
log.trace("ACK sent to " +
( (channel instanceof SocketChannel) ?
((SocketChannel)channel).socket().getInetAddress() :
((DatagramChannel)channel).socket().getInetAddress()));
}
} catch ( java.io.IOException x ) {
log.warn(sm.getString("nioReplicationTask.unable.ack", x.getMessage()));
}
}
public void setRxBufSize(int rxBufSize) {
this.rxBufSize = rxBufSize;
}
public int getRxBufSize() {
return rxBufSize;
}
}

View File

@@ -0,0 +1,402 @@
/*
* 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.transport.nio;
import java.io.EOFException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import org.apache.catalina.tribes.RemoteProcessException;
import org.apache.catalina.tribes.io.XByteBuffer;
import org.apache.catalina.tribes.transport.AbstractSender;
import org.apache.catalina.tribes.util.StringManager;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
/**
* This class is NOT thread safe and should never be used with more than one thread at a time
*
* This is a state machine, handled by the process method
* States are:
* - NOT_CONNECTED -&gt; connect() -&gt; CONNECTED
* - CONNECTED -&gt; setMessage() -&gt; READY TO WRITE
* - READY_TO_WRITE -&gt; write() -&gt; READY TO WRITE | READY TO READ
* - READY_TO_READ -&gt; read() -&gt; READY_TO_READ | TRANSFER_COMPLETE
* - TRANSFER_COMPLETE -&gt; CONNECTED
*
* @version 1.0
*/
public class NioSender extends AbstractSender {
private static final Log log = LogFactory.getLog(NioSender.class);
protected static final StringManager sm = StringManager.getManager(NioSender.class);
protected Selector selector;
protected SocketChannel socketChannel = null;
protected DatagramChannel dataChannel = null;
/*
* STATE VARIABLES *
*/
protected ByteBuffer readbuf = null;
protected ByteBuffer writebuf = null;
protected volatile byte[] current = null;
protected final XByteBuffer ackbuf = new XByteBuffer(128,true);
protected int remaining = 0;
protected boolean complete;
protected boolean connecting = false;
public NioSender() {
super();
}
/**
* State machine to send data.
* @param key The key to use
* @param waitForAck Wait for an ack
* @return <code>true</code> if the processing was successful
* @throws IOException An IO error occurred
*/
public boolean process(SelectionKey key, boolean waitForAck) throws IOException {
int ops = key.readyOps();
key.interestOps(key.interestOps() & ~ops);
//in case disconnect has been called
if ((!isConnected()) && (!connecting)) throw new IOException(sm.getString("nioSender.sender.disconnected"));
if ( !key.isValid() ) throw new IOException(sm.getString("nioSender.key.inValid"));
if ( key.isConnectable() ) {
if ( socketChannel.finishConnect() ) {
completeConnect();
if ( current != null ) key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
return false;
} else {
//wait for the connection to finish
key.interestOps(key.interestOps() | SelectionKey.OP_CONNECT);
return false;
}//end if
} else if ( key.isWritable() ) {
boolean writecomplete = write();
if ( writecomplete ) {
//we are completed, should we read an ack?
if ( waitForAck ) {
//register to read the ack
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
} else {
//if not, we are ready, setMessage will reregister us for another write interest
//do a health check, we have no way of verify a disconnected
//socket since we don't register for OP_READ on waitForAck=false
read();//this causes overhead
setRequestCount(getRequestCount()+1);
return true;
}
} else {
//we are not complete, lets write some more
key.interestOps(key.interestOps()|SelectionKey.OP_WRITE);
}//end if
} else if ( key.isReadable() ) {
boolean readcomplete = read();
if ( readcomplete ) {
setRequestCount(getRequestCount()+1);
return true;
} else {
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
}//end if
} else {
//unknown state, should never happen
log.warn(sm.getString("nioSender.unknown.state", Integer.toString(ops)));
throw new IOException(sm.getString("nioSender.unknown.state", Integer.toString(ops)));
}//end if
return false;
}
private void configureSocket() throws IOException {
if (socketChannel!=null) {
socketChannel.configureBlocking(false);
socketChannel.socket().setSendBufferSize(getTxBufSize());
socketChannel.socket().setReceiveBufferSize(getRxBufSize());
socketChannel.socket().setSoTimeout((int)getTimeout());
socketChannel.socket().setSoLinger(getSoLingerOn(),getSoLingerOn()?getSoLingerTime():0);
socketChannel.socket().setTcpNoDelay(getTcpNoDelay());
socketChannel.socket().setKeepAlive(getSoKeepAlive());
socketChannel.socket().setReuseAddress(getSoReuseAddress());
socketChannel.socket().setOOBInline(getOoBInline());
socketChannel.socket().setSoLinger(getSoLingerOn(),getSoLingerTime());
socketChannel.socket().setTrafficClass(getSoTrafficClass());
} else if (dataChannel!=null) {
dataChannel.configureBlocking(false);
dataChannel.socket().setSendBufferSize(getUdpTxBufSize());
dataChannel.socket().setReceiveBufferSize(getUdpRxBufSize());
dataChannel.socket().setSoTimeout((int)getTimeout());
dataChannel.socket().setReuseAddress(getSoReuseAddress());
dataChannel.socket().setTrafficClass(getSoTrafficClass());
}
}
private void completeConnect() {
//we connected, register ourselves for writing
setConnected(true);
connecting = false;
setRequestCount(0);
setConnectTime(System.currentTimeMillis());
}
protected boolean read() throws IOException {
//if there is no message here, we are done
if ( current == null ) return true;
int read = isUdpBased()?dataChannel.read(readbuf) : socketChannel.read(readbuf);
//end of stream
if ( read == -1 ) throw new IOException(sm.getString("nioSender.unable.receive.ack"));
//no data read
else if ( read == 0 ) return false;
readbuf.flip();
ackbuf.append(readbuf,read);
readbuf.clear();
if (ackbuf.doesPackageExist() ) {
byte[] ackcmd = ackbuf.extractDataPackage(true).getBytes();
boolean ack = Arrays.equals(ackcmd,org.apache.catalina.tribes.transport.Constants.ACK_DATA);
boolean fack = Arrays.equals(ackcmd,org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA);
if ( fack && getThrowOnFailedAck() ) throw new RemoteProcessException(sm.getString("nioSender.receive.failedAck"));
return ack || fack;
} else {
return false;
}
}
protected boolean write() throws IOException {
if ( (!isConnected()) || (this.socketChannel==null && this.dataChannel==null)) {
throw new IOException(sm.getString("nioSender.not.connected"));
}
if ( current != null ) {
if ( remaining > 0 ) {
//we have written everything, or we are starting a new package
//protect against buffer overwrite
int byteswritten = isUdpBased()?dataChannel.write(writebuf) : socketChannel.write(writebuf);
if (byteswritten == -1 ) throw new EOFException();
remaining -= byteswritten;
//if the entire message was written from the buffer
//reset the position counter
if ( remaining < 0 ) {
remaining = 0;
}
}
return (remaining==0);
}
//no message to send, we can consider that complete
return true;
}
/**
* connect - blocking in this operation
*
* @throws IOException
* TODO Implement this org.apache.catalina.tribes.transport.IDataSender method
*/
@Override
public synchronized void connect() throws IOException {
if ( connecting || isConnected()) return;
connecting = true;
if ( isConnected() ) throw new IOException(sm.getString("nioSender.already.connected"));
if ( readbuf == null ) {
readbuf = getReadBuffer();
} else {
readbuf.clear();
}
if ( writebuf == null ) {
writebuf = getWriteBuffer();
} else {
writebuf.clear();
}
if (isUdpBased()) {
InetSocketAddress daddr = new InetSocketAddress(getAddress(),getUdpPort());
if ( dataChannel != null ) throw new IOException(sm.getString("nioSender.datagram.already.established"));
dataChannel = DatagramChannel.open();
configureSocket();
dataChannel.connect(daddr);
completeConnect();
dataChannel.register(getSelector(),SelectionKey.OP_WRITE, this);
} else {
InetSocketAddress addr = new InetSocketAddress(getAddress(),getPort());
if ( socketChannel != null ) throw new IOException(sm.getString("nioSender.socketChannel.already.established"));
socketChannel = SocketChannel.open();
configureSocket();
if ( socketChannel.connect(addr) ) {
completeConnect();
socketChannel.register(getSelector(), SelectionKey.OP_WRITE, this);
} else {
socketChannel.register(getSelector(), SelectionKey.OP_CONNECT, this);
}
}
}
/**
* disconnect
*
* TODO Implement this org.apache.catalina.tribes.transport.IDataSender method
*/
@Override
public void disconnect() {
try {
connecting = false;
setConnected(false);
if (socketChannel != null) {
try {
try {
socketChannel.socket().close();
} catch (Exception x) {
// Ignore
}
//error free close, all the way
//try {socket.shutdownOutput();}catch ( Exception x){}
//try {socket.shutdownInput();}catch ( Exception x){}
//try {socket.close();}catch ( Exception x){}
try {
socketChannel.close();
} catch (Exception x) {
// Ignore
}
} finally {
socketChannel = null;
}
}
if (dataChannel != null) {
try {
try {
dataChannel.socket().close();
} catch (Exception x) {
// Ignore
}
//error free close, all the way
//try {socket.shutdownOutput();}catch ( Exception x){}
//try {socket.shutdownInput();}catch ( Exception x){}
//try {socket.close();}catch ( Exception x){}
try {
dataChannel.close();
} catch (Exception x) {
// Ignore
}
} finally {
dataChannel = null;
}
}
} catch ( Exception x ) {
log.error(sm.getString("nioSender.unable.disconnect", x.getMessage()));
if ( log.isDebugEnabled() ) log.debug(sm.getString("nioSender.unable.disconnect", x.getMessage()),x);
}
}
public void reset() {
if ( isConnected() && readbuf == null) {
readbuf = getReadBuffer();
}
if ( readbuf != null ) readbuf.clear();
if ( writebuf != null ) writebuf.clear();
current = null;
ackbuf.clear();
remaining = 0;
complete = false;
setAttempt(0);
setUdpBased(false);
}
private ByteBuffer getReadBuffer() {
return getBuffer(getRxBufSize());
}
private ByteBuffer getWriteBuffer() {
return getBuffer(getTxBufSize());
}
private ByteBuffer getBuffer(int size) {
return getDirectBuffer()?ByteBuffer.allocateDirect(size):ByteBuffer.allocate(size);
}
/**
* sendMessage
*
* @param data ChannelMessage
* @throws IOException
* TODO Implement this org.apache.catalina.tribes.transport.IDataSender method
*/
public void setMessage(byte[] data) throws IOException {
setMessage(data,0,data.length);
}
public void setMessage(byte[] data,int offset, int length) throws IOException {
if (data != null) {
synchronized (this) {
current = data;
remaining = length;
ackbuf.clear();
if (writebuf != null) {
writebuf.clear();
} else {
writebuf = getBuffer(length);
}
if (writebuf.capacity() < length) {
writebuf = getBuffer(length);
}
// TODO use ByteBuffer.wrap to avoid copying the data.
writebuf.put(data,offset,length);
writebuf.flip();
if (isConnected()) {
if (isUdpBased())
dataChannel.register(getSelector(), SelectionKey.OP_WRITE, this);
else
socketChannel.register(getSelector(), SelectionKey.OP_WRITE, this);
}
}
}
}
public byte[] getMessage() {
return current;
}
public boolean isComplete() {
return complete;
}
public Selector getSelector() {
return selector;
}
public void setSelector(Selector selector) {
this.selector = selector;
}
public void setComplete(boolean complete) {
this.complete = complete;
}
}

View File

@@ -0,0 +1,374 @@
/*
* 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.transport.nio;
import java.io.IOException;
import java.net.UnknownHostException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
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.UniqueId;
import org.apache.catalina.tribes.io.ChannelData;
import org.apache.catalina.tribes.io.XByteBuffer;
import org.apache.catalina.tribes.transport.AbstractSender;
import org.apache.catalina.tribes.transport.MultiPointSender;
import org.apache.catalina.tribes.transport.SenderState;
import org.apache.catalina.tribes.util.Logs;
import org.apache.catalina.tribes.util.StringManager;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
public class ParallelNioSender extends AbstractSender implements MultiPointSender {
private static final Log log = LogFactory.getLog(ParallelNioSender.class);
protected static final StringManager sm = StringManager.getManager(ParallelNioSender.class);
protected final long selectTimeout = 5000; //default 5 seconds, same as send timeout
protected final Selector selector;
protected final HashMap<Member, NioSender> nioSenders = new HashMap<>();
public ParallelNioSender() throws IOException {
selector = Selector.open();
setConnected(true);
}
@Override
public synchronized void sendMessage(Member[] destination, ChannelMessage msg)
throws ChannelException {
long start = System.currentTimeMillis();
this.setUdpBased((msg.getOptions()&Channel.SEND_OPTIONS_UDP) == Channel.SEND_OPTIONS_UDP);
byte[] data = XByteBuffer.createDataPackage((ChannelData)msg);
NioSender[] senders = setupForSend(destination);
connect(senders);
setData(senders,data);
int remaining = senders.length;
ChannelException cx = null;
try {
//loop until complete, an error happens, or we timeout
long delta = System.currentTimeMillis() - start;
boolean waitForAck = (Channel.SEND_OPTIONS_USE_ACK &
msg.getOptions()) == Channel.SEND_OPTIONS_USE_ACK;
while ( (remaining>0) && (delta<getTimeout()) ) {
try {
SendResult result = doLoop(selectTimeout, getMaxRetryAttempts(),waitForAck,msg);
remaining -= result.getCompleted();
if (result.getFailed() != null) {
remaining -= result.getFailed().getFaultyMembers().length;
if (cx == null) cx = result.getFailed();
else cx.addFaultyMember(result.getFailed().getFaultyMembers());
}
} catch (Exception x ) {
if (log.isTraceEnabled()) log.trace("Error sending message", x);
if (cx == null) {
if ( x instanceof ChannelException ) cx = (ChannelException)x;
else cx = new ChannelException(sm.getString("parallelNioSender.send.failed"), x);
}
for (int i=0; i<senders.length; i++ ) {
if (!senders[i].isComplete()) {
cx.addFaultyMember(senders[i].getDestination(),x);
}
}
throw cx;
}
delta = System.currentTimeMillis() - start;
}
if ( remaining > 0 ) {
//timeout has occurred
ChannelException cxtimeout = new ChannelException(sm.getString(
"parallelNioSender.operation.timedout", Long.toString(getTimeout())));
if (cx == null) {
cx = new ChannelException(sm.getString("parallelNioSender.operation.timedout",
Long.toString(getTimeout())));
}
for (int i=0; i<senders.length; i++ ) {
if (!senders[i].isComplete()) {
cx.addFaultyMember(senders[i].getDestination(),cxtimeout);
}
}
throw cx;
} else if ( cx != null ) {
//there was an error
throw cx;
}
} catch (Exception x ) {
try {
this.disconnect();
} catch (Exception e) {
// Ignore
}
if ( x instanceof ChannelException ) throw (ChannelException)x;
else throw new ChannelException(x);
}
}
private SendResult doLoop(long selectTimeOut, int maxAttempts, boolean waitForAck, ChannelMessage msg)
throws ChannelException {
SendResult result = new SendResult();
int selectedKeys;
try {
selectedKeys = selector.select(selectTimeOut);
} catch (IOException ioe) {
throw new ChannelException(sm.getString("parallelNioSender.send.failed"), ioe);
}
if (selectedKeys == 0) {
return result;
}
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey sk = it.next();
it.remove();
int readyOps = sk.readyOps();
sk.interestOps(sk.interestOps() & ~readyOps);
NioSender sender = (NioSender) sk.attachment();
try {
if (sender.process(sk,waitForAck)) {
sender.setComplete(true);
result.complete(sender);
if ( Logs.MESSAGES.isTraceEnabled() ) {
Logs.MESSAGES.trace("ParallelNioSender - Sent msg:" +
new UniqueId(msg.getUniqueId()) + " at " +
new java.sql.Timestamp(System.currentTimeMillis()) + " to " +
sender.getDestination().getName());
}
SenderState.getSenderState(sender.getDestination()).setReady();
}//end if
} catch (Exception x) {
if (log.isTraceEnabled()) {
log.trace("Error while processing send to " + sender.getDestination().getName(),
x);
}
SenderState state = SenderState.getSenderState(sender.getDestination());
int attempt = sender.getAttempt()+1;
boolean retry = (attempt <= maxAttempts && maxAttempts>0);
synchronized (state) {
//sk.cancel();
if (state.isSuspect()) state.setFailing();
if (state.isReady()) {
state.setSuspect();
if ( retry )
log.warn(sm.getString("parallelNioSender.send.fail.retrying", sender.getDestination().getName()));
else
log.warn(sm.getString("parallelNioSender.send.fail", sender.getDestination().getName()), x);
}
}
if ( !isConnected() ) {
log.warn(sm.getString("parallelNioSender.sender.disconnected.notRetry", sender.getDestination().getName()));
ChannelException cx = new ChannelException(sm.getString("parallelNioSender.sender.disconnected.sendFailed"), x);
cx.addFaultyMember(sender.getDestination(),x);
result.failed(cx);
break;
}
byte[] data = sender.getMessage();
if (retry) {
try {
sender.disconnect();
sender.connect();
sender.setAttempt(attempt);
sender.setMessage(data);
} catch (Exception ignore){
state.setFailing();
}
} else {
ChannelException cx = new ChannelException(
sm.getString("parallelNioSender.sendFailed.attempt",
Integer.toString(sender.getAttempt()),
Integer.toString(maxAttempts)), x);
cx.addFaultyMember(sender.getDestination(),x);
result.failed(cx);
}//end if
}
}
return result;
}
private static class SendResult {
private List<NioSender> completeSenders = new ArrayList<>();
private ChannelException exception = null;
private void complete(NioSender sender) {
if (!completeSenders.contains(sender)) completeSenders.add(sender);
}
private int getCompleted() {
return completeSenders.size();
}
private void failed(ChannelException cx){
if (exception == null) exception = cx;
exception.addFaultyMember(cx.getFaultyMembers());
}
private ChannelException getFailed() {
return exception;
}
}
private void connect(NioSender[] senders) throws ChannelException {
ChannelException x = null;
for (int i=0; i<senders.length; i++ ) {
try {
senders[i].connect();
}catch ( IOException io ) {
if ( x==null ) x = new ChannelException(io);
x.addFaultyMember(senders[i].getDestination(),io);
}
}
if ( x != null ) throw x;
}
private void setData(NioSender[] senders, byte[] data) throws ChannelException {
ChannelException x = null;
for (int i=0; i<senders.length; i++ ) {
try {
senders[i].setMessage(data);
}catch ( IOException io ) {
if ( x==null ) x = new ChannelException(io);
x.addFaultyMember(senders[i].getDestination(),io);
}
}
if ( x != null ) throw x;
}
private NioSender[] setupForSend(Member[] destination) throws ChannelException {
ChannelException cx = null;
NioSender[] result = new NioSender[destination.length];
for ( int i=0; i<destination.length; i++ ) {
NioSender sender = nioSenders.get(destination[i]);
try {
if (sender == null) {
sender = new NioSender();
AbstractSender.transferProperties(this, sender);
nioSenders.put(destination[i], sender);
}
sender.reset();
sender.setDestination(destination[i]);
sender.setSelector(selector);
sender.setUdpBased(isUdpBased());
result[i] = sender;
}catch ( UnknownHostException x ) {
if (cx == null) cx = new ChannelException(sm.getString("parallelNioSender.unable.setup.NioSender"), x);
cx.addFaultyMember(destination[i], x);
}
}
if ( cx != null ) throw cx;
else return result;
}
@Override
public void connect() {
//do nothing, we connect on demand
setConnected(true);
}
private synchronized void close() throws ChannelException {
ChannelException x = null;
Object[] members = nioSenders.keySet().toArray();
for (int i=0; i<members.length; i++ ) {
Member mbr = (Member)members[i];
try {
NioSender sender = nioSenders.get(mbr);
sender.disconnect();
}catch ( Exception e ) {
if ( x == null ) x = new ChannelException(e);
x.addFaultyMember(mbr,e);
}
nioSenders.remove(mbr);
}
if ( x != null ) throw x;
}
@Override
public void add(Member member) {
// NOOP
}
@Override
public void remove(Member member) {
//disconnect senders
NioSender sender = nioSenders.remove(member);
if ( sender != null ) sender.disconnect();
}
@Override
public synchronized void disconnect() {
setConnected(false);
try {
close();
} catch (Exception x) {
// Ignore
}
}
@Override
public void finalize() throws Throwable {
try {disconnect(); }catch ( Exception e){/*Ignore*/}
try {
selector.close();
}catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Failed to close selector", e);
}
}
super.finalize();
}
@Override
public boolean keepalive() {
boolean result = false;
for (Iterator<Entry<Member,NioSender>> i = nioSenders.entrySet().iterator(); i.hasNext();) {
Map.Entry<Member, NioSender> entry = i.next();
NioSender sender = entry.getValue();
if ( sender.keepalive() ) {
//nioSenders.remove(entry.getKey());
i.remove();
result = true;
} else {
try {
sender.read();
}catch ( IOException x ) {
sender.disconnect();
sender.reset();
//nioSenders.remove(entry.getKey());
i.remove();
result = true;
}catch ( Exception x ) {
log.warn(sm.getString("parallelNioSender.error.keepalive", sender),x);
}
}
}
//clean up any cancelled keys
if ( result ) try { selector.selectNow(); }catch (Exception e){/*Ignore*/}
return result;
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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.transport.nio;
import java.io.IOException;
import org.apache.catalina.tribes.ChannelException;
import org.apache.catalina.tribes.ChannelMessage;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.transport.AbstractSender;
import org.apache.catalina.tribes.transport.DataSender;
import org.apache.catalina.tribes.transport.PooledSender;
import org.apache.catalina.tribes.util.StringManager;
public class PooledParallelSender extends PooledSender implements PooledParallelSenderMBean {
protected static final StringManager sm = StringManager.getManager(PooledParallelSender.class);
@Override
public void sendMessage(Member[] destination, ChannelMessage message) throws ChannelException {
if (!isConnected()) {
throw new ChannelException(sm.getString("pooledParallelSender.sender.disconnected"));
}
ParallelNioSender sender = (ParallelNioSender)getSender();
if (sender == null) {
ChannelException cx = new ChannelException(sm.getString(
"pooledParallelSender.unable.retrieveSender.timeout",
Long.toString(getMaxWait())));
for (int i = 0; i < destination.length; i++)
cx.addFaultyMember(destination[i], new NullPointerException(sm.getString("pooledParallelSender.unable.retrieveSender")));
throw cx;
} else {
try {
if (!sender.isConnected()) sender.connect();
sender.sendMessage(destination, message);
sender.keepalive();
} catch (ChannelException x) {
sender.disconnect();
throw x;
} finally {
returnSender(sender);
}
}
}
@Override
public DataSender getNewDataSender() {
try {
ParallelNioSender sender = new ParallelNioSender();
AbstractSender.transferProperties(this,sender);
return sender;
} catch ( IOException x ) {
throw new RuntimeException(sm.getString("pooledParallelSender.unable.open"),x);
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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.transport.nio;
public interface PooledParallelSenderMBean {
// Transport Attributes
public int getRxBufSize();
public int getTxBufSize();
public int getUdpRxBufSize();
public int getUdpTxBufSize();
public boolean getDirectBuffer();
public int getKeepAliveCount();
public long getKeepAliveTime();
public long getTimeout();
public int getMaxRetryAttempts();
public boolean getOoBInline();
public boolean getSoKeepAlive();
public boolean getSoLingerOn();
public int getSoLingerTime();
public boolean getSoReuseAddress();
public int getSoTrafficClass();
public boolean getTcpNoDelay();
public boolean getThrowOnFailedAck();
// PooledSender Attributes
public int getPoolSize();
public long getMaxWait();
// Operation
public boolean isConnected();
public int getInPoolSize();
public int getInUsePoolSize();
}