1 /*
2 * BidderHouse.cc --
3 *
4 * FIXME: This file needs a description here.
5 *
6 * Copyright (c) 2001-2002 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * A. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * B. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * C. Neither the names of the copyright holders nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
22 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "BidderHouse.h"
35 #include "pipe_rend.h"
36
37 static class BidderHouseClass : public TclClass {
38 public:
39 BidderHouseClass() : TclClass ("BidderHouse") {}
40 TclObject* create(int argc, const char*const* argv) {
41 BidderHouse* house;
42 if (argc == 5)
43 house = new BidderHouse(atoi(argv[4]));
44 else
45 house = new BidderHouse(128000);
46 // ASSERT(house != NULL);
47 return house;
48 }
49 private:
50 } BidderHouseClass;
51
52 int
53 BidderHouse::command(int argc, const char*const* argv) {
54 Tcl& tcl = Tcl::instance();
55 if (argc == 2) {
56 if (strcmp(argv[1], "hold_bid") == 0) {
57 // this is called once at the start and it keeps calling itself after that.
58 tcl.evalf("after %d %s hold_bid", BID_INTERVAL, name());
59 sellBandwidth();
60 return (TCL_OK);
61 } else if (strcmp(argv[1], "update_bw") == 0) {
62 // called once at start and calls itself after that. Update the bandwidth display.
63 tcl.evalf("after %d %s update_bw", UPDATE_INTERVAL, name());
64 getBandwidthUsage();
65 return (TCL_OK);
66 }
67 } else if (argc == 4) {
68 if (strcmp(argv[1], "set_priority") == 0) {
69 // sets the wage, is called when the slider is moved...
70 PipeRenderer* src = (PipeRenderer*)TclObject::lookup(argv[2]);
71 setPriority(src, atoi(argv[3]));
72 return (TCL_OK);
73 }
74 }
75 return (TCL_ERROR);
76 }
77
78 // add a new source into the auction.
79 void
80 BidderHouse::addSource(PipeRenderer* msource) {
81 Bidder* source = new Bidder(0,0,0,0,0,msource);
82 sources.push_back(source);
83 }
84
85 // called by the source to tell the auction house how much bandwidth this
86 // particular source wants.
87 void
88 BidderHouse::setDiffCount(PipeRenderer* msource,
89 int diffCount, int meanDiffSize)
90 {
91 Bidder* source = lookupSource(msource);
92 source->diffsWant = diffCount;
93 source->diffSize = meanDiffSize;
94 // printf("setting Diff count for %d to %d\n",source, diffCount);
95 }
96
97 Bidder*
98 BidderHouse::lookupSource(PipeRenderer* msource)
99 {
100 for (vector<Bidder*>::iterator e = sources.begin();
101 e != sources.end(); e++) {
102 if ((*e)->msource == msource)
103 return *e;
104 }
105
106 // assert(0);
107 return NULL;
108 }
109
110 // called after the auction. tells the source to send its data and
111 // then updates all relevant fields.
112 void
113 BidderHouse::giveBWtoSource(Bidder* source, int price) {
114 if ((source->diffsWant == 0) || (source->money == 0) || (source->wage == 0))
115 return;
116
117 int temp = source->diffsWant * source->diffSize;
118 bytesToSend -= temp;
119 source->bandwidth += temp*8;
120 source->money -= price*temp;
121 source->msource->giveToEncoder(source->diffsWant);
122 source->diffsWant = 0;
123 //printf("sold bw to %d, money taken is %d, price is %d\n\n",source, price*temp,price);
124 }
125
126 // sorts the bidders to find the highest price.
127 void
128 BidderHouse::lotterySort(int num_of_sources) {
129 // simple order n squared sort of the arrays by price
130 int temp, temp2, u_holder, p_holder;
131 Bidder* s_holder;
132 for (temp = 0; temp < (num_of_sources-1); temp++) {
133 for (temp2 = 0; temp2 < (num_of_sources-1); temp2++) {
134 if (lottery_price[temp2] < lottery_price[temp2+1]) {
135 s_holder = lottery_source[temp2];
136 lottery_source[temp2] = lottery_source[temp2+1];
137 lottery_source[temp2+1] = s_holder;
138 u_holder = lottery_units[temp2];
139 lottery_units[temp2] = lottery_units[temp2+1];
140 lottery_units[temp2+1] = u_holder;
141 p_holder = lottery_price[temp2];
142 lottery_price[temp2] = lottery_price[temp2+1];
143 lottery_price[temp2+1] = p_holder;
144 }
145 }
146 }
147 }
148
149 // called regularly based on BID_INTERVAL and does the actual auction.
150 void
151 BidderHouse::sellBandwidth()
152 {
153 int totalDemand = 0;
154 int temp,x;
155 vector<Bidder*>::iterator e;
156 Bidder* source;
157
158 // increment the bandwidth pool only if it doesn't allready have too much saved up.
159 if (bytesToSend < (MAX_BW_SECONDS*bps)/8)
160 //increment the amount of bandwidth we have available
161 bytesToSend += (bps * BID_INTERVAL) / (1000 * 8);
162
163 // update the money for each bidder.
164 for (e = sources.begin(); e != sources.end(); e++) {
165 source = *e;
166 // insure that no one has too much money saved
167 if (source->money < MAX_SAVED_MONEY)
168 // pay everyone
169 source->money += (source->wage*WAGE_FACTOR);
170 // printf("source %d has %d money\n",(int)source, source->money);
171 // find how many total bytes we want to send
172 totalDemand += source->diffsWant * source->diffSize;
173 }
174
175 if ((totalDemand == 0) || (bytesToSend == 0)) {
176 // printf("not sending anything because no demand or no bw left\n");
177 return;
178 } else if (totalDemand > bytesToSend) {
179 // setup the arrays for doing the market
180 int num_of_sources = 0;
181 for (e = sources.begin(); e != sources.end(); e++,num_of_sources++) {
182 source = *e;
183 lottery_source[num_of_sources] = source;
184 lottery_units[num_of_sources] = source->diffsWant * source->diffSize;
185 if (lottery_units[num_of_sources] == 0)
186 lottery_price[num_of_sources] = 0;
187 else
188 lottery_price[num_of_sources] = source->money/lottery_units[num_of_sources];
189 //printf("source %d has %d money, %d units, %d diffs, and can pay %d\n",lottery_source[num_of_sources],source->money,lottery_units[num_of_sources],source->diffsWant,lottery_price[num_of_sources]);
190 }
191
192 // sort the array
193 lotterySort(num_of_sources);
194
195 // go up the array till you find the point at which you go over units
196 temp = 0;
197 for (x = 0; x < num_of_sources; x++) {
198 temp += lottery_units[x];
199 if (temp > bytesToSend)
200 break;
201 }
202
203 // pick the price right below that point.
204 if (x > 0) {
205 for (temp=0; temp<x; temp++) {
206 giveBWtoSource(lottery_source[temp], lottery_price[x-1]);
207 }
208 } else {
209 //printf("not enough bw. wants %d, but has %d\n\n", lottery_units[0],bytesToSend);
210 }
211 } else {
212 // give everyone what they want...
213 for (e = sources.begin(); e != sources.end(); e++) {
214 giveBWtoSource(*e, 1);
215 }
216 }
217 }
218
219 // forwards the bandwidth usage data to the GUI to be displayed.
220 void
221 BidderHouse::getBandwidthUsage()
222 {
223 for (vector<Bidder*>::iterator e = sources.begin();
224 e != sources.end(); e++) {
225 Bidder* source = *e;
226 int calculated_bps = (source->bandwidth * 1000)/UPDATE_INTERVAL;
227 source->bandwidth = 0;
228 source->msource->bandwidthUsage(calculated_bps/1000);
229 // Tcl::instance().evalf("puts \"set bandwidth to %d\"", source->bandwidth/1000);
230 }
231 }
232
233 // called from the UI to set a source's wage.
234 void
235 BidderHouse::setPriority(PipeRenderer* msource, int percentage)
236 {
237 lookupSource(msource)->wage = percentage;
238 }
239
240
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.