Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/network/TrafficControl.cc @ 11948

Last change on this file since 11948 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

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