1 /* $Id: dbapi_svc_mapper.cpp 586267 2019-05-13 18:15:06Z ucko $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Sergey Sikorskiy
27 *
28 */
29
30 #include <ncbi_pch.hpp>
31
32 #include <dbapi/driver/dbapi_svc_mapper.hpp>
33 #include <dbapi/driver/exception.hpp>
34 #include <corelib/ncbiapp.hpp>
35 // #include <connect/ncbi_socket.h>
36 #include <algorithm>
37
38
39 BEGIN_NCBI_SCOPE
40
41
42 //////////////////////////////////////////////////////////////////////////////
43 static
44 CRef<CDBServerOption>
make_server(const CTempString & specification,double & preference)45 make_server(const CTempString& specification, double& preference)
46 {
47 CTempString server;
48 // string host;
49 Uint4 host = 0;
50 Uint2 port = 0;
51 string::size_type pos = 0;
52
53 pos = specification.find_first_of("@(", pos);
54 if (pos != string::npos) {
55 server = specification.substr(0, pos);
56
57 if (specification[pos] == '@') {
58 // string::size_type old_pos = pos + 1;
59 pos = specification.find_first_of(":(", pos + 1);
60 if (pos != string::npos) {
61 // string host_str = specification.substr(old_pos, pos - old_pos);
62 // Ignore host in order to avoid dependebcy on libconnect.
63 // SOCK_StringToHostPort(specification.c_str() + old_pos, &host, &port);
64 if (specification[pos] == ':') {
65 port = NStr::StringToUInt(specification.substr(pos + 1),
66 NStr::fAllowLeadingSpaces |
67 NStr::fAllowTrailingSymbols |
68 NStr::fConvErr_NoThrow);
69 pos = specification.find("(", pos + 1);
70 if (pos != string::npos) {
71 // preference = NStr::StringToDouble(
72 preference = NStr::StringToUInt(
73 specification.substr(pos + 1),
74 NStr::fAllowLeadingSpaces |
75 NStr::fAllowTrailingSymbols |
76 NStr::fConvErr_NoThrow);
77 }
78 } else {
79 // preference = NStr::StringToDouble(
80 preference = NStr::StringToUInt(
81 specification.substr(pos + 1),
82 NStr::fAllowLeadingSpaces |
83 NStr::fAllowTrailingSymbols |
84 NStr::fConvErr_NoThrow);
85 }
86 } else {
87 // host = specification.substr(old_pos);
88 // Ignore host in order to avoid dependebcy on libconnect.
89 // SOCK_StringToHostPort(specification.c_str() + old_pos, &host, &port);
90 }
91 } else {
92 // preference = NStr::StringToDouble(
93 preference = NStr::StringToUInt(
94 specification.substr(pos + 1),
95 NStr::fAllowLeadingSpaces |
96 NStr::fAllowTrailingSymbols |
97 NStr::fConvErr_NoThrow);
98 }
99 } else {
100 server = specification;
101 }
102
103 if (server.empty() && host == 0) {
104 DATABASE_DRIVER_ERROR("Either server name or host name expected.",
105 110100 );
106 }
107
108 return CRef<CDBServerOption>
109 (new CDBServerOption(server, host, port, preference));
110 }
111
112
113
114 //////////////////////////////////////////////////////////////////////////////
CDBDefaultServiceMapper(void)115 CDBDefaultServiceMapper::CDBDefaultServiceMapper(void)
116 {
117 }
118
~CDBDefaultServiceMapper(void)119 CDBDefaultServiceMapper::~CDBDefaultServiceMapper(void)
120 {
121 }
122
GetName(void) const123 string CDBDefaultServiceMapper::GetName(void) const
124 {
125 return CDBServiceMapperTraits<CDBDefaultServiceMapper>::GetName();
126 }
127
128 void
Configure(const IRegistry *)129 CDBDefaultServiceMapper::Configure(const IRegistry*)
130 {
131 // Do nothing.
132 }
133
134 TSvrRef
GetServer(const string & service)135 CDBDefaultServiceMapper::GetServer(const string& service)
136 {
137 if (m_ExcludeMap.find(service) != m_ExcludeMap.end()) {
138 return TSvrRef();
139 }
140
141 return TSvrRef(new CDBServer(service));
142 }
143
144 void
SetPreference(const string &,const TSvrRef &,double)145 CDBDefaultServiceMapper::SetPreference(const string&,
146 const TSvrRef&,
147 double)
148 {
149 // Do nothing.
150 }
151
152
153 //////////////////////////////////////////////////////////////////////////////
CDBServiceMapperCoR(void)154 CDBServiceMapperCoR::CDBServiceMapperCoR(void)
155 {
156 }
157
~CDBServiceMapperCoR(void)158 CDBServiceMapperCoR::~CDBServiceMapperCoR(void)
159 {
160 }
161
GetName(void) const162 string CDBServiceMapperCoR::GetName(void) const
163 {
164 if (Top().NotEmpty()) {
165 return Top()->GetName();
166 } else {
167 return CDBServiceMapperTraits<CDBServiceMapperCoR>::GetName();
168 }
169 }
170
171 void
Configure(const IRegistry * registry)172 CDBServiceMapperCoR::Configure(const IRegistry* registry)
173 {
174 CFastMutexGuard mg(m_Mtx);
175
176 ConfigureFromRegistry(registry);
177 }
178
179 TSvrRef
GetServer(const string & service)180 CDBServiceMapperCoR::GetServer(const string& service)
181 {
182 CFastMutexGuard mg(m_Mtx);
183
184 TSvrRef server;
185 TDelegates::reverse_iterator dg_it = m_Delegates.rbegin();
186 TDelegates::reverse_iterator dg_end = m_Delegates.rend();
187
188 for (; server.Empty() && dg_it != dg_end; ++dg_it) {
189 server = (*dg_it)->GetServer(service);
190 }
191
192 return server;
193 }
194
195 void
Exclude(const string & service,const TSvrRef & server)196 CDBServiceMapperCoR::Exclude(const string& service,
197 const TSvrRef& server)
198 {
199 CFastMutexGuard mg(m_Mtx);
200
201 NON_CONST_ITERATE(TDelegates, dg_it, m_Delegates) {
202 (*dg_it)->Exclude(service, server);
203 }
204 }
205
206 void
CleanExcluded(const string & service)207 CDBServiceMapperCoR::CleanExcluded(const string& service)
208 {
209 CFastMutexGuard mg(m_Mtx);
210
211 NON_CONST_ITERATE(TDelegates, dg_it, m_Delegates) {
212 (*dg_it)->CleanExcluded(service);
213 }
214 }
215
216 void
SetPreference(const string & service,const TSvrRef & preferred_server,double preference)217 CDBServiceMapperCoR::SetPreference(const string& service,
218 const TSvrRef& preferred_server,
219 double preference)
220 {
221 CFastMutexGuard mg(m_Mtx);
222
223 NON_CONST_ITERATE(TDelegates, dg_it, m_Delegates) {
224 (*dg_it)->SetPreference(service, preferred_server, preference);
225 }
226 }
227
228 void
GetServersList(const string & service,list<string> * serv_list) const229 CDBServiceMapperCoR::GetServersList(const string& service, list<string>* serv_list) const
230 {
231 CFastMutexGuard mg(m_Mtx);
232
233 TDelegates::const_reverse_iterator dg_it = m_Delegates.rbegin();
234 TDelegates::const_reverse_iterator dg_end = m_Delegates.rend();
235 for (; serv_list->empty() && dg_it != dg_end; ++dg_it) {
236 (*dg_it)->GetServersList(service, serv_list);
237 }
238 }
239
240 void
GetServerOptions(const string & service,TOptions * options)241 CDBServiceMapperCoR::GetServerOptions(const string& service, TOptions* options)
242 {
243 CFastMutexGuard mg(m_Mtx);
244
245 TDelegates::reverse_iterator dg_it = m_Delegates.rbegin();
246 TDelegates::reverse_iterator dg_end = m_Delegates.rend();
247 for (; options->empty() && dg_it != dg_end; ++dg_it) {
248 (*dg_it)->GetServerOptions(service, options);
249 }
250 }
251
252
253 bool
RecordServer(I_ConnectionExtra & extra) const254 CDBServiceMapperCoR::RecordServer(I_ConnectionExtra& extra) const
255 {
256 CFastMutexGuard mg(m_Mtx);
257 REVERSE_ITERATE (TDelegates, dg_it, m_Delegates) {
258 if ((*dg_it)->RecordServer(extra)) {
259 return true;
260 }
261 }
262 return false;
263 }
264
265
266 void
ConfigureFromRegistry(const IRegistry * registry)267 CDBServiceMapperCoR::ConfigureFromRegistry(const IRegistry* registry)
268 {
269 NON_CONST_ITERATE (TDelegates, dg_it, m_Delegates) {
270 (*dg_it)->Configure(registry);
271 }
272 }
273
274 void
Push(const CRef<IDBServiceMapper> & mapper)275 CDBServiceMapperCoR::Push(const CRef<IDBServiceMapper>& mapper)
276 {
277 if (mapper.NotNull()) {
278 CFastMutexGuard mg(m_Mtx);
279
280 m_Delegates.push_back(mapper);
281 }
282 }
283
284 void
Pop(void)285 CDBServiceMapperCoR::Pop(void)
286 {
287 CFastMutexGuard mg(m_Mtx);
288
289 m_Delegates.pop_back();
290 }
291
292 CRef<IDBServiceMapper>
Top(void) const293 CDBServiceMapperCoR::Top(void) const
294 {
295 CFastMutexGuard mg(m_Mtx);
296
297 return m_Delegates.back();
298 }
299
300 bool
Empty(void) const301 CDBServiceMapperCoR::Empty(void) const
302 {
303 CFastMutexGuard mg(m_Mtx);
304
305 return m_Delegates.empty();
306 }
307
308 //////////////////////////////////////////////////////////////////////////////
CDBUDRandomMapper(const IRegistry * registry)309 CDBUDRandomMapper::CDBUDRandomMapper(const IRegistry* registry)
310 {
311 random_device rdev;
312 m_RandomEngine.seed(rdev());
313 ConfigureFromRegistry(registry);
314 }
315
~CDBUDRandomMapper(void)316 CDBUDRandomMapper::~CDBUDRandomMapper(void)
317 {
318 }
319
GetName(void) const320 string CDBUDRandomMapper::GetName(void) const
321 {
322 return CDBServiceMapperTraits<CDBUDRandomMapper>::GetName();
323 }
324
325 void
Configure(const IRegistry * registry)326 CDBUDRandomMapper::Configure(const IRegistry* registry)
327 {
328 CFastMutexGuard mg(m_Mtx);
329
330 ConfigureFromRegistry(registry);
331 }
332
333 void
ConfigureFromRegistry(const IRegistry * registry)334 CDBUDRandomMapper::ConfigureFromRegistry(const IRegistry* registry)
335 {
336 const string section_name
337 (CDBServiceMapperTraits<CDBUDRandomMapper>::GetName());
338 list<string> entries;
339
340 // Get current registry ...
341 if (!registry && CNcbiApplication::Instance()) {
342 registry = &CNcbiApplication::Instance()->GetConfig();
343 }
344
345 if (registry) {
346 // Erase previous data ...
347 m_LBNameMap.clear();
348 m_ServerMap.clear();
349 m_FavoritesMap.clear();
350 m_PreferenceMap.clear();
351
352 registry->EnumerateEntries(section_name, &entries);
353 ITERATE(list<string>, cit, entries) {
354 vector<string> server_name;
355 string service_name = *cit;
356
357 NStr::Split(registry->GetString(section_name,
358 service_name,
359 service_name),
360 " ,;",
361 server_name,
362 NStr::fSplit_MergeDelimiters);
363
364 // Replace with new data ...
365 if (!server_name.empty()) {
366 TOptions& server_list = m_ServerMap[service_name];
367
368 ITERATE(vector<string>, sn_it, server_name) {
369 double tmp_preference = 0;
370
371 // Parse server preferences.
372 auto cur_server = make_server(*sn_it, tmp_preference);
373 if (tmp_preference < 0) {
374 cur_server->m_Ranking = 0;
375 } else if (tmp_preference >= 100) {
376 cur_server->m_Ranking = 100;
377 m_FavoritesMap[service_name].push_back(cur_server);
378 }
379
380 server_list.push_back(cur_server);
381
382 }
383 x_RecalculatePreferences(service_name);
384 }
385 }
386 }
387 }
388
389 TSvrRef
GetServer(const string & service)390 CDBUDRandomMapper::GetServer(const string& service)
391 {
392 CFastMutexGuard mg(m_Mtx);
393
394 if (m_LBNameMap.find(service) != m_LBNameMap.end() &&
395 m_LBNameMap[service] == false) {
396 // We've tried this service already. It is not served by load
397 // balancer. There is no reason to try it again.
398 return TSvrRef();
399 }
400
401 const auto& it = m_PreferenceMap.find(service);
402 if (it != m_PreferenceMap.end()) {
403 m_LBNameMap[service] = true;
404 return it->second.servers[(*it->second.distribution)(m_RandomEngine)];
405 }
406
407 m_LBNameMap[service] = false;
408 return TSvrRef();
409 }
410
411 void
Add(const string & service,const TSvrRef & server,double preference)412 CDBUDRandomMapper::Add(const string& service,
413 const TSvrRef& server,
414 double preference)
415 {
416 _ASSERT(false);
417
418 if (service.empty() || server.Empty()) {
419 return;
420 }
421
422 TOptions& server_list = m_ServerMap[service];
423 CRef<CDBServerOption> option
424 (new CDBServerOption(server->GetName(), server->GetHost(),
425 server->GetPort(), preference));
426
427 if (preference < 0) {
428 option->m_Ranking = 0;
429 } else if (preference >= 100) {
430 option->m_Ranking = 100;
431 m_FavoritesMap[service].push_back(option);
432 }
433
434 server_list.push_back(option);
435
436 x_RecalculatePreferences(service);
437 }
438
439 void
Exclude(const string & service,const TSvrRef & server)440 CDBUDRandomMapper::Exclude(const string& service, const TSvrRef& server)
441 {
442 CFastMutexGuard mg(m_Mtx);
443 auto svc = m_ServerMap.find(service);
444 if (svc != m_ServerMap.end()) {
445 for (auto svr : svc->second) {
446 if (svr == server || *svr == *server) {
447 svr->m_State |= CDBServerOption::fState_Excluded;
448 }
449 }
450 x_RecalculatePreferences(service);
451 }
452 }
453
454 void
CleanExcluded(const string & service)455 CDBUDRandomMapper::CleanExcluded(const string& service)
456 {
457 CFastMutexGuard mg(m_Mtx);
458 auto svc = m_ServerMap.find(service);
459 if (svc != m_ServerMap.end()) {
460 for (auto svr : svc->second) {
461 svr->m_State &= ~CDBServerOption::fState_Excluded;
462 }
463 x_RecalculatePreferences(service);
464 }
465 }
466
467 bool
HasExclusions(const string & service) const468 CDBUDRandomMapper::HasExclusions(const string& service) const
469 {
470 CFastMutexGuard mg(m_Mtx);
471 auto svc = m_ServerMap.find(service);
472 auto prefs = m_PreferenceMap.find(service);
473 if (svc == m_ServerMap.end()) {
474 return false;
475 } else if (prefs == m_PreferenceMap.end()) {
476 return true;
477 } else if (svc->second.size() == prefs->second.servers.size()) {
478 return false;
479 } else if (prefs->second.servers.size() != 1) {
480 return true;
481 } else {
482 return prefs->second.servers[0]->GetRanking() < 100.0;
483 }
484 }
485
486 void
SetPreference(const string & service,const TSvrRef & preferred_server,double preference)487 CDBUDRandomMapper::SetPreference(const string& service,
488 const TSvrRef& preferred_server,
489 double preference)
490 {
491 CFastMutexGuard mg(m_Mtx);
492
493 auto svc = m_ServerMap.find(service);
494 if (svc != m_ServerMap.end()) {
495 for (auto svr : svc->second) {
496 if (svr == preferred_server || *svr == *preferred_server) {
497 double old_preference = svr->GetRanking();
498 svr->m_Ranking = max(0.0, min(100.0, preference));
499 if (preference >= 100.0 && old_preference < 100.0) {
500 m_FavoritesMap[service].push_back(svr);
501 } else if (preference < 100.0 && old_preference >= 100.0) {
502 auto& favorites = m_FavoritesMap[service];
503 favorites.erase(find(favorites.begin(), favorites.end(),
504 svr));
505 if (favorites.empty()) {
506 m_FavoritesMap.erase(service);
507 }
508 }
509 }
510 }
511 x_RecalculatePreferences(service);
512 }
513 }
514
515 void
GetServerOptions(const string & service,TOptions * options)516 CDBUDRandomMapper::GetServerOptions(const string& service, TOptions* options)
517 {
518 CFastMutexGuard mg(m_Mtx);
519 auto it = m_ServerMap.find(service);
520 if (it == m_ServerMap.end()) {
521 options->clear();
522 } else {
523 *options = it->second;
524 }
525 }
526
527 IDBServiceMapper*
Factory(const IRegistry * registry)528 CDBUDRandomMapper::Factory(const IRegistry* registry)
529 {
530 return new CDBUDRandomMapper(registry);
531 }
532
533 void
x_RecalculatePreferences(const string & service)534 CDBUDRandomMapper::x_RecalculatePreferences(const string& service)
535 {
536 SPreferences& service_preferences = m_PreferenceMap[service];
537 service_preferences.servers.clear();
538 {{
539 TServiceMap::const_iterator favs = m_FavoritesMap.find(service);
540 if (favs != m_FavoritesMap.end()) {
541 REVERSE_ITERATE(TOptions, it, favs->second) {
542 if ( !(*it)->IsExcluded() ) {
543 service_preferences.servers.push_back(*it);
544 service_preferences.distribution.reset
545 (new discrete_distribution<>({100.0}));
546 return;
547 }
548 }
549 }
550 }}
551 vector<double> weights;
552 bool all_zero = true;
553 for (const auto & it : m_ServerMap[service]) {
554 if ( !it->IsExcluded() ) {
555 double weight = it->GetRanking();
556 _ASSERT(weight < 100.0);
557 if (weight > 0.0) {
558 all_zero = false;
559 }
560 }
561 }
562 if (all_zero) {
563 for (auto & w : weights) {
564 w = 1.0;
565 }
566 }
567 service_preferences.distribution.reset
568 (new discrete_distribution<>(weights.begin(), weights.end()));
569 }
570
571
572 //////////////////////////////////////////////////////////////////////////////
CDBUDPriorityMapper(const IRegistry * registry)573 CDBUDPriorityMapper::CDBUDPriorityMapper(const IRegistry* registry)
574 {
575 ConfigureFromRegistry(registry);
576 }
577
~CDBUDPriorityMapper(void)578 CDBUDPriorityMapper::~CDBUDPriorityMapper(void)
579 {
580 }
581
GetName(void) const582 string CDBUDPriorityMapper::GetName(void) const
583 {
584 return CDBServiceMapperTraits<CDBUDPriorityMapper>::GetName();
585 }
586
587 void
Configure(const IRegistry * registry)588 CDBUDPriorityMapper::Configure(const IRegistry* registry)
589 {
590 CFastMutexGuard mg(m_Mtx);
591
592 ConfigureFromRegistry(registry);
593 }
594
595 void
ConfigureFromRegistry(const IRegistry * registry)596 CDBUDPriorityMapper::ConfigureFromRegistry(const IRegistry* registry)
597 {
598 const string section_name
599 (CDBServiceMapperTraits<CDBUDPriorityMapper>::GetName());
600 list<string> entries;
601
602 // Get current registry ...
603 if (!registry && CNcbiApplication::Instance()) {
604 registry = &CNcbiApplication::Instance()->GetConfig();
605 }
606
607 if (registry) {
608 // Erase previous data ...
609 m_ServerMap.clear();
610 m_ServiceUsageMap.clear();
611
612 registry->EnumerateEntries(section_name, &entries);
613
614 ITERATE(list<string>, cit, entries) {
615 vector<string> server_name;
616 string service_name = *cit;
617
618 NStr::Split(registry->GetString(section_name,
619 service_name,
620 service_name),
621 " ,;",
622 server_name,
623 NStr::fSplit_MergeDelimiters);
624
625 // Replace with new data ...
626 if (!server_name.empty()) {
627 // TSvrMap& server_list = m_ServerMap[service_name];
628 // TServerUsageMap& usage_map = m_ServiceUsageMap[service_name];
629
630 ITERATE(vector<string>, sn_it, server_name) {
631 double tmp_preference = 0;
632
633 // Parse server preferences.
634 TSvrRef cur_server = make_server(*sn_it, tmp_preference);
635
636 // Replaced with Add()
637 // if (tmp_preference < 0) {
638 // tmp_preference = 0;
639 // } else if (tmp_preference > 100) {
640 // tmp_preference = 100;
641 // }
642 //
643 // server_list.insert(
644 // TSvrMap::value_type(cur_server, tmp_preference));
645 // usage_map.insert(TServerUsageMap::value_type(
646 // 100 - tmp_preference,
647 // cur_server));
648
649 Add(service_name, cur_server, tmp_preference);
650 }
651 }
652 }
653 }
654 }
655
656 TSvrRef
GetServer(const string & service)657 CDBUDPriorityMapper::GetServer(const string& service)
658 {
659 CFastMutexGuard mg(m_Mtx);
660
661 if (m_LBNameMap.find(service) != m_LBNameMap.end() &&
662 m_LBNameMap[service] == false) {
663 // We've tried this service already. It is not served by load
664 // balancer. There is no reason to try it again.
665 return TSvrRef();
666 }
667
668 TServerUsageMap& usage_map = m_ServiceUsageMap[service];
669 TSvrMap& server_map = m_ServerMap[service];
670
671 if (!server_map.empty() && !usage_map.empty()) {
672 TServerUsageMap::iterator su_it = usage_map.begin();
673 double new_preference = su_it->first;
674 TSvrRef cur_server = su_it->second;
675
676 // Recalculate preferences ...
677 TSvrMap::const_iterator pr_it = server_map.find(cur_server);
678
679 if (pr_it != server_map.end()) {
680 new_preference += 100 - pr_it->second;
681 } else {
682 new_preference += 100;
683 }
684
685 // Reset usage map ...
686 usage_map.erase(su_it);
687 usage_map.insert(TServerUsageMap::value_type(new_preference,
688 cur_server));
689
690 m_LBNameMap[service] = true;
691 return cur_server;
692 }
693
694 m_LBNameMap[service] = false;
695 return TSvrRef();
696 }
697
698 void
Exclude(const string & service,const TSvrRef & server)699 CDBUDPriorityMapper::Exclude(const string& service,
700 const TSvrRef& server)
701 {
702 IDBServiceMapper::Exclude(service, server);
703
704 CFastMutexGuard mg(m_Mtx);
705
706 TServerUsageMap& usage_map = m_ServiceUsageMap[service];
707
708 // Remove elements ...
709 for (TServerUsageMap::iterator it = usage_map.begin();
710 it != usage_map.end();) {
711
712 if (it->second == server) {
713 usage_map.erase(it++);
714 }
715 else {
716 ++it;
717 }
718 }
719 }
720
721 void
CleanExcluded(const string & service)722 CDBUDPriorityMapper::CleanExcluded(const string& service)
723 {
724 IDBServiceMapper::CleanExcluded(service);
725
726 CFastMutexGuard mg(m_Mtx);
727 m_ServiceUsageMap[service] = m_OrigServiceUsageMap[service];
728 }
729
730 void
SetPreference(const string & service,const TSvrRef & preferred_server,double preference)731 CDBUDPriorityMapper::SetPreference(const string& service,
732 const TSvrRef& preferred_server,
733 double preference)
734 {
735 CFastMutexGuard mg(m_Mtx);
736
737 TSvrMap& server_map = m_ServerMap[service];
738 TSvrMap::iterator pr_it = server_map.find(preferred_server);
739
740 if (preference < 0) {
741 preference = 0;
742 } else if (preference > 100) {
743 preference = 100;
744 }
745
746 if (pr_it != server_map.end()) {
747 pr_it->second = preference;
748 }
749 }
750
751
752 void
Add(const string & service,const TSvrRef & server,double preference)753 CDBUDPriorityMapper::Add(const string& service,
754 const TSvrRef& server,
755 double preference)
756 {
757 TSvrMap& server_list = m_ServerMap[service];
758 TServerUsageMap& usage_map = m_ServiceUsageMap[service];
759 TServerUsageMap& usage_map2 = m_OrigServiceUsageMap[service];
760
761 if (preference < 0) {
762 preference = 0;
763 } else if (preference > 100) {
764 preference = 100;
765 }
766
767 server_list.insert(
768 TSvrMap::value_type(server, preference)
769 );
770 TServerUsageMap::value_type usage(100 - preference, server);
771 usage_map.insert(usage);
772 usage_map2.insert(usage);
773 }
774
775
776 IDBServiceMapper*
Factory(const IRegistry * registry)777 CDBUDPriorityMapper::Factory(const IRegistry* registry)
778 {
779 return new CDBUDPriorityMapper(registry);
780 }
781
782
783 //////////////////////////////////////////////////////////////////////////////
CDBUniversalMapper(const IRegistry * registry,const TMapperConf & ext_mapper)784 CDBUniversalMapper::CDBUniversalMapper(const IRegistry* registry,
785 const TMapperConf& ext_mapper)
786 {
787 if (!ext_mapper.first.empty() && ext_mapper.second != NULL) {
788 m_ExtMapperConf = ext_mapper;
789 }
790
791 this->ConfigureFromRegistry(registry);
792 CDBServiceMapperCoR::ConfigureFromRegistry(registry);
793 }
794
~CDBUniversalMapper(void)795 CDBUniversalMapper::~CDBUniversalMapper(void)
796 {
797 }
798
GetName(void) const799 string CDBUniversalMapper::GetName(void) const
800 {
801 if (Top().NotEmpty()) {
802 return Top()->GetName();
803 } else {
804 return CDBServiceMapperTraits<CDBUniversalMapper>::GetName();
805 }
806 }
807
808 void
Configure(const IRegistry * registry)809 CDBUniversalMapper::Configure(const IRegistry* registry)
810 {
811 CFastMutexGuard mg(m_Mtx);
812
813 this->ConfigureFromRegistry(registry);
814 CDBServiceMapperCoR::ConfigureFromRegistry(registry);
815 }
816
817 void
ConfigureFromRegistry(const IRegistry * registry)818 CDBUniversalMapper::ConfigureFromRegistry(const IRegistry* registry)
819 {
820 vector<string> service_name;
821 const string section_name
822 (CDBServiceMapperTraits<CDBUniversalMapper>::GetName());
823 const string def_mapper_name =
824 (m_ExtMapperConf.second ? m_ExtMapperConf.first :
825 CDBServiceMapperTraits<CDBUDRandomMapper>::GetName());
826
827 // Get current registry ...
828 if (!registry && CNcbiApplication::Instance()) {
829 registry = &CNcbiApplication::Instance()->GetConfig();
830 }
831
832 if (registry) {
833
834 NStr::Split(registry->GetString
835 (section_name, "MAPPERS",
836 def_mapper_name),
837 " ,;",
838 service_name,
839 NStr::fSplit_MergeDelimiters);
840
841 } else {
842 service_name.push_back(def_mapper_name);
843 }
844
845 ITERATE(vector<string>, it, service_name) {
846 IDBServiceMapper* mapper = NULL;
847 string mapper_name = *it;
848
849 if (NStr::CompareNocase
850 (mapper_name,
851 CDBServiceMapperTraits<CDBDefaultServiceMapper>::GetName()) ==
852 0) {
853 mapper = new CDBDefaultServiceMapper();
854 } else if (NStr::CompareNocase
855 (mapper_name,
856 CDBServiceMapperTraits<CDBUDRandomMapper>::GetName())
857 == 0) {
858 mapper = new CDBUDRandomMapper(registry);
859 } else if (NStr::CompareNocase
860 (mapper_name,
861 CDBServiceMapperTraits<CDBUDPriorityMapper>::GetName())
862 == 0) {
863 mapper = new CDBUDPriorityMapper(registry);
864 } else if (m_ExtMapperConf.second && NStr::CompareNocase
865 (mapper_name, m_ExtMapperConf.first) == 0) {
866 mapper = (*m_ExtMapperConf.second)(registry);
867 }
868
869 Push(CRef<IDBServiceMapper>(mapper));
870 }
871 }
872
873
874 //////////////////////////////////////////////////////////////////////////////
875 string
GetName(void)876 CDBServiceMapperTraits<CDBDefaultServiceMapper>::GetName(void)
877 {
878 return "DEFAULT_NAME_MAPPER";
879 }
880
881 string
GetName(void)882 CDBServiceMapperTraits<CDBServiceMapperCoR>::GetName(void)
883 {
884 return "COR_NAME_MAPPER";
885 }
886
887 string
GetName(void)888 CDBServiceMapperTraits<CDBUDRandomMapper>::GetName(void)
889 {
890 return "USER_DEFINED_RANDOM_DBNAME_MAPPER";
891 }
892
893 string
GetName(void)894 CDBServiceMapperTraits<CDBUDPriorityMapper>::GetName(void)
895 {
896 return "USER_DEFINED_PRIORITY_DBNAME_MAPPER";
897 }
898
899 string
GetName(void)900 CDBServiceMapperTraits<CDBUniversalMapper>::GetName(void)
901 {
902 return "UNIVERSAL_NAME_MAPPER";
903 }
904
905 END_NCBI_SCOPE
906
907