NCBI C Toolkit Cross Reference

C/connect/ncbi_lb.c


  1 /*  $Id: ncbi_lb.c,v 1.12 2008/02/14 16:25:55 kazimird Exp $
  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 <assert.h>
 35 #include <stdlib.h>
 36 
 37 
 38 #define NCBI_USE_ERRCODE_X   Connect_LB
 39 
 40 
 41 size_t LB_Select(SERV_ITER     iter,          void*  data,
 42                  FGetCandidate get_candidate, double bonus)
 43 {
 44     double total = 0.0, access = 0.0, point = 0.0, p = 0.0, status = 0.0;
 45     const SSERV_Info* info;
 46     SLB_Candidate* cand;
 47     int/*bool*/ fixed;
 48     size_t i = 0, n;
 49 
 50     assert(bonus >= 1.0);
 51     assert(iter  &&  get_candidate);
 52     if (iter->ismask  ||  iter->ok_down  ||  iter->ok_suppressed)
 53         return 0/*first entry (DISPD: probably) fits*/;
 54     fixed = 0/*false*/;
 55     for (n = 0; ; n++) {
 56         int/*bool*/ latch;
 57         if (!(cand = get_candidate(data, n)))
 58             break;
 59         info   = cand->info;
 60         status = cand->status;
 61         latch  = iter->host  &&  iter->host == info->host
 62             && (!iter->port  ||  iter->port == info->port);
 63         if (latch  ||  (!fixed  &&  !iter->host  &&
 64                         info->locl  &&  info->coef < 0.0)) {
 65             if (fixed < latch) {
 66                 fixed = latch;
 67                 access = point = 0.0;
 68             }
 69             if (iter->pref  ||  info->coef <= 0.0) {
 70                 status *= bonus;
 71                 if (access < status  &&  (iter->pref  ||  info->coef < 0.0)) {
 72                     access =  status;         /* always take the largest */
 73                     point  =  total + status; /* mark this local server  */
 74                     p      = -info->coef;     /* NB: may end up negative */
 75                     i      = n;
 76                 }
 77             } else /* assert(latch); */
 78                 status *= info->coef;
 79         }
 80         total       += status;
 81         cand->status = total;
 82 #ifdef NCBI_LB_DEBUG
 83         {{
 84             char addr[80];
 85             const char* name = SERV_NameOfInfo(info);
 86             SOCK_HostPortToString(info->host, info->port, addr, sizeof(addr));
 87             CORE_LOGF(eLOG_Note,
 88                       ("%d: %s %s\tR=%lf\tS=%lf\tT=%lf\tA=%lf\tP=%lf",
 89                        (int) n, name, addr, info->rate, status, total,
 90                        access, point));
 91         }}
 92 #endif /*NCBI_LB_DEBUG*/
 93     }
 94     assert(n > 0);
 95 
 96     if (fixed  &&  iter->pref < 0.0) {
 97         /* fixed preference */
 98         cand = get_candidate(data, i);
 99         status = access;
100     } else {
101         if (iter->pref > 0.0) {
102             if (point > 0.0  &&  access > 0.0  &&  total != access) {
103                 p = SERV_Preference(iter->pref, access/total, n);
104 #ifdef NCBI_LB_DEBUG
105                 CORE_LOGF(eLOG_Note,
106                           ("(P=%lf,\tA=%lf,\tT=%lf,\tA/T=%lf,\tN=%d) "
107                            "-> P=%lf",
108                            iter->pref, access, total, access/total,
109                            (int) n, p));
110 #endif /*NCBI_LB_DEBUG*/
111                 status = total * p;
112                 p = total * (1.0 - p) / (total - access);
113                 for (i = 0; i < n; i++) {
114                     cand = get_candidate(data, i);
115                     if (point <= cand->status)
116                         cand->status  = p * (cand->status - access) + status;
117                     else
118                         cand->status *= p;
119                 }
120 #ifdef NCBI_LB_DEBUG
121                 status = 0.0;
122                 for (i = 0;  i < n;  i++) {
123                     char addr[80];
124                     cand   = get_candidate(data, i);
125                     info   = cand->info;
126                     p      = cand->status - status;
127                     status = cand->status;
128                     SOCK_HostPortToString(info->host, info->port,
129                                           addr, sizeof(addr));
130                     CORE_LOGF(eLOG_Note,
131                               ("%d: %s %s\tS=%lf\t%.2lf%%",
132                                (int) i, SERV_NameOfInfo(info), addr,
133                                p, p / total * 100.0));
134                 }
135 #endif /*NCBI_LB_DEBUG*/
136             }
137             point = -1.0;
138         }
139 
140         /* We take pre-chosen local server only if its status is not less
141            than p% of the average remaining status; otherwise, we ignore
142            the server, and apply the generic procedure by random seeding.*/
143         if (point <= 0.0  ||  access * (n - 1) < p * 0.01 * (total - access)) {
144             point = (total * rand()) / (double) RAND_MAX;
145 #ifdef NCBI_LB_DEBUG
146             CORE_LOGF(eLOG_Note, ("P = %lf", point));
147 #endif /*NCBI_LB_DEBUG*/
148         }
149 
150         total = 0.0;
151         for (i = 0; i < n; i++) {
152             cand = get_candidate(data, i);
153             assert(cand);
154             if (point <= cand->status) {
155                 status = cand->status - total;
156                 break;
157             }
158             total = cand->status;
159         }
160     }
161 
162     assert(cand  &&  i < n);
163     cand->status = status;
164 
165     return i;
166 }
167 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.