Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

trafficControl working now, but further tweaking in diff and priorities is needed

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