NCBI C++ ToolKit
ncbi_lb.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: ncbi_lb.c 82543 2018-06-11 18:09:29Z lavr $
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  * Please cite the author in any work or product based on this material.
22  *
23  * ===========================================================================
24  *
25  * Author: Anton Lavrentiev
26  *
27  * File Description:
28  * Generic LB API
29  *
30  */
31 
32 #include "ncbi_lb.h"
33 #include "ncbi_priv.h"
34 #include <stdlib.h>
35 
36 #define NCBI_USE_ERRCODE_X Connect_LBSM
37 
38 
39 /*
40  * Note parameters' ranges here:
41  * 0.0 <= pref <= 1.0
42  * 0.0 < gap <= 1.0
43  * n >= 2
44  * Hence, the formula below always yields in a value from the range [0..1].
45  */
46 static double s_Preference(double pref, double gap, size_t n)
47 {
48  double spread;
49  assert(0.0 <= pref && pref <= 1.0);
50  assert(0.0 < gap && gap <= 1.0);
51  assert(n >= 2);
52  if (gap >= pref)
53  return gap;
54  spread = 14.0/((double) n + 12.0);
55  if (gap >= spread/((double) n))
56  return pref;
57  else
58  return 2.0/spread * gap * pref;
59 }
60 
61 
62 size_t LB_Select(SERV_ITER iter, void* data,
63  FGetCandidate get_candidate, double bonus)
64 {
65  double total = 0.0, access = 0.0, point = 0.0, p = 0.0, status = 0.0;
66  const SSERV_Info* info;
67  SLB_Candidate* cand;
68  int/*bool*/ fixed;
69  size_t i = 0, n;
70 
71  assert(bonus >= 1.0);
72  assert(iter && get_candidate);
73  if (iter->ismask || iter->ok_down || iter->ok_suppressed)
74  return 0/*first entry (DISPD: probably) fits*/;
75  fixed = 0/*false*/;
76  for (n = 0; ; ++n) {
77  int/*bool*/ latch;
78  if (!(cand = get_candidate(data, n)))
79  break;
80  info = cand->info;
81  status = cand->status;
82  latch = iter->host && iter->host == info->host
83  && (!iter->port || iter->port == info->port);
84  if (latch || (!fixed && !iter->host && info->coef < 0.0
85  && (info->site & (fSERV_Local | fSERV_Private)))) {
86  if (fixed < latch) {
87  fixed = latch;
88  access = point = 0.0;
89  }
90  if (iter->pref || info->coef <= 0.0) {
91  status *= bonus;
92  if (access < status && (iter->pref || info->coef < 0.0)) {
93  access = status; /* always take the largest */
94  point = total + status; /* mark this local server */
95  p = -info->coef; /* NB: may end up negative */
96  i = n;
97  }
98  } else /* assert(latch); */
99  status *= info->coef;
100  }
101  total += status;
102  cand->status = total;
103 #ifdef NCBI_LB_DEBUG
104  {{
105  char addr[80];
106  const char* name = SERV_NameOfInfo(info);
107  SOCK_HostPortToString(info->host, info->port, addr, sizeof(addr));
109  ("%d: %s %s\tR=%lf\tS=%lf\tT=%lf\tA=%lf\tP=%lf",
110  (int) n, name, addr, info->rate, status, total,
111  access, point));
112  }}
113 #endif /*NCBI_LB_DEBUG*/
114  }
115  assert(n > 0);
116 
117  if (fixed && iter->pref < 0.0) {
118  /* fixed preference */
119  cand = get_candidate(data, i);
120  status = access;
121  } else {
122  if (iter->pref > 0.0) {
123  if (point > 0.0 && access > 0.0 && total != access) {
124  p = s_Preference(iter->pref, access/total, n);
125 #ifdef NCBI_LB_DEBUG
127  ("(P=%lf,\tA=%lf,\tT=%lf,\tA/T=%lf,\tN=%d) "
128  "-> P=%lf",
129  iter->pref, access, total, access/total,
130  (int) n, p));
131 #endif /*NCBI_LB_DEBUG*/
132  status = total * p;
133  p = total * (1.0 - p) / (total - access);
134  for (i = 0; i < n; ++i) {
135  cand = get_candidate(data, i);
136  if (point <= cand->status)
137  cand->status = p * (cand->status - access) + status;
138  else
139  cand->status *= p;
140  }
141 #ifdef NCBI_LB_DEBUG
142  status = 0.0;
143  for (i = 0; i < n; ++i) {
144  char addr[80];
145  cand = get_candidate(data, i);
146  info = cand->info;
147  p = cand->status - status;
148  status = cand->status;
149  SOCK_HostPortToString(info->host, info->port,
150  addr, sizeof(addr));
152  ("%d: %s %s\tS=%lf\t%.2lf%%",
153  (int) i, SERV_NameOfInfo(info), addr,
154  p, p / total * 100.0));
155  }
156 #endif /*NCBI_LB_DEBUG*/
157  }
158  point = -1.0;
159  }
160 
161  /* We take pre-chosen local server only if its status is not less
162  than p% of the average remaining status; otherwise, we ignore
163  the server, and apply the generic procedure by random seeding.*/
164  if (point <= 0.0
165  || access * (double)(n - 1) < p * 0.01 * (total - access)) {
166  point = (total * rand()) / (double) RAND_MAX;
167 #ifdef NCBI_LB_DEBUG
168  CORE_LOGF(eLOG_Note, ("P = %lf", point));
169 #endif /*NCBI_LB_DEBUG*/
170  }
171 
172  total = 0.0;
173  for (i = 0; i < n; ++i) {
174  cand = get_candidate(data, i);
175  assert(cand);
176  if (point <= cand->status) {
177  status = cand->status - total;
178  break;
179  }
180  total = cand->status;
181  }
182  }
183 
184  assert(cand && i < n);
185  cand->status = status;
186 
187  return i;
188 }
@ fSERV_Local
@ fSERV_Private
size_t SOCK_HostPortToString(unsigned int host, unsigned short port, char *buf, size_t bufsize)
Print numeric string "host:port" into a buffer provided, not to exceed 'bufsize' bytes (including the...
Definition: ncbi_socket.c:8949
@ eLOG_Note
Definition: ncbi_core.h:294
int i
yy_size_t n
static MDB_envinfo info
Definition: mdb_load.c:37
static double s_Preference(double pref, double gap, size_t n)
Definition: ncbi_lb.c:46
size_t LB_Select(SERV_ITER iter, void *data, FGetCandidate get_candidate, double bonus)
Definition: ncbi_lb.c:62
SLB_Candidate *(* FGetCandidate)(void *data, size_t n)
Definition: ncbi_lb.h:53
#define CORE_LOGF(level, fmt_args)
Definition: ncbi_priv.h:158
const char * SERV_NameOfInfo(const SSERV_Info *info)
#define assert(x)
Definition: srv_diag.hpp:58
const SSERV_Info * info
Definition: ncbi_lb.h:48
double status
Definition: ncbi_lb.h:49
unsigned ok_suppressed
Definition: ncbi_servicep.h:99
unsigned ok_down
Definition: ncbi_servicep.h:96
unsigned short port
Definition: ncbi_servicep.h:93
unsigned ismask
Definition: ncbi_servicep.h:95
unsigned int host
Definition: ncbi_servicep.h:92
Modified on Thu Nov 30 04:53:32 2023 by modify_doxy.py rev. 669887