Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Nov 4, 2008, 5:12:31 PM (16 years ago)
Author:
scheusso
Message:

bidirectional synchronisation works now:
register variables with mode direction::serverMaster or direction::clientMaster
clientMaster: both sides may change the variable but the client is master
serverMaster: both sides may change the variable but the server is master

Location:
code/branches/objecthierarchy/src/network
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • code/branches/objecthierarchy/src/network/Synchronisable.cc

    r2112 r2132  
    5050// #include "core/Identifier.h"
    5151
     52#include "Host.h"
    5253namespace orxonox
    5354{
     
    5758  std::queue<unsigned int> Synchronisable::deletedObjects_;
    5859
    59   int Synchronisable::state_=0x1; // detemines wheter we are server (default) or client
     60  uint8_t Synchronisable::state_=0x1; // detemines wheter we are server (default) or client
    6061
    6162  /**
     
    99100      for(std::list<synchronisableVariable *>::iterator it = syncList->begin(); it!=syncList->end(); it++)
    100101        delete (*it)->callback;
    101       if (this->objectMode_ != 0x0)
     102      if (this->objectMode_ != 0x0 && (Host::running() && Host::isServer()))
    102103        deletedObjects_.push(objectID);
    103104//       COUT(3) << "destruct synchronisable +++" << objectID << " | " << classID << std::endl;
     
    143144   * @return pointer to the newly created synchronisable
    144145   */
    145   Synchronisable *Synchronisable::fabricate(uint8_t*& mem, int mode)
     146  Synchronisable *Synchronisable::fabricate(uint8_t*& mem, uint8_t mode)
    146147  {
    147148    synchronisableHeader *header = (synchronisableHeader *)mem;
     
    238239  * @param cb callback object that should get called, if the value of the variable changes
    239240  */
    240   void Synchronisable::registerVar(void *var, int size, variableType t, int mode, NetworkCallbackBase *cb){
     241  void Synchronisable::registerVar(void *var, int size, variableType t, uint8_t mode, NetworkCallbackBase *cb){
    241242    assert( mode==direction::toclient || mode==direction::toserver || mode==direction::serverMaster || mode==direction::clientMaster);
    242243    // create temporary synch.Var struct
     
    249250    if( ( mode & direction::bidirectional ) )
    250251    {
    251       temp->varBuffer = new uint8_t[size];
    252       memcpy(temp->varBuffer, temp->var, size); //now fill the buffer for the first time
     252      if(t!=STRING)
     253      {
     254        temp->varBuffer = new uint8_t[size];
     255        memcpy(temp->varBuffer, temp->var, size); //now fill the buffer for the first time
     256      }
     257      else
     258      {
     259        temp->varBuffer=new std::string( *static_cast<std::string*>(var) );
     260      }
    253261      temp->varReference = 0;
    254262    }
     
    280288   * @return true: if !doSync or if everything was successfully saved
    281289   */
    282   bool Synchronisable::getData(uint8_t*& mem, unsigned int id, int mode){
     290  bool Synchronisable::getData(uint8_t*& mem, unsigned int id, uint8_t mode){
     291    if(mode==0x0)
     292      mode=state_;
    283293    //if this tick is we dont synchronise, then abort now
    284     if(!doSync(id))
     294    if(!doSync(id, mode))
    285295      return true;
    286296    //std::cout << "inside getData" << std::endl;
    287297    unsigned int tempsize = 0;
    288     if(mode==0x0)
    289       mode=state_;
    290298    if(classID==0)
    291299      COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
     
    307315    header->classID = this->classID;
    308316    header->dataAvailable = true;
    309     tempsize+=sizeof(synchronisableHeader);
    310     mem+=sizeof(synchronisableHeader);
     317    tempsize += sizeof(synchronisableHeader);
     318    mem += sizeof(synchronisableHeader);
    311319    // end copy header
    312320
     
    319327        continue;  // this variable should only be received
    320328      }
     329     
     330      // =========== start bidirectional stuff =============
    321331      // if the variable gets synchronised bidirectional, then add the reference to the bytestream
    322332      if( ( (*i)->mode & direction::bidirectional ) == direction::bidirectional )
    323333      {
     334        if( ( ((*i)->mode == direction::serverMaster) && (mode == 0x1) ) || \
     335            ( ((*i)->mode == direction::clientMaster) && (mode == 0x2) ) )
     336        {
     337          // MASTER
     338          if((*i)->type==DATA){
     339            if( memcmp((*i)->var,(*i)->varBuffer,(*i)->size) != 0 ) //check whether the variable changed during the last tick
     340            {
     341              ((*i)->varReference)++;   //the variable changed so increase the refnr
     342              memcpy((*i)->varBuffer, (*i)->var, (*i)->size); //set the buffer to the new value
     343            }
     344          }
     345          else //STRING
     346          {
     347            if( *static_cast<std::string*>((*i)->var) != *static_cast<std::string*>((*i)->varBuffer) ) //the string changed
     348            {
     349              ((*i)->varReference)++;   //the variable changed
     350              *static_cast<std::string*>((*i)->varBuffer) = *static_cast<std::string*>((*i)->var);  //now set the buffer to the new value
     351            }
     352          }
     353        }
     354        // copy the reference number to the stream
    324355        *(uint8_t*)mem = (*i)->varReference;
    325356        mem += sizeof( (*i)->varReference );
    326357        tempsize += sizeof( (*i)->varReference );
    327358      }
     359      // ================== end bidirectional stuff
     360       
    328361      switch((*i)->type){
    329362        case DATA:
    330363          memcpy( (void *)(mem), (void*)((*i)->var), (*i)->size);
    331           mem+=(*i)->size;
    332           tempsize+=(*i)->size;
     364          mem += (*i)->size;
     365          tempsize += (*i)->size;
    333366          break;
    334367        case STRING:
    335368          memcpy( (void *)(mem), (void *)&((*i)->size), sizeof(size_t) );
    336           mem+=sizeof(size_t);
     369          mem += sizeof(size_t);
    337370          const char *data = ( ( *(std::string *) (*i)->var).c_str());
    338371          memcpy( mem, (void*)data, (*i)->size);
    339372          COUT(5) << "synchronisable: char: " << (const char *)(mem) << " data: " << data << " string: " << *(std::string *)((*i)->var) << std::endl;
    340           mem+=(*i)->size;
    341           tempsize+=(*i)->size + sizeof(size_t);
     373          mem += (*i)->size;
     374          tempsize += (*i)->size + sizeof(size_t);
    342375          break;
    343376      }
     
    354387   * @return true/false
    355388   */
    356   bool Synchronisable::updateData(uint8_t*& mem, int mode, bool forceCallback){
     389  bool Synchronisable::updateData(uint8_t*& mem, uint8_t mode, bool forceCallback){
    357390    if(mode==0x0)
    358391      mode=state_;
    359392    std::list<synchronisableVariable *>::iterator i;
     393    //assert(objectMode_!=0x0);
     394    //assert( (mode ^ objectMode_) != 0);
    360395    if(syncList->empty()){
    361396      COUT(4) << "Synchronisable::updateData syncList is empty" << std::endl;
     
    367402    synchronisableHeader *syncHeader = (synchronisableHeader *)mem;
    368403    assert(syncHeader->objectID==this->objectID);
    369 //    assert(syncHeader->creatorID==this->creatorID);
     404    assert(syncHeader->creatorID==this->creatorID);
     405    assert(this->classID==syncHeader->classID); //TODO: fix this!!! maybe a problem with the identifier ?
    370406    if(syncHeader->dataAvailable==false){
    371       mem+=syncHeader->size;
     407      mem += syncHeader->size;
    372408      return true;
    373409    }
    374410
    375     mem+=sizeof(synchronisableHeader);
     411    mem += sizeof(synchronisableHeader);
    376412    // stop extract header
    377     assert(this->objectID==syncHeader->objectID);
    378 //    assert(this->classID==syncHeader->classID); //TODO: fix this!!! maybe a problem with the identifier ?
    379413
    380414    COUT(5) << "Synchronisable: objectID " << syncHeader->objectID << ", classID " << syncHeader->classID << " size: " << syncHeader->size << " synchronising data" << std::endl;
     
    382416      if( ((*i)->mode ^ mode) == 0 ){
    383417        COUT(5) << "synchronisable: not updating variable " << std::endl;
     418        // if we have a forcecallback then do the callback
    384419        continue;  // this variable should only be set
    385420      }
    386421      COUT(5) << "Synchronisable: element size: " << (*i)->size << " type: " << (*i)->type << std::endl;
    387422      bool callback=false;
     423      bool master=false;
     424     
     425      if( ( (*i)->mode & direction::bidirectional ) == direction::bidirectional )
     426      {
     427        uint8_t refNr = *(uint8_t *)mem;
     428        if( ( ((*i)->mode == direction::serverMaster) && (mode == 0x1) ) || \
     429            ( ((*i)->mode == direction::clientMaster) && (mode == 0x2) ) )
     430        { // MASTER
     431          master=true;
     432          if( refNr != (*i)->varReference || ( memcmp((*i)->var, (*i)->varBuffer, (*i)->size) != 0 ) )
     433          { // DISCARD data
     434            if( (*i)->type == DATA )
     435            {
     436              mem += sizeof((*i)->varReference) + (*i)->size;
     437            }
     438            else //STRING
     439            {
     440              mem += sizeof(size_t) + *(size_t *)mem;
     441            }
     442            if( forceCallback && (*i)->callback)
     443              (*i)->callback->call();
     444            continue;
     445          }//otherwise everything is ok and we update the value
     446        }
     447        else // SLAVE
     448        {
     449          if( (*i)->varReference == refNr ){
     450            //discard data because it's outdated or not different to what we've got
     451            if( (*i)->type == DATA )
     452            {
     453              mem += sizeof((*i)->varReference) + (*i)->size;
     454            }
     455            else //STRING
     456            {
     457              mem += sizeof(size_t) + *(size_t *)mem;
     458            }
     459            if( forceCallback && (*i)->callback)
     460              (*i)->callback->call();
     461            continue;
     462          }
     463          else
     464            (*i)->varReference = refNr; //copy the reference value for this variable
     465        }
     466        mem += sizeof((*i)->varReference);
     467      }
     468     
    388469      switch((*i)->type){
    389470        case DATA:
    390           if( ( (*i)->mode & direction::bidirectional ) == direction::bidirectional )
     471          if((*i)->callback) // check whether this variable changed (but only if callback was set)
    391472          {
    392             if( ( mode == 0x1 && (*i)->mode == direction::serverMaster ) || \
    393                   ( mode == 0x2 && (*i)->mode == direction::clientMaster ) )    // if true we are master on this variable
    394             {
    395               uint8_t refNr = *(uint8_t *)mem;
    396               if( refNr != (*i)->varReference )
    397               {
    398                 mem += sizeof((*i)->varReference) + (*i)->size; // the reference for this variable is not recent, discard data
    399                 break;
    400               }
    401             }
    402             else //we are slave for this variable
    403             {
    404               (*i)->varReference = *(uint8_t *)mem; //copy the reference value for this variable
    405             }
    406             mem += sizeof((*i)->varReference);
     473            if(memcmp((*i)->var, mem, (*i)->size) != 0)
     474              callback=true;
    407475          }
    408           if((*i)->callback) // check whether this variable changed (but only if callback was set)
    409             if(strncmp((char *)(*i)->var, (char *)mem, (*i)->size)!=0)
    410               callback=true;
    411           memcpy((void*)(*i)->var, mem, (*i)->size);
    412           mem+=(*i)->size;
     476          if( master )
     477          {
     478            if( callback || memcmp((*i)->var, mem, (*i)->size) != 0 )
     479              //value changed, so set the buffer to the new value
     480              memcpy((*i)->varBuffer, mem, (*i)->size);
     481          }
     482          memcpy((*i)->var, mem, (*i)->size);
     483          mem += (*i)->size;
    413484          break;
    414485        case STRING:
    415           if( ( (*i)->mode & direction::bidirectional ) == direction::bidirectional )
     486          (*i)->size = *(size_t *)mem;
     487          mem += sizeof(size_t);
     488         
     489          if( (*i)->callback) // check whether this string changed
     490            if( *static_cast<std::string*>((*i)->var) != std::string((char *)mem) )
     491              callback=true;
     492          if( master )
    416493          {
    417             if( ( mode == 0x1 && (*i)->mode == direction::serverMaster ) || \
    418                   ( mode == 0x2 && (*i)->mode == direction::clientMaster ) )    // if true we are master for this variable
    419             {
    420               uint8_t refNr = *(uint8_t *)mem;
    421               mem += sizeof( (*i)->varReference );
    422               if( refNr != (*i)->varReference ){
    423                 mem += sizeof(size_t) + *(size_t *)mem; // the reference for this variable is not recent, discard data
    424                 break;
    425               }
    426             }
    427             else //we are slave for this variable
    428             {
    429               (*i)->varReference = *(uint8_t *)mem; //copy the reference value for this variable
    430             }
    431             mem += sizeof( (*i)->varReference );
     494            if( callback || *static_cast<std::string*>((*i)->var) != std::string((char *)mem) )
     495              //string changed. set the buffer to the new one
     496              *static_cast<std::string*>((*i)->varBuffer)=*static_cast<std::string*>( (void*)(mem+sizeof(size_t)) );
    432497          }
    433           (*i)->size = *(size_t *)mem;
    434           COUT(5) << "string size: " << (*i)->size << std::endl;
    435           mem += sizeof(size_t);
    436           if((*i)->callback) // check whether this string changed
    437             if( *(std::string *)((*i)->var) != std::string((char *)mem) )
    438               callback=true;
     498         
    439499          *((std::string *)((*i)->var)) = std::string((const char*)mem);
    440500          COUT(5) << "synchronisable: char: " << (const char*)mem << " string: " << std::string((const char*)mem) << std::endl;
     
    446506        (*i)->callback->call();
    447507    }
     508    assert(mem == data+syncHeader->size);
    448509    return true;
    449510  }
     
    455516  * @return amount of bytes
    456517  */
    457   uint32_t Synchronisable::getSize(unsigned int id, int mode){
    458     if(!doSync(id))
    459       return 0;
     518  uint32_t Synchronisable::getSize(unsigned int id, uint8_t mode){
    460519    int tsize=sizeof(synchronisableHeader);
    461520    if(mode==0x0)
    462521      mode=state_;
     522    if(!doSync(id, mode))
     523      return 0;
    463524    std::list<synchronisableVariable *>::iterator i;
    464525    for(i=syncList->begin(); i!=syncList->end(); i++){
     
    489550   * @return true/false
    490551   */
    491   bool Synchronisable::doSync(unsigned int id){
    492     return ( (objectMode_&state_)!=0 && (!syncList->empty() ) );
     552  bool Synchronisable::doSync(unsigned int id, uint8_t mode){
     553    if(mode==0x0)
     554      mode=state_;
     555    return ( (objectMode_&mode)!=0 && (!syncList->empty() ) );
    493556  }
    494557
    495558  bool Synchronisable::doSelection(unsigned int id){
    496     return ( id==0 || id%objectFrequency_==objectID%objectFrequency_ ) && ((objectMode_&state_)!=0);
     559    return true; //TODO: change this
     560    //return ( id==0 || id%objectFrequency_==objectID%objectFrequency_ ) && ((objectMode_&state_)!=0);
    497561  }
    498562
     
    510574  /**
    511575   * This function sets the synchronisation mode of the object
     576   * If set to 0x0 variables will not be synchronised at all
    512577   * If set to 0x1 variables will only be synchronised to the client
    513578   * If set to 0x2 variables will only be synchronised to the server
     
    515580   * @param mode same as in registerVar
    516581   */
    517   void Synchronisable::setObjectMode(int mode){
     582  void Synchronisable::setObjectMode(uint8_t mode){
    518583    assert(mode==0x0 || mode==0x1 || mode==0x2 || mode==0x3);
    519584    objectMode_=mode;
  • code/branches/objecthierarchy/src/network/Synchronisable.h

    r2112 r2132  
    6262  namespace syncmode{
    6363    enum mode{
    64       one=0,
     64      once=0,
    6565      always=1
    6666    };
     
    8181
    8282  struct _NetworkExport synchronisableVariable{
    83     unsigned int size;
    84     int mode; // this determines in which direction the variable gets synchronised
     83    size_t size;
     84    uint8_t mode; // this determines in which direction the variable gets synchronised
    8585    void *var;
    8686    variableType type;
     
    9898  public:
    9999    friend class packet::Gamestate;
    100     friend class GamestateClient;
    101     friend class Server;
     100//     friend class Server;
    102101    virtual ~Synchronisable();
    103102
     
    106105    static void setClient(bool b);
    107106
    108     static Synchronisable *fabricate(uint8_t*& mem, int mode=0x0);
     107    static Synchronisable *fabricate(uint8_t*& mem, uint8_t mode=0x0);
    109108    static bool deleteObject(unsigned int objectID);
    110109    static Synchronisable *getSynchronisable(unsigned int objectID);
     
    116115  protected:
    117116    Synchronisable(BaseObject* creator);
    118     void registerVar(void *var, int size, variableType t, int mode=1, NetworkCallbackBase *cb=0);
    119     void setObjectMode(int mode);
     117    void registerVar(void *var, int size, variableType t, uint8_t mode=0x1, NetworkCallbackBase *cb=0);
     118    void setObjectMode(uint8_t mode);
    120119    void setObjectFrequency(unsigned int freq){ objectFrequency_ = freq; }
    121120
    122121
    123122  private:
    124     bool getData(uint8_t*& men, unsigned int id, int mode=0x0);
    125     uint32_t getSize(unsigned int id, int mode=0x0);
    126     bool updateData(uint8_t*& mem, int mode=0x0, bool forceCallback=false);
     123    bool getData(uint8_t*& men, unsigned int id, uint8_t mode=0x0);
     124    uint32_t getSize(unsigned int id, uint8_t mode=0x0);
     125    bool updateData(uint8_t*& mem, uint8_t mode=0x0, bool forceCallback=false);
    127126    bool isMyData(uint8_t* mem);
    128127    bool doSelection(unsigned int id);
    129     bool doSync(unsigned int id);
     128    bool doSync(unsigned int id, uint8_t mode=0x0);
    130129
    131130    unsigned int objectID;
     
    134133
    135134    std::list<synchronisableVariable *> *syncList;
    136     static int state_; // detemines wheter we are server (default) or client
     135    static uint8_t state_; // detemines wheter we are server (default) or client
    137136    bool backsync_; // if true the variables with mode > 1 will be synchronised to server (client -> server)
    138137    unsigned int objectFrequency_;
  • code/branches/objecthierarchy/src/network/packet/Gamestate.cc

    r2112 r2132  
    7171}
    7272
    73 bool Gamestate::collectData(int id, int mode)
    74 {
    75   int tempsize=0, currentsize=0;
     73bool Gamestate::collectData(int id, uint8_t mode)
     74{
     75  unsigned int tempsize=0, currentsize=0;
    7676  assert(data_==0);
    77   int size = calcGamestateSize(id, mode);
     77  unsigned int size = calcGamestateSize(id, mode);
    7878
    7979  COUT(4) << "G.ST.Man: producing gamestate with id: " << id << std::endl;
     
    8686  }
    8787
    88 #ifndef NDEBUG
    89   std::list<Synchronisable*> slist;
    90   std::list<Synchronisable*>::iterator iit;
    91 #endif
    9288  //start collect data synchronisable by synchronisable
    9389  uint8_t *mem=data_;
     
    9894
    9995    if(currentsize+tempsize > size){
     96      assert(0); // if we don't use multithreading this part shouldn't be neccessary
    10097      // start allocate additional memory
    10198      COUT(3) << "G.St.Man: need additional memory" << std::endl;
     
    110107    }// stop allocate additional memory
    111108
    112 #ifndef NDEBUG
    113     for(iit=slist.begin(); iit!=slist.end(); iit++)
    114       assert((*iit)!=*it);
    115     slist.push_back(*it);
    116 #endif
    117109
    118110    //if(it->doSelection(id))
     
    127119  //start write gamestate header
    128120  HEADER->packetType = ENUM::Gamestate;
    129   assert( *(ENUM::Type *)(data_) == ENUM::Gamestate);
    130121  HEADER->datasize = currentsize;
    131122  HEADER->id = id;
     
    140131}
    141132
    142 bool Gamestate::spreadData(int mode)
     133bool Gamestate::spreadData(uint8_t mode)
    143134{
    144135  assert(data_);
     
    163154      bool b = s->updateData(mem, mode);
    164155      assert(b);
    165       //if(!s->updateData(mem, mode))
    166         //return false;
    167156    }
    168157  }
     
    367356    assert(it->second->objectID==oldobjectheader->objectID);
    368357    *newobjectheader = *oldobjectheader;
    369     objectOffset=sizeof(uint8_t)+sizeof(bool); //skip the size and the availableData variables in the objectheader
     358    objectOffset=sizeof(synchronisableHeader); //skip the size and the availableData variables in the objectheader
    370359    if(it->second->doSelection(HEADER->id)){
    371360      newobjectheader->dataAvailable=true; //TODO: probably not neccessary
     
    565554
    566555
    567 unsigned int Gamestate::calcGamestateSize(unsigned int id, int mode)
    568 {
    569   int size=0;
     556unsigned int Gamestate::calcGamestateSize(unsigned int id, uint8_t mode)
     557{
     558  unsigned int size=0;
    570559    // get the start of the Synchronisable list
    571560  ObjectList<Synchronisable>::iterator it;
  • code/branches/objecthierarchy/src/network/packet/Gamestate.h

    r2112 r2132  
    6969    ~Gamestate();
    7070
    71     bool collectData(int id, int mode=0x0);
    72     bool spreadData(int mode=0x0);
     71    bool collectData(int id, uint8_t mode=0x0);
     72    bool spreadData( uint8_t mode=0x0);
    7373    int getID();
    7474    bool isDiffed();
     
    9090    bool operator ==(packet::Gamestate gs);
    9191  private:
    92     unsigned int calcGamestateSize(unsigned int id, int mode=0x0);
     92    unsigned int calcGamestateSize(unsigned int id, uint8_t mode=0x0);
    9393    void removeObject(ObjectListIterator<Synchronisable> &it);
    9494    std::map<unsigned int, Synchronisable*> dataMap_;
  • code/branches/objecthierarchy/src/network/packet/Packet.cc

    r2112 r2132  
    5353#define _PACKETID           0
    5454
    55 std::map<ENetPacket *, Packet *> Packet::packetMap_;
     55std::map<size_t, Packet *> Packet::packetMap_;
    5656
    5757Packet::Packet(){
     
    134134    // Add the packet to a global list so we can access it again once enet calls our
    135135    // deletePacket method. We can of course only give a one argument function to the ENet C library.
    136     packetMap_[enetPacket_] = this;
     136    packetMap_[(size_t)(void*)enetPacket_] = this;
    137137  }
    138138#ifndef NDEBUG
     
    208208void Packet::deletePacket(ENetPacket *enetPacket){
    209209  // Get our Packet from a gloabal map with all Packets created in the send() method of Packet.
    210   std::map<ENetPacket*, Packet*>::iterator it = packetMap_.find(enetPacket);
     210  std::map<size_t, Packet*>::iterator it = packetMap_.find((size_t)enetPacket);
    211211  assert(it != packetMap_.end());
    212212  // Make sure we don't delete it again in the destructor
  • code/branches/objecthierarchy/src/network/packet/Packet.h

    r2112 r2132  
    9292    bool bDataENetAllocated_;
    9393  private:
    94     static std::map<ENetPacket *, Packet *> packetMap_;
     94    static std::map<size_t, Packet *> packetMap_;
    9595    ENetPacket *enetPacket_;
    9696};
Note: See TracChangeset for help on using the changeset viewer.