Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/lib/network/synchronizeable.cc @ 7512

Last change on this file since 7512 was 7512, checked in by patrick, 18 years ago

network: just modified the comments

File size: 7.7 KB
RevLine 
[5523]1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
[5547]11
[5523]12### File Specific:
13   main-programmer: Silvan Nellen
[5997]14   co-programmer: Benjamin Wuest
[5547]15*/
[5523]16
[6139]17#define DEBUG_MODULE_NETWORK
18
[6695]19#include "shared_network_data.h"
20#include "network_stream.h"
[5547]21#include "netdefs.h"
[5529]22
[6695]23#include "state.h"
[5996]24
[6753]25#include <cassert>
[6695]26
27#include "synchronizeable.h"
28
29
30
[5547]31/**
[5807]32 *  default constructor
[5547]33 */
[5996]34Synchronizeable::Synchronizeable()
[5997]35{
[6341]36  this->setClassID(CL_SYNCHRONIZEABLE, "Synchronizeable");
[6753]37  this->owner = -1;
[6695]38  this->hostID = SharedNetworkData::getInstance()->getHostID();
[6341]39  this->setIsServer(this->hostID == 0);
[6695]40  this->uniqueID = NET_UID_UNASSIGNED;
[6145]41  this->networkStream = NULL;
[6695]42  this->bSynchronize = false;
43
44  if( State::isOnline())
45  {
46    NetworkStream* nd = SharedNetworkData::getInstance()->getDefaultSyncStream();
47    assert(nd != NULL);
48    nd->connectSynchronizeable(*this);
49    this->setUniqueID(SharedNetworkData::getInstance()->getNewUniqueID());
50  }
[7512]51
[7444]52  this->registerVar( new SynchronizeableString( &this->objectName, &this->objectName, "objectName" ) );
[5997]53}
54
[5523]55
[5996]56
[5547]57/**
[5807]58 *  default destructor deletes all unneded stuff
[5547]59 */
60Synchronizeable::~Synchronizeable()
[6139]61{
62  if ( this->networkStream )
63    this->networkStream->disconnectSynchronizeable(*this);
64}
[5523]65
[5547]66/**
[5997]67 * Sets the server flag to a given value
68 * @param isServer: the boolean value which the server flag is to set to
69 */
70void Synchronizeable::setIsServer(bool isServer)
71{
72  if( isServer )
73    this->state = this->state | STATE_SERVER;
74  else
75    this->state = this->state & (~STATE_SERVER);
76}
77
[6695]78
[5997]79/**
[7444]80 * Determines if the server flag is set
81 * @return true, if the server flag is true, false else
[5997]82 */
[7444]83bool Synchronizeable::isServer()
[5997]84{
[7444]85  return (this->state & STATE_SERVER) >0;
[5997]86}
87
[6695]88
[5997]89/**
[7444]90 * get the diff to last acked state of userId
91 * @param userId user to create diff for
92 * @param data buffer to copy diff in
93 * @param maxLength max bytes to copy into data
94 * @param stateId id of current state
95 * @param priorityTH tells getStateDiff to not send element with priority \< priorityTH
96 * @return n bytes copied into data
[5997]97 */
[7508]98int Synchronizeable::getStateDiff( int userId, byte* data, int maxLength, int stateId, int fromStateId, int priorityTH )
[5997]99{
[7508]100  //make sure this user has his history
101  if ( sentStates.size() <= userId )
102    sentStates.resize( userId+1 );
[7512]103
[7508]104  //calculate needed memory
105  int neededSize = 0;
[7512]106
[7508]107  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
108    neededSize += (*it)->getSize();
[7512]109
[7508]110  assert( neededSize <= maxLength );
[7512]111
[7508]112  //remove older states from history than fromStateId
113  StateHistory::iterator it = sentStates[userId].begin();
[7512]114
[7508]115  while ( it != sentStates[userId].end() && (*it)->stateId < fromStateId )
116    it++;
[7512]117
[7508]118  if ( it != sentStates[userId].begin() )
119  {
120    for ( StateHistory::iterator it2 = sentStates[userId].begin(); it2 != it; it2++ )
121    {
122      if ( (*it2)->data != NULL )
123      {
124        delete (*it2)->data;
125        (*it2)->data = NULL;
126      }
127    }
128    sentStates[userId].erase( sentStates[userId].begin(), it );
129  }
[7512]130
[7508]131  //find state to create diff from
132  StateHistoryEntry * stateFrom = NULL;
[7512]133
[7508]134  it = sentStates[userId].begin();
135  while ( it != sentStates[userId].end() && (*it)->stateId != fromStateId )
136    it++;
[7512]137
[7508]138  if ( it == sentStates[userId].end() )
139  {
140    StateHistoryEntry * initialEntry = new StateHistoryEntry();
[7512]141
[7508]142    initialEntry->stateId = fromStateId;
143    initialEntry->dataLength = 0;
144    initialEntry->data = NULL;
[7512]145
[7508]146    stateFrom = initialEntry;
147  }
148  else
149    stateFrom = (*it);
[7512]150
[7508]151  StateHistoryEntry * stateTo = new StateHistoryEntry();
[7512]152
[7508]153  stateTo->stateId = stateId;
154  stateTo->dataLength = neededSize;
155  stateTo->data = (byte*)malloc( neededSize );
[7512]156
[7508]157  std::list<int>::iterator sizeIter = stateFrom->sizeList.begin();
[7512]158
[7508]159  int i = 0;
160  int n;
[7512]161
[7508]162  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
163  {
164    if ( (*it)->getPriority() >= priorityTH || sizeIter == stateFrom->sizeList.end() )
165    {
166      n = (*it)->writeToBuf( stateTo->data+i, stateTo->dataLength - i );
167      stateTo->sizeList.push_back( n );
168      i += n;
169    }
170    else
171    {
172      for ( int j = 0; j<(*sizeIter); j++ )
173      {
174        assert( i < stateFrom->dataLength );
175        stateTo->data[i] = stateFrom->data[i];
176        i++;
177      }
178      stateTo->sizeList.push_back( (*sizeIter) );
179    }
[7512]180
[7508]181    if ( sizeIter != stateFrom->sizeList.end() )
182      sizeIter++;
183  }
[7512]184
[7508]185  sentStates[userId].push_back( stateTo );
[7512]186
[7508]187  //write diff to data
188  for ( i = 0; i<neededSize; i++ )
189  {
190    if ( i < stateFrom->dataLength )
191      data[i] = stateTo->data[i] - stateFrom->data[i];
192    else
193      data[i] = stateTo->data[i];
194  }
[7512]195
[7508]196  return neededSize;
[5997]197}
198
199/**
[7444]200 * sets a new state out of a diff created on another host
201 * @param userId hostId of user who send me that diff
202 * @param data pointer to diff
203 * @param length length of diff
204 * @param stateId id of current state
[7512]205 * @param fromStateId id of the base state id
[7444]206 * @return true on success
[5997]207 */
[7508]208bool Synchronizeable::setStateDiff( int userId, byte* data, int length, int stateId, int fromStateId )
[5997]209{
[7508]210  //make sure this user has his history
211  if ( recvStates.size() <= userId )
212    recvStates.resize( userId+1 );
[7512]213
[7508]214  //create new state
215  StateHistoryEntry * stateTo = new StateHistoryEntry();
216  stateTo->stateId = stateId;
217  stateTo->dataLength = length;
218  stateTo->data = (byte*)malloc( length );
[7512]219
220  //remove old states
[7508]221  StateHistory::iterator it = recvStates[userId].begin();
[7512]222
[7508]223  while ( it != recvStates[userId].end() && (*it)->stateId < fromStateId )
224    it++;
[7512]225
[7508]226  if ( it != recvStates[userId].begin() )
227  {
228    for ( StateHistory::iterator it2 = recvStates[userId].begin(); it2 != it; it2++ )
229    {
230      if ( (*it2)->data != NULL )
231      {
232        delete (*it2)->data;
233        (*it2)->data = NULL;
234      }
235    }
236    recvStates[userId].erase( recvStates[userId].begin(), it );
237  }
[7512]238
[7508]239  //find state to apply diff to
240  StateHistoryEntry * stateFrom = NULL;
[7512]241
[7508]242  it = recvStates[userId].begin();
243  while ( it != recvStates[userId].end() && (*it)->stateId != fromStateId )
244    it++;
[7512]245
[7508]246  if ( it == recvStates[userId].end() )
247  {
248    StateHistoryEntry * initialEntry = new StateHistoryEntry();
[7512]249
[7508]250    initialEntry->stateId = fromStateId;
251    initialEntry->dataLength = 0;
252    initialEntry->data = NULL;
[7512]253
[7508]254    stateFrom = initialEntry;
255  }
256  else
257    stateFrom = (*it);
[7512]258
[7508]259  //apply diff
260  for ( int i = 0; i<length; i++ )
261  {
262    if ( i < stateFrom->dataLength )
263      stateTo->data[i] = stateFrom->data[i] + data[i];
264    else
265      stateTo->data[i] = data[i];
266  }
[7512]267
[7508]268  //add state to state history
269  recvStates[userId].push_back( stateTo );
[7512]270
271  int i = 0;
272
[7508]273  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
274  {
275    i += (*it)->readFromBuf( stateTo->data + i, stateTo->dataLength - i );
276  }
[7512]277
[7508]278  assert( i == length -1 );
[7512]279
[7508]280  return length;
[5997]281}
[6139]282
[7444]283 /**
284 * override this function to be notified on change
285 * of your registred variables.
286 * @param id id's which have changed
287 */
[7445]288void Synchronizeable::varChangeHandler( std::list<int> & id )
[7444]289{
290}
[6695]291
[6341]292/**
[7444]293 * registers a varable to be synchronized over network
294 * @param var see src/lib/network/synchronizeable_var/ for available classes
[6341]295 */
[7444]296void Synchronizeable::registerVar( SynchronizeableVar * var )
[6341]297{
[7508]298  syncVarList.push_back( var );
[6341]299}
[6139]300
[6341]301/**
[7444]302 * registers a varable to be synchronized over network
303 * return value is passed to varChangeHandler on change
304 * @param var see src/lib/network/synchronizeable_var/ for available classes
305 * @return handle passed to varChangeHandler on changes
[6341]306 */
[7444]307int Synchronizeable::registerVarId( SynchronizeableVar * var )
[6341]308{
[7508]309  syncVarList.push_back( var );
310  return syncVarList.size()-1;
[6341]311}
[6139]312
[6341]313
Note: See TracBrowser for help on using the repository browser.