@@ -353,14 +353,15 @@ namespace ds {
353
353
#endif // _WIN32
354
354
typedef mysql::TCPIP TCPIP_old;
355
355
356
+
356
357
template <typename DS_t, typename DS_opt>
357
358
struct DS_pair : public std ::pair<DS_t, DS_opt>
358
359
{
359
360
DS_pair (const DS_pair&) = default ;
360
361
#ifdef HAVE_MOVE_CTORS
361
362
DS_pair (DS_pair&&) = default;
362
363
#endif
363
- DS_pair (DS_t &ds, DS_opt &opt) : std::pair<DS_t, DS_opt>(ds, opt)
364
+ DS_pair (const DS_t &ds, const DS_opt &opt) : std::pair<DS_t, DS_opt>(ds, opt)
364
365
{}
365
366
};
366
367
@@ -369,12 +370,12 @@ namespace ds {
369
370
A data source which encapsulates several other data sources (all of which
370
371
are assumed to hold the same data).
371
372
372
- When adding data sources to a multi source, a priority and a weight can
373
- be specified. When a visitor is visiting the multi source, the data sources
374
- are presented to the visitor in decreasing priority order. If several data
375
- sources have the same priority, they are presented in random order, taking
376
- into account specified weights. If no priorities were specified, then data
377
- sources are presented in the order in which they were added.
373
+ When adding data sources to a multi source, a priority can be specified.
374
+ When a visitor is visiting the multi source, the data sources it contains
375
+ are presented to the visitor in increasing priority order. If several data
376
+ sources have the same priority, they are presented in random order. If
377
+ no priorities were specified, then data sources are presented in the order
378
+ in which they were added.
378
379
379
380
If priorities are specified, they must be specified for all data sources
380
381
that are added to the multi source.
@@ -394,8 +395,8 @@ namespace ds {
394
395
>
395
396
DS_variant;
396
397
397
- bool m_is_prioritized;
398
- unsigned short m_counter;
398
+ bool m_is_prioritized = false ;
399
+ unsigned short m_counter = 0 ;
399
400
400
401
struct Prio
401
402
{
@@ -412,79 +413,62 @@ namespace ds {
412
413
}
413
414
};
414
415
415
- typedef std::multimap<Prio, DS_variant, std::greater <Prio>> DS_list;
416
+ typedef std::multimap<Prio, DS_variant, std::less <Prio>> DS_list;
416
417
DS_list m_ds_list;
417
418
uint32_t m_total_weight = 0 ;
418
419
419
420
public:
420
421
421
- Multi_source () : m_is_prioritized(false ), m_counter(65535 )
422
- {
423
- std::srand ((unsigned int )time (NULL ));
424
- }
422
+ // Add data source without explicit priority.
425
423
426
424
template <class DS_t , class DS_opt >
427
- void add (const DS_t &ds, const DS_opt &opt,
428
- unsigned short prio, uint16_t weight = 1 )
425
+ void add (const DS_t& ds, const DS_opt& opt, uint16_t weight = 1 )
429
426
{
430
- if (m_ds_list. size () == 0 )
427
+ if (m_is_prioritized )
431
428
{
432
- m_is_prioritized = (prio > 0 );
429
+ throw_error (
430
+ " Adding un-prioritized items to prioritized list is not allowed"
431
+ );
433
432
}
434
- else
435
- {
436
- if (m_is_prioritized && prio == 0 )
437
- throw Error (cdkerrc::generic_error,
438
- " Adding un-prioritized items to prioritized list is not allowed" );
439
433
440
- if (!m_is_prioritized && prio > 0 )
441
- throw Error (cdkerrc::generic_error,
442
- " Adding prioritized items to un-prioritized list is not allowed" );
443
- }
434
+ m_ds_list.emplace (Prio{ m_counter++, weight }, DS_pair<DS_t, DS_opt>{ ds, opt });
435
+ }
444
436
445
- /*
446
- The internal placement of priorities will be as this:
447
- if list is a no-priority one the map has to retain the order of
448
- elements at the time of the placement. Therefore, it will count-down
449
- from max(unsigned short)
450
- */
451
- DS_pair<DS_t, DS_opt> pair (const_cast <DS_t&>(ds),
452
- const_cast <DS_opt&>(opt));
453
- if (m_is_prioritized)
454
- m_ds_list.emplace (Prio ({prio,weight}), pair);
455
- else
437
+ // Add data source with priority.
438
+
439
+ template <class DS_t , class DS_opt >
440
+ void add_prio (const DS_t &ds, const DS_opt &opt, unsigned short prio, uint16_t weight = 1 )
441
+ {
442
+ if (m_ds_list.size () == 0 )
443
+ m_is_prioritized = true ;
444
+
445
+ if (!m_is_prioritized)
456
446
{
457
- /*
458
- When list is not prioritized the map should keep the order of elements.
459
- This is achieved by decrementing the counter every time a new element
460
- goes into the list.
461
- */
462
- m_ds_list.emplace (Prio ({m_counter--,weight}), pair);
447
+ throw_error (
448
+ " Adding prioritized items to un-prioritized list is not allowed"
449
+ );
463
450
}
464
451
465
- m_total_weight += weight;
452
+ m_ds_list. emplace (Prio{ prio, weight }, DS_pair<DS_t, DS_opt>{ ds, opt }) ;
466
453
}
467
454
468
- private:
455
+ private:
469
456
470
457
template <typename Visitor>
471
458
struct Variant_visitor
472
459
{
473
- Visitor *vis;
474
- bool stop_processing;
475
-
476
- Variant_visitor () : stop_processing(false )
477
- { }
460
+ Visitor *vis = nullptr ;
461
+ bool stop_processing = false ;
478
462
479
463
template <class DS_t , class DS_opt >
480
464
void operator () (const DS_pair<DS_t, DS_opt> &ds_pair)
481
465
{
466
+ assert (vis);
482
467
stop_processing = (bool )(*vis)(ds_pair.first , ds_pair.second );
483
468
}
484
469
};
485
470
486
-
487
- public:
471
+ public:
488
472
489
473
/*
490
474
Call visitor(ds,opts) for each data source ds with options
@@ -496,80 +480,59 @@ namespace ds {
496
480
template <class Visitor >
497
481
void visit (Visitor &visitor)
498
482
{
483
+ Variant_visitor<Visitor> variant_visitor;
484
+ variant_visitor.vis = &visitor;
485
+
486
+ std::random_device rnd;
499
487
bool stop_processing = false ;
500
- std::vector<DS_variant*> same_prio;
501
488
std::vector<uint16_t > weights;
502
- std::random_device generator ;
489
+ std::set<DS_variant*> same_prio ;
503
490
504
491
for (auto it = m_ds_list.begin (); !stop_processing;)
505
492
{
506
- DS_variant *item = NULL ;
493
+ if (it == m_ds_list.end ())
494
+ break ;
507
495
508
- if (m_is_prioritized)
509
- {
510
- if (same_prio.empty ())
511
- {
512
- if (it == m_ds_list.end ())
513
- break ;
496
+ assert (same_prio.empty ());
514
497
515
- // Get items with the same priority and store them in same_prio set
498
+ {
499
+ // Get items with the same priority and store them in same_prio set
516
500
517
- auto same_range = m_ds_list.equal_range (it->first );
518
- it = same_range.second ;
501
+ auto same_range = m_ds_list.equal_range (it->first );
502
+ it = same_range.second ; // move it to the first element after the range
519
503
520
- for (auto it1 = same_range.first ; it1 != same_range.second ; ++it1)
521
- {
522
- // If weight is not specified, we need to set all weight values
523
- // with same, os that discrete_distribution works as expected
524
- weights.push_back (it1->first .weight );
525
- same_prio.push_back (&(it1->second ));
526
- }
504
+ for (auto it1 = same_range.first ; it1 != same_range.second ; ++it1)
505
+ {
506
+ same_prio.insert (&(it1->second ));
507
+ weights.push_back (it1->first .weight );
527
508
}
509
+ }
528
510
529
- std::discrete_distribution<int > distribution (
530
- weights.begin (), weights.end ()
531
- );
532
-
511
+ for (size_t size = same_prio.size (); size > 0 ; size = same_prio.size ())
512
+ {
533
513
auto el = same_prio.begin ();
514
+ size_t pos = 0 ;
534
515
535
- int pos = 0 ;
536
-
537
- if (same_prio.size () > 1 )
516
+ if (size > 1 )
538
517
{
539
- pos = distribution (generator);
518
+ std::discrete_distribution<int > distr (
519
+ weights.begin (), weights.end ()
520
+ );
521
+ pos = distr (rnd);
540
522
std::advance (el, pos);
541
523
}
542
524
543
- item = *el;
544
- same_prio.erase (same_prio.begin ()+pos);
545
- weights.erase (weights.begin ()+pos);
525
+ (*el)->visit (variant_visitor);
526
+ stop_processing = variant_visitor.stop_processing ;
546
527
547
- } // if (m_is_prioritized)
548
- else
549
- {
550
- if (it == m_ds_list.end ())
528
+ if (stop_processing)
551
529
break ;
552
530
553
- // Just get the next item from the list if no priority is given
554
- item = &(it->second );
555
- ++it;
531
+ same_prio.erase (el);
532
+ weights.erase (weights.begin () + pos);
556
533
}
557
534
558
- // Give values to the visitor
559
- Variant_visitor<Visitor> variant_visitor;
560
- variant_visitor.vis = &visitor;
561
- /*
562
- Cannot use lambda because auto type for lambdas is only
563
- supported in C++14
564
- */
565
- item->visit (variant_visitor);
566
- stop_processing = variant_visitor.stop_processing ;
567
-
568
- /* Exit if visit reported true or if we advanced to the end of the list */
569
- if (stop_processing || it == m_ds_list.end ())
570
- break ;
571
-
572
- } // for
535
+ } // for m_ds_llist
573
536
}
574
537
575
538
void clear ()
@@ -647,9 +610,7 @@ namespace ds {
647
610
Options::TLS_options tls (m_opts.get_tls ());
648
611
tls.set_host_name (el.name );
649
612
opt1.set_tls (tls);
650
- // Prio is negative because for URI prio, less is better, but for
651
- // SRV record, more is better
652
- src.add (ds::TCPIP (el.name , el.port ), opt1, -el.prio , el.weight );
613
+ src.add_prio (ds::TCPIP (el.name , el.port ), opt1, el.prio , el.weight );
653
614
}
654
615
655
616
return src;
0 commit comments