Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/network/TrafficControl.cc @ 2416

Last change on this file since 2416 was 2416, checked in by scheusso, 16 years ago

some improvement in diffing (after trimming the objectlist we sort the list after the datastream again)

File size: 15.4 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>, (C) 2008
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "TrafficControl.h"
30
31#include "synchronisable/Synchronisable.h"
32#include "core/ConfigValueIncludes.h"
33
34#include <cassert>
35#include <boost/bind.hpp>
36
37namespace orxonox {
38 
39  static const unsigned int SCHED_PRIORITY_OFFSET = -1;
40
41  objInfo::objInfo(uint32_t ID, uint32_t creatorID, int32_t curGsID, int32_t diffGsID, uint32_t size, unsigned int prioperm, unsigned int priosched)
42  { 
43    objID = ID; objCreatorID = creatorID; objCurGS = curGsID; objDiffGS = diffGsID; objSize = size; objValuePerm = prioperm; objValueSched = priosched; 
44  }
45 
46  objInfo::objInfo()
47  { 
48    objID = OBJECTID_UNKNOWN; objCreatorID = OBJECTID_UNKNOWN; objCurGS = GAMESTATEID_INITIAL; objDiffGS = objCurGS; objSize = 0; objValuePerm = 0; objValueSched = 0; 
49  }
50 
51 
52 
53  obj::obj()
54  { 
55    objID = OBJECTID_UNKNOWN; objCreatorID = OBJECTID_UNKNOWN; objSize = 0; objDataOffset = 0; 
56  }
57  obj::obj( uint32_t ID, uint32_t creatorID, uint32_t size, uint32_t offset )
58  {
59    objID = ID; objCreatorID = creatorID; objSize = size; objDataOffset = offset;
60  }
61 
62/**
63*Initializing protected members
64*/
65        TrafficControl *TrafficControl::instance_=0;
66       
67        /**
68        * @brief Constructor: assures that only one reference will be created and sets the pointer
69        */
70        TrafficControl::TrafficControl()
71        {
72    RegisterObject(TrafficControl);
73          assert(instance_==0);
74          instance_=this;
75    this->setConfigValues();
76        }
77       
78        /**
79        * @brief Destructor: resets the instance pointer to 0
80        */
81        TrafficControl::~TrafficControl()
82        {
83          instance_=0;
84        }
85
86/**
87*Definition of public members
88*/
89
90  void TrafficControl::setConfigValues()
91  {
92    SetConfigValue ( bActive_, true );
93    SetConfigValue ( targetSize, 5000 );
94  }
95
96  /**
97          *eigener sortieralgorithmus
98  */
99//   bool TrafficControl::priodiffer(obj i, obj j)
100//   {
101//     std::map<unsigned int, objInfo>::iterator iti;
102//     std::map<unsigned int, objInfo>::iterator itj;
103//     iti=listToProcess_.find(i.objID);
104//     itj=listToProcess_.find(j.objID);
105//     return iti->second.objValuePerm < itj->second.objValuePerm;
106//   }
107 
108  /**
109  * sort-algorithm for sorting the objectlist after priorities
110  */
111  bool TrafficControl::prioritySort(uint32_t clientID, obj i, obj j)
112  {
113    assert(clientListPerm_.find(clientID) != clientListPerm_.end());  //make sure the client exists in our list
114    assert(clientListPerm_[clientID].find(i.objID) != clientListPerm_[clientID].end()); // make sure the object i is in the client list
115    assert(clientListPerm_[clientID].find(j.objID) != clientListPerm_[clientID].end()); // make sure the object j is in the client list
116   
117    int prio1 = clientListPerm_[clientID][i.objID].objValuePerm + clientListPerm_[clientID][i.objID].objValueSched;
118    int prio2 = clientListPerm_[clientID][j.objID].objValuePerm + clientListPerm_[clientID][j.objID].objValueSched;
119    return prio1 < prio2;
120  }
121
122  /**
123  * sort-algorithm for sorting the objectList after position in original data stream
124  */
125  bool TrafficControl::dataSort(obj i, obj j)
126  {
127    int pos1 = i.objDataOffset;
128    int pos2 = j.objDataOffset;
129    return pos1 < pos2;
130  }
131
132 
133
134        void TrafficControl::processObjectList(unsigned int clientID, unsigned int gamestateID, std::list<obj> *list)
135        {
136//        copiedVector = *list;
137          currentClientID=clientID;
138          currentGamestateID=gamestateID;
139          evaluateList(clientID, list);
140          //list hatte vorher ja vielmehr elemente, nach zuweisung nicht mehr... speicherplatz??
141//        *list=copiedVector;
142    //später wird copiedVector ja überschrieben, ist das ein problem für list-dh. für gamestatemanager?
143          return;
144        }
145 
146  TrafficControl *TrafficControl::getInstance()
147  {
148    assert(instance_);
149    return instance_;
150  }
151       
152        void TrafficControl::ack(unsigned int clientID, unsigned int gamestateID)
153        {
154          std::list<obj>::iterator itvec;  // iterator to iterate through the acked objects
155   
156    //assertions to make sure the maps already exist
157    assert(clientListTemp_.find(clientID) != clientListTemp_.end() );
158    assert(clientListPerm_.find(clientID) != clientListPerm_.end() );
159          assert( clientListTemp_[clientID].find(gamestateID) != clientListTemp_[clientID].end() );
160   
161    for(itvec = clientListTemp_[clientID][gamestateID].begin(); itvec != clientListTemp_[clientID][gamestateID].end(); itvec++)
162          {
163      if(clientListPerm_[clientID].find((*itvec).objID) != clientListPerm_[clientID].end()) // check whether the obj already exists in our lists
164      {
165        clientListPerm_[clientID][(*itvec).objID].objCurGS = gamestateID;
166        clientListPerm_[clientID][(*itvec).objID].objValueSched = 0; //set scheduling value back
167      }
168      else
169      {
170        assert(0);
171        clientListPerm_[clientID][(*itvec).objID].objCurGS = gamestateID;
172        clientListPerm_[clientID][(*itvec).objID].objID = (*itvec).objID;
173        clientListPerm_[clientID][(*itvec).objID].objCreatorID = (*itvec).objCreatorID;
174        clientListPerm_[clientID][(*itvec).objID].objSize = (*itvec).objSize;
175      }
176          }
177           // remove temporary list (with acked objects) from the map
178    clientListTemp_[clientID].erase( clientListTemp_[clientID].find(gamestateID) );
179        }
180
181/**
182*Definition of private members
183*/
184       
185       
186        /**
187        *copyList gets list of Gamestate Manager and turns it to *listToProcess
188        */
189//      void TrafficControl::copyList(std::list<obj> *list)
190//      {
191//        std::list<obj>::iterator itvec;
192//        for(itvec = (*list).begin(); itvec != (*list).end(); itvec++)
193//        {
194//          objInfo objectA;
195//          objectA.objCreatorID=(*itvec).objCreatorID;
196//          objectA.objSize = (*itvec).objSize;
197//          listToProcess_.insert(std::pair<currentClientID, map<(*itvec).objID,objectA>>);//unsicher: ob map<...> so richtig ist
198//        }
199//      }
200        /**
201        *updateReferenceList compares the sent list by GSmanager with the current *reference list and updates it.
202        *returns void
203        */
204//      void TrafficControl::updateReferenceList(std::map<unsigned int, objInfo> *list)
205//      {
206//        std::map<unsigned int, Synchronisable*>::iterator itref;
207//        std::map<unsigned int, objInfo>::iterator itproc;
208//        for(itproc=listToProcess_.begin(); itproc != listToProcess_.end(); itproc++)
209//        {
210//          //itproc->first=objectid that is looked for
211//          if(referenceList_->find(itproc->first))
212//          {
213//            continue;
214//          }
215//          else
216//          {
217//            (*referenceList_).insert(pair<unsigned int,          Synchronisable*>((*itproc).first,Synchronisable::getSynchronisable((*itproc).first)));//important: how to get adress of an object!
218//            insertinClientListPerm(currentClientID,itproc->first,itproc->second);
219//          }
220//        }
221//      }
222        /**
223        *updateClientListPerm
224        *returns void
225        */
226        void TrafficControl::insertinClientListPerm(unsigned int clientID, obj objinf)
227        { 
228          std::map<unsigned int,std::map<unsigned int, objInfo> >::iterator itperm;//iterator clientListPerm over clientIDs
229//        itperm = (clientListPerm_).find(clientID);
230//        assert(itperm != clientListPerm_.end() );
231    unsigned int gsid=GAMESTATEID_INITIAL, gsdiff=currentGamestateID, prioperm=Synchronisable::getSynchronisable(objinf.objID)->getPriority(), priomom=0;
232    clientListPerm_[clientID][objinf.objID] = objInfo(objinf.objID, objinf.objCreatorID,gsid,gsdiff, objinf.objSize,prioperm,priomom);
233//        itperm->second.insert(std::pair<unsigned int, objInfo>(objid,objinf));
234//     permObjPrio_.insert(objid, objinf.objValuePerm);
235        }
236       
237  /**
238  * updateClientListTemp
239  * takes the shortened list which will be sent to the gsmanager and puts the *info into clientListTemp
240  */   
241  void TrafficControl::updateClientListTemp(std::list<obj> *list)
242  {
243    clientListTemp_[currentClientID][currentGamestateID] = std::list<obj>(*list);
244//     std::list<obj>::iterator itvec;
245//     std::map<unsigned int,std::map<unsigned int, obj> >::iterator ittemp;
246//     std::map<unsigned int, obj>::iterator ittempgs;
247//     ittemp = clientListTemp_.find(currentClientID);
248//     ittempgs = (*ittemp).find(currentGamestateID);
249//     for(itvec = list.begin(); itvec!=list.end(), itvec++)
250//     {
251//       ittempgs.insert(itvec);static
252//     }
253  }
254
255  /**
256  *cut
257  *takes the current list that has to be returned to the gsmanager and shortens it in criteria of bandwidth of clientID(XY)
258  */
259  void TrafficControl::cut(std::list<obj> *list, unsigned int targetsize)
260  {
261    unsigned int size=0;
262    std::list<obj>::iterator itvec, ittemp;
263    assert(!list->empty());
264    for(itvec = list->begin(); itvec != list->end();)
265    {
266      assert( (*itvec).objSize < 1000);
267      if ( ( size + (*itvec).objSize ) < targetsize )
268      {
269        size += (*itvec).objSize;//objSize is given in bytes
270        ++itvec;
271      }
272      else
273      {
274        clientListPerm_[currentClientID][(*itvec).objID].objValueSched += SCHED_PRIORITY_OFFSET; // NOTE: SCHED_PRIORITY_OFFSET is negative
275        list->erase(itvec++);
276      }
277//       printList(list, currentClientID);
278    }
279    assert(!list->empty());
280  }
281
282
283        /**
284        *evaluateList evaluates whether new obj are there, whether there are things to be updatet and manipulates all this.
285        */
286        void TrafficControl::evaluateList(unsigned int clientID, std::list<obj> *list)
287        {
288          //copyList(list);
289       
290          //now the sorting
291       
292          //compare listToProcess vs clientListPerm
293    //if listToProcess contains new Objects, add them to clientListPerm
294//        std::map<unsigned int, objInfo>::iterator itproc;
295    std::list<obj>::iterator itvec;
296//        std::map<unsigned int, std::map<unsigned int, objInfo> >::iterator itperm;
297//        std::map<unsigned int, objInfo>::iterator itpermobj;
298          for( itvec=list->begin(); itvec != list->end(); itvec++)
299          {
300//          itperm = clientListPerm_.find(clientID);
301            if ( clientListPerm_[clientID].find( (*itvec).objID) != clientListPerm_[clientID].end() )
302      {
303        // we already have the object in our map
304        //obj bleibt in liste und permanente prio wird berechnet
305        clientListPerm_[clientID][(*itvec).objID].objDiffGS = currentGamestateID - clientListPerm_[clientID][(*itvec).objID].objCurGS;
306//         ((*itpermobj).second).objDiffGS = ((*itpermobj).second).objCurGS - currentGamestateID;
307//         permprio = clientListPerm_[clientID][(*itproc).first].objValuePerm;
308//         itpermprio = (permObjPrio_).find((*itproc).first);
309//         ((*itpermobj).second).objValuePerm = ((*itpermobj).second).objDiffGS * (*itpermprio).second;
310        continue;//check next objId
311      }
312      else
313      {
314        // insert the object into clientListPerm
315        insertinClientListPerm(clientID,*itvec);
316//         itpermobj=(*itperm).find((*itproc).first)
317//         ((*itpermobj).second).objDiffGS = ((*itpermobj).second).objCurGS - currentGamestateID;
318//         itpermprio = (permObjPrio_).find((*itproc).first);
319//         ((*itpermobj).second).objValuePerm = ((*itpermobj).second).objDiffGS * (*itpermprio).second;
320        continue;//check next objId
321      }
322    }
323          //end compare listToProcess vs clientListPerm
324       
325    //listToProc vs clientListTemp
326    //TODO: uncomment it again and change some things
327    /*
328    std::map<unsigned int, std::map<unsigned int, unsigned int> >::iterator ittemp;
329    std::map<unsigned int, unsigned int>::iterator ittempgs;
330    for( itproc=listToProcess_.begin(); itproc != listToProcess_.end();itproc++)
331    {
332      ittemp = clientListTemp_->find(currentClientID);
333      if( ittempgs = (*ittemp).find(currentGamestateID))
334      {
335        if((*itproc).first == (*ittempgs).find((*itproc).first))//ja, dann ist objekt schon in der zu sendenden liste-muss nicht nochmal gesendet werden
336        {
337          (listToProcess_).erase (itproc);
338        }
339        else
340          continue;
341      }
342      else
343        continue;
344    }*/
345    //end listToProc vs clientListTemp
346   
347    //TODO: check whether we need this, cause i don't think so.
348    //listToProcess contains obj to send now, and since we give gsmanager the copiedlist and not listToProcess shorten copiedlist therefor too.
349    /*std::list<obj>::iterator itvec;
350    for(itvec = copiedVector.begin(); itvec != copiedVector.end(); itvec++)
351    {
352      if ( listToProcess_.find(itvec->objID) )
353      {
354        continue;//therefore object wasnt thrown out yet and has to be sent back to gsmanager
355      }
356      else
357      {
358        copiedVector.remove(itvec);
359      }
360    }*/
361    //sort copied list aufgrund der objprioperm in clientlistperm
362    // use boost bind here because we need to pass a memberfunction to stl sort
363    list->sort(boost::bind(&TrafficControl::prioritySort, this, clientID, _1, _2) );
364   
365    //now we check, that the creator of an object always exists on a client
366//     printList(list, clientID);
367    std::list<obj>::iterator itcreator;
368    for(itvec = list->begin(); itvec != list->end(); itvec++)
369    { 
370      fixCreatorDependencies(itvec, list, clientID);
371    }
372    //end of sorting
373    //now the cutting, work the same obj out in processobjectlist and copiedlist, compression rate muss noch festgelegt werden.
374    cut(list, targetSize);
375   
376    //now sort again after objDataOffset
377    list->sort(boost::bind(&TrafficControl::dataSort, this, _1, _2) );
378//     printList(list, clientID);
379    //diese Funktion updateClientList muss noch gemacht werden
380    updateClientListTemp(list);
381    //end of sorting
382  }
383
384  void TrafficControl::printList(std::list<obj> *list, unsigned int clientID)
385  {
386    std::list<obj>::iterator it;
387    COUT(0) << "=========== Objectlist ===========" << endl;
388    for( it=list->begin(); it!=list->end(); it++)
389      COUT(0) << "ObjectID: " << (*it).objID << " creatorID: " << (*it).objCreatorID << " Priority: " << clientListPerm_[clientID][(*it).objID].objValuePerm + clientListPerm_[clientID][(*it).objID].objValueSched << " size: " << (*it).objSize << endl;
390  }
391 
392  void TrafficControl::fixCreatorDependencies(std::list<obj>::iterator it1, std::list<obj> *list, unsigned int clientID)
393  {
394    if ( (*it1).objCreatorID == OBJECTID_UNKNOWN )
395      return;
396    if( clientListPerm_[clientID][(*it1).objCreatorID].objCurGS != GAMESTATEID_INITIAL )
397      return;
398    std::list<obj>::iterator it2, it3=it1;
399    for( it2 = ++it3; it2 != list->end(); it2++ )
400    {
401      if( (*it2).objID == (*it1).objCreatorID )
402      {
403        it3 = list->insert(it1, *it2); //insert creator before it1
404        list->erase(it2);
405//         printList(list, clientID);
406        fixCreatorDependencies( it3, list, clientID );
407        break;
408      }
409    }
410  }
411 
412  void TrafficControl::clientDisconnected(unsigned int clientID)
413  {
414    assert(clientListTemp_.find(clientID) != clientListTemp_.end() );
415    assert(clientListPerm_.find(clientID) != clientListPerm_.end() );
416    clientListTemp_.erase(clientListTemp_.find(clientID));
417    clientListPerm_.erase(clientListPerm_.find(clientID));
418  }
419
420/*
421void bvlabla(list *a){
422//sort a
423list *cache;
424cache = new list<unsigned int>(*a);
425return a;
426}
427*/
428
429
430}//namespace network
Note: See TracBrowser for help on using the repository browser.