Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/output/src/libraries/network/TrafficControl.cc @ 8991

Last change on this file since 8991 was 8807, checked in by landauf, 13 years ago

Replaced COUT with orxout in network library. Tried to set levels and contexts in a more or less useful way, but not really optimized. Used contexts network, packets, and master_server.
Please use endl instead of \n in the future (@smerkli) ;)

  • Property svn:eol-style set to native
File size: 11.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Oliver Scheuss <scheusso [at] ee.ethz.ch>
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "TrafficControl.h"
30
31#include <cassert>
32#include <boost/bind.hpp>
33
34#include "core/CoreIncludes.h"
35#include "core/ConfigValueIncludes.h"
36#include "synchronisable/Synchronisable.h"
37
38namespace orxonox {
39
40  static const unsigned int SCHED_PRIORITY_OFFSET = static_cast<unsigned int>(-1);
41
42  objInfo::objInfo(uint32_t ID, uint32_t creatorID, int32_t curGsID, int32_t diffGsID, uint32_t size, unsigned int prioperm, unsigned int priosched)
43  {
44    objID = ID; objCreatorID = creatorID; objCurGS = curGsID; objDiffGS = diffGsID; objSize = size; objValuePerm = prioperm; objValueSched = priosched;
45  }
46
47  objInfo::objInfo()
48  {
49    objID = OBJECTID_UNKNOWN; objCreatorID = OBJECTID_UNKNOWN; objCurGS = GAMESTATEID_INITIAL; objDiffGS = objCurGS; objSize = 0; objValuePerm = 0; objValueSched = 0;
50  }
51
52
53
54  obj::obj()
55  {
56    objID = OBJECTID_UNKNOWN; objCreatorID = OBJECTID_UNKNOWN; objSize = 0; objDataOffset = 0;
57  }
58  obj::obj( uint32_t ID, uint32_t creatorID, uint32_t size, uint32_t offset )
59  {
60    objID = ID; objCreatorID = creatorID; objSize = size; objDataOffset = offset;
61  }
62
63/**
64*Initializing protected members
65*/
66    TrafficControl *TrafficControl::instance_=0;
67
68    /**
69    * @brief Constructor: assures that only one reference will be created and sets the pointer
70    */
71    TrafficControl::TrafficControl()
72    {
73    RegisterObject(TrafficControl);
74      assert(instance_==0);
75      instance_=this;
76    this->setConfigValues();
77    }
78
79    /**
80    * @brief Destructor: resets the instance pointer to 0
81    */
82    TrafficControl::~TrafficControl()
83    {
84      instance_=0;
85    }
86
87/**
88*Definition of public members
89*/
90
91  void TrafficControl::setConfigValues()
92  {
93    SetConfigValue ( bActive_, false );
94    SetConfigValue ( targetSize, 10000 );
95  }
96
97  /**
98  * sort-algorithm for sorting the objectlist after priorities
99  */
100  bool TrafficControl::prioritySort(uint32_t clientID, obj i, obj j)
101  {
102    assert(clientListPerm_.find(clientID) != clientListPerm_.end());  //make sure the client exists in our list
103    assert(clientListPerm_[clientID].find(i.objID) != clientListPerm_[clientID].end()); // make sure the object i is in the client list
104    assert(clientListPerm_[clientID].find(j.objID) != clientListPerm_[clientID].end()); // make sure the object j is in the client list
105
106    int prio1 = clientListPerm_[clientID][i.objID].objValuePerm + clientListPerm_[clientID][i.objID].objValueSched;
107    int prio2 = clientListPerm_[clientID][j.objID].objValuePerm + clientListPerm_[clientID][j.objID].objValueSched;
108    return prio1 < prio2;
109  }
110
111  /**
112  * sort-algorithm for sorting the objectList after position in original data stream
113  */
114  bool TrafficControl::dataSort(obj i, obj j)
115  {
116    int pos1 = i.objDataOffset;
117    int pos2 = j.objDataOffset;
118    return pos1 < pos2;
119  }
120
121
122
123    void TrafficControl::processObjectList(unsigned int clientID, unsigned int gamestateID, std::list<obj>& list)
124    {
125      currentClientID=clientID;
126      currentGamestateID=gamestateID;
127      evaluateList(clientID, list);
128      return;
129    }
130
131  TrafficControl *TrafficControl::getInstance()
132  {
133    assert(instance_);
134    return instance_;
135  }
136
137    void TrafficControl::ack(unsigned int clientID, unsigned int gamestateID)
138    {
139    if ( !this->bActive_ )
140      return;
141      std::list<obj>::iterator itvec;  // iterator to iterate through the acked objects
142
143    //assertions to make sure the maps already exist
144    assert(clientListTemp_.find(clientID) != clientListTemp_.end() );
145    assert(clientListPerm_.find(clientID) != clientListPerm_.end() );
146    assert( clientListTemp_[clientID].find(gamestateID) != clientListTemp_[clientID].end() );
147
148    // shortcut for maps
149    std::map<unsigned int, objInfo >& objectListPerm = clientListPerm_[clientID];
150    std::map<unsigned int, std::list<obj> >& objectListTemp = clientListTemp_[clientID];
151
152    for(itvec = objectListTemp[gamestateID].begin(); itvec != objectListTemp[gamestateID].end(); itvec++)
153      {
154      if(objectListPerm.find(itvec->objID) != objectListPerm.end()) // check whether the obj already exists in our lists
155      {
156        objectListPerm[itvec->objID].objCurGS = gamestateID;
157        objectListPerm[itvec->objID].objValueSched = 0; //set scheduling value back
158      }
159      else
160      {
161        assert(0);
162        objectListPerm[itvec->objID].objCurGS = gamestateID;
163        objectListPerm[itvec->objID].objID = itvec->objID;
164        objectListPerm[itvec->objID].objCreatorID = itvec->objCreatorID;
165        objectListPerm[itvec->objID].objSize = itvec->objSize;
166      }
167      }
168       // remove temporary list (with acked objects) from the map
169    objectListTemp.erase( objectListTemp.find(gamestateID) );
170    }
171
172/**
173*Definition of private members
174*/
175
176    /**
177    *updateClientListPerm
178    *returns void
179    */
180    void TrafficControl::insertinClientListPerm(unsigned int clientID, obj objinf)
181    {
182      std::map<unsigned int,std::map<unsigned int, objInfo> >::iterator itperm;//iterator clientListPerm over clientIDs
183    unsigned int gsid=GAMESTATEID_INITIAL, gsdiff=currentGamestateID, prioperm=Synchronisable::getSynchronisable(objinf.objID)->getPriority(), priomom=0;
184    clientListPerm_[clientID][objinf.objID] = objInfo(objinf.objID, objinf.objCreatorID,gsid,gsdiff, objinf.objSize,prioperm,priomom);
185    }
186
187  /**
188  * updateClientListTemp
189  * takes the shortened list which will be sent to the gsmanager and puts the *info into clientListTemp
190  */
191  void TrafficControl::updateClientListTemp(std::list<obj>& list)
192  {
193    clientListTemp_[currentClientID][currentGamestateID] = list;
194  }
195
196  /**
197  *cut
198  *takes the current list that has to be returned to the gsmanager and shortens it in criteria of bandwidth of clientID(XY)
199  */
200  void TrafficControl::cut(std::list<obj>& list, unsigned int targetsize)
201  {
202    unsigned int size=0;
203    std::list<obj>::iterator itvec, ittemp;
204    assert(!list.empty());
205    for(itvec = list.begin(); itvec != list.end();)
206    {
207      assert( itvec->objSize < 1000);
208      if ( ( size + itvec->objSize ) < targetsize )
209      {
210        size += itvec->objSize;//objSize is given in bytes
211        ++itvec;
212      }
213      else
214      {
215        clientListPerm_[currentClientID][itvec->objID].objValueSched += SCHED_PRIORITY_OFFSET; // NOTE: SCHED_PRIORITY_OFFSET is negative
216        list.erase(itvec, list.end());
217        break;
218      }
219//       printList(list, currentClientID);
220    }
221    assert(!list.empty());
222  }
223
224
225    /**
226    *evaluateList evaluates whether new obj are there, whether there are things to be updatet and manipulates all this.
227    */
228    void TrafficControl::evaluateList(unsigned int clientID, std::list<obj>& list)
229    {
230
231    if( bActive_ )
232    {
233      //now the sorting
234
235      //compare listToProcess vs clientListPerm
236      //if listToProcess contains new Objects, add them to clientListPerm
237      std::list<obj>::iterator itvec;
238
239      std::map<unsigned int, objInfo >& objectListPerm = clientListPerm_[clientID];
240
241      for( itvec=list.begin(); itvec != list.end(); itvec++)
242      {
243        if ( objectListPerm.find( itvec->objID) != objectListPerm.end() )
244        {
245        // we already have the object in our map
246        //obj bleibt in liste und permanente prio wird berechnet
247          objectListPerm[itvec->objID].objDiffGS = currentGamestateID - objectListPerm[itvec->objID].objCurGS;
248          continue;//check next objId
249        }
250        else
251        {
252        // insert the object into clientListPerm
253          insertinClientListPerm(clientID,*itvec);
254          continue;//check next objId
255        }
256      }
257    //end compare listToProcess vs clientListPerm
258
259      //sort copied list according to priorities
260      // use boost bind here because we need to pass a memberfunction to stl sort
261//       sort( list.begin(), list.end(), boost::bind(&TrafficControl::prioritySort, this, clientID, _1, _2) );
262      list.sort( boost::bind(&TrafficControl::prioritySort, this, clientID, _1, _2) );
263
264//       list.sort(boost::bind(&TrafficControl::prioritySort, this, clientID, _1, _2) );
265
266      //now we check, that the creator of an object always exists on a client
267      std::list<obj>::iterator itcreator;
268      for(itvec = list.begin(); itvec != list.end(); itvec++)
269      {
270        fixCreatorDependencies(itvec, list, clientID);
271      }
272      //end of sorting
273      //now the cutting, work the same obj out in processobjectlist and copiedlist, compression rate muss noch festgelegt werden.
274//       printList(list, clientID);
275      cut(list, targetSize);
276      //now sort again after objDataOffset
277//       sort(list.begin(), list.end(), boost::bind(&TrafficControl::dataSort, this, _1, _2) );
278      list.sort( boost::bind(&TrafficControl::dataSort, this, _1, _2) );
279
280      //diese Funktion updateClientList muss noch gemacht werden
281      updateClientListTemp(list);
282      //end of sorting
283    }
284  }
285
286  void TrafficControl::printList(std::list<obj>& list, unsigned int clientID)
287  {
288    std::list<obj>::iterator it;
289    orxout(debug_output, context::network) << "=========== Objectlist ===========" << endl;
290    for( it=list.begin(); it!=list.end(); it++)
291      orxout(debug_output, context::network) << "ObjectID: " << it->objID << " creatorID: " << it->objCreatorID << " Priority: " << clientListPerm_[clientID][it->objID].objValuePerm + clientListPerm_[clientID][it->objID].objValueSched << " size: " << it->objSize << endl;
292  }
293
294  void TrafficControl::fixCreatorDependencies(std::list<obj>::iterator it1, std::list<obj>& list, unsigned int clientID)
295  {
296    if ( it1->objCreatorID == OBJECTID_UNKNOWN )
297      return;
298    if( clientListPerm_[clientID][it1->objCreatorID].objCurGS != GAMESTATEID_INITIAL )
299      return;
300    std::list<obj>::iterator it2, it3=it1;
301    for( it2 = ++it3; it2 != list.end(); it2++ )
302    {
303      if( it2->objID == it1->objCreatorID )
304      {
305        it3 = list.insert(it1, *it2); //insert creator before it1
306        list.erase(it2);
307//         printList(list, clientID);
308        fixCreatorDependencies( it3, list, clientID );
309        break;
310      }
311    }
312  }
313
314  void TrafficControl::clientDisconnected(unsigned int clientID)
315  {
316    if( clientListPerm_.find(clientID) == clientListPerm_.end() )
317    {
318      assert(!this->bActive_);
319      return;
320    }
321    clientListTemp_.erase(clientListTemp_.find(clientID));
322    if( clientListTemp_.find(clientID) != clientListTemp_.end() )
323      clientListPerm_.erase(clientListPerm_.find(clientID));
324  }
325
326
327}//namespace network
Note: See TracBrowser for help on using the repository browser.