Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9215 was 8858, checked in by landauf, 13 years ago

merged output branch back to trunk.

Changes:

  • you have to include util/Output.h instead of util/Debug.h
  • COUT(x) is now called orxout(level)
  • output levels are now defined by an enum instead of numbers. see util/Output.h for the definition
  • it's possible to use output contexts with orxout(level, context). see util/Output.h for some common contexts. you can define more contexts
  • you must use 'endl' at the end of an output message, '\n' does not flush the message

Output levels:

  • instead of COUT(0) use orxout()
  • instead of COUT(1) use orxout(user_error) or orxout(internal_error)
  • instead of COUT(2) use orxout(user_warning) or orxout(internal_warning)
  • instead of COUT(3) use orxout(user_status/user_info) or orxout(internal_status/internal_info)
  • instead of COUT(4) use orxout(verbose)
  • instead of COUT(5) use orxout(verbose_more)
  • instead of COUT(6) use orxout(verbose_ultra)

Guidelines:

  • user_* levels are for the user, visible in the console and the log-file
  • internal_* levels are for developers, visible in the log-file
  • verbose_* levels are for debugging, only visible if the context of the output is activated

Usage in C++:

  • orxout() << "message" << endl;
  • orxout(level) << "message" << endl;
  • orxout(level, context) << "message" << endl;

Usage in Lua:

  • orxout("message")
  • orxout(orxonox.level.levelname, "message")
  • orxout(orxonox.level.levelname, "context", "message")

Usage in Tcl (and in the in-game-console):

  • orxout levelname message
  • orxout_context levelname context message
  • shortcuts: log message, error message, warning message, status message, info message, debug message
  • Property svn:eol-style set to native
File size: 11.1 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>
32#include <boost/bind.hpp>
33
[2896]34#include "core/CoreIncludes.h"
[2382]35#include "core/ConfigValueIncludes.h"
[3214]36#include "synchronisable/Synchronisable.h"
[2355]37
38namespace orxonox {
39
[3301]40  static const unsigned int SCHED_PRIORITY_OFFSET = static_cast<unsigned int>(-1);
[2485]41
[2355]42  objInfo::objInfo(uint32_t ID, uint32_t creatorID, int32_t curGsID, int32_t diffGsID, uint32_t size, unsigned int prioperm, unsigned int priosched)
[2485]43  {
44    objID = ID; objCreatorID = creatorID; objCurGS = curGsID; objDiffGS = diffGsID; objSize = size; objValuePerm = prioperm; objValueSched = priosched;
[2355]45  }
[2485]46
[2355]47  objInfo::objInfo()
[2485]48  {
49    objID = OBJECTID_UNKNOWN; objCreatorID = OBJECTID_UNKNOWN; objCurGS = GAMESTATEID_INITIAL; objDiffGS = objCurGS; objSize = 0; objValuePerm = 0; objValueSched = 0;
[2355]50  }
[2485]51
52
53
[2355]54  obj::obj()
[2485]55  {
56    objID = OBJECTID_UNKNOWN; objCreatorID = OBJECTID_UNKNOWN; objSize = 0; objDataOffset = 0;
[2355]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  }
[2485]62
[2355]63/**
64*Initializing protected members
65*/
[6073]66    TrafficControl *TrafficControl::instance_=0;
[2485]67
[6073]68    /**
69    * @brief Constructor: assures that only one reference will be created and sets the pointer
70    */
71    TrafficControl::TrafficControl()
72    {
[2413]73    RegisterObject(TrafficControl);
[6073]74      assert(instance_==0);
75      instance_=this;
[2413]76    this->setConfigValues();
[6073]77    }
[2485]78
[6073]79    /**
80    * @brief Destructor: resets the instance pointer to 0
81    */
82    TrafficControl::~TrafficControl()
83    {
84      instance_=0;
85    }
[2355]86
87/**
88*Definition of public members
89*/
90
[2413]91  void TrafficControl::setConfigValues()
92  {
[3084]93    SetConfigValue ( bActive_, false );
94    SetConfigValue ( targetSize, 10000 );
[2413]95  }
[2485]96
[2355]97  /**
[2416]98  * sort-algorithm for sorting the objectlist after priorities
[2355]99  */
[2416]100  bool TrafficControl::prioritySort(uint32_t clientID, obj i, obj j)
[2355]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
[2485]105
[2355]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
[2416]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  }
[2355]120
[2416]121
[2485]122
[6073]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    }
[2485]130
[2382]131  TrafficControl *TrafficControl::getInstance()
132  {
133    assert(instance_);
134    return instance_;
135  }
[2485]136
[6073]137    void TrafficControl::ack(unsigned int clientID, unsigned int gamestateID)
138    {
[3198]139    if ( !this->bActive_ )
140      return;
[6073]141      std::list<obj>::iterator itvec;  // iterator to iterate through the acked objects
[2485]142
[2355]143    //assertions to make sure the maps already exist
144    assert(clientListTemp_.find(clientID) != clientListTemp_.end() );
145    assert(clientListPerm_.find(clientID) != clientListPerm_.end() );
[3084]146    assert( clientListTemp_[clientID].find(gamestateID) != clientListTemp_[clientID].end() );
[6417]147
[3084]148    // shortcut for maps
149    std::map<unsigned int, objInfo >& objectListPerm = clientListPerm_[clientID];
150    std::map<unsigned int, std::list<obj> >& objectListTemp = clientListTemp_[clientID];
[2485]151
[3084]152    for(itvec = objectListTemp[gamestateID].begin(); itvec != objectListTemp[gamestateID].end(); itvec++)
[6073]153      {
[6417]154      if(objectListPerm.find(itvec->objID) != objectListPerm.end()) // check whether the obj already exists in our lists
[2355]155      {
[6417]156        objectListPerm[itvec->objID].objCurGS = gamestateID;
157        objectListPerm[itvec->objID].objValueSched = 0; //set scheduling value back
[2355]158      }
159      else
160      {
[2381]161        assert(0);
[6417]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;
[2355]166      }
[6073]167      }
168       // remove temporary list (with acked objects) from the map
[3084]169    objectListTemp.erase( objectListTemp.find(gamestateID) );
[6073]170    }
[2355]171
172/**
173*Definition of private members
174*/
[2418]175
[6073]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
[2355]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);
[6073]185    }
[2485]186
[2355]187  /**
188  * updateClientListTemp
189  * takes the shortened list which will be sent to the gsmanager and puts the *info into clientListTemp
[2485]190  */
[3084]191  void TrafficControl::updateClientListTemp(std::list<obj>& list)
[2355]192  {
[3198]193    clientListTemp_[currentClientID][currentGamestateID] = list;
[2355]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  */
[3084]200  void TrafficControl::cut(std::list<obj>& list, unsigned int targetsize)
[2355]201  {
202    unsigned int size=0;
[2381]203    std::list<obj>::iterator itvec, ittemp;
[3084]204    assert(!list.empty());
205    for(itvec = list.begin(); itvec != list.end();)
[2355]206    {
[6417]207      assert( itvec->objSize < 1000);
208      if ( ( size + itvec->objSize ) < targetsize )
[2355]209      {
[6417]210        size += itvec->objSize;//objSize is given in bytes
[2381]211        ++itvec;
[2355]212      }
213      else
214      {
[6417]215        clientListPerm_[currentClientID][itvec->objID].objValueSched += SCHED_PRIORITY_OFFSET; // NOTE: SCHED_PRIORITY_OFFSET is negative
[3084]216        list.erase(itvec, list.end());
217        break;
[2355]218      }
[2381]219//       printList(list, currentClientID);
[2355]220    }
[3084]221    assert(!list.empty());
[2355]222  }
223
224
[6073]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    {
[2485]230
[3198]231    if( bActive_ )
232    {
233      //now the sorting
[2485]234
[3198]235      //compare listToProcess vs clientListPerm
236      //if listToProcess contains new Objects, add them to clientListPerm
237      std::list<obj>::iterator itvec;
[6417]238
[3198]239      std::map<unsigned int, objInfo >& objectListPerm = clientListPerm_[clientID];
[6417]240
[3198]241      for( itvec=list.begin(); itvec != list.end(); itvec++)
[2355]242      {
[6417]243        if ( objectListPerm.find( itvec->objID) != objectListPerm.end() )
[3198]244        {
[2355]245        // we already have the object in our map
246        //obj bleibt in liste und permanente prio wird berechnet
[6417]247          objectListPerm[itvec->objID].objDiffGS = currentGamestateID - objectListPerm[itvec->objID].objCurGS;
[3198]248          continue;//check next objId
249        }
250        else
251        {
[2355]252        // insert the object into clientListPerm
[3198]253          insertinClientListPerm(clientID,*itvec);
254          continue;//check next objId
255        }
[2355]256      }
[3198]257    //end compare listToProcess vs clientListPerm
[6417]258
[2418]259      //sort copied list according to priorities
260      // use boost bind here because we need to pass a memberfunction to stl sort
[3084]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) );
[6417]263
[3084]264//       list.sort(boost::bind(&TrafficControl::prioritySort, this, clientID, _1, _2) );
[2485]265
[2418]266      //now we check, that the creator of an object always exists on a client
267      std::list<obj>::iterator itcreator;
[3084]268      for(itvec = list.begin(); itvec != list.end(); itvec++)
[2485]269      {
[2418]270        fixCreatorDependencies(itvec, list, clientID);
[2355]271      }
[2418]272      //end of sorting
[2485]273      //now the cutting, work the same obj out in processobjectlist and copiedlist, compression rate muss noch festgelegt werden.
[2419]274//       printList(list, clientID);
[2418]275      cut(list, targetSize);
276      //now sort again after objDataOffset
[3084]277//       sort(list.begin(), list.end(), boost::bind(&TrafficControl::dataSort, this, _1, _2) );
278      list.sort( boost::bind(&TrafficControl::dataSort, this, _1, _2) );
[6417]279
[3198]280      //diese Funktion updateClientList muss noch gemacht werden
281      updateClientListTemp(list);
282      //end of sorting
[2355]283    }
284  }
285
[3084]286  void TrafficControl::printList(std::list<obj>& list, unsigned int clientID)
[2355]287  {
288    std::list<obj>::iterator it;
[8858]289    orxout(debug_output, context::network) << "=========== Objectlist ===========" << endl;
[3084]290    for( it=list.begin(); it!=list.end(); it++)
[8858]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;
[2355]292  }
[2485]293
[3084]294  void TrafficControl::fixCreatorDependencies(std::list<obj>::iterator it1, std::list<obj>& list, unsigned int clientID)
[2355]295  {
[6417]296    if ( it1->objCreatorID == OBJECTID_UNKNOWN )
[2355]297      return;
[6417]298    if( clientListPerm_[clientID][it1->objCreatorID].objCurGS != GAMESTATEID_INITIAL )
[2355]299      return;
300    std::list<obj>::iterator it2, it3=it1;
[3084]301    for( it2 = ++it3; it2 != list.end(); it2++ )
[2355]302    {
[6417]303      if( it2->objID == it1->objCreatorID )
[2355]304      {
[3084]305        it3 = list.insert(it1, *it2); //insert creator before it1
306        list.erase(it2);
[2355]307//         printList(list, clientID);
308        fixCreatorDependencies( it3, list, clientID );
309        break;
310      }
311    }
312  }
[2485]313
[2413]314  void TrafficControl::clientDisconnected(unsigned int clientID)
[2387]315  {
[3312]316    if( clientListPerm_.find(clientID) == clientListPerm_.end() )
317    {
318      assert(!this->bActive_);
319      return;
320    }
[2387]321    clientListTemp_.erase(clientListTemp_.find(clientID));
[3312]322    if( clientListTemp_.find(clientID) != clientListTemp_.end() )
323      clientListPerm_.erase(clientListPerm_.find(clientID));
[2387]324  }
[2355]325
326
327}//namespace network
Note: See TracBrowser for help on using the repository browser.