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

Go to the SVN repository for this file.

1 /* $Id: ncbi_local.c 92500 2021-01-26 18:54:55Z 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  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Anton Lavrentiev
27  *
28  * File Description:
29  * Low-level API to resolve NCBI service name to the server meta-address
30  * with the use of local registry.
31  *
32  */
33 
34 #include "ncbi_ansi_ext.h"
35 #include "ncbi_comm.h"
36 #include "ncbi_lb.h"
37 #include "ncbi_local.h"
38 #include "ncbi_priv.h"
39 #include <stdlib.h>
40 
41 
42 #ifdef __cplusplus
43 extern "C" {
44 #endif /*__cplusplus*/
46  static void s_Reset (SERV_ITER);
47  static void s_Close (SERV_ITER);
48 
49  static const SSERV_VTable s_op = {
50  s_GetNextInfo, 0/*Feedback*/, 0/*Update*/, s_Reset, s_Close, "LOCAL"
51  };
52 #ifdef __cplusplus
53 } /* extern "C" */
54 #endif /*__cplusplus*/
55 
56 
57 struct SLOCAL_Data {
59  size_t i_cand;
60  size_t n_cand;
61  size_t a_cand;
62  int/*bool*/ reset;
63 };
64 
65 
66 static int/*bool*/ s_AddService(const SSERV_Info* info,
67  struct SLOCAL_Data* data)
68 {
69  SLB_Candidate* temp;
70  size_t n;
71 
72  if (data->a_cand <= data->n_cand) {
73  n = data->a_cand + 10;
74  temp = (SLB_Candidate*)(data->cand
75  ? realloc(data->cand,n * sizeof(*data->cand))
76  : malloc ( n * sizeof(*data->cand)));
77  if (!temp)
78  return 0/*false*/;
79  data->a_cand = n;
80  data->cand = temp;
81  }
82 
83  n = (size_t) rand() % ++data->n_cand;
84  if (n < data->n_cand - 1) {
85  temp = data->cand + n++;
86  memmove(temp + 1, temp, (data->n_cand - n) * sizeof(*data->cand));
87  }
88  data->cand[n].info = info;
89  return 1/*true*/;
90 }
91 
92 
93 static int/*bool*/ s_LoadSingleService(const char* name, SERV_ITER iter)
94 {
97  struct SLOCAL_Data* data = (struct SLOCAL_Data*) iter->data;
98  char key[sizeof(REG_CONN_LOCAL_SERVER) + 10];
99  int/*bool*/ ok = 0/*failed*/;
100  SSERV_Info* info;
101  int n;
102 
103  info = 0;
104  strcpy(key, REG_CONN_LOCAL_SERVER "_");
105  for (n = 0; n <= 100; ++n) {
106  const char* svc;
107  char buf[1024];
108 
109  if (info) {
110  free((void*) info);
111  info = 0;
112  }
113  sprintf(key + sizeof(REG_CONN_LOCAL_SERVER), "%d", n);
114  if (!(svc = ConnNetInfo_GetValue(name, key, buf, sizeof(buf), 0)))
115  continue;
116  if (!(info = SERV_ReadInfoEx
117  (svc, iter->ismask || iter->reverse_dns ? name : "", 0))) {
118  continue;
119  }
120  if (iter->external && (info->site & (fSERV_Local | fSERV_Private)))
121  continue; /* external mapping for local server not allowed */
122  if (!info->host || (info->site & fSERV_Private)) {
123  unsigned int localhost = SOCK_GetLocalHostAddress(eDefault);
124  if (!info->host)
125  info->host = localhost;
126  if (!iter->ok_private && (info->site & fSERV_Private)
127  && info->host != localhost) {
128  continue; /* private server */
129  }
130  }
131  if (!iter->reverse_dns && info->type != fSERV_Dns) {
132  if (types != fSERV_Any && !(types & info->type))
133  continue; /* type doesn't match */
134  if (types == fSERV_Any && info->type == fSERV_Dns)
135  continue; /* DNS entries have to be req'd explicitly */
136  if ((iter->types & fSERV_Stateless)&&(info->mode & fSERV_Stateful))
137  continue; /* skip stateful only servers */
138  }
139  if (!info->rate)
140  info->rate = LBSM_DEFAULT_RATE;
141  if (!info->time)
142  info->time = LBSM_DEFAULT_TIME;
143 
144  if (!s_AddService(info, data))
145  break;
146 
147  info = 0;
148  ok = 1/*succeeded*/;
149  }
150  if (info)
151  free((void*) info);
152 
153  return ok/*whatever*/;
154 }
155 
156 
157 static int/*bool*/ s_LoadServices(SERV_ITER iter)
158 {
159  int/*bool*/ ok = 0/*false*/;
160  char services[1024];
161  const char* c;
162  char* s;
163 
164  if (!iter->ismask) {
165  ok = s_LoadSingleService(iter->name, iter);
166  if (!ok || !iter->reverse_dns)
167  return ok;
168  }
170  services, sizeof(services), 0)) || !*c) {
171  return ok;
172  }
173 
174  s = services;
175  ok = 0/*false*/;
176  for (s += strspn(s, " \t"); *s; s += strspn(s, " \t")) {
177  size_t len = strcspn(s, " \t");
178  assert(len);
179  if (s[len])
180  s[len++] = '\0';
181  if (!(c = SERV_ServiceName(s)))
182  break;
183  if ((iter->reverse_dns
184  || (iter->ismask
185  && (!*iter->name || UTIL_MatchesMask(c, iter->name))))
186  && s_LoadSingleService(c, iter)) {
187  ok = 1/*succeeded*/;
188  }
189  free((void*) c);
190  s += len;
191  }
192 
193  return ok/*whatever*/;
194 }
195 
196 
197 static int s_Sort(const void* p1, const void* p2)
198 {
199  const SLB_Candidate* c1 = (const SLB_Candidate*) p1;
200  const SLB_Candidate* c2 = (const SLB_Candidate*) p2;
201  if (c1->info->type == fSERV_Dns || c2->info->type == fSERV_Dns) {
202  if (c1->info->type != fSERV_Dns)
203  return -1;
204  if (c2->info->type != fSERV_Dns)
205  return 1;
206  }
207  if ((int) c1->info->type < (int) c2->info->type)
208  return -1;
209  if ((int) c1->info->type > (int) c2->info->type)
210  return 1;
211  return 0;
212 }
213 
214 
215 static SLB_Candidate* s_GetCandidate(void* user_data, size_t i)
216 {
217  struct SLOCAL_Data* data = (struct SLOCAL_Data*) user_data;
218  return i < data->i_cand ? &data->cand[i] : 0;
219 }
220 
221 
222 static SSERV_Info* s_GetNextInfo(SERV_ITER iter, HOST_INFO* host_info)
223 {
224  const TSERV_Type types = iter->types & (TSERV_Type)(~fSERV_Firewall);
225  struct SLOCAL_Data* data = (struct SLOCAL_Data*) iter->data;
226  int/*bool*/ dns_info_seen = 0/*false*/;
227  SSERV_Info* info;
228  size_t i, n;
229 
230  assert(data);
231  if (data->reset) {
232  data->reset = 0/*false*/;
233  if (!s_LoadServices(iter))
234  return 0;
235  if (data->n_cand > 1)
236  qsort(data->cand, data->n_cand, sizeof(*data->cand), s_Sort);
237  }
238 
239  i = 0;
240  data->i_cand = 0;
241  while (i < data->n_cand) {
242  /* NB all servers have been loaded in accordance with their locality */
243  info = (SSERV_Info*) data->cand[i].info;
244  if (info->rate > 0.0 || iter->ok_down) {
245  const char* c = SERV_NameOfInfo(info);
246  for (n = 0; n < iter->n_skip; n++) {
247  const SSERV_Info* skip = iter->skip[n];
248  const char* s = SERV_NameOfInfo(skip);
249  if (*s) {
250  assert(iter->ismask || iter->reverse_dns);
251  if (strcasecmp(s, c) == 0
252  && ((skip->type == fSERV_Dns && !skip->host) ||
253  SERV_EqualInfo(skip, info))) {
254  break;
255  }
256  } else if (SERV_EqualInfo(skip, info))
257  break;
258  if (iter->reverse_dns && skip->type == fSERV_Dns
259  && skip->host == info->host
260  && (!skip->port || skip->port == info->port)) {
261  break;
262  }
263  }
264  } else
265  n = 0;
266  if (!iter->ismask) {
267  if (types == fSERV_Any) {
268  if (iter->reverse_dns && info->type != fSERV_Dns)
269  dns_info_seen = 1/*true*/;
270  } else if ((types & info->type) && info->type == fSERV_Dns)
271  dns_info_seen = 1/*true*/;
272  }
273  if (n < iter->n_skip) {
274  if (i < --data->n_cand) {
275  memmove(data->cand + i, data->cand + i + 1,
276  (data->n_cand - i) * sizeof(*data->cand));
277  }
278  free(info);
279  } else {
280  if (types != fSERV_Any && !(types & info->type))
281  break;
282  if (types == fSERV_Any && info->type == fSERV_Dns)
283  break;
284  data->i_cand++;
285  data->cand[i].status = info->rate < 0.0 ? 0.0 : info->rate;
286  if (iter->ok_down)
287  break;
288  i++;
289  }
290  }
291 
292  if (data->i_cand) {
293  n = LB_Select(iter, data, s_GetCandidate, 1.0);
294  info = (SSERV_Info*) data->cand[n].info;
295  if (iter->reverse_dns && info->type != fSERV_Dns) {
296  dns_info_seen = 0/*false*/;
297  for (i = 0; i < data->n_cand; i++) {
298  SSERV_Info* temp = (SSERV_Info*) data->cand[i].info;
299  if (temp->type != fSERV_Dns ||
300  temp->host != info->host || temp->port != info->port) {
301  continue;
302  }
303  if (!iter->ismask)
304  dns_info_seen = 1/*true*/;
305  if (iter->external
306  && (temp->site & (fSERV_Local | fSERV_Private))) {
307  continue; /* external mapping req'd; local server */
308  }
309  if (temp->rate > 0.0 || iter->ok_down) {
310  data->cand[i].status = data->cand[n].status;
311  info = temp;
312  n = i;
313  break;
314  }
315  }
316  if (i >= data->n_cand && dns_info_seen)
317  info = 0;
318  }
319 
320  if (info) {
321  info->rate = data->cand[n].status;
322  info->time += iter->time;
323  if (n < --data->n_cand) {
324  memmove(data->cand + n, data->cand + n + 1,
325  (data->n_cand - n) * sizeof(*data->cand));
326  }
327  }
328  } else if (iter->last || iter->n_skip || !dns_info_seen) {
329  info = 0;
330  } else if ((info = SERV_CreateDnsInfo(0)) != 0)
331  info->time = NCBI_TIME_INFINITE;
332 
333  if (info && host_info)
334  *host_info = 0;
335  return info;
336 }
337 
338 
339 static void s_Reset(SERV_ITER iter)
340 {
341  struct SLOCAL_Data* data = (struct SLOCAL_Data*) iter->data;
342  assert(data);
343  if (data->cand) {
344  size_t i;
345  assert(data->a_cand);
346  for (i = 0; i < data->n_cand; i++)
347  free((void*) data->cand[i].info);
348  data->n_cand = 0;
349  }
350  data->reset = 1/*true*/;
351 }
352 
353 
354 static void s_Close(SERV_ITER iter)
355 {
356  struct SLOCAL_Data* data = (struct SLOCAL_Data*) iter->data;
357  /* NB: s_Reset() must have been called before */
358  assert(data && !data->n_cand && data->reset);
359  if (data->cand) {
360  assert(data->a_cand);
361  data->a_cand = 0;
362  free(data->cand);
363  data->cand = 0;
364  }
365  iter->data = 0;
366  free(data);
367 }
368 
369 
370 /***********************************************************************
371  * EXTERNAL
372  ***********************************************************************/
373 
375 {
376  struct SLOCAL_Data* data;
377 
378  if (!(data = (struct SLOCAL_Data*) calloc(1, sizeof(*data))))
379  return 0;
380  iter->data = data;
381 
382  if (g_NCBI_ConnectRandomSeed == 0) {
385  }
386 
387  if (!s_LoadServices(iter)) {
388  s_Reset(iter);
389  s_Close(iter);
390  return 0;
391  }
392  assert(data->n_cand);
393  if (data->n_cand > 1)
394  qsort(data->cand, data->n_cand, sizeof(*data->cand), s_Sort);
395 
396  /* call GetNextInfo subsequently if info is actually needed */
397  if (info)
398  *info = 0;
399  return &s_op;
400 }
static const struct type types[]
Definition: type.c:22
char data[12]
Definition: iconv.c:80
@ eDefault
Definition: ncbi_types.h:112
SSERV_Info * SERV_CreateDnsInfo(unsigned int host)
TSERV_Site site
unsigned int TSERV_Type
Bitwise OR of ESERV_Type[Special].
Definition: ncbi_service.h:94
unsigned int host
unsigned short port
int SERV_EqualInfo(const SSERV_Info *info1, const SSERV_Info *info2)
ESERV_Type type
@ fSERV_Firewall
@ fSERV_Dns
@ fSERV_Stateless
Stateless servers only.
Definition: ncbi_service.h:81
@ fSERV_Any
Definition: ncbi_service.h:79
@ fSERV_Stateful
@ fSERV_Local
@ fSERV_Private
unsigned int SOCK_GetLocalHostAddress(ESwitch reget)
Get (and cache for faster follow-up retrievals) IPv4 address of local host.
Definition: ncbi_socket.c:8827
int UTIL_MatchesMask(const char *text, const char *mask)
Shortcut for UTIL_MatchesMaskEx(text, mask, 1), that is matching is done case-insensitively for the l...
Definition: ncbi_util.c:1378
const char * ConnNetInfo_GetValue(const char *service, const char *param, char *value, size_t value_size, const char *def_value)
#define NCBI_TIME_INFINITE
Definition: ncbi_types.h:147
#define REG_CONN_LOCAL_SERVICES
#define REG_CONN_LOCAL_SERVER
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
char * buf
int i
if(yy_accept[yy_current_state])
yy_size_t n
int len
static MDB_envinfo info
Definition: mdb_load.c:37
const struct ncbi::grid::netcache::search::fields::KEY key
#define strcasecmp
#define LBSM_DEFAULT_RATE
Definition: ncbi_comm.h:46
#define LBSM_DEFAULT_TIME
Definition: ncbi_comm.h:45
size_t LB_Select(SERV_ITER iter, void *data, FGetCandidate get_candidate, double bonus)
Definition: ncbi_lb.c:62
static const SSERV_VTable s_op
Definition: ncbi_local.c:49
static void s_Close(SERV_ITER)
Definition: ncbi_local.c:354
static SLB_Candidate * s_GetCandidate(void *user_data, size_t i)
Definition: ncbi_local.c:215
static int s_LoadSingleService(const char *name, SERV_ITER iter)
Definition: ncbi_local.c:93
static int s_LoadServices(SERV_ITER iter)
Definition: ncbi_local.c:157
static void s_Reset(SERV_ITER)
Definition: ncbi_local.c:339
const SSERV_VTable * SERV_LOCAL_Open(SERV_ITER iter, SSERV_Info **info)
Definition: ncbi_local.c:374
static int s_AddService(const SSERV_Info *info, struct SLOCAL_Data *data)
Definition: ncbi_local.c:66
static int s_Sort(const void *p1, const void *p2)
Definition: ncbi_local.c:197
static SSERV_Info * s_GetNextInfo(SERV_ITER, HOST_INFO *)
Definition: ncbi_local.c:222
unsigned int g_NCBI_ConnectRandomSeed
Definition: ncbi_priv.c:51
#define NCBI_CONNECT_SRAND_ADDEND
Definition: ncbi_priv.h:343
SSERV_Info * SERV_ReadInfoEx(const char *str, const char *name, int lazy)
const char * SERV_NameOfInfo(const SSERV_Info *info)
char * SERV_ServiceName(const char *service)
Definition: ncbi_service.c:186
#define memmove(a, b, c)
#define assert(x)
Definition: srv_diag.hpp:58
const SSERV_Info * info
Definition: ncbi_lb.h:48
size_t n_cand
Definition: ncbi_local.c:60
size_t a_cand
Definition: ncbi_local.c:61
SLB_Candidate * cand
Definition: ncbi_local.c:58
size_t i_cand
Definition: ncbi_local.c:59
unsigned external
unsigned ok_down
Definition: ncbi_servicep.h:96
const char * name
Definition: ncbi_servicep.h:89
SSERV_InfoCPtr * skip
unsigned ismask
Definition: ncbi_servicep.h:95
SSERV_InfoCPtr last
unsigned ok_private
unsigned reverse_dns
TSERV_TypeOnly types
Definition: ncbi_servicep.h:94
TNCBI_Time time
Definition: ncbi_servicep.h:91
void free(voidpf ptr)
voidp malloc(uInt size)
voidp calloc(uInt items, uInt size)
Modified on Wed Jul 17 13:20:46 2024 by modify_doxy.py rev. 669887