1 
2 /*
3  * dmucs_host.cc: a DmucsHost is a representation of a compilation host.
4  *
5  * Copyright (C) 2005, 2006  Victor T. Norman
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 2 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15  * Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 
22 #include "dmucs.h"
23 #include "dmucs_dprop.h"
24 #include "dmucs_host.h"
25 #include "dmucs_db.h"
26 #include "dmucs_hosts_file.h"
27 #include "dmucs_host_state.h"
28 #include "dmucs_resolve.h"
29 #include <stdio.h>
30 #include <netdb.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <sys/socket.h>
34 
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38 
39 
DmucsHost(const struct in_addr & ipAddr,const DmucsDprop dprop,const int numCpus,const int powerIndex)40 DmucsHost::DmucsHost(const struct in_addr &ipAddr,
41 		     const DmucsDprop dprop,
42 		     const int numCpus, const int powerIndex) :
43     ipAddr_(ipAddr), dprop_(dprop), ncpus_(numCpus), pindex_(powerIndex),
44     ldavg1_(0), ldavg5_(0), ldavg10_(0),
45     lastUpdate_(0)
46 {
47     state_ = DmucsHostStateAvail::getInstance();
48 }
49 
50 
51 DmucsHost *
createHost(const struct in_addr & ipAddr,const DmucsDprop dprop,const std::string & hostsInfoFile)52 DmucsHost::createHost(const struct in_addr &ipAddr,
53 		      const DmucsDprop dprop,
54 		      const std::string &hostsInfoFile)
55 {
56     /*
57      * Read the hosts file, and find the entry in it for this host.
58      */
59     DmucsHostsFile *hostsFile = DmucsHostsFile::getInstance(hostsInfoFile);
60     int numCpus = 1;
61     int powerIndex = 1;
62     hostsFile->getDataForHost(ipAddr, &numCpus, &powerIndex);
63     DmucsHost *newHost = new DmucsHost(ipAddr, dprop, numCpus, powerIndex);
64 
65     DmucsDb::getInstance()->addNewHost(newHost);
66 
67     return newHost;
68 }
69 
70 const int
getStateAsInt() const71 DmucsHost::getStateAsInt() const
72 {
73     return state_->asInt();
74 }
75 
76 int
getTier() const77 DmucsHost::getTier() const
78 {
79     return calcTier(ldavg1_, ldavg5_, ldavg10_, pindex_);
80 }
81 
82 int
calcTier(float ldavg1,float ldavg5,float ldavg10,int pindex) const83 DmucsHost::calcTier(float ldavg1, float ldavg5, float ldavg10,
84 		    int pindex) const
85 {
86     if (ldavg1 < 0.9) {
87 	return pindex;
88     } else if (ldavg5 < 0.7) {
89 	return pindex;
90     } else if (ldavg10 < 0.8) {
91 	return pindex - 1;
92     } else {
93 	return 0;	// 0 means don't use this host.
94     }
95 }
96 
97 
98 void
updateTier(float ldAvg1,float ldAvg5,float ldAvg10)99 DmucsHost::updateTier(float ldAvg1, float ldAvg5, float ldAvg10)
100 {
101     ldAvg1 /= (float) ncpus_;
102     ldAvg5 /= (float) ncpus_;
103     ldAvg10 /= (float) ncpus_;
104     int newTier = calcTier(ldAvg1, ldAvg5, ldAvg10, pindex_);
105     int oldTier = getTier();
106 
107     if (newTier != oldTier) {
108         DMUCS_DEBUG((stderr, "oldTier %d, newTier %d\n", oldTier, newTier));
109 	if (newTier == 0) {
110 	    /* This host is completely overloaded: remove the CPU objects
111 	       from their current tier, and move this host object to the
112 	       overloaded state. */
113 	    overloaded();
114 	    ldavg1_ = ldAvg1; ldavg5_ = ldAvg5; ldavg10_ = ldAvg10;
115 	} else if (oldTier == 0) {
116 	    /* This host was overloaded, but now it is not.
117 	       Move the cpu objects from one tier to another. */
118 	    DmucsDb::getInstance()->moveCpus(this, oldTier, newTier);
119 	    ldavg1_ = ldAvg1; ldavg5_ = ldAvg5; ldavg10_ = ldAvg10;
120 	} else {
121 	    /* Move the cpu objects from one tier to another. */
122 	    DmucsDb::getInstance()->moveCpus(this, oldTier, newTier);
123 	    ldavg1_ = ldAvg1; ldavg5_ = ldAvg5; ldavg10_ = ldAvg10;
124 	}
125     } else {
126 	ldavg1_ = ldAvg1; ldavg5_ = ldAvg5; ldavg10_ = ldAvg10;
127     }
128     lastUpdate_ = time(0);
129 }
130 
131 
132 
133 void
avail()134 DmucsHost::avail()
135 {
136     state_->avail(this);
137 }
138 
139 
140 void
unavail()141 DmucsHost::unavail()
142 {
143     state_->unavail(this);
144 }
145 
146 
147 void
silent()148 DmucsHost::silent()
149 {
150     state_->silent(this);
151 }
152 
153 
154 void
overloaded()155 DmucsHost::overloaded()
156 {
157     state_->overloaded(this);
158 }
159 
160 
161 void
changeState(DmucsHostState * state)162 DmucsHost::changeState(DmucsHostState *state)
163 {
164     state_ = state;
165     state_->addToDb(this);
166 }
167 
168 
169 bool
seemsDown() const170 DmucsHost::seemsDown() const
171 {
172     return (time(0) - lastUpdate_ > DMUCS_HOST_SILENT_TIME);
173 }
174 
175 
176 bool
isUnavailable() const177 DmucsHost::isUnavailable() const
178 {
179     return (state_->asInt() == STATUS_UNAVAILABLE);
180 }
181 
182 bool
isSilent() const183 DmucsHost::isSilent() const
184 {
185     return (state_->asInt() == STATUS_SILENT);
186 }
187 
188 bool
isOverloaded() const189 DmucsHost::isOverloaded() const
190 {
191     return (state_->asInt() == STATUS_OVERLOADED);
192 }
193 
194 
195 void
dump()196 DmucsHost::dump()
197 {
198     fprintf(stderr,
199 	    "Host: %20.20s  Dprop: %8.8s  State: %s Pindex: %d Ncpus %d\n",
200 	    inet_ntoa(ipAddr_), dprop2cstr(dprop_), state_->dump(),
201 	    pindex_, ncpus_);
202 }
203 
204 
205 const std::string &
getName()206 DmucsHost::getName()
207 {
208     if (! resolvedName_.empty()) {
209 	return resolvedName_;
210     }
211 
212     return getHostName(resolvedName_, ipAddr_);
213 }
214 
215 
216 /*
217  * Given in IP address, find the host in the host database.  If its name has
218  * already been found, then return it.  Otherwise, resolve it and store it
219  * in the host and return the string.
220  */
221 std::string
resolveIp2Name(unsigned int ipAddr,DmucsDprop dprop)222 DmucsHost::resolveIp2Name(unsigned int ipAddr, DmucsDprop dprop)
223 {
224     /* Search for DmucsHost, based on Ip Address */
225     struct in_addr c;
226     c.s_addr = ipAddr;
227     return DmucsDb::getInstance()->getHost(c, dprop)->getName();
228 }
229