init
This commit is contained in:
1641
java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
Normal file
1641
java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
Normal file
File diff suppressed because it is too large
Load Diff
223
java/org/apache/catalina/tribes/tipis/LazyReplicatedMap.java
Normal file
223
java/org/apache/catalina/tribes/tipis/LazyReplicatedMap.java
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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.tipis;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.catalina.tribes.Channel;
|
||||
import org.apache.catalina.tribes.ChannelException;
|
||||
import org.apache.catalina.tribes.Member;
|
||||
import org.apache.catalina.tribes.UniqueId;
|
||||
import org.apache.catalina.tribes.util.Arrays;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A smart implementation of a stateful replicated map. uses primary/secondary backup strategy.
|
||||
* One node is always the primary and one node is always the backup.
|
||||
* This map is synchronized across a cluster, and only has one backup member.<br>
|
||||
* A perfect usage for this map would be a session map for a session manager in a clustered environment.<br>
|
||||
* The only way to modify this list is to use the <code>put, putAll, remove</code> methods.
|
||||
* entrySet, entrySetFull, keySet, keySetFull, returns all non modifiable sets.<br><br>
|
||||
* If objects (values) in the map change without invoking <code>put()</code> or <code>remove()</code>
|
||||
* the data can be distributed using two different methods:<br>
|
||||
* <code>replicate(boolean)</code> and <code>replicate(Object, boolean)</code><br>
|
||||
* These two methods are very important two understand. The map can work with two set of value objects:<br>
|
||||
* 1. Serializable - the entire object gets serialized each time it is replicated<br>
|
||||
* 2. ReplicatedMapEntry - this interface allows for a isDirty() flag and to replicate diffs if desired.<br>
|
||||
* Implementing the <code>ReplicatedMapEntry</code> interface allows you to decide what objects
|
||||
* get replicated and how much data gets replicated each time.<br>
|
||||
* If you implement a smart AOP mechanism to detect changes in underlying objects, you can replicate
|
||||
* only those changes by implementing the ReplicatedMapEntry interface, and return true when isDiffable()
|
||||
* is invoked.<br><br>
|
||||
*
|
||||
* This map implementation doesn't have a background thread running to replicate changes.
|
||||
* If you do have changes without invoking put/remove then you need to invoke one of the following methods:
|
||||
* <ul>
|
||||
* <li><code>replicate(Object,boolean)</code> - replicates only the object that belongs to the key</li>
|
||||
* <li><code>replicate(boolean)</code> - Scans the entire map for changes and replicates data</li>
|
||||
* </ul>
|
||||
* the <code>boolean</code> value in the <code>replicate</code> method used to decide
|
||||
* whether to only replicate objects that implement the <code>ReplicatedMapEntry</code> interface
|
||||
* or to replicate all objects. If an object doesn't implement the <code>ReplicatedMapEntry</code> interface
|
||||
* each time the object gets replicated the entire object gets serialized, hence a call to <code>replicate(true)</code>
|
||||
* will replicate all objects in this map that are using this node as primary.
|
||||
*
|
||||
* <br><br><b>REMEMBER TO CALL</b> <code>breakdown()</code> or <code>finalize()</code> when you are done with the map to
|
||||
* avoid memory leaks.<br><br>
|
||||
* TODO implement periodic sync/transfer thread
|
||||
*
|
||||
* @param <K> The type of Key
|
||||
* @param <V> The type of Value
|
||||
*/
|
||||
public class LazyReplicatedMap<K,V> extends AbstractReplicatedMap<K,V> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
// Lazy init to support serialization
|
||||
private transient volatile Log log;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CONSTRUCTORS / DESTRUCTORS
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Creates a new map
|
||||
* @param owner The map owner
|
||||
* @param channel The channel to use for communication
|
||||
* @param timeout long - timeout for RPC messages
|
||||
* @param mapContextName String - unique name for this map, to allow multiple maps per channel
|
||||
* @param initialCapacity int - the size of this map, see HashMap
|
||||
* @param loadFactor float - load factor, see HashMap
|
||||
* @param cls Class loaders
|
||||
*/
|
||||
public LazyReplicatedMap(MapOwner owner, Channel channel, long timeout, String mapContextName, int initialCapacity, float loadFactor, ClassLoader[] cls) {
|
||||
super(owner,channel,timeout,mapContextName,initialCapacity,loadFactor, Channel.SEND_OPTIONS_DEFAULT,cls, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map
|
||||
* @param owner The map owner
|
||||
* @param channel The channel to use for communication
|
||||
* @param timeout long - timeout for RPC messages
|
||||
* @param mapContextName String - unique name for this map, to allow multiple maps per channel
|
||||
* @param initialCapacity int - the size of this map, see HashMap
|
||||
* @param cls Class loaders
|
||||
*/
|
||||
public LazyReplicatedMap(MapOwner owner, Channel channel, long timeout, String mapContextName, int initialCapacity, ClassLoader[] cls) {
|
||||
super(owner, channel,timeout,mapContextName,initialCapacity, AbstractReplicatedMap.DEFAULT_LOAD_FACTOR, Channel.SEND_OPTIONS_DEFAULT, cls, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map
|
||||
* @param owner The map owner
|
||||
* @param channel The channel to use for communication
|
||||
* @param timeout long - timeout for RPC messages
|
||||
* @param mapContextName String - unique name for this map, to allow multiple maps per channel
|
||||
* @param cls Class loaders
|
||||
*/
|
||||
public LazyReplicatedMap(MapOwner owner, Channel channel, long timeout, String mapContextName, ClassLoader[] cls) {
|
||||
super(owner, channel,timeout,mapContextName, AbstractReplicatedMap.DEFAULT_INITIAL_CAPACITY,AbstractReplicatedMap.DEFAULT_LOAD_FACTOR,Channel.SEND_OPTIONS_DEFAULT, cls, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map
|
||||
* @param owner The map owner
|
||||
* @param channel The channel to use for communication
|
||||
* @param timeout long - timeout for RPC messages
|
||||
* @param mapContextName String - unique name for this map, to allow multiple maps per channel
|
||||
* @param cls Class loaders
|
||||
* @param terminate boolean - Flag for whether to terminate this map that failed to start.
|
||||
*/
|
||||
public LazyReplicatedMap(MapOwner owner, Channel channel, long timeout, String mapContextName, ClassLoader[] cls, boolean terminate) {
|
||||
super(owner, channel,timeout,mapContextName, AbstractReplicatedMap.DEFAULT_INITIAL_CAPACITY,
|
||||
AbstractReplicatedMap.DEFAULT_LOAD_FACTOR,Channel.SEND_OPTIONS_DEFAULT, cls, terminate);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// METHODS TO OVERRIDE
|
||||
//------------------------------------------------------------------------------
|
||||
@Override
|
||||
protected int getStateMessageType() {
|
||||
return AbstractReplicatedMap.MapMessage.MSG_STATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getReplicateMessageType() {
|
||||
return AbstractReplicatedMap.MapMessage.MSG_BACKUP;
|
||||
}
|
||||
|
||||
/**
|
||||
* publish info about a map pair (key/value) to other nodes in the cluster
|
||||
* @param key Object
|
||||
* @param value Object
|
||||
* @return Member - the backup node
|
||||
* @throws ChannelException Cluster error
|
||||
*/
|
||||
@Override
|
||||
protected Member[] publishEntryInfo(Object key, Object value) throws ChannelException {
|
||||
Log log = getLog();
|
||||
if (! (key instanceof Serializable && value instanceof Serializable) ) return new Member[0];
|
||||
Member[] members = getMapMembers();
|
||||
int firstIdx = getNextBackupIndex();
|
||||
int nextIdx = firstIdx;
|
||||
Member[] backup = new Member[0];
|
||||
|
||||
//there are no backups
|
||||
if ( members.length == 0 || firstIdx == -1 ) return backup;
|
||||
|
||||
boolean success = false;
|
||||
do {
|
||||
//select a backup node
|
||||
Member next = members[nextIdx];
|
||||
|
||||
//increment for the next round of back up selection
|
||||
nextIdx = nextIdx + 1;
|
||||
if ( nextIdx >= members.length ) nextIdx = 0;
|
||||
|
||||
if (next == null) {
|
||||
continue;
|
||||
}
|
||||
MapMessage msg = null;
|
||||
try {
|
||||
Member[] tmpBackup = wrap(next);
|
||||
//publish the backup data to one node
|
||||
msg = new MapMessage(getMapContextName(), MapMessage.MSG_BACKUP, false,
|
||||
(Serializable) key, (Serializable) value, null, channel.getLocalMember(false), tmpBackup);
|
||||
if ( log.isTraceEnabled() )
|
||||
log.trace("Publishing backup data:"+msg+" to: "+next.getName());
|
||||
UniqueId id = getChannel().send(tmpBackup, msg, getChannelSendOptions());
|
||||
if ( log.isTraceEnabled() )
|
||||
log.trace("Data published:"+msg+" msg Id:"+id);
|
||||
//we published out to a backup, mark the test success
|
||||
success = true;
|
||||
backup = tmpBackup;
|
||||
}catch ( ChannelException x ) {
|
||||
log.error(sm.getString("lazyReplicatedMap.unableReplicate.backup", key, next, x.getMessage()), x);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
//publish the data out to all nodes
|
||||
Member[] proxies = excludeFromSet(backup, getMapMembers());
|
||||
if (success && proxies.length > 0 ) {
|
||||
msg = new MapMessage(getMapContextName(), MapMessage.MSG_PROXY, false,
|
||||
(Serializable) key, null, null, channel.getLocalMember(false),backup);
|
||||
if ( log.isTraceEnabled() )
|
||||
log.trace("Publishing proxy data:"+msg+" to: "+Arrays.toNameString(proxies));
|
||||
getChannel().send(proxies, msg, getChannelSendOptions());
|
||||
}
|
||||
}catch ( ChannelException x ) {
|
||||
//log the error, but proceed, this should only happen if a node went down,
|
||||
//and if the node went down, then it can't receive the message, the others
|
||||
//should still get it.
|
||||
log.error(sm.getString("lazyReplicatedMap.unableReplicate.proxy", key, next, x.getMessage()), x);
|
||||
}
|
||||
} while ( !success && (firstIdx!=nextIdx));
|
||||
return backup;
|
||||
}
|
||||
|
||||
|
||||
private Log getLog() {
|
||||
if (log == null) {
|
||||
synchronized (this) {
|
||||
if (log == null) {
|
||||
log = LogFactory.getLog(LazyReplicatedMap.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
return log;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
# 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.
|
||||
|
||||
abstractReplicatedMap.broadcast.noReplies=broadcast received 0 replies, probably a timeout.
|
||||
abstractReplicatedMap.heartbeat.failed=Unable to send AbstractReplicatedMap.ping message
|
||||
abstractReplicatedMap.init.completed=AbstractReplicatedMap[{0}] initialization was completed in [{1}] ms.
|
||||
abstractReplicatedMap.init.start=Initializing AbstractReplicatedMap with context name:[{0}]
|
||||
abstractReplicatedMap.leftOver.ignored=Message[{0}] is ignored.
|
||||
abstractReplicatedMap.leftOver.pingMsg=PING message has been received beyond the timeout period. The map member[{0}] might have been removed from the map membership.
|
||||
abstractReplicatedMap.mapMember.unavailable=Member[{0}] is not available yet.
|
||||
abstractReplicatedMap.mapMemberAdded.added=Map member added:[{0}]
|
||||
abstractReplicatedMap.mapMemberAdded.nullMember=Notified member is not registered in the membership:[{0}].
|
||||
abstractReplicatedMap.member.disappeared=Member[{0}] disappeared. Related map entries will be relocated to the new node.
|
||||
abstractReplicatedMap.ping.stateTransferredMember=Member[{0}] is state transferred but not available yet.
|
||||
abstractReplicatedMap.ping.timeout=Member[{0}] in the Map[{1}] has timed-out in the ping processing.
|
||||
abstractReplicatedMap.relocate.complete=Relocation of map entries was complete in [{0}] ms.
|
||||
abstractReplicatedMap.transferState.noReplies=Transfer state, 0 replies, probably a timeout.
|
||||
abstractReplicatedMap.unable.deserialize.MapMessage=Unable to deserialize MapMessage.
|
||||
abstractReplicatedMap.unable.diffObject=Unable to diff object. Will replicate the entire object instead.
|
||||
abstractReplicatedMap.unable.get=Unable to replicate out data for an AbstractReplicatedMap.get operation
|
||||
abstractReplicatedMap.unable.put=Unable to replicate out data for an AbstractReplicatedMap.put operation
|
||||
abstractReplicatedMap.unable.relocate=Unable to relocate[{0}] to a new backup node
|
||||
abstractReplicatedMap.unable.remove=Unable to replicate out data for an AbstractReplicatedMap.remove operation
|
||||
abstractReplicatedMap.unable.replicate=Unable to replicate data.
|
||||
abstractReplicatedMap.unable.retrieve=Unable to retrieve remote object for key:[{0}]
|
||||
abstractReplicatedMap.unable.transferState=Unable to transfer AbstractReplicatedMap state.
|
||||
abstractReplicatedMap.unableApply.diff=Unable to apply diff to key:[{0}]
|
||||
abstractReplicatedMap.unableSelect.backup=Unable to select backup node.
|
||||
abstractReplicatedMap.unableSend.startMessage=Unable to send map start message.
|
||||
abstractReplicatedMap.unableStart=Unable to start replicated map.
|
||||
|
||||
lazyReplicatedMap.unableReplicate.backup=Unable to replicate backup key:[{0}] to backup:[{1}]. Reason:[{2}]
|
||||
lazyReplicatedMap.unableReplicate.proxy=Unable to replicate proxy key:[{0}] to backup:[{1}]. Reason:[{2}]
|
||||
|
||||
mapMessage.deserialize.error.key=Failed to deserialize MapMessage key
|
||||
mapMessage.deserialize.error.value=Failed to deserialize MapMessage value
|
||||
|
||||
replicatedMap.member.disappeared=Member[{0}] disappeared. Related map entries will be relocated to the new node.
|
||||
replicatedMap.relocate.complete=Relocation of map entries was complete in [{0}] ms.
|
||||
replicatedMap.unable.relocate=Unable to relocate[{0}] to a new backup node
|
||||
replicatedMap.unableReplicate.completely=Unable to replicate backup key:[{0}]. Success nodes:[{1}]. Failed nodes:[{2}].
|
||||
@@ -0,0 +1,20 @@
|
||||
# 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.
|
||||
|
||||
abstractReplicatedMap.broadcast.noReplies=Broadcast hat keine Antworten erhalten; Vermutlich eine Zeitüberschreitung
|
||||
abstractReplicatedMap.leftOver.ignored=Nachricht [{0}] wird ignoriert.
|
||||
|
||||
replicatedMap.relocate.complete=Das Verschieben der Map Einträge ist fertig und hat [{0}] ms gedauert.
|
||||
replicatedMap.unable.relocate=[{0}] kann nicht auch einen Backup-Node umgezogen werden
|
||||
@@ -0,0 +1,23 @@
|
||||
# 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.
|
||||
|
||||
abstractReplicatedMap.broadcast.noReplies=Se recibieron 0 repuestas del broadcast, posiblemente un timeout
|
||||
abstractReplicatedMap.leftOver.ignored=Mensaje [{0}] ignorado.
|
||||
abstractReplicatedMap.unable.get=Imposilbe replicar datos fuera de la operación AbstractReplicatedMap.get
|
||||
|
||||
lazyReplicatedMap.unableReplicate.proxy=Imposible replicar llave de proxy:[{0}] hacia el respaldo:[{1}]. Motivo:[{2}]
|
||||
|
||||
replicatedMap.relocate.complete=La reubicación de las entradas de mapas fue completada en [{0}] ms.
|
||||
replicatedMap.unable.relocate=No se pudo mover [{0}] a un nuevo nodo de respaldo
|
||||
@@ -0,0 +1,53 @@
|
||||
# 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.
|
||||
|
||||
abstractReplicatedMap.broadcast.noReplies=La diffusion (broadcast) n'a pas recu de réponse, probablement un dépassement du temps imparti
|
||||
abstractReplicatedMap.heartbeat.failed=Impossible d'envoyer le message AbstractReplicatedMap.ping
|
||||
abstractReplicatedMap.init.completed=L''initialisation de l''AbstractReplicatedMap[{0}] s''est terminé en [{1}] ms
|
||||
abstractReplicatedMap.init.start=Initialisation de l''AbstractReplicatedMap avec le nom de contexte [{0}]
|
||||
abstractReplicatedMap.leftOver.ignored=Le message [{0}] a été ignoré.
|
||||
abstractReplicatedMap.leftOver.pingMsg=Le délai d''attente a été dépassé pour le message PING, le membre [{0}] a pu être enlevé de la structure du registre de membres
|
||||
abstractReplicatedMap.mapMember.unavailable=Le membre [{0}] n''est pas encore disponible
|
||||
abstractReplicatedMap.mapMemberAdded.added=Le membre de la structure répliquée a été ajouté: [{0}]
|
||||
abstractReplicatedMap.mapMemberAdded.nullMember=Notifié que le membre n''est pas disponible dans le registre de membres: [{0}]
|
||||
abstractReplicatedMap.member.disappeared=Le membre [{0}] a disparu, les entrées correspondantes seront déplacées sur le nouveau nœud
|
||||
abstractReplicatedMap.ping.stateTransferredMember=L''état du membre [{0}] est transféré mais il n''est pas encore disponible
|
||||
abstractReplicatedMap.ping.timeout=Le membre [{0}] dans la carte répliquée [{1}] a fait un timeout lors du traitement d''un ping
|
||||
abstractReplicatedMap.relocate.complete=La relocation des entrées de la structure répliquée a été finie en [{0}] ms
|
||||
abstractReplicatedMap.transferState.noReplies=État de transfert, 0 réponses, probablement un timeout
|
||||
abstractReplicatedMap.unable.deserialize.MapMessage=Impossible de désérialiser MapMessage
|
||||
abstractReplicatedMap.unable.diffObject=Impossible d'obtenir les différences de l'objet, il sera entièrement répliqué
|
||||
abstractReplicatedMap.unable.get=Incapable de répliquer les données pour une opération AbstractReplicatedMap.get
|
||||
abstractReplicatedMap.unable.put=Impossible de répliquer les données pour l'opération AbstractReplicatedMap.put
|
||||
abstractReplicatedMap.unable.relocate=Impossible de déplacer [{0}] sur un nouveau nœud de sauvegarde
|
||||
abstractReplicatedMap.unable.remove=Impossible de répliquer les données de sortie pour l'opération AbstractReplicatedMap.remove
|
||||
abstractReplicatedMap.unable.replicate=Impossible de répliquer les données
|
||||
abstractReplicatedMap.unable.retrieve=Impossible de récupérer les objets distants pour les clés: [{0}]
|
||||
abstractReplicatedMap.unable.transferState=Impossible de transférer l'état de la AbstractReplicatedMap
|
||||
abstractReplicatedMap.unableApply.diff=Impossible d''appliquer le diff à la clé: [{0}]
|
||||
abstractReplicatedMap.unableSelect.backup=Impossible de choisir un nœud de sauvegarde
|
||||
abstractReplicatedMap.unableSend.startMessage=Impossible d'envoyer le message de démarrage de la structure répliquée
|
||||
abstractReplicatedMap.unableStart=Impossible de démarrer la structure répliquée
|
||||
|
||||
lazyReplicatedMap.unableReplicate.backup=Impossible de répliquer la clé de sauvegarde: [{0}]
|
||||
lazyReplicatedMap.unableReplicate.proxy=Incapable de répliquer la clé de proxy : [{0}] vers le secours (backup) : [{1}]. Raison : [{2}]
|
||||
|
||||
mapMessage.deserialize.error.key=Erreur de désérialisation de la clé du MapMessage
|
||||
mapMessage.deserialize.error.value=Erreur de désérialisation de la valeur du MapMessage
|
||||
|
||||
replicatedMap.member.disappeared=Le membre [{0}] a disparu, les entrées correspondantes seront déplacées sur un nouveau nœud
|
||||
replicatedMap.relocate.complete=La relocation des entrées de la structure répliquée a été accomplie en [{0}] ms
|
||||
replicatedMap.unable.relocate=Impossible de déplacer [{0}] sur un nouveau noeud auxiliaire.
|
||||
replicatedMap.unableReplicate.completely=Impossible de répliquer la clé de sauvegarde: [{0}], succès pour les nœuds: [{1}], échec pour les nœuds: [{2}]
|
||||
@@ -0,0 +1,53 @@
|
||||
# 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.
|
||||
|
||||
abstractReplicatedMap.broadcast.noReplies=恐らくタイムアウトが発生したため、ブロードキャストの返信は 0 でした。
|
||||
abstractReplicatedMap.heartbeat.failed=AbstractReplicatedMap.pingメッセージを送信できません。
|
||||
abstractReplicatedMap.init.completed=AbstractReplicatedMap [{0}]の初期化は[{1}] msで完了しました。
|
||||
abstractReplicatedMap.init.start=コンテキスト名:[{0}]を使用してAbstractReplicatedMapを初期化しています。
|
||||
abstractReplicatedMap.leftOver.ignored=メッセージ [{0}] は無視します。
|
||||
abstractReplicatedMap.leftOver.pingMsg=PINGメッセージがタイムアウト期間を超えて受信されました。 マップメンバー[{0}]はマップメンバーシップから削除されている可能性があります。
|
||||
abstractReplicatedMap.mapMember.unavailable=メンバー[{0}]はまだ利用できません。
|
||||
abstractReplicatedMap.mapMemberAdded.added=マップメンバーが追加されました:[{0}]
|
||||
abstractReplicatedMap.mapMemberAdded.nullMember=通知されたメンバーはメンバーシップに登録されていません:[{0}]
|
||||
abstractReplicatedMap.member.disappeared=メンバー[{0}]が消えました。 関連するマップエントリは、新しいノードに再配置されます。
|
||||
abstractReplicatedMap.ping.stateTransferredMember=メンバー [{0}] は状態を転送中で利用可能ではありません。
|
||||
abstractReplicatedMap.ping.timeout=マップ[{1}]のメンバー[{0}]がping処理でタイムアウトしました。
|
||||
abstractReplicatedMap.relocate.complete=マップ要素の再配置は [{0}] ミリ秒で完了しました。
|
||||
abstractReplicatedMap.transferState.noReplies=転送状態、0 レスポンス、おそらくタイムアウトです。
|
||||
abstractReplicatedMap.unable.deserialize.MapMessage=MapMessageのデシリアライズが出来ません。
|
||||
abstractReplicatedMap.unable.diffObject=オブジェクトのdiffを取れません。 代わりにオブジェクト全体を複製します。
|
||||
abstractReplicatedMap.unable.get=AbstractReplicatedMap.get オペレーションでデータの複製ができません
|
||||
abstractReplicatedMap.unable.put=AbstractReplicatedMap.putオペレーションのデータをレプリケートできません
|
||||
abstractReplicatedMap.unable.relocate=[{0}] を新しいバックアップノードへ再配置できません。
|
||||
abstractReplicatedMap.unable.remove=AbstractReplicatedMap.remove オペレーションのデータをレプリケートできません。
|
||||
abstractReplicatedMap.unable.replicate=データを複製できません。
|
||||
abstractReplicatedMap.unable.retrieve=キー:[{0}]のリモートオブジェクトを取得できません。
|
||||
abstractReplicatedMap.unable.transferState=AbstractReplicatedMapの状態を転送できません。
|
||||
abstractReplicatedMap.unableApply.diff=キー [{0}] の差分を計算できません。
|
||||
abstractReplicatedMap.unableSelect.backup=バックアップノードを選択できません。
|
||||
abstractReplicatedMap.unableSend.startMessage=マップ開始メッセージを送信できません。
|
||||
abstractReplicatedMap.unableStart=レプリケーションマップの起動が出来ません。
|
||||
|
||||
lazyReplicatedMap.unableReplicate.backup=[{2}] により、バックアップキー [{0}] をメンバー [{1}] へ複製できません。
|
||||
lazyReplicatedMap.unableReplicate.proxy=[{2}] のため、プロキシキーを [{0}] からバックアップの [{1}] へ複製できません。
|
||||
|
||||
mapMessage.deserialize.error.key=MapMessage キーのデシリアライズに失敗しました。
|
||||
mapMessage.deserialize.error.value=MapMessageの値のデシリアライズに失敗しました。
|
||||
|
||||
replicatedMap.member.disappeared=メンバー[{0}]が消えました。 関連するマップエントリは、新しいノードに再配置されます。
|
||||
replicatedMap.relocate.complete=マップ要素の再配置は [{0}] ms で完了しました。
|
||||
replicatedMap.unable.relocate=[{0}]を新しいバックアップノードに再配置できません
|
||||
replicatedMap.unableReplicate.completely=バックアップキー[{0}]を複製できません。 成功ノード:[{1}]。 障害ノード:[{2}]。
|
||||
@@ -0,0 +1,53 @@
|
||||
# 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.
|
||||
|
||||
abstractReplicatedMap.broadcast.noReplies=broadcast 메소드가 0개의 응답을 받았습니다. 아마도 제한 시간 초과인 듯 합니다.
|
||||
abstractReplicatedMap.heartbeat.failed=AbstractReplicatedMap.ping 메시지를 보낼 수 없습니다.
|
||||
abstractReplicatedMap.init.completed=AbstractReplicatedMap[{0}] 초기화가 [{1}] 밀리초 내에 완료되었습니다.
|
||||
abstractReplicatedMap.init.start=컨텍스트 이름 [{0}]을(를) 사용하여 AbstractReplicatedMap을 초기화합니다.
|
||||
abstractReplicatedMap.leftOver.ignored=메시지 [{0}]은(는) 무시됩니다.
|
||||
abstractReplicatedMap.leftOver.pingMsg=PING 메시지가 제한 시간을 초과하여 수신되었습니다. 해당 map 멤버 [{0}]은(는), map 멤버십으로부터 이미 제거되었을 수 있습니다.
|
||||
abstractReplicatedMap.mapMember.unavailable=멤버 [{0}]은(는) 아직 가용하지 않습니다.
|
||||
abstractReplicatedMap.mapMemberAdded.added=Map 멤버가 추가되었습니다:[{0}]
|
||||
abstractReplicatedMap.mapMemberAdded.nullMember=통지된 멤버는 멤버십에 등록되어 있지 않습니다: [{0}]
|
||||
abstractReplicatedMap.member.disappeared=멤버 [{0}]이(가) 사라졌습니다. 관련 Map 엔트리들은 새 노드로 다시 위치시킬 것입니다.
|
||||
abstractReplicatedMap.ping.stateTransferredMember=멤버 [{0}]이(가), 상태가 이전된 상태이지만, 아직 가용하지 않습니다.
|
||||
abstractReplicatedMap.ping.timeout=Map [{1}] 내의 멤버 [{0}]은(는) ping 처리 중에 제한 시간 초과되었습니다.
|
||||
abstractReplicatedMap.relocate.complete=Map 엔트리들을 재위치시키는 작업이 [{0}] 밀리초에 완료되었습니다.
|
||||
abstractReplicatedMap.transferState.noReplies=transferState에서 응답이 하나도 없었습니다. 아마도 제한 시간 초과된 듯합니다.
|
||||
abstractReplicatedMap.unable.deserialize.MapMessage=MapMessage를 역직렬화할 수 없습니다.
|
||||
abstractReplicatedMap.unable.diffObject=객체에 대한 diff를 생성할 수 없습니다. 대신 전체 객체를 복제하겠습니다.
|
||||
abstractReplicatedMap.unable.get=AbstractReplicatedMap.get 오퍼레이션에서, 데이터를 복제하여 반환할 수 없습니다.
|
||||
abstractReplicatedMap.unable.put=AbstractReplicatedMap.put 오퍼레이션을 위한 데이터를 외부로 복제할 수 없습니다.
|
||||
abstractReplicatedMap.unable.relocate=[{0}]을(를) 새로운 백업 노드로 재위치시킬 수 없습니다.
|
||||
abstractReplicatedMap.unable.remove=AbstractReplicatedMap.remove 오퍼레이션에서, 복제를 위한 데이터를 전송할 수 없습니다.
|
||||
abstractReplicatedMap.unable.replicate=데이터를 복제할 수 없습니다.
|
||||
abstractReplicatedMap.unable.retrieve=키 [{0}]을(를) 위한 원격 객체를 검색할 수 없습니다.
|
||||
abstractReplicatedMap.unable.transferState=AbstractReplicatedMap 상태를 전이시킬 수 없습니다.
|
||||
abstractReplicatedMap.unableApply.diff=키 [{0}]에 diff를 적용할 수 없습니다.
|
||||
abstractReplicatedMap.unableSelect.backup=백업 노드를 선택할 수 없습니다.
|
||||
abstractReplicatedMap.unableSend.startMessage=Map 시작 메시지를 전송할 수 없습니다.
|
||||
abstractReplicatedMap.unableStart=ReplicatedMap을 시작할 수 없습니다.
|
||||
|
||||
lazyReplicatedMap.unableReplicate.backup=백업 키 [{0}]을(를) 백업 [{1}]에 복제할 수 없습니다. 사유:[{2}]
|
||||
lazyReplicatedMap.unableReplicate.proxy=프록시 키 [{0}]을(를) 백업인 [{1}](으)로 복제할 수 없습니다. 사유: [{2}]
|
||||
|
||||
mapMessage.deserialize.error.key=MapMessage.key()에서 역직렬화에 실패했습니다.
|
||||
mapMessage.deserialize.error.value=MapMessage 값을 역직렬화하지 못했습니다.
|
||||
|
||||
replicatedMap.member.disappeared=멤버 [{0}]이(가) 사라졌습니다. 관련 Map의 엔트리들은 새 노드로 다시 위치시킬 것입니다.
|
||||
replicatedMap.relocate.complete=Map의 엔트리들 모두 다시 위치시켰습니다. 소요시간: [{0}] 밀리초.
|
||||
replicatedMap.unable.relocate=멤버 [{0}]에 새로운 백업 노드를 다시 지정할 수 없습니다.
|
||||
replicatedMap.unableReplicate.completely=백업 키 [{0}]을(를) 복제할 수 없습니다. 성공 노드들: [{1}]. 실패 노드들: [{2}]
|
||||
@@ -0,0 +1,16 @@
|
||||
# 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.
|
||||
|
||||
abstractReplicatedMap.leftOver.ignored=Сообщение[{0}] проигнорированно.
|
||||
@@ -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.
|
||||
|
||||
abstractReplicatedMap.broadcast.noReplies=广播收到0回复,可能是超时了。
|
||||
abstractReplicatedMap.leftOver.ignored=消息[{0}]被忽略
|
||||
abstractReplicatedMap.member.disappeared=成员[{0}]已消失。相关的映射项将重新定位到新节点。
|
||||
abstractReplicatedMap.transferState.noReplies=传输状态,0响应,也许是超时。
|
||||
abstractReplicatedMap.unable.get=无法复制 AbstractReplicatedMap.get 操作的数据
|
||||
abstractReplicatedMap.unable.put=无法复制AbstractReplicatedMap.Put操作的数据
|
||||
abstractReplicatedMap.unable.relocate=无法将[{0}]重新定位到新的备份节点
|
||||
abstractReplicatedMap.unableSelect.backup=无法选择备用节点
|
||||
abstractReplicatedMap.unableSend.startMessage=无法发送map启动消息。
|
||||
abstractReplicatedMap.unableStart=无法启动复制Map
|
||||
|
||||
lazyReplicatedMap.unableReplicate.proxy=不能复制proxy key:[{0}]到备份:[{1}]. 原因是:[{2}]
|
||||
|
||||
mapMessage.deserialize.error.key=反序列化MapMessage主键失败
|
||||
mapMessage.deserialize.error.value=MapMessage.value的反序列化误差
|
||||
|
||||
replicatedMap.member.disappeared=成员[{0}]消失,关联的键值实体会重新关联到一个新的节点。
|
||||
replicatedMap.relocate.complete=map 条目的重定位在 [{0}] ms内完成。
|
||||
replicatedMap.unable.relocate=不能为一个新的备份节点重启定位[{0}]
|
||||
277
java/org/apache/catalina/tribes/tipis/ReplicatedMap.java
Normal file
277
java/org/apache/catalina/tribes/tipis/ReplicatedMap.java
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* 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.tipis;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.catalina.tribes.Channel;
|
||||
import org.apache.catalina.tribes.ChannelException;
|
||||
import org.apache.catalina.tribes.ChannelException.FaultyMember;
|
||||
import org.apache.catalina.tribes.Member;
|
||||
import org.apache.catalina.tribes.RemoteProcessException;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* All-to-all replication for a hash map implementation. Each node in the cluster will carry an identical
|
||||
* copy of the map.<br><br>
|
||||
* This map implementation doesn't have a background thread running to replicate changes.
|
||||
* If you do have changes without invoking put/remove then you need to invoke one of the following methods:
|
||||
* <ul>
|
||||
* <li><code>replicate(Object,boolean)</code> - replicates only the object that belongs to the key</li>
|
||||
* <li><code>replicate(boolean)</code> - Scans the entire map for changes and replicates data</li>
|
||||
* </ul>
|
||||
* the <code>boolean</code> value in the <code>replicate</code> method used to decide
|
||||
* whether to only replicate objects that implement the <code>ReplicatedMapEntry</code> interface
|
||||
* or to replicate all objects. If an object doesn't implement the <code>ReplicatedMapEntry</code> interface
|
||||
* each time the object gets replicated the entire object gets serialized, hence a call to <code>replicate(true)</code>
|
||||
* will replicate all objects in this map that are using this node as primary.
|
||||
*
|
||||
* <br><br><b>REMEMBER TO CALL <code>breakdown()</code> or <code>finalize()</code>
|
||||
* when you are done with the map to avoid memory leaks.</b><br><br>
|
||||
* TODO implement periodic sync/transfer thread<br>
|
||||
* TODO memberDisappeared, should do nothing except change map membership
|
||||
* by default it relocates the primary objects
|
||||
*
|
||||
* @param <K> The type of Key
|
||||
* @param <V> The type of Value
|
||||
*/
|
||||
public class ReplicatedMap<K,V> extends AbstractReplicatedMap<K,V> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// Lazy init to support serialization
|
||||
private transient volatile Log log;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// CONSTRUCTORS / DESTRUCTORS
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* Creates a new map
|
||||
* @param owner The map owner
|
||||
* @param channel The channel to use for communication
|
||||
* @param timeout long - timeout for RPC messages
|
||||
* @param mapContextName String - unique name for this map, to allow multiple maps per channel
|
||||
* @param initialCapacity int - the size of this map, see HashMap
|
||||
* @param loadFactor float - load factor, see HashMap
|
||||
* @param cls Class loaders
|
||||
*/
|
||||
public ReplicatedMap(MapOwner owner, Channel channel, long timeout, String mapContextName, int initialCapacity,float loadFactor, ClassLoader[] cls) {
|
||||
super(owner,channel, timeout, mapContextName, initialCapacity, loadFactor, Channel.SEND_OPTIONS_DEFAULT, cls, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map
|
||||
* @param owner The map owner
|
||||
* @param channel The channel to use for communication
|
||||
* @param timeout long - timeout for RPC messages
|
||||
* @param mapContextName String - unique name for this map, to allow multiple maps per channel
|
||||
* @param initialCapacity int - the size of this map, see HashMap
|
||||
* @param cls Class loaders
|
||||
*/
|
||||
public ReplicatedMap(MapOwner owner, Channel channel, long timeout, String mapContextName, int initialCapacity, ClassLoader[] cls) {
|
||||
super(owner,channel, timeout, mapContextName, initialCapacity, AbstractReplicatedMap.DEFAULT_LOAD_FACTOR,Channel.SEND_OPTIONS_DEFAULT, cls, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map
|
||||
* @param owner The map owner
|
||||
* @param channel The channel to use for communication
|
||||
* @param timeout long - timeout for RPC messages
|
||||
* @param mapContextName String - unique name for this map, to allow multiple maps per channel
|
||||
* @param cls Class loaders
|
||||
*/
|
||||
public ReplicatedMap(MapOwner owner, Channel channel, long timeout, String mapContextName, ClassLoader[] cls) {
|
||||
super(owner, channel, timeout, mapContextName,AbstractReplicatedMap.DEFAULT_INITIAL_CAPACITY, AbstractReplicatedMap.DEFAULT_LOAD_FACTOR, Channel.SEND_OPTIONS_DEFAULT, cls, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map
|
||||
* @param owner The map owner
|
||||
* @param channel The channel to use for communication
|
||||
* @param timeout long - timeout for RPC messages
|
||||
* @param mapContextName String - unique name for this map, to allow multiple maps per channel
|
||||
* @param cls Class loaders
|
||||
* @param terminate boolean - Flag for whether to terminate this map that failed to start.
|
||||
*/
|
||||
public ReplicatedMap(MapOwner owner, Channel channel, long timeout, String mapContextName, ClassLoader[] cls, boolean terminate) {
|
||||
super(owner, channel, timeout, mapContextName,AbstractReplicatedMap.DEFAULT_INITIAL_CAPACITY,
|
||||
AbstractReplicatedMap.DEFAULT_LOAD_FACTOR, Channel.SEND_OPTIONS_DEFAULT, cls, terminate);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// METHODS TO OVERRIDE
|
||||
//------------------------------------------------------------------------------
|
||||
@Override
|
||||
protected int getStateMessageType() {
|
||||
return AbstractReplicatedMap.MapMessage.MSG_STATE_COPY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getReplicateMessageType() {
|
||||
return AbstractReplicatedMap.MapMessage.MSG_COPY;
|
||||
}
|
||||
|
||||
/**
|
||||
* publish info about a map pair (key/value) to other nodes in the cluster
|
||||
* @param key Object
|
||||
* @param value Object
|
||||
* @return Member - the backup node
|
||||
* @throws ChannelException Cluster error
|
||||
*/
|
||||
@Override
|
||||
protected Member[] publishEntryInfo(Object key, Object value) throws ChannelException {
|
||||
if (! (key instanceof Serializable && value instanceof Serializable) ) return new Member[0];
|
||||
//select a backup node
|
||||
Member[] backup = getMapMembers();
|
||||
|
||||
if (backup == null || backup.length == 0) return null;
|
||||
|
||||
try {
|
||||
//publish the data out to all nodes
|
||||
MapMessage msg = new MapMessage(getMapContextName(), MapMessage.MSG_COPY, false,
|
||||
(Serializable) key, (Serializable) value, null,channel.getLocalMember(false), backup);
|
||||
|
||||
getChannel().send(backup, msg, getChannelSendOptions());
|
||||
} catch (ChannelException e) {
|
||||
FaultyMember[] faultyMembers = e.getFaultyMembers();
|
||||
if (faultyMembers.length == 0) throw e;
|
||||
List<Member> faulty = new ArrayList<>();
|
||||
for (FaultyMember faultyMember : faultyMembers) {
|
||||
if (!(faultyMember.getCause() instanceof RemoteProcessException)) {
|
||||
faulty.add(faultyMember.getMember());
|
||||
}
|
||||
}
|
||||
Member[] realFaultyMembers = faulty.toArray(new Member[faulty.size()]);
|
||||
if (realFaultyMembers.length != 0) {
|
||||
backup = excludeFromSet(realFaultyMembers, backup);
|
||||
if (backup.length == 0) {
|
||||
throw e;
|
||||
} else {
|
||||
if (getLog().isWarnEnabled()) {
|
||||
getLog().warn(sm.getString("replicatedMap.unableReplicate.completely", key,
|
||||
Arrays.toString(backup), Arrays.toString(realFaultyMembers)), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return backup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void memberDisappeared(Member member) {
|
||||
boolean removed = false;
|
||||
Log log = getLog();
|
||||
synchronized (mapMembers) {
|
||||
removed = (mapMembers.remove(member) != null );
|
||||
if (!removed) {
|
||||
if (log.isDebugEnabled()) log.debug("Member["+member+"] disappeared, but was not present in the map.");
|
||||
return; //the member was not part of our map.
|
||||
}
|
||||
}
|
||||
if (log.isInfoEnabled())
|
||||
log.info(sm.getString("replicatedMap.member.disappeared", member));
|
||||
long start = System.currentTimeMillis();
|
||||
for (Entry<K, MapEntry<K, V>> e : innerMap.entrySet()) {
|
||||
MapEntry<K,V> entry = innerMap.get(e.getKey());
|
||||
if (entry==null) continue;
|
||||
if (entry.isPrimary()) {
|
||||
try {
|
||||
Member[] backup = getMapMembers();
|
||||
if (backup.length > 0) {
|
||||
MapMessage msg = new MapMessage(getMapContextName(), MapMessage.MSG_NOTIFY_MAPMEMBER,false,
|
||||
(Serializable)entry.getKey(),null,null,channel.getLocalMember(false),backup);
|
||||
getChannel().send(backup, msg, getChannelSendOptions());
|
||||
}
|
||||
entry.setBackupNodes(backup);
|
||||
entry.setPrimary(channel.getLocalMember(false));
|
||||
} catch (ChannelException x) {
|
||||
log.error(sm.getString("replicatedMap.unable.relocate", entry.getKey()), x);
|
||||
}
|
||||
} else if (member.equals(entry.getPrimary())) {
|
||||
entry.setPrimary(null);
|
||||
}
|
||||
|
||||
if ( entry.getPrimary() == null &&
|
||||
entry.isCopy() &&
|
||||
entry.getBackupNodes()!=null &&
|
||||
entry.getBackupNodes().length > 0 &&
|
||||
entry.getBackupNodes()[0].equals(channel.getLocalMember(false)) ) {
|
||||
try {
|
||||
entry.setPrimary(channel.getLocalMember(false));
|
||||
entry.setBackup(false);
|
||||
entry.setProxy(false);
|
||||
entry.setCopy(false);
|
||||
Member[] backup = getMapMembers();
|
||||
if (backup.length > 0) {
|
||||
MapMessage msg = new MapMessage(getMapContextName(), MapMessage.MSG_NOTIFY_MAPMEMBER,false,
|
||||
(Serializable)entry.getKey(),null,null,channel.getLocalMember(false),backup);
|
||||
getChannel().send(backup, msg, getChannelSendOptions());
|
||||
}
|
||||
entry.setBackupNodes(backup);
|
||||
if ( mapOwner!=null ) mapOwner.objectMadePrimary(entry.getKey(),entry.getValue());
|
||||
|
||||
} catch (ChannelException x) {
|
||||
log.error(sm.getString("replicatedMap.unable.relocate", entry.getKey()), x);
|
||||
}
|
||||
}
|
||||
|
||||
} //while
|
||||
long complete = System.currentTimeMillis() - start;
|
||||
if (log.isInfoEnabled()) log.info(sm.getString("replicatedMap.relocate.complete",
|
||||
Long.toString(complete)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapMemberAdded(Member member) {
|
||||
if ( member.equals(getChannel().getLocalMember(false)) ) return;
|
||||
boolean memberAdded = false;
|
||||
synchronized (mapMembers) {
|
||||
if (!mapMembers.containsKey(member) ) {
|
||||
mapMembers.put(member, Long.valueOf(System.currentTimeMillis()));
|
||||
memberAdded = true;
|
||||
}
|
||||
}
|
||||
if ( memberAdded ) {
|
||||
synchronized (stateMutex) {
|
||||
Member[] backup = getMapMembers();
|
||||
for (Entry<K, MapEntry<K, V>> e : innerMap.entrySet()) {
|
||||
MapEntry<K,V> entry = innerMap.get(e.getKey());
|
||||
if ( entry == null ) continue;
|
||||
if (entry.isPrimary() && !inSet(member,entry.getBackupNodes())) {
|
||||
entry.setBackupNodes(backup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Log getLog() {
|
||||
if (log == null) {
|
||||
synchronized (this) {
|
||||
if (log == null) {
|
||||
log = LogFactory.getLog(ReplicatedMap.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
return log;
|
||||
}
|
||||
}
|
||||
143
java/org/apache/catalina/tribes/tipis/ReplicatedMapEntry.java
Normal file
143
java/org/apache/catalina/tribes/tipis/ReplicatedMapEntry.java
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.tipis;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* For smarter replication, an object can implement this interface to replicate diffs<br>
|
||||
* The replication logic will call the methods in the following order:<br>
|
||||
* <code>
|
||||
* 1. if ( entry.isDirty() ) <br>
|
||||
* try {
|
||||
* 2. entry.lock();<br>
|
||||
* 3. byte[] diff = entry.getDiff();<br>
|
||||
* 4. entry.reset();<br>
|
||||
* } finally {<br>
|
||||
* 5. entry.unlock();<br>
|
||||
* }<br>
|
||||
* }<br>
|
||||
* </code>
|
||||
* <br>
|
||||
* <br>
|
||||
* When the data is deserialized the logic is called in the following order<br>
|
||||
* <code>
|
||||
* 1. ReplicatedMapEntry entry = (ReplicatedMapEntry)objectIn.readObject();<br>
|
||||
* 2. if ( isBackup(entry)||isPrimary(entry) ) entry.setOwner(owner); <br>
|
||||
* </code>
|
||||
* <br>
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface ReplicatedMapEntry extends Serializable {
|
||||
|
||||
/**
|
||||
* Has the object changed since last replication
|
||||
* and is not in a locked state
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isDirty();
|
||||
|
||||
/**
|
||||
* If this returns true, the map will extract the diff using getDiff()
|
||||
* Otherwise it will serialize the entire object.
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isDiffable();
|
||||
|
||||
/**
|
||||
* Returns a diff and sets the dirty map to false
|
||||
* @return Serialized diff data
|
||||
* @throws IOException IO error serializing
|
||||
*/
|
||||
public byte[] getDiff() throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Applies a diff to an existing object.
|
||||
* @param diff Serialized diff data
|
||||
* @param offset Array offset
|
||||
* @param length Array length
|
||||
* @throws IOException IO error deserializing
|
||||
* @throws ClassNotFoundException Serialization error
|
||||
*/
|
||||
public void applyDiff(byte[] diff, int offset, int length) throws IOException, ClassNotFoundException;
|
||||
|
||||
/**
|
||||
* Resets the current diff state and resets the dirty flag
|
||||
*/
|
||||
public void resetDiff();
|
||||
|
||||
/**
|
||||
* Lock during serialization
|
||||
*/
|
||||
public void lock();
|
||||
|
||||
/**
|
||||
* Unlock after serialization
|
||||
*/
|
||||
public void unlock();
|
||||
|
||||
/**
|
||||
* This method is called after the object has been
|
||||
* created on a remote map. On this method,
|
||||
* the object can initialize itself for any data that wasn't
|
||||
*
|
||||
* @param owner Object
|
||||
*/
|
||||
public void setOwner(Object owner);
|
||||
|
||||
/**
|
||||
* For accuracy checking, a serialized attribute can contain a version number
|
||||
* This number increases as modifications are made to the data.
|
||||
* The replicated map can use this to ensure accuracy on a periodic basis
|
||||
* @return long - the version number or -1 if the data is not versioned
|
||||
*/
|
||||
public long getVersion();
|
||||
|
||||
/**
|
||||
* Forces a certain version to a replicated map entry<br>
|
||||
* @param version long
|
||||
*/
|
||||
public void setVersion(long version);
|
||||
|
||||
/**
|
||||
* @return the last replicate time.
|
||||
*/
|
||||
public long getLastTimeReplicated();
|
||||
|
||||
/**
|
||||
* Set the last replicate time.
|
||||
* @param lastTimeReplicated New timestamp
|
||||
*/
|
||||
public void setLastTimeReplicated(long lastTimeReplicated);
|
||||
|
||||
/**
|
||||
* If this returns true, to replicate that an object has been accessed
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isAccessReplicate();
|
||||
|
||||
/**
|
||||
* Access to an existing object.
|
||||
*/
|
||||
public void accessEntry();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user