1
/* $Id: lbapi.c,v 1.11 1999/02/26 21:17:36 shavirin Exp $
2
* ===========================================================================
5
* National Center for Biotechnology Information
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.
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
22
* Please cite the author in any work or product based on this material.
24
* ===========================================================================
26
* File Name: $RCSfile: lbapi.c,v $
28
* Author: Sergei Shavirin
30
* Initial Version Creation Date: 03/24/1997
35
* Utilities for the load balancing client library
38
* Revision 1.11 1999/02/26 21:17:36 shavirin
39
* Moved al ntohl function to the lbdaemon area.
41
* Revision 1.10 1999/02/02 21:10:28 shavirin
42
* Changed formula to calculate status:
43
* Added adjustment of load and used 4th lb-parameter.
45
* Revision 1.9 1998/12/07 19:01:50 shavirin
46
* Added complience with little-big endian platforms.
48
* Revision 1.8 1998/09/22 17:22:57 yaschenk
49
* LBCalculateStatus: changed additive constant 1 which is very high to 0.01
51
* Revision 1.7 1998/05/08 15:26:57 vakatov
52
* [LB_DIRECT] now can skip IP addresses(for the dispatcher hosts) which
53
* were already offered by the load-balancing daemon but failed by some reason
55
* Revision 1.6 1998/04/23 14:26:18 shavirin
56
* Added include #include <sys/ipc.h>
58
* Revision 1.5 1998/04/07 14:17:27 vakatov
59
* Skip all code(#ifdef'd) if LB_DIRECT is not defined or if compiled on
60
* any platform but Solaris and IRIX
62
* Revision 1.4 1998/04/03 21:50:08 shavirin
63
* Added include file for TCP/IP address define
65
* Revision 1.3 1998/04/03 21:16:47 vakatov
66
* Cleaned up the code and prepared "lbapi.[ch]" to be moved to "netcli" lib
68
* Revision 1.2 1998/04/02 17:36:04 yaschenk
69
* Adding dispd-ncbid shortcut when they are on the same server, adding preference to same server in stateless mode
71
* Revision 1.1 1998/03/06 18:54:25 shavirin
73
* ==========================================================================
84
#include <netinet/in.h>
85
#include <arpa/inet.h>
87
#include <sys/socket.h>
91
#define SHM_FLAGS ((SHM_R >> 6) | (SHM_R >> 3) | SHM_R)
92
#define MAX_RAND_NUMBER 0x7FFF
95
typedef struct LBUserInfo {
96
LB_MessagePtr lbtable;
98
} LBUserInfo, *LBUserInfoPtr;
100
typedef struct LBStatus {
104
} LBStatus, *LBStatusPtr;
107
static LBUserInfo theinfo;
109
static float LBCalculateStatus(LB_MessagePtr msgp)
114
/* Penalize machine if load[0]/256 > load[1] */
116
cpuload = msgp->load[0];
118
if(msgp->load[0] > (msgp->load[1]<<8))
119
cpuload *= exp(msgp->load[0] / (256.0*msgp->load[1]) - 1.0);
121
status = 0.01 + 256000*msgp->load[1] / (float)(cpuload*msgp->load[2] + 1);
123
status = status * msgp->load[3];
128
static int LBClientInit(void)
130
/* setting it completely random */
133
if ((theinfo.shmemid = shmget(LB_SHARED_KEY,
134
sizeof(LB_Message) * MAX_NUM_HOSTS,
138
if ((theinfo.lbtable = (LB_MessagePtr)
139
shmat(theinfo.shmemid, (void *)0, SHM_RDONLY)) == (LB_MessagePtr)-1)
146
extern int LBPrintTable(void)
149
struct sockaddr_in sin;
152
LB_MessagePtr lbtable;
154
if((lbtable = theinfo.lbtable) == NULL) {
155
if(LBClientInit() < 0)
157
lbtable = theinfo.lbtable;
160
for(j = 0; j < MAX_NUM_HOSTS; j++) {
161
if(lbtable[j].address != 0) {
162
sin.sin_addr.s_addr = lbtable[j].address;
164
hp = gethostbyaddr((char *)&sin.sin_addr,
165
sizeof (sin.sin_addr), AF_INET);
167
hp == NULL? inet_ntoa(sin.sin_addr) : hp->h_name);
169
status = LBCalculateStatus(&lbtable[j]);
170
printf("%-10.2f ", status);
172
for(i = 0; i < NUM_LOAD_PARAMETERS; i++)
173
printf("%5d ", lbtable[j].load[i]);
175
for(i = 0; i < MAX_NUM_SERVICES; i++) {
176
if(*lbtable[j].service[i] != '\0')
177
printf("%s ", lbtable[j].service[i]);
189
extern unsigned LBGetIPAddress(const char *service, unsigned int pref_ip,
190
unsigned *skip_ip, size_t n_skip)
193
LBStatus trace[MAX_NUM_HOSTS];
195
float status, all_status, point;
196
LB_MessagePtr lbtable;
198
if (!theinfo.lbtable && LBClientInit() < 0)
201
lbtable = theinfo.lbtable;
203
memset(trace, '\0', sizeof(trace));
205
/* the hosts to be skipped */
206
for (j = 0; j < MAX_NUM_HOSTS; j++) {
208
for (m = 0; m < n_skip; m++)
209
if (lbtable[j].address == skip_ip[m]) {
215
/* first try to find the preferred address */
217
for (j = 0, i = 0; j < MAX_NUM_HOSTS; j++) {
218
if (pref_ip == lbtable[j].address) {
221
for (k = 0; k < MAX_NUM_SERVICES; k++) {
222
if ( !strcmp(lbtable[j].service[k], service) )
231
for (j = 0, i = 0; j < MAX_NUM_HOSTS; j++) {
235
for (k = 0; k < MAX_NUM_SERVICES; k++) {
236
if(!strcmp(lbtable[j].service[k], service)) {
237
status = LBCalculateStatus(&lbtable[j]);
238
all_status += status;
239
trace[i].status = all_status;
250
point = (float)(trace[count-1].status * rand()) / (float)MAX_RAND_NUMBER;
252
for (i = 0; i < count; i++) {
253
if (point < trace[i].status)
257
return lbtable[trace[i].index].address;
260
#endif /* LB_DIRECT */