home *** CD-ROM | disk | FTP | other *** search
- /* START_LICENSE_HEADER
-
- Copyright (C) 2000 Martin Piper, original design and program code
- Copyright (C) 2001-2005 Replica Software
-
- This program file is copyright (C) Replica Software and can only be used under license.
- For more information visit: http://www.replicanet.com/
- Or email: info@replicanet.com
-
- END_LICENSE_HEADER */
- #if defined(_WIN32)
- #pragma warning(disable : 4786)
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include "DataBlock_GenericSTLVirtual.h"
- #include "RNReplicaNet/Inc/ReplicaNet.h"
- #include "RNPlatform/Inc/MessageHelper.h"
- #include "RNPlatform/Inc/MemoryTracking.h"
-
- using namespace RNReplicaNet;
-
- DataBlock_GenericSTLVirtual::DataBlock_GenericSTLVirtual() : mData(0)
- {
- // Because we are going to be updating an stl list or vector then we want to make sure updates are in order.
- SetReliableFlag(true);
- }
-
- DataBlock_GenericSTLVirtual::~DataBlock_GenericSTLVirtual()
- {
- std::map<int,SessionBlock *>::iterator st,en;
- st = mPerSessionData.begin();
- en = mPerSessionData.end();
-
- // Delete the remaining session blocks attached to this datablock
- while(st != en)
- {
- SessionBlock *sessdataptr = (*st++).second;
- delete sessdataptr;
- }
- }
-
- void DataBlock_GenericSTLVirtual::Poll(DataBlockReason *reason)
- {
- if (!reason)
- {
- return;
- }
-
- switch (reason->mReasonCode)
- {
- case kDataBlockReason_SomeoneJoined:
- {
- if (!reason->mMessageHelper)
- {
- return;
- }
- SessionBlock *sessdataptr = new SessionBlock(reason->mSessionReference);
- DoInitialSettingsFor(sessdataptr,GetElementSize());
- // Insert SessionBlock into the std::map with the key reason->mSessionReference
- mPerSessionData[reason->mSessionReference] = sessdataptr;
-
- // Someone joined so calculate an immediate update
- DataBlock::Poll(reason);
- // Number of elements
- reason->mMessageHelper->AddVariable(&sessdataptr->mNumElements,sizeof(sessdataptr->mNumElements));
- // Number of elements changed
- reason->mMessageHelper->AddVariable(&sessdataptr->mNumElements,sizeof(sessdataptr->mNumElements));
- int i;
- for (i=0;i<sessdataptr->mNumElements;i++)
- {
- reason->mMessageHelper->AddVariable(&i,sizeof(i));
- reason->mMessageHelper->AddVariable(sessdataptr->mOrderedElementData[i],GetElementSize());
- }
-
- return;
- }
-
- case kDataBlockReason_SomeoneLeft:
- {
- std::map<int,SessionBlock *>::iterator found;
- found = mPerSessionData.find(reason->mSessionReference);
- if (found != mPerSessionData.end())
- {
- SessionBlock *sessdataptr = (*found).second;
- assert (sessdataptr->mSessionID == reason->mSessionReference);
- mPerSessionData.erase(found);
- delete sessdataptr;
- return;
- }
- break;
- }
-
- case kDataBlockReason_RecordingNormalPoll:
- {
- // Send the best of what we have so far. This happens to be the current replica state.
- DataBlock::Poll(reason);
- int numElements = GetNumberOfElements();
- reason->mMessageHelper->AddVariable(&numElements,sizeof(numElements));
- // Number of elements changed
- reason->mMessageHelper->AddVariable(&numElements,sizeof(numElements));
- int i;
- for (i=0;i<numElements;i++)
- {
- reason->mMessageHelper->AddVariable(&i,sizeof(i));
- reason->mMessageHelper->AddVariable(GetElementPointerAt(i),GetElementSize());
- }
- break;
- }
-
- case kDataBlockReason_NormalPoll:
- {
- if (!reason->mMessageHelper)
- {
- return;
- }
-
- std::map<int,SessionBlock *>::iterator found;
- found = mPerSessionData.find(reason->mSessionReference);
- if (found != mPerSessionData.end())
- {
- SessionBlock *sessdataptr = (*found).second;
- assert (sessdataptr->mSessionID == reason->mSessionReference);
-
- int numElementsChanged = 0;
- bool theSizeChanged = false;
- int i;
- for (i=0;i<GetNumberOfElements();i++)
- {
- // If the data is the same then do nothing
- if (memcmp(sessdataptr->mOrderedElementData[i],GetElementPointerAt(i),GetElementSize()) != 0)
- {
- numElementsChanged++;
- }
- }
-
- if (GetNumberOfElements() != sessdataptr->mNumElements)
- {
- theSizeChanged = true;
- }
-
- // If either the size or the contents have changed then
- if (theSizeChanged || numElementsChanged > 0)
- {
- // Send the update data
- DataBlock::Poll(reason);
- // Number of elements
- reason->mMessageHelper->AddVariable(&sessdataptr->mNumElements,sizeof(sessdataptr->mNumElements));
- // Number of elements changed
- reason->mMessageHelper->AddVariable(&numElementsChanged,sizeof(numElementsChanged));
- int i;
- for (i=0;i<sessdataptr->mNumElements;i++)
- {
- if (memcmp(sessdataptr->mOrderedElementData[i],GetElementPointerAt(i),GetElementSize()) != 0)
- {
- reason->mMessageHelper->AddVariable(&i,sizeof(i));
- reason->mMessageHelper->AddVariable(GetElementPointerAt(i),GetElementSize());
- }
- }
-
- // After sending the update then copy what we sent
- DoInitialSettingsFor(sessdataptr,GetElementSize());
- }
-
- return;
- }
- break;
- }
-
- default:
- break;
- }
- }
-
- void DataBlock_GenericSTLVirtual::ParseMessage(MessageHelper *message)
- {
- // Decode our updates
- int newSize;
- int numChanged;
- message->GetVariable(&newSize,sizeof(newSize));
- message->GetVariable(&numChanged,sizeof(numChanged));
-
- SetNumberOfElements(newSize);
- int i;
- for (i=0;i<numChanged;i++)
- {
- int index;
- message->GetVariable(&index,sizeof(index));
- void *data = GetElementPointerAt(index);
- message->GetVariable(data,GetElementSize());
- }
- }
-
- DataBlock_GenericSTLVirtual::SessionBlock::SessionBlock(int sessid)
- {
- mSessionID = sessid;
- mOrderedElementData = 0;
- mNumElements = 0;
- }
-
- DataBlock_GenericSTLVirtual::SessionBlock::~SessionBlock()
- {
- if (mOrderedElementData)
- {
- int i;
- for (i=0;i<mNumElements;i++)
- {
- free(mOrderedElementData[i]);
- }
- free(mOrderedElementData);
- mOrderedElementData = 0;
- }
- }
-
- void DataBlock_GenericSTLVirtual::DoInitialSettingsFor(SessionBlock *sessionBlock,const int elementSize)
- {
- // First free all of our blocks
- if (sessionBlock->mOrderedElementData)
- {
- int i;
- for (i=0;i<sessionBlock->mNumElements;i++)
- {
- free(sessionBlock->mOrderedElementData[i]);
- }
- free(sessionBlock->mOrderedElementData);
- sessionBlock->mOrderedElementData = 0;
- }
-
- sessionBlock->mNumElements = GetNumberOfElements();
-
- if (sessionBlock->mNumElements > 0)
- {
-
- sessionBlock->mOrderedElementData = (void **) malloc(sizeof(void *) * sessionBlock->mNumElements);
- int i;
- for (i=0;i<sessionBlock->mNumElements;i++)
- {
- sessionBlock->mOrderedElementData[i] = malloc(elementSize);
- void *data = GetElementPointerAt(i);
- memcpy(sessionBlock->mOrderedElementData[i],data,elementSize);
- }
- }
- }
-
-