Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 7954 in orxonox.OLD for trunk/src/lib/network/synchronizeable.cc


Ignore:
Timestamp:
May 29, 2006, 3:28:41 PM (18 years ago)
Author:
patrick
Message:

trunk: merged the network branche back to trunk.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/network/synchronizeable.cc

    r6753 r7954  
    2020#include "network_stream.h"
    2121#include "netdefs.h"
     22#include "network_log.h"
    2223
    2324#include "state.h"
     
    3637  this->setClassID(CL_SYNCHRONIZEABLE, "Synchronizeable");
    3738  this->owner = -1;
    38   this->state = 0;
    3939  this->hostID = SharedNetworkData::getInstance()->getHostID();
    4040  this->setIsServer(this->hostID == 0);
    4141  this->uniqueID = NET_UID_UNASSIGNED;
    4242  this->networkStream = NULL;
    43   this->setRequestedSync( false );
    44   this->setIsOutOfSync( !(this->isServer()) );
    4543  this->bSynchronize = false;
    46 
     44 
    4745  if( State::isOnline())
    4846  {
     
    5250    this->setUniqueID(SharedNetworkData::getInstance()->getNewUniqueID());
    5351  }
     52
     53  /* make sure loadClassId is first synced var because this is read by networkStream */
     54  assert( syncVarList.size() == 0 );
     55  mLeafClassId = this->registerVarId( new SynchronizeableInt( (int*)&this->getLeafClassID(), (int*)&this->getLeafClassID(), "leafClassId" ) );
     56   
     57  this->registerVar( new SynchronizeableInt( &this->owner, &this->owner, "owner" ) );
     58  this->registerVar( new SynchronizeableString( &this->objectName, &this->objectName, "objectName" ) );
    5459}
    5560
     
    6469    this->networkStream->disconnectSynchronizeable(*this);
    6570}
    66 
    67 
    68 /**
    69  *  write data to NetworkStream
    70  */
    71 int Synchronizeable::writeBytes(const byte* data, int length, int sender)
    72 {
    73   PRINTF(5)("Synchronizeable::writeBytes was called\n");
    74 }
    75 
    76 
    77 /**
    78  *  read data from NetworkStream
    79  */
    80 int Synchronizeable::readBytes(byte* data, int maxLength, int * reciever)
    81 {
    82   PRINTF(5)("Synchronizeable::readBytes was called\n");
    83 }
    84 
    85 
    86 void Synchronizeable::writeDebug() const
    87 {}
    88 
    89 
    90 void Synchronizeable::readDebug() const
    91 {}
    92 
    9371
    9472/**
     
    10684
    10785/**
    108  * Sets the outofsync flag to a given value
    109  * @param outOfSync: the boolean value which the outofsync flag is to set to
    110  */
    111 void Synchronizeable::setIsOutOfSync(bool outOfSync)
    112 {
    113   if( outOfSync )
    114     this->state = this->state | STATE_OUTOFSYNC;
    115   else
    116     this->state = this->state & (~STATE_OUTOFSYNC);
    117   //PRINTF(0)("isoutofsync %s %d\n", this->getClassName(), state);
    118 }
    119 
    120 
    121 /**
    12286 * Determines if the server flag is set
    12387 * @return true, if the server flag is true, false else
     
    12993
    13094
    131 /**
    132  * Determines if the outofsync flag is set
    133  * @return true, if the outofsync flag is true, false else
    134  */
    135 bool Synchronizeable::isOutOfSync()
    136 {
    137   return (this->state & STATE_OUTOFSYNC) >0;
    138 }
    139 
    140 
    141 /**
    142  * Determines if the requestedSync flag is set
    143  * @return true, if the requestedSync flag is true, false else
    144  */
    145 bool Synchronizeable::requestedSync()
    146 {
    147   return (this->state & STATE_REQUESTEDSYNC) >0;
    148 }
    149 
    150 
    151 /**
    152  * Sets the requestedsync flag to a given value
    153  * @param requestedSync: the boolean value which the requestedsync flag is to set to
    154  */
    155 void Synchronizeable::setRequestedSync( bool requestedSync )
    156 {
    157   if( requestedSync )
    158     this->state = this->state | STATE_REQUESTEDSYNC;
     95
     96int Synchronizeable::getStateDiff( int userId, byte* data, int maxLength, int stateId, int fromStateId, int priorityTH )
     97{
     98  //make sure this user has his history
     99  if ( sentStates.size() <= userId )
     100    sentStates.resize( userId+1 );
     101
     102  //calculate needed memory
     103  int neededSize = 0;
     104
     105  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
     106    neededSize += (*it)->getSize();
     107
     108  if ( !( neededSize <= maxLength ) )
     109  {
     110    PRINTF(0)( "%d > %d\n", neededSize, maxLength );
     111    assert(false);
     112  }
     113
     114  //remove older states from history than fromStateId
     115  StateHistory::iterator it = sentStates[userId].begin();
     116
     117  while ( it != sentStates[userId].end() && (*it)->stateId < fromStateId )
     118    it++;
     119
     120  if ( it != sentStates[userId].begin() )
     121  {
     122    for ( StateHistory::iterator it2 = sentStates[userId].begin(); it2 != it; it2++ )
     123    {
     124      if ( (*it2)->data != NULL )
     125      {
     126        delete [] (*it2)->data;
     127        (*it2)->data = NULL;
     128      }
     129    }
     130    sentStates[userId].erase( sentStates[userId].begin(), it );
     131  }
     132
     133  //find state to create diff from
     134  StateHistoryEntry * stateFrom = NULL;
     135
     136  it = sentStates[userId].begin();
     137  while ( it != sentStates[userId].end() && (*it)->stateId != fromStateId )
     138    it++;
     139 
     140//  if ( getLeafClassID() == CL_SPACE_SHIP )
     141//  {
     142//    PRINTF(0)("getStateDiff:SpaceShip from: %d stateId: %d\n", (it == sentStates[userId].end())?-1:fromStateId, stateId);
     143//  }
     144
     145  if ( it == sentStates[userId].end() )
     146  {
     147    StateHistoryEntry * initialEntry = new StateHistoryEntry();
     148
     149    initialEntry->stateId = fromStateId;
     150    initialEntry->dataLength = 0;
     151    initialEntry->data = NULL;
     152
     153    stateFrom = initialEntry;
     154  }
    159155  else
    160     this->state = this->state & (~STATE_REQUESTEDSYNC);
    161 }
    162 
    163 
    164 
     156    stateFrom = (*it);
     157
     158  StateHistoryEntry * stateTo = new StateHistoryEntry();
     159
     160  stateTo->stateId = stateId;
     161  stateTo->dataLength = neededSize;
     162  stateTo->data = new byte[ neededSize ];
     163
     164  std::list<int>::iterator sizeIter = stateFrom->sizeList.begin();
     165
     166  int i = 0;
     167  int n;
     168 
     169  bool hasPermission;
     170
     171  // now do the actual synchronization: kick all variables to write into a common buffer
     172  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
     173  {
     174    hasPermission = (
     175            this->isServer() && (*it)->checkPermission( PERMISSION_SERVER ) ||
     176            this->owner == this->hostID && (*it)->checkPermission( PERMISSION_OWNER ) ||
     177            (*it)->checkPermission( PERMISSION_ALL )
     178                    );
     179   
     180    if ( ( hasPermission && (*it)->getPriority() >= priorityTH ) || sizeIter == stateFrom->sizeList.end() )
     181    {
     182      n = (*it)->writeToBuf( stateTo->data+i, stateTo->dataLength - i );
     183      //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), n);
     184      stateTo->sizeList.push_back( n );
     185      //(*it)->debug();
     186      i += n;
     187    }
     188    else
     189    {
     190      for ( int j = 0; j<(*sizeIter); j++ )
     191      {
     192        assert( i < stateFrom->dataLength );
     193        stateTo->data[i] = stateFrom->data[i];
     194        i++;
     195      }
     196      //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), *sizeIter);
     197      stateTo->sizeList.push_back( (*sizeIter) );
     198    }
     199
     200    if ( sizeIter != stateFrom->sizeList.end() )
     201      sizeIter++;
     202  }
     203
     204  sentStates[userId].push_back( stateTo );
     205 
     206  assert( i == neededSize );
     207
     208  //write diff to data
     209  for ( i = 0; i<neededSize; i++ )
     210  {
     211    if ( i < stateFrom->dataLength )
     212      data[i] = stateTo->data[i] - stateFrom->data[i];
     213    else
     214      data[i] = stateTo->data[i];
     215  }
     216
     217  return neededSize;
     218}
     219
     220/**
     221 * sets a new state out of a diff created on another host
     222 * @param userId hostId of user who send me that diff
     223 * @param data pointer to diff
     224 * @param length length of diff
     225 * @param stateId id of current state
     226 * @param fromStateId id of the base state id
     227 * @return number bytes read
     228 * @todo check for permissions
     229 */
     230int Synchronizeable::setStateDiff( int userId, byte* data, int length, int stateId, int fromStateId )
     231{
     232  //make sure this user has his history
     233  if ( recvStates.size() <= userId )
     234    recvStates.resize( userId+1 );
     235
     236  //create new state
     237  StateHistoryEntry * stateTo = new StateHistoryEntry();
     238  stateTo->stateId = stateId;
     239  stateTo->dataLength = length;
     240  stateTo->data = new byte[ length ];
     241
     242
     243  //find state to apply diff to
     244  StateHistoryEntry * stateFrom = NULL;
     245
     246  StateHistory::iterator it = recvStates[userId].begin();
     247  while ( it != recvStates[userId].end() && (*it)->stateId != fromStateId )
     248    it++;
     249
     250 
     251//  if ( getLeafClassID() == CL_SPACE_SHIP )
     252//  {
     253//    PRINTF(0)("setStateDiff:SpaceShip from: %d stateId: %d\n", (it == recvStates[userId].end())?-1:fromStateId, stateId);
     254//  }
     255
     256  if ( it == recvStates[userId].end() )
     257  {
     258    StateHistoryEntry * initialEntry = new StateHistoryEntry();
     259
     260    initialEntry->stateId = fromStateId;
     261    initialEntry->dataLength = 0;
     262    initialEntry->data = NULL;
     263
     264    stateFrom = initialEntry;
     265  }
     266  else
     267    stateFrom = (*it);
     268 
     269  //apply diff
     270  for ( int i = 0; i<length; i++ )
     271  {
     272    if ( i < stateFrom->dataLength )
     273      stateTo->data[i] = stateFrom->data[i] + data[i];
     274    else
     275      stateTo->data[i] = data[i];
     276   
     277  }
     278 
     279  //add state to state history
     280  recvStates[userId].push_back( stateTo );
     281 
     282  int i = 0;
     283  int n = 0;
     284  std::list<int> changes;
     285 
     286  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
     287  {
     288    if (
     289        (*it)->checkPermission( PERMISSION_SERVER ) && networkStream->isUserServer( userId ) ||
     290        (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == userId ||
     291        (*it)->checkPermission( PERMISSION_ALL )
     292       )
     293    {
     294      n = (*it)->readFromBuf( stateTo->data + i, stateTo->dataLength - i );
     295      i += n;
     296      //NETPRINTF(0)("%s::setvar %s %d\n", getClassName(), (*it)->getName().c_str(), n);
     297      //(*it)->debug();
     298      if ( (*it)->getHasChanged() )
     299      {
     300        changes.push_back( (*it)->getVarId() );
     301      }
     302    }
     303    else
     304    {
     305//      PRINTF(0)("DONT SET VAR BECAUSE OF PERMISSION: %s %d %d %d %d %d %d\n", (*it)->getName().c_str(), (*it)->checkPermission( PERMISSION_SERVER ), (*it)->checkPermission( PERMISSION_OWNER ), (*it)->checkPermission( PERMISSION_ALL ), networkStream->isUserServer( userId ), this->owner, userId );
     306      n = (*it)->getSizeFromBuf( stateTo->data + i, stateTo->dataLength - i );
     307      //NETPRINTF(0)("%s::setvar %s %d\n", getClassName(), (*it)->getName().c_str(), n);
     308      //(*it)->debug();
     309      i += n;
     310    }
     311  }
     312
     313  this->varChangeHandler( changes );
     314 
     315  return i;
     316}
     317
     318 /**
     319 * override this function to be notified on change
     320 * of your registred variables.
     321 * @param id id's which have changed
     322 */
     323void Synchronizeable::varChangeHandler( std::list<int> & id )
     324{
     325}
     326
     327/**
     328 * registers a varable to be synchronized over network
     329 * @param var see src/lib/network/synchronizeable_var/ for available classes
     330 */
     331void Synchronizeable::registerVar( SynchronizeableVar * var )
     332{
     333  PRINTF(0)("ADDING VAR: %s\n", var->getName().c_str());
     334  syncVarList.push_back( var );
     335}
     336
     337/**
     338 * registers a varable to be synchronized over network
     339 * return value is passed to varChangeHandler on change
     340 * @param var see src/lib/network/synchronizeable_var/ for available classes
     341 * @return handle passed to varChangeHandler on changes
     342 */
     343int Synchronizeable::registerVarId( SynchronizeableVar * var )
     344{
     345  PRINTF(0)("ADDING VAR: %s\n", var->getName().c_str());
     346  syncVarList.push_back( var );
     347  var->setWatched( true );
     348  var->setVarId( syncVarList.size()-1 );
     349  return syncVarList.size()-1;
     350}
     351
     352/**
     353 * removed user's states from memory
     354 * @param userId user to clean
     355 */
     356void Synchronizeable::cleanUpUser( int userId )
     357{
     358  for ( UserStateHistory::iterator it = sentStates.begin(); it != sentStates.end(); it++ )
     359  {
     360    for ( StateHistory::iterator it2 = it->begin(); it2 != it->end(); it2++ )
     361    {
     362      if ( (*it2)->data )
     363        delete [] (*it2)->data;
     364      (*it2)->data = NULL;
     365     
     366      delete *it2;
     367    }
     368  }
     369 
     370  sentStates.clear();
     371 
     372  for ( UserStateHistory::iterator it = recvStates.begin(); it != recvStates.end(); it++ )
     373  {
     374    for ( StateHistory::iterator it2 = it->begin(); it2 != it->end(); it2++ )
     375    {
     376      if ( (*it2)->data )
     377        delete [] (*it2)->data;
     378      (*it2)->data = NULL;
     379     
     380      delete *it2;
     381    }
     382  }
     383 
     384  recvStates.clear();
     385}
     386
     387/**
     388 * this function is called after recieving a state.
     389 * @param userId
     390 * @param stateId
     391 * @param fromStateId
     392 */
     393void Synchronizeable::handleRecvState( int userId, int stateId, int fromStateId )
     394{
     395   //make sure this user has his history
     396  if ( recvStates.size() <= userId )
     397    recvStates.resize( userId+1 );
     398 
     399  //remove old states
     400  StateHistory::iterator it = recvStates[userId].begin();
     401
     402#if 0
     403  while ( it != recvStates[userId].end() && (*it)->stateId < fromStateId )
     404    it++;
     405
     406  if ( it != recvStates[userId].begin() )
     407  {
     408    for ( StateHistory::iterator it2 = recvStates[userId].begin(); it2 != it; it2++ )
     409    {
     410      if ( (*it2)->data != NULL )
     411      {
     412        delete [] (*it2)->data;
     413        (*it2)->data = NULL;
     414      }
     415    }
     416    recvStates[userId].erase( recvStates[userId].begin(), it );
     417  }
     418#endif
     419
     420  for ( it = recvStates[userId].begin(); it != recvStates[userId].end();  )
     421  {
     422    if ( (*it)->stateId < fromStateId )
     423    {
     424      StateHistory::iterator delIt = it;
     425      it ++;
     426     
     427      if ( (*delIt)->data )
     428        delete [] (*delIt)->data;
     429      recvStates[userId].erase( delIt );
     430     
     431      continue;
     432    }
     433    it++;
     434  }
     435 
     436  StateHistory::iterator fromState = recvStates[userId].end();
     437  StateHistory::iterator toState = recvStates[userId].end();
     438 
     439  for ( it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
     440  {
     441    if ( (*it)->stateId == stateId )
     442      toState = it;
     443    if ( (*it)->stateId == fromStateId )
     444      fromState = it;
     445   
     446    if ( fromState != recvStates[userId].end() && toState != recvStates[userId].end() )
     447      break;
     448  }
     449 
     450  // setStateDiff was not called and i know fromStateId
     451  if ( fromState != recvStates[userId].end() && toState == recvStates[userId].end() )
     452  {
     453    StateHistoryEntry * entry = new StateHistoryEntry;
     454   
     455    entry->dataLength = (*fromState)->dataLength;
     456    if ( entry->dataLength > 0 )
     457    {
     458      entry->data = new byte[entry->dataLength];
     459         
     460      assert( (*fromState)->data );
     461      memcpy( entry->data, (*fromState)->data, entry->dataLength );
     462    }
     463    else
     464      entry->data = NULL;
     465   
     466    entry->sizeList = (*fromState)->sizeList;
     467    entry->stateId = stateId;
     468   
     469    recvStates[userId].push_back(entry);
     470  }
     471}
     472
     473/**
     474 * this function is called after sending a state
     475 * @param userId
     476 * @param stateId
     477 * @param fromStateId
     478 */
     479void Synchronizeable::handleSentState( int userId, int stateId, int fromStateId )
     480{
     481   //make sure this user has his history
     482  if ( sentStates.size() <= userId )
     483    sentStates.resize( userId+1 );
     484
     485   //remove old states
     486  StateHistory::iterator it = sentStates[userId].begin();
     487
     488  for ( it = sentStates[userId].begin(); it != sentStates[userId].end();  )
     489  {
     490    if ( (*it)->stateId < fromStateId )
     491    {
     492      StateHistory::iterator delIt = it;
     493      it ++;
     494     
     495      if ( (*delIt)->data )
     496        delete [] (*delIt)->data;
     497      sentStates[userId].erase( delIt );
     498     
     499      continue;
     500    }
     501    it++;
     502  }
     503
     504 
     505  StateHistory::iterator fromState = sentStates[userId].end();
     506  StateHistory::iterator toState = sentStates[userId].end();
     507 
     508  for ( it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
     509  {
     510    if ( (*it)->stateId == stateId )
     511      toState = it;
     512    if ( (*it)->stateId == fromStateId )
     513      fromState = it;
     514   
     515    if ( fromState != sentStates[userId].end() && toState != sentStates[userId].end() )
     516      break;
     517  }
     518
     519 
     520  // getStateDiff was not called and i know fromStateId
     521  if ( fromState != sentStates[userId].end() && toState == sentStates[userId].end() )
     522  {
     523    StateHistoryEntry * entry = new StateHistoryEntry;
     524   
     525    entry->dataLength = (*fromState)->dataLength;
     526    if ( entry->dataLength > 0 )
     527    {
     528      entry->data = new byte[entry->dataLength];
     529     
     530      assert( (*fromState)->data );
     531      memcpy( entry->data, (*fromState)->data, entry->dataLength );
     532    }
     533    else
     534      entry->data = NULL;
     535   
     536    entry->sizeList = (*fromState)->sizeList;
     537    entry->stateId = stateId;
     538   
     539    sentStates[userId].push_back(entry);
     540  }
     541 
     542}
     543
     544
     545
Note: See TracChangeset for help on using the changeset viewer.