20
20
import com .rabbitmq .client .impl .ConnectionParams ;
21
21
import com .rabbitmq .client .impl .FrameHandlerFactory ;
22
22
import com .rabbitmq .client .impl .NetworkConnection ;
23
+ import com .rabbitmq .utility .Utility ;
23
24
24
25
import java .io .IOException ;
25
26
import java .net .InetAddress ;
26
27
import java .util .ArrayList ;
27
28
import java .util .Collection ;
28
- import java .util .HashMap ;
29
+ import java .util .Collections ;
29
30
import java .util .HashSet ;
30
31
import java .util .Iterator ;
32
+ import java .util .LinkedHashMap ;
31
33
import java .util .List ;
32
34
import java .util .Map ;
33
35
import java .util .Set ;
@@ -60,19 +62,19 @@ public class AutorecoveringConnection implements Connection, Recoverable, Networ
60
62
private final RecoveryAwareAMQConnectionFactory cf ;
61
63
private final Map <Integer , AutorecoveringChannel > channels ;
62
64
private final ConnectionParams params ;
63
- private RecoveryAwareAMQConnection delegate ;
65
+ private volatile RecoveryAwareAMQConnection delegate ;
64
66
65
- private final List <ShutdownListener > shutdownHooks = new ArrayList <ShutdownListener >();
66
- private final List <RecoveryListener > recoveryListeners = new ArrayList <RecoveryListener >();
67
- private final List <BlockedListener > blockedListeners = new ArrayList <BlockedListener >();
67
+ private final List <ShutdownListener > shutdownHooks = Collections . synchronizedList ( new ArrayList <ShutdownListener >() );
68
+ private final List <RecoveryListener > recoveryListeners = Collections . synchronizedList ( new ArrayList <RecoveryListener >() );
69
+ private final List <BlockedListener > blockedListeners = Collections . synchronizedList ( new ArrayList <BlockedListener >() );
68
70
69
71
// Records topology changes
70
- private final Map <String , RecordedQueue > recordedQueues = new ConcurrentHashMap <String , RecordedQueue >();
71
- private final List <RecordedBinding > recordedBindings = new ArrayList <RecordedBinding >();
72
- private final Map <String , RecordedExchange > recordedExchanges = new ConcurrentHashMap <String , RecordedExchange >();
73
- private final Map <String , RecordedConsumer > consumers = new ConcurrentHashMap <String , RecordedConsumer >();
74
- private final List <ConsumerRecoveryListener > consumerRecoveryListeners = new ArrayList <ConsumerRecoveryListener >();
75
- private final List <QueueRecoveryListener > queueRecoveryListeners = new ArrayList <QueueRecoveryListener >();
72
+ private final Map <String , RecordedQueue > recordedQueues = Collections . synchronizedMap ( new LinkedHashMap <String , RecordedQueue >() );
73
+ private final List <RecordedBinding > recordedBindings = Collections . synchronizedList ( new ArrayList <RecordedBinding >() );
74
+ private final Map <String , RecordedExchange > recordedExchanges = Collections . synchronizedMap ( new LinkedHashMap <String , RecordedExchange >() );
75
+ private final Map <String , RecordedConsumer > consumers = Collections . synchronizedMap ( new LinkedHashMap <String , RecordedConsumer >() );
76
+ private final List <ConsumerRecoveryListener > consumerRecoveryListeners = Collections . synchronizedList ( new ArrayList <ConsumerRecoveryListener >() );
77
+ private final List <QueueRecoveryListener > queueRecoveryListeners = Collections . synchronizedList ( new ArrayList <QueueRecoveryListener >() );
76
78
77
79
// Used to block connection recovery attempts after close() is invoked.
78
80
private volatile boolean manuallyClosed = false ;
@@ -136,10 +138,10 @@ public Channel createChannel(int channelNumber) throws IOException {
136
138
* @return Recovering channel.
137
139
*/
138
140
private Channel wrapChannel (RecoveryAwareChannelN delegateChannel ) {
139
- final AutorecoveringChannel channel = new AutorecoveringChannel (this , delegateChannel );
140
141
if (delegateChannel == null ) {
141
142
return null ;
142
143
} else {
144
+ final AutorecoveringChannel channel = new AutorecoveringChannel (this , delegateChannel );
143
145
this .registerChannel (channel );
144
146
return channel ;
145
147
}
@@ -514,13 +516,13 @@ synchronized private void beginAutomaticRecovery() throws InterruptedException {
514
516
}
515
517
516
518
private void recoverShutdownListeners (final RecoveryAwareAMQConnection newConn ) {
517
- for (ShutdownListener sh : this .shutdownHooks ) {
519
+ for (ShutdownListener sh : Utility . copy ( this .shutdownHooks ) ) {
518
520
newConn .addShutdownListener (sh );
519
521
}
520
522
}
521
523
522
524
private void recoverBlockedListeners (final RecoveryAwareAMQConnection newConn ) {
523
- for (BlockedListener bl : this .blockedListeners ) {
525
+ for (BlockedListener bl : Utility . copy ( this .blockedListeners ) ) {
524
526
newConn .addBlockedListener (bl );
525
527
}
526
528
}
@@ -564,7 +566,7 @@ private void recoverChannels(final RecoveryAwareAMQConnection newConn) {
564
566
}
565
567
566
568
private void notifyRecoveryListeners () {
567
- for (RecoveryListener f : this .recoveryListeners ) {
569
+ for (RecoveryListener f : Utility . copy ( this .recoveryListeners ) ) {
568
570
f .handleRecovery (this );
569
571
}
570
572
}
@@ -585,7 +587,7 @@ private void recoverExchanges() {
585
587
// recorded exchanges are guaranteed to be
586
588
// non-predefined (we filter out predefined ones
587
589
// in exchangeDeclare). MK.
588
- for (RecordedExchange x : this .recordedExchanges .values ()) {
590
+ for (RecordedExchange x : Utility . copy ( this .recordedExchanges ) .values ()) {
589
591
try {
590
592
x .recover ();
591
593
} catch (Exception cause ) {
@@ -598,8 +600,7 @@ private void recoverExchanges() {
598
600
}
599
601
600
602
private void recoverQueues () {
601
- Map <String , RecordedQueue > copy = new HashMap <String , RecordedQueue >(this .recordedQueues );
602
- for (Map .Entry <String , RecordedQueue > entry : copy .entrySet ()) {
603
+ for (Map .Entry <String , RecordedQueue > entry : Utility .copy (this .recordedQueues ).entrySet ()) {
603
604
String oldName = entry .getKey ();
604
605
RecordedQueue q = entry .getValue ();
605
606
try {
@@ -621,7 +622,7 @@ private void recoverQueues() {
621
622
this .recordedQueues .put (newName , q );
622
623
}
623
624
}
624
- for (QueueRecoveryListener qrl : this .queueRecoveryListeners ) {
625
+ for (QueueRecoveryListener qrl : Utility . copy ( this .queueRecoveryListeners ) ) {
625
626
qrl .queueRecovered (oldName , newName );
626
627
}
627
628
} catch (Exception cause ) {
@@ -634,7 +635,7 @@ private void recoverQueues() {
634
635
}
635
636
636
637
private void recoverBindings () {
637
- for (RecordedBinding b : this .recordedBindings ) {
638
+ for (RecordedBinding b : Utility . copy ( this .recordedBindings ) ) {
638
639
try {
639
640
b .recover ();
640
641
} catch (Exception cause ) {
@@ -647,8 +648,7 @@ private void recoverBindings() {
647
648
}
648
649
649
650
private void recoverConsumers () {
650
- Map <String , RecordedConsumer > copy = new HashMap <String , RecordedConsumer >(this .consumers );
651
- for (Map .Entry <String , RecordedConsumer > entry : copy .entrySet ()) {
651
+ for (Map .Entry <String , RecordedConsumer > entry : Utility .copy (this .consumers ).entrySet ()) {
652
652
String tag = entry .getKey ();
653
653
RecordedConsumer consumer = entry .getValue ();
654
654
@@ -659,7 +659,7 @@ private void recoverConsumers() {
659
659
this .consumers .remove (tag );
660
660
this .consumers .put (newTag , consumer );
661
661
}
662
- for (ConsumerRecoveryListener crl : this .consumerRecoveryListeners ) {
662
+ for (ConsumerRecoveryListener crl : Utility . copy ( this .consumerRecoveryListeners ) ) {
663
663
crl .consumerRecovered (tag , newTag );
664
664
}
665
665
} catch (Exception cause ) {
@@ -672,22 +672,22 @@ private void recoverConsumers() {
672
672
}
673
673
674
674
private void propagateQueueNameChangeToBindings (String oldName , String newName ) {
675
- for (RecordedBinding b : this .recordedBindings ) {
675
+ for (RecordedBinding b : Utility . copy ( this .recordedBindings ) ) {
676
676
if (b .getDestination ().equals (oldName )) {
677
677
b .setDestination (newName );
678
678
}
679
679
}
680
680
}
681
681
682
682
private void propagateQueueNameChangeToConsumers (String oldName , String newName ) {
683
- for (RecordedConsumer c : this .consumers .values ()) {
683
+ for (RecordedConsumer c : Utility . copy ( this .consumers ) .values ()) {
684
684
if (c .getQueue ().equals (oldName )) {
685
685
c .setQueue (newName );
686
686
}
687
687
}
688
688
}
689
689
690
- synchronized void recordQueueBinding (AutorecoveringChannel ch ,
690
+ void recordQueueBinding (AutorecoveringChannel ch ,
691
691
String queue ,
692
692
String exchange ,
693
693
String routingKey ,
@@ -701,7 +701,7 @@ synchronized void recordQueueBinding(AutorecoveringChannel ch,
701
701
this .recordedBindings .add (binding );
702
702
}
703
703
704
- synchronized boolean deleteRecordedQueueBinding (AutorecoveringChannel ch ,
704
+ boolean deleteRecordedQueueBinding (AutorecoveringChannel ch ,
705
705
String queue ,
706
706
String exchange ,
707
707
String routingKey ,
@@ -714,7 +714,7 @@ synchronized boolean deleteRecordedQueueBinding(AutorecoveringChannel ch,
714
714
return this .recordedBindings .remove (b );
715
715
}
716
716
717
- synchronized void recordExchangeBinding (AutorecoveringChannel ch ,
717
+ void recordExchangeBinding (AutorecoveringChannel ch ,
718
718
String destination ,
719
719
String source ,
720
720
String routingKey ,
@@ -728,7 +728,7 @@ synchronized void recordExchangeBinding(AutorecoveringChannel ch,
728
728
this .recordedBindings .add (binding );
729
729
}
730
730
731
- synchronized boolean deleteRecordedExchangeBinding (AutorecoveringChannel ch ,
731
+ boolean deleteRecordedExchangeBinding (AutorecoveringChannel ch ,
732
732
String destination ,
733
733
String source ,
734
734
String routingKey ,
@@ -784,7 +784,9 @@ void maybeDeleteRecordedAutoDeleteQueue(String queue) {
784
784
RecordedQueue q = this .recordedQueues .get (queue );
785
785
// last consumer on this connection is gone, remove recorded queue
786
786
// if it is auto-deleted. See bug 26364.
787
- if ((q != null ) && q .isAutoDelete ()) { this .recordedQueues .remove (queue ); }
787
+ if ((q != null ) && q .isAutoDelete ()) {
788
+ deleteRecordedQueue (queue );
789
+ }
788
790
}
789
791
}
790
792
}
@@ -793,11 +795,13 @@ void maybeDeleteRecordedAutoDeleteQueue(String queue) {
793
795
void maybeDeleteRecordedAutoDeleteExchange (String exchange ) {
794
796
synchronized (this .recordedExchanges ) {
795
797
synchronized (this .consumers ) {
796
- if (!hasMoreDestinationsBoundToExchange (this .recordedBindings , exchange )) {
798
+ if (!hasMoreDestinationsBoundToExchange (Utility . copy ( this .recordedBindings ) , exchange )) {
797
799
RecordedExchange x = this .recordedExchanges .get (exchange );
798
800
// last binding where this exchange is the source is gone, remove recorded exchange
799
801
// if it is auto-deleted. See bug 26364.
800
- if ((x != null ) && x .isAutoDelete ()) { this .recordedExchanges .remove (exchange ); }
802
+ if ((x != null ) && x .isAutoDelete ()) {
803
+ this .recordedExchanges .remove (exchange );
804
+ }
801
805
}
802
806
}
803
807
}
@@ -825,13 +829,15 @@ boolean hasMoreConsumersOnQueue(Collection<RecordedConsumer> consumers, String q
825
829
return result ;
826
830
}
827
831
828
- synchronized Set <RecordedBinding > removeBindingsWithDestination (String s ) {
829
- Set <RecordedBinding > result = new HashSet <RecordedBinding >();
830
- for (Iterator <RecordedBinding > it = this .recordedBindings .iterator (); it .hasNext (); ) {
831
- RecordedBinding b = it .next ();
832
- if (b .getDestination ().equals (s )) {
833
- it .remove ();
834
- result .add (b );
832
+ Set <RecordedBinding > removeBindingsWithDestination (String s ) {
833
+ final Set <RecordedBinding > result = new HashSet <RecordedBinding >();
834
+ synchronized (this .recordedBindings ) {
835
+ for (Iterator <RecordedBinding > it = this .recordedBindings .iterator (); it .hasNext (); ) {
836
+ RecordedBinding b = it .next ();
837
+ if (b .getDestination ().equals (s )) {
838
+ it .remove ();
839
+ result .add (b );
840
+ }
835
841
}
836
842
}
837
843
return result ;
0 commit comments