34
34
35
35
#include < algorithm>
36
36
#include < assert.h>
37
+ #include < iomanip>
38
+ #include < ios>
37
39
#include < uv.h>
38
40
39
41
#define CASS_NETWORK_TOPOLOGY_STRATEGY " NetworkTopologyStrategy"
@@ -143,12 +145,32 @@ class ByteOrderedPartitioner {
143
145
static StringRef name () { return " ByteOrderedPartitioner" ; }
144
146
};
145
147
148
+ inline std::ostream& operator <<(std::ostream& os, const RandomPartitioner::Token& token) {
149
+ os << std::setfill (' 0' ) << std::setw (16 ) << std::hex << token.hi << std::setfill (' 0' )
150
+ << std::setw (16 ) << std::hex << token.lo ;
151
+ return os;
152
+ }
153
+
154
+ inline std::ostream& operator <<(std::ostream& os, const ByteOrderedPartitioner::Token& token) {
155
+ for (ByteOrderedPartitioner::Token::const_iterator it = token.begin (), end = token.end ();
156
+ it != end; ++it) {
157
+ os << std::hex << *it;
158
+ }
159
+ return os;
160
+ }
161
+
146
162
class HostSet : public DenseHashSet <Host::Ptr> {
147
163
public:
148
164
HostSet () {
149
165
set_empty_key (Host::Ptr (new Host (Address::EMPTY_KEY)));
150
166
set_deleted_key (Host::Ptr (new Host (Address::DELETED_KEY)));
151
167
}
168
+
169
+ template <class InputIterator >
170
+ HostSet (InputIterator first, InputIterator last)
171
+ : DenseHashSet<Host::Ptr>(first, last, Host::Ptr(new Host(Address::EMPTY_KEY))) {
172
+ set_deleted_key (Host::Ptr (new Host (Address::DELETED_KEY)));
173
+ }
152
174
};
153
175
154
176
class RackSet : public DenseHashSet <uint32_t > {
@@ -355,6 +377,17 @@ void ReplicationStrategy<Partitioner>::build_replicas(const TokenHostVec& tokens
355
377
}
356
378
}
357
379
380
+ // Adds unique replica. It returns true if the replica was added.
381
+ inline bool add_replica (CopyOnWriteHostVec& hosts, const Host::Ptr& host) {
382
+ for (HostVec::const_reverse_iterator it = hosts->rbegin (); it != hosts->rend (); ++it) {
383
+ if ((*it)->address () == host->address ()) {
384
+ return false ; // Already in the replica set
385
+ }
386
+ }
387
+ hosts->push_back (host);
388
+ return true ;
389
+ }
390
+
358
391
template <class Partitioner >
359
392
void ReplicationStrategy<Partitioner>::build_replicas_network_topology(
360
393
const TokenHostVec& tokens, const DatacenterMap& datacenters, TokenReplicasVec& result) const {
@@ -443,24 +476,27 @@ void ReplicationStrategy<Partitioner>::build_replicas_network_topology(
443
476
// datacenter only then consider hosts in the same rack
444
477
445
478
if (rack == 0 || racks_observed_this_dc.size () == rack_count_this_dc) {
446
- ++replica_count_this_dc;
447
- replicas->push_back (Host::Ptr (host));
479
+ if (add_replica (replicas, Host::Ptr (host))) {
480
+ ++replica_count_this_dc;
481
+ }
448
482
} else {
449
483
TokenHostQueue& skipped_endpoints_this_dc = dc_rack_info.skipped_endpoints ;
450
484
if (racks_observed_this_dc.count (rack) > 0 ) {
451
485
skipped_endpoints_this_dc.push_back (curr_token_it);
452
486
} else {
453
- ++replica_count_this_dc;
454
- replicas->push_back (Host::Ptr (host));
455
- racks_observed_this_dc.insert (rack);
487
+ if (add_replica (replicas, Host::Ptr (host))) {
488
+ ++replica_count_this_dc;
489
+ racks_observed_this_dc.insert (rack);
490
+ }
456
491
457
492
// Once we visited every rack in the current datacenter then starting considering
458
493
// hosts we've already skipped.
459
494
if (racks_observed_this_dc.size () == rack_count_this_dc) {
460
495
while (!skipped_endpoints_this_dc.empty () &&
461
496
replica_count_this_dc < replication_factor) {
462
- ++replica_count_this_dc;
463
- replicas->push_back (Host::Ptr (skipped_endpoints_this_dc.front ()->second ));
497
+ if (add_replica (replicas, Host::Ptr (skipped_endpoints_this_dc.front ()->second ))) {
498
+ ++replica_count_this_dc;
499
+ }
464
500
skipped_endpoints_this_dc.pop_front ();
465
501
}
466
502
}
@@ -484,9 +520,10 @@ void ReplicationStrategy<Partitioner>::build_replicas_simple(const TokenHostVec&
484
520
for (typename TokenHostVec::const_iterator i = tokens.begin (), end = tokens.end (); i != end;
485
521
++i) {
486
522
CopyOnWriteHostVec replicas (new HostVec ());
523
+ replicas->reserve (num_replicas);
487
524
typename TokenHostVec::const_iterator token_it = i;
488
525
do {
489
- replicas-> push_back (Host::Ptr (token_it->second ));
526
+ add_replica ( replicas, Host::Ptr (Host::Ptr (token_it->second ) ));
490
527
++token_it;
491
528
if (token_it == tokens.end ()) {
492
529
token_it = tokens.begin ();
@@ -578,7 +615,11 @@ class TokenMapImpl : public TokenMap {
578
615
virtual const CopyOnWriteHostVec& get_replicas (const String& keyspace_name,
579
616
const String& routing_key) const ;
580
617
581
- // Test only
618
+ virtual String dump (const String& keyspace_name) const ;
619
+
620
+ public:
621
+ // Testing only
622
+
582
623
bool contains (const Token& token) const {
583
624
for (typename TokenHostVec::const_iterator i = tokens_.begin (), end = tokens_.end (); i != end;
584
625
++i) {
@@ -587,6 +628,8 @@ class TokenMapImpl : public TokenMap {
587
628
return false ;
588
629
}
589
630
631
+ const TokenReplicasVec& token_replicas (const String& keyspace_name) const ;
632
+
590
633
private:
591
634
void update_keyspace (const VersionNumber& cassandra_version, const ResultResponse* result,
592
635
bool should_build_replicas);
@@ -713,6 +756,35 @@ const CopyOnWriteHostVec& TokenMapImpl<Partitioner>::get_replicas(const String&
713
756
return no_replicas_dummy_;
714
757
}
715
758
759
+ template <class Partitioner >
760
+ String TokenMapImpl<Partitioner>::dump(const String& keyspace_name) const {
761
+ String result;
762
+ typename KeyspaceReplicaMap::const_iterator ks_it = replicas_.find (keyspace_name);
763
+ const TokenReplicasVec& replicas = ks_it->second ;
764
+
765
+ for (typename TokenReplicasVec::const_iterator it = replicas.begin (), end = replicas.end ();
766
+ it != end; ++it) {
767
+ OStringStream ss;
768
+ ss << std::setw (20 ) << it->first << " [ " ;
769
+ const CopyOnWriteHostVec& hosts = it->second ;
770
+ for (HostVec::const_iterator host_it = hosts->begin (), end = hosts->end (); host_it != end;
771
+ ++host_it) {
772
+ ss << (*host_it)->address_string () << " " ;
773
+ }
774
+ ss << " ]\n " ;
775
+ result.append (ss.str ());
776
+ }
777
+ return result;
778
+ }
779
+
780
+ template <class Partitioner >
781
+ const typename TokenMapImpl<Partitioner>::TokenReplicasVec&
782
+ TokenMapImpl<Partitioner>::token_replicas(const String& keyspace_name) const {
783
+ typename KeyspaceReplicaMap::const_iterator ks_it = replicas_.find (keyspace_name);
784
+ static TokenReplicasVec not_found;
785
+ return ks_it != replicas_.end () ? ks_it->second : not_found;
786
+ }
787
+
716
788
template <class Partitioner >
717
789
void TokenMapImpl<Partitioner>::update_keyspace(const VersionNumber& cassandra_version,
718
790
const ResultResponse* result,
@@ -773,6 +845,8 @@ void TokenMapImpl<Partitioner>::build_replicas() {
773
845
const String& keyspace_name = i->first ;
774
846
const ReplicationStrategy<Partitioner>& strategy = i->second ;
775
847
strategy.build_replicas (tokens_, datacenters_, replicas_[keyspace_name]);
848
+ LOG_TRACE (" Replicas for keyspace '%s':\n %s" , keyspace_name.c_str (),
849
+ dump (keyspace_name).c_str ());
776
850
}
777
851
}
778
852
0 commit comments