Changeset 7954 in orxonox.OLD for trunk/src/lib/network/synchronizeable.cc
- Timestamp:
- May 29, 2006, 3:28:41 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lib/network/synchronizeable.cc
r6753 r7954 20 20 #include "network_stream.h" 21 21 #include "netdefs.h" 22 #include "network_log.h" 22 23 23 24 #include "state.h" … … 36 37 this->setClassID(CL_SYNCHRONIZEABLE, "Synchronizeable"); 37 38 this->owner = -1; 38 this->state = 0;39 39 this->hostID = SharedNetworkData::getInstance()->getHostID(); 40 40 this->setIsServer(this->hostID == 0); 41 41 this->uniqueID = NET_UID_UNASSIGNED; 42 42 this->networkStream = NULL; 43 this->setRequestedSync( false );44 this->setIsOutOfSync( !(this->isServer()) );45 43 this->bSynchronize = false; 46 44 47 45 if( State::isOnline()) 48 46 { … … 52 50 this->setUniqueID(SharedNetworkData::getInstance()->getNewUniqueID()); 53 51 } 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" ) ); 54 59 } 55 60 … … 64 69 this->networkStream->disconnectSynchronizeable(*this); 65 70 } 66 67 68 /**69 * write data to NetworkStream70 */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 NetworkStream79 */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() const87 {}88 89 90 void Synchronizeable::readDebug() const91 {}92 93 71 94 72 /** … … 106 84 107 85 /** 108 * Sets the outofsync flag to a given value109 * @param outOfSync: the boolean value which the outofsync flag is to set to110 */111 void Synchronizeable::setIsOutOfSync(bool outOfSync)112 {113 if( outOfSync )114 this->state = this->state | STATE_OUTOFSYNC;115 else116 this->state = this->state & (~STATE_OUTOFSYNC);117 //PRINTF(0)("isoutofsync %s %d\n", this->getClassName(), state);118 }119 120 121 /**122 86 * Determines if the server flag is set 123 87 * @return true, if the server flag is true, false else … … 129 93 130 94 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 96 int 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 } 159 155 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 */ 230 int 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 */ 323 void 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 */ 331 void 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 */ 343 int 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 */ 356 void 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 */ 393 void 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 */ 479 void 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.