void MemoryConsumption::scan(void)
{
    FieldContainerFactory::the()->lockStore();

    FieldContainerFactoryBase::ContainerStoreConstIt sIt  =
        FieldContainerFactory::the()->beginStore();
    FieldContainerFactoryBase::ContainerStoreConstIt sEnd =
        FieldContainerFactory::the()->endStore();

    for(; sIt != sEnd; ++sIt)
    {
        FieldContainer *pFC = (*sIt).second->getPtr();

        if(pFC == NULL)
            continue;

        TypeMemMapIt tmIt    = _memMap.find(pFC->getType().getId());
        SizeT        binSize = pFC->getBinSize(TypeTraits<BitVector>::BitsSet);

        if(tmIt != _memMap.end())
        {
            tmIt->second.first  += binSize;
            tmIt->second.second += 1;
        }
        else
        {
            _memMap[pFC->getType().getId()] = MemCountPair(binSize, 1);
        }
    }

    FieldContainerFactory::the()->unlockStore();
}
Beispiel #2
0
void printFieldContainer() {
    int N = FieldContainerFactory::the()->getNumTotalContainers();
    for (int i=0;i<N;++i) {
        FieldContainer* fc = FieldContainerFactory::the()->getContainer(i);
        if(fc == 0) continue;

        // skip prototypes
        if(fc->getType().getPrototype() == 0 || fc->getType().getPrototype() == fc  ) continue;

        //cout << "\nFC id: " << fc->getId() << flush;

        AttachmentContainer* ac = dynamic_cast<AttachmentContainer*>(fc);
        if (ac == 0) {
            Attachment* a = dynamic_cast<Attachment*>(fc);
            if (a != 0) {
                FieldContainer* dad = 0;
                if (a->getMFParents()->size() > 0) dad = a->getParents(0);
                ac = dynamic_cast<AttachmentContainer*>(dad);
            }
        }

        const Char8* name = getName(ac);
        if (name != 0) printf("Detected living FC %s (%s) %p refcount %d ID %d\n", fc->getTypeName(), name, fc, fc->getRefCount(), fc->getId());
        else printf( "Detected living FC %s %p refcount %d ID %d\n", fc->getTypeName(), fc, fc->getRefCount(), fc->getId() );
    }
}
void
QFCItem::setup(void)
{
    FieldContainer *pFCAsp = getFC().getAspectCPtr(getAspect());

    if(!pFCAsp)
        return;

    UInt32 uiNumFields = pFCAsp->getType().getNumFieldDescs();
    
    for(UInt32  fieldId = 1; fieldId <= uiNumFields; ++fieldId)
    {
        FieldDescription *pDesc     = 
            pFCAsp->getType().getFieldDescription     (fieldId);
        Field            *pField    = pFCAsp->getField(fieldId);
        
        if(isSFFieldContainerPtr(pField))
        {
            if(stringcmp(pDesc->getCName(), "parent" ) == 0)
                continue;

            SFFieldContainerPtr *pSFFCPtr = 
                reinterpret_cast<SFFieldContainerPtr *>(pField);

            if(pSFFCPtr->getValue() != NullFC)
            {
                setExpandable(this);
                break;
            }
        }
        else if(isMFFieldContainerPtr(pField))
        {
            MFFieldContainerPtr *pMFFCPtr =
                reinterpret_cast<MFFieldContainerPtr *>(pField);

            if(stringcmp(pDesc->getCName(), "parents") == 0)
            {
                if(pMFFCPtr->size() > 1)
                {
                    setExpandable(this);
                    break;
                }
            }
            else
            {
                if(pMFFCPtr->size() > 0)
                {
                    setExpandable(this);
                    break;
                }
            }
        }
    }

    Inherited::setup();
}
void ChangeList::addCreated(const UInt32 uiContainerId, 
                                  BitVector bFlags    )
{
#ifdef OSG_ENABLE_VALGRIND_CHECKS
    VALGRIND_CHECK_VALUE_IS_DEFINED(uiContainerId);
#endif

#ifndef SILENT
    FieldContainer *fcPtr =  
        FieldContainerFactory::the()->getContainer(uiContainerId);

    fprintf(stderr, "Add Create %u : %d : %s\n",
            uiContainerId,
            fcPtr != NULL ? fcPtr->getTypeId() : -1,
            fcPtr != NULL ? fcPtr->getType  ().getCName() : "Unknow");
#endif
    if(_bReadOnly == true)
        return;

    ContainerChangeEntry *pEntry = getNewCreatedEntry();

    pEntry->uiEntryDesc   = ContainerChangeEntry::Create;
    pEntry->uiContainerId = uiContainerId;
    pEntry->whichField    = bFlags;
}
/*! Visits a SFFieldContainerPtr (or more specific pointer type) during
    preWrite. It creates an element for the pointed to container and
    calls preWrite on it. If the pointed to container is not in the
    root's id set it is added and thus scheduled for writing.

    \param[in] fieldId Id of the field in the container of this element.
 */
void
OSBCommonElement::preWritePtrSingleField(const UInt32 fieldId)
{
    OSG_OSB_LOG(("OSBCommonElement::preWritePtrSingleField: "
            "fieldId: [%u]\n", fieldId));

    OSBRootElement     *root       = editRoot();

    FieldContainerPtrSFieldBase::GetHandlePtr sfPtrField =
        boost::dynamic_pointer_cast<FieldContainerPtrSFieldBase::GetHandle>(
            getContainer()->getField(fieldId));

    if(sfPtrField == NULL || sfPtrField->isValid() == false)
        return;

    FieldContainer *refedFC = (*sfPtrField)->getValue();

    if(refedFC == NULL)
        return;

    UInt32             refedId  = refedFC->getId  ();
    const std::string &typeName = refedFC->getType().getName();

    // only schedule a container once
    if(root->getIdSet().count(refedId) == 0)
    {
        OSBElementBase *elem = OSBElementFactory::the()->acquire(
            typeName, root);

        root->editIdSet      ().insert   (refedId);
        root->editElementList().push_back(elem   );
        elem->setContainer(refedFC);
        elem->preWrite    (refedFC);
    }
}
void ContainerChangeEntry::commitChanges(UInt32 AdditionalChangeOrigin)
{
#ifdef OSG_ENABLE_VALGRIND_CHECKS
    VALGRIND_CHECK_VALUE_IS_DEFINED(uiContainerId);
#endif
    FieldContainer *pTmp =
        FieldContainerFactory::the()->getContainer(uiContainerId);

    if(pTmp != NULL)
    {
#ifndef SILENT
        fprintf(stderr, "Commit for %u %s\n",
                uiContainerId, pTmp->getType().getCName());
#endif
        
        BitVector tmpChanges;
        //OSG_ASSERT(NULL !=  bvUncommittedChanges);

        if (NULL != bvUncommittedChanges)
        { 
#ifdef OSG_ENABLE_MEMORY_DEBUGGING
           OSG_ASSERT(*bvUncommittedChanges != 0xDEADBEEF);
#endif
           tmpChanges             = *bvUncommittedChanges; 
           whichField            |= *bvUncommittedChanges;
           *bvUncommittedChanges  = TypeTraits<BitVector>::BitsClear;

           pTmp->changed      (tmpChanges, ChangedOrigin::Commit | AdditionalChangeOrigin, 0);
        }
    }
}
void RemoteAspect::receiveChanged(Connection                &con,
                                  FieldContainerFactoryBase *fcFactory)
{
    UInt32          remoteId  = 0;
    UInt32          localId   = 0;
    BitVector       fieldMask = 0;
    UInt32          len       = 0;
    FieldContainer *fcPtr     = NULL;

    con.getValue(remoteId);
    con.getValue(fieldMask);
    con.getValue(len);

    if(getLocalId(remoteId, localId))
    {
        fcPtr = fcFactory->getContainer(localId);

#ifndef OSG_REMOTE_ASPECT_SILENT
        SLOG << "Receive CHANGED: id (r/l) '" << remoteId
             << "/" << localId
             << "' mask '0x"
             << std::hex << fieldMask << std::dec
             << "' len '" << len
             << "' type name '"
             << (fcPtr != NULL ? fcPtr->getType().getName() : "")
             << "'\n";
#endif

        if(fcPtr == NULL)
        {
            clearFCMapping(localId, remoteId);

            char dummy;

            while(len--)
                con.get(&dummy, 1);
        }
        else
        {
            fcPtr->copyFromBin(con, fieldMask);

            callChanged(fcPtr);
        }
    }
    else
    {
        char dummy;

        SWARNING << "Can not do CHANGED for unknown FC remote id "
                 << remoteId
                 << " skip "
                 << len
                 << " bytes."
                 << std::endl;

        while(len--)
            con.get(&dummy, 1);
    }
}
void InsertFieldElementCommand::execute(void)
{
    //Check for a valid Field Container
    if(_FC == NULL)
    {
        SWARNING << "FieldContainer is NULL." << std::endl;
        return;
    }

    //Check for valid Field
    EditFieldHandlePtr TheFieldHandle = _FC->editField(_FieldId);
    if(!TheFieldHandle->isValid())
    {
        SWARNING << "No Field with Id: " << _FieldId << " in FieldContainers of type " << _FC->getType().getName() << std::endl;
        return;
    }

    //Check for valid Field cardinality
    if(TheFieldHandle->getCardinality() != FieldType::MultiField)
    {
        SWARNING << "Field: " << _FC->getType().getName() << " is not a MultiField" << std::endl;
        return;
    }

    //Check for valid indexing
    if(TheFieldHandle->getCardinality() == FieldType::MultiField && _Index > TheFieldHandle->size())
    {
        SWARNING << "Cannot insert the value " << _Value << " at index " << _Index << ", on field " << TheFieldHandle->getDescription()->getName() 
                 << ", on FieldContianer of type " << _FC->getType().getName()
                 << " because that field has size " << TheFieldHandle->size() << std::endl;
        return;
    }
        
    if(TheFieldHandle->isPointerField())
    {
        EditMFieldHandle<FieldContainerPtrMFieldBase>* TheHandle(dynamic_cast<EditMFieldHandle<FieldContainerPtrMFieldBase>*>(TheFieldHandle.get()));
        FieldContainer* FC = FieldContainerFactory::the()->getContainer(boost::lexical_cast<UInt32>(_Value));
        //Check the pointer types match
        if(!isFieldContentDerivedFrom(TheFieldHandle->getType(),&FC->getType()))
        {
            SWARNING << "Cannot insert the value of field " << TheFieldHandle->getDescription()->getName() 
                     << ", on FieldContianer of type " << _FC->getType().getName()
                     << " because the value attemting to be set is not derived from the type the field stores." << std::endl;
            return;
        }

        TheHandle->insert(_Index, FC);
    }
    else
    {
        TheFieldHandle->insertIndexedValueFromCString(_Value.c_str(), _Index);
    }

    Inherited::execute();
	_HasBeenDone = true;
}
void
QFCItem::expand(void)
{
    if(childCount() != 0)
        return;

    FieldContainer *pFCAsp = getFC().getAspectCPtr(getAspect());

    if(!pFCAsp)
        return;

    FieldContainerType &fcType      = pFCAsp->getType();
    UInt32              uiNumFields = fcType.getNumFieldDescs();

    for(UInt32 fieldId = 1; fieldId <= uiNumFields; ++fieldId)
    {
        FieldDescription *pFieldDesc = fcType.getFieldDescription(fieldId);
        Field            *pField     = pFCAsp->getField          (fieldId);
        
        //add Items for all referenced containers (except parents)
        if(isSFFieldContainerPtr(pField))
        {
            if(stringcmp(pFieldDesc->getCName(), "parent" ) == 0)
                continue;

            addRefedContainer(
                reinterpret_cast<SFFieldContainerPtr *>(pField));
        }
        else if(isMFFieldContainerPtr(pField))
        {
            if(stringcmp(pFieldDesc->getCName(), "parents") == 0)
            {
                addParents(
                    reinterpret_cast<MFFieldContainerPtr *>(pField));
            }
            else
            {
                addRefedContainer(
                    reinterpret_cast<MFFieldContainerPtr *>(pField), 
                    pFieldDesc   );
            }
        }

        //add attachments
        if(stringcmp(pFieldDesc->getCName(), "attachments") == 0)
        {
            addAttachments(dynamic_cast<SFAttachmentMap *>(pField));
        }
    }

    PNOTICE << endLog;
}
/*! Writes all fields to the stream, except for those whose name is in
    \a excludeFields. Optionally writes an end marker.

    The excludeFields string has the format: "'name1' 'name2' 'name3'",
    the spaces between the "'" are mandatory.

    \param[in] excludeFields String of field names that shall be skipped.
    \param[in] endMarker Write an end marker to the stream after all fields are
    processed.
 */
void
OSBCommonElement::writeFields(
    const std::string &excludeFields, const bool endMarker)
{
    OSG_OSB_LOG(("OSBCommonElement::writeFields: "
            "excludeFields: [%s]\n", excludeFields.c_str()));

    FieldContainer *fc         = getContainer();
    UInt32          fieldCount = fc->getType().getNumFieldDescs();

    // go through all fields and write them.
    for(UInt32 fieldId = 1; fieldId <= fieldCount; ++fieldId)
    {
        const FieldDescriptionBase *fieldDesc =
            fc->getFieldDescription(fieldId);
        const std::string          &fieldName = fieldDesc->getName();

        // skip internal fields
        if(fieldDesc->isInternal())
        {
            OSG_OSB_LOG(("OSBCommonElement::writeFields: "
                    "Skipping internal field: [%s]\n", fieldName.c_str()));
            continue;
        }

        // skip excluded fields
        if((!excludeFields.empty()                                        ) &&
           (excludeFields.find("'" + fieldName + "'") != std::string::npos)   )
        {
            OSG_OSB_LOG(("OSBCommonElement::writeFields: "
                    "Skipping excluded field: [%s]\n", fieldName.c_str()));
            continue;
        }

        const FieldType   &fieldType     = fieldDesc->getFieldType();
        const std::string &fieldTypeName = fieldType .getName     ();
        BitVector          fieldMask     = fieldDesc->getFieldMask();
        UInt32             fieldSize     = UInt32(fc->getBinSize(fieldMask));

        writeFieldHeader (fieldName, fieldTypeName, fieldSize);
        writeFieldContent(fieldId                            );
    }

    if(endMarker)
    {
        writeEndMarker();
    }
}
/*! Visits a MFFieldContainerPtr (or more specific pointer type) during
    preWrite. It creates elements for the pointed to containers and
    calls preWrite on them. If the pointed to containers are not in the
    root's id set they are added and thus scheduled for writing.

    \param[in] fieldId Id of the field in the container of this element.
 */
void
OSBCommonElement::preWritePtrMultiField(const UInt32 fieldId)
{
    OSG_OSB_LOG(("OSBCommonElement::preWritePtrMultiField: "
            "fieldId: [%u]\n", fieldId));

    OSBRootElement           *root       = editRoot();

    FieldContainerPtrMFieldBase::GetHandlePtr mfPtrField =
        boost::dynamic_pointer_cast<FieldContainerPtrMFieldBase::GetHandle>(
            getContainer()->getField(fieldId));

    if(mfPtrField == NULL || mfPtrField->isValid() == false)
        return;

    FieldContainerPtrMFieldBase::const_iterator fieldIt  = 
        (*mfPtrField)->begin();

    FieldContainerPtrMFieldBase::const_iterator fieldEnd = 
        (*mfPtrField)->end  ();

    for(; fieldIt != fieldEnd; ++fieldIt)
    {
        FieldContainer *refedFC = *fieldIt;

        if(refedFC == NULL)
            continue;

        UInt32             refedId  = refedFC->getId  ();
        const std::string &typeName = refedFC->getType().getName();

        // only schedule a container once
        if(root->getIdSet().count(refedId) > 0)
            continue;

        OSBElementBase *elem = OSBElementFactory::the()->acquire(
            typeName, root);

        root->editIdSet      ().insert   (refedId);
        root->editElementList().push_back(elem   );
        elem->setContainer(refedFC);
        elem->preWrite    (refedFC);
    }
}
/*! Fills this changelist with entries that represent the current state of
    the system starting at the container with the given id.
    Prototypes are skipped unless skipPrototypes is false.

    For every container a 'Create' entry and a 'Change' entry (marking all fields
    as modified) is added and as many 'AddReference' entries as the ref count
    of the container.
 */
void ChangeList::fillFromCurrentState(UInt32 uiFieldContainerId,
                                      bool   skipPrototypes     )
{
    this->clear();

    UInt32 uiNumContainers = 
        FieldContainerFactory::the()->getNumContainers();

    if(uiNumContainers <= uiFieldContainerId)
    {
        return;
    }

    for(UInt32 i = uiFieldContainerId; i < uiNumContainers; ++i)
    {
        FieldContainer *pContainer = 
            FieldContainerFactory::the()->getContainer(i);

        // skip destroyed FC
        if(pContainer == NULL)
          continue;

        // skip prototypes - unless requested
        if(skipPrototypes == true &&
           (pContainer->getType().getPrototype() == pContainer ||
            pContainer->getType().getPrototype() == NULL         ))
        {
            continue;
        }

        this->addCreated(i, TypeTraits<BitVector>::BitsClear);

        for(Int32 j = 0; j < pContainer->getRefCount(); ++j)
            this->addAddRefd(i);

        ContainerChangeEntry *pEntry = this->getNewEntry();

        pEntry->uiEntryDesc   = ContainerChangeEntry::Change;
        pEntry->pFieldFlags   = pContainer->getFieldFlags();
        pEntry->uiContainerId = i;
        pEntry->whichField    = FieldBits::AllFields;
        pEntry->pList         = this;
    }
}
void RemoteAspect::receiveSubRefed(Connection                &con,
                                   FieldContainerFactoryBase *fcFactory,
                                   ChangeList                *pChangeList)
{
    UInt32          remoteId = 0;
    UInt32          localId  = 0;
    FieldContainer *fcPtr    = NULL;

    con.getValue(remoteId);

    if(getLocalId(remoteId, localId))
    {
        fcPtr = fcFactory->getContainer(localId);

#ifndef OSG_REMOTE_ASPECT_SILENT
        SLOG << "Receive SUBREFED: remote id '" << remoteId
             << "' local id '"                  << localId
             << "' type name '"
             << (fcPtr != NULL ? fcPtr->getType().getName() : "")
             << "'\n";
#endif

        if(fcPtr == NULL)
        {
            clearFCMapping(localId, remoteId);
        }
        else
        {
            pChangeList->addDelayedSubRef<RecordedRefCountPolicy>(fcPtr);
        }
    }
    else
    {
        SWARNING << "Can not do SUBREFED for unknown FC remote id "
                 << remoteId << std::endl;
    }
}
/*! Fills the "pointer field" described by \a ptrField with the correct
    pointers.

    \param[in] ptrField Field to fill.
 */
void
OSBRootElement::mapPtrField(const PtrFieldInfo &ptrField)
{
    OSG_OSB_LOG(("OSBRootElement::mapPtrField\n"));

    PtrFieldInfo::PtrIdStoreConstIt   idIt       = ptrField.beginIdStore();
    PtrFieldInfo::PtrIdStoreConstIt   idEnd      = ptrField.endIdStore  ();

    PtrFieldInfo::BindingStoreConstIt bindingIt  = ptrField.beginBindingStore();
    PtrFieldInfo::BindingStoreConstIt bindingEnd = ptrField.endBindingStore  ();

    const FieldContainerIdMap        &idMap      = getIdMap();
          FieldContainerIdMapConstIt  idMapIt;
          FieldContainerIdMapConstIt  idMapEnd   = idMap.end();
        
    if(bindingIt != bindingEnd)
    {
        if(ptrField.getHandledField() == true)
        {
            FieldContainer    *fieldCon = ptrField.getContainer();
            UInt32             fieldId  = ptrField.getFieldId();
        
            EditFieldHandlePtr fHandle  = fieldCon->editField(fieldId);

            EditMapFieldHandlePtr sfMapField =
                boost::dynamic_pointer_cast<EditMapFieldHandle>(fHandle);

            if(sfMapField == NULL || sfMapField->isValid() == false)
                return;

            sfMapField->fillFrom(ptrField.getBindingStore(),
                                 ptrField.getIdStore     (),
                                 idMap);
        }
        else
        {
            Attachment          *att    = NULL;
            AttachmentContainer *attCon =
                dynamic_cast<AttachmentContainer *>(ptrField.getContainer());
            
            for(; (idIt != idEnd) && (bindingIt != bindingEnd); ++idIt, 
                                                                ++bindingIt)
            {
                if(*idIt != 0)
                {
                    idMapIt = idMap.find(*idIt);
                    
                    if(idMapIt != idMapEnd)
                    {
                        att = dynamic_cast<Attachment *>(
                            FieldContainerFactory::the()->getContainer(
                                idMapIt->second));
                    }
                    else
                    {
                        FWARNING(("OSBRootElement::mapPtrField: could not find "
                                  "FieldContainer with id [%u]\n", *idIt));
                        att = NULL;
                    }
                }
                else
                {
                    att = NULL;
                }
                
                if(att != NULL)
                {
                    OSG_OSB_LOG(("OSBRootElement::mapPtrField: adding "
                            "attchment [%u] [%u]\n",
                            att->getType().getGroupId(), *bindingIt));
                }

                attCon->addAttachment(att, *bindingIt);
            }
        }
    }
    else
    {
        FieldContainer    *fc       = NULL;
        FieldContainer    *fieldCon = ptrField.getContainer();
        UInt32             fieldId  = ptrField.getFieldId();
        
        EditFieldHandlePtr fHandle  = fieldCon->editField(fieldId);
        
        FieldContainerPtrSFieldBase::EditHandlePtr pSFHandle = 
            boost::dynamic_pointer_cast<
                FieldContainerPtrSFieldBase::EditHandle>(fHandle);
            
        FieldContainerPtrMFieldBase::EditHandlePtr pMFHandle = 
            boost::dynamic_pointer_cast<
                FieldContainerPtrMFieldBase::EditHandle>(fHandle);
        
        for(; idIt != idEnd; ++idIt)
        {
            if(*idIt != 0)
            {
                idMapIt = idMap.find(*idIt);
                
                if(idMapIt != idMapEnd)
                {
                    fc = FieldContainerFactory::the()->getContainer(
                        idMapIt->second);
                }
                else
                {
                    FWARNING(("OSBRootElement::mapPtrField: could not find "
                              "FieldContainer with (file) id [%u]\n", *idIt));
                    fc = NULL;
                }
            }
            else
            {
                fc = NULL;
            }

            if(pSFHandle != NULL && pSFHandle->isValid())
            {
                pSFHandle->set(fc);
            }
            else if(pMFHandle != NULL && pMFHandle->isValid())
            {
                pMFHandle->add(fc);
            }
            else
            {
                FWARNING(("OSBRootElement::mapPtrField: FieldHandles invalid, "
                          "can not set pointer - target fc [%u][%s] "
                          "fieldId [%u][%s] file id [%u] system id [%u]\n",
                          (fc != NULL ? fc->getId() : 0),
                          (fc != NULL ? fc->getType().getCName() : ""),
                          fieldId,
                          (fc != NULL ?
                          fc->getType().getFieldDesc(fieldId)->getCName() : ""),
                          *idIt,
                          (idMapIt != idMapEnd ? idMapIt->second : 0) ));
            }
        }
    }
}
void
OSBGeometryElement::preWrite(FieldContainer * const fc)
{
    OSG_OSB_LOG(("OSBGeometryElement::preWrite\n"));

    OSBRootElement *root       = editRoot();
    UInt32          fieldCount = fc->getType().getNumFieldDescs();

    UInt8 quanResPositions = root->getOptions().quantizePositions();
    UInt8 quanResNormals   = root->getOptions().quantizeNormals  ();
    UInt8 quanResTexCoords = root->getOptions().quantizeTexCoords();
    bool  packIndices      = root->getOptions().packIndices      ();

    // go through all fields and find those refering to other FCs
    for(UInt32 fieldId = 1; fieldId <= fieldCount; ++fieldId)
    {
        const FieldDescriptionBase *fieldDesc = fc->getFieldDescription(fieldId);
        const FieldType            &fieldType = fieldDesc->getFieldType();
        const std::string          &fieldName = fieldDesc->getName     ();

        // skip internal fields
        if(fieldDesc->isInternal())
        {
            OSG_OSB_LOG(("OSBGeometryElement::preWrite: "
                    "Skipping internal field: [%s]\n", fieldName.c_str()));
            continue;
        }

        if(fieldName == "properties")
        {
            // "properties" might be quantized
            FieldContainerPtrMFieldBase::GetHandlePtr fP =
                boost::dynamic_pointer_cast<
                    FieldContainerPtrMFieldBase::GetHandle>(
                        getContainer()->getField(fieldId));

            if(fP == NULL || fP->isValid() == false)
                continue;

            FieldContainerPtrMFieldBase::const_iterator fieldIt  = 
                (*fP)->begin();

            FieldContainerPtrMFieldBase::const_iterator fieldEnd = 
                (*fP)->end  ();

            for(UInt32 i = 0; fieldIt != fieldEnd; ++fieldIt, ++i)
            {
                FieldContainer *refedFC = *fieldIt;

                if(refedFC == NULL)
                    continue;

                      UInt32      refedId  = refedFC->getId  ();
                const std::string typeName = refedFC->getType().getName();

                // only schedule a container once
                if(root->getIdSet().count(refedId) > 0)
                    continue;

                OSBElementBase              *elem     =
                    OSBElementFactory::the()->acquire(typeName, root);
                OSBGeoVectorPropertyElement *propElem =
                    dynamic_cast<OSBGeoVectorPropertyElement *>(elem);

                if((propElem != 0) && (i == Geometry::PositionsIndex))
                {
                    propElem->setQuantizeResolution(quanResPositions);
                }
                else if((propElem != 0) && (i == Geometry::NormalsIndex))
                {
                    propElem->setQuantizeResolution(quanResNormals);
                }
                else if((propElem != 0) && (i >= Geometry::TexCoordsIndex) &&
                        (i <= Geometry::TexCoords7Index)                     )
                {
                    propElem->setQuantizeResolution(quanResTexCoords);
                }

                root->editIdSet      ().insert   (refedId);
                root->editElementList().push_back(elem   );
                elem->setContainer(refedFC);
                elem->preWrite    (refedFC);
            }
        }
        else if(fieldName == "propIndices")
        {
            // "propIndices" might be packed
            FieldContainerPtrMFieldBase::GetHandlePtr fP =
                boost::dynamic_pointer_cast<
                    FieldContainerPtrMFieldBase::GetHandle>(
                        getContainer()->getField(fieldId));

            if(fP == NULL || fP->isValid() == false)
                continue;

            FieldContainerPtrMFieldBase::const_iterator fieldIt  = 
                (*fP)->begin();
            FieldContainerPtrMFieldBase::const_iterator fieldEnd = 
                (*fP)->end  ();

            for(UInt32 i = 0; fieldIt != fieldEnd; ++fieldIt, ++i)
            {
                FieldContainer *refedFC = *fieldIt;

                if(refedFC == NULL)
                    continue;

                      UInt32      refedId  = refedFC->getId  ();
                const std::string typeName = refedFC->getType().getName();

                // only schedule a container once
                if(root->getIdSet().count(refedId) > 0)
                    continue;

                OSBElementBase                *elem     =
                    OSBElementFactory::the()->acquire(typeName, root);
                OSBGeoIntegralPropertyElement *propElem =
                    dynamic_cast<OSBGeoIntegralPropertyElement *>(elem);

                if((propElem != 0) && (packIndices == true))
                {
                    propElem->setPackData(true);
                }

                root->editIdSet      ().insert   (refedId);
                root->editElementList().push_back(elem   );
                elem->setContainer(refedFC);
                elem->preWrite    (refedFC);
            }
        }
        else if(fieldName == "attachments")
        {
            preWriteAttachmentMapField(fieldId);
        }
        else
        {
            // check if field refers to another FC, i.e. its a field holding
            // FieldContainerPtr or an FieldContainerAttachmentMap
            if(fieldType.getContentType().isDerivedFrom(
                FieldTraits<FieldContainer *>::getType()) == true)
            {
                if(fieldType.getCardinality() == FieldType::SingleField)
                {
                    preWritePtrSingleField(fieldId);
                }
                else if(fieldType.getCardinality() == FieldType::MultiField)
                {
                    preWritePtrMultiField(fieldId);
                }
            }
        }
    }
}
void ChangeList::dump(      UInt32    uiIndent,
                      const BitVector bvFlags ) const
{
    ChangedStoreConstIt cIt  = _createdStore.begin();
    ChangedStoreConstIt cEnd = _createdStore.end  ();

    fprintf(stderr, "CL created dump\n");

    while(cIt != cEnd)
    {
        for(UInt32 i = 0; i < uiIndent + 4; ++i)
        {
            fprintf(stderr, " ");
        }

        fprintf(stderr, "CE : %u %u\n",
                (*cIt)->uiEntryDesc,
                (*cIt)->uiContainerId);

        ++cIt;
    }

    cIt  = _changedStore.begin();
    cEnd = _changedStore.end  ();

    fprintf(stderr, "CL changed dump\n");

    while(cIt != cEnd)
    {
        for(UInt32 i = 0; i < uiIndent + 4; ++i)
        {
            fprintf(stderr, " ");
        }

        FieldContainer *pTmp =
            FieldContainerFactory::the()->getContainer((*cIt)->uiContainerId);

        std::string szTmp("Unknown");

        if(pTmp != NULL)
        {
            szTmp.assign(pTmp->getType().getCName());
        }

        BitVector tmpChanges = 0xDEADBEEF;

        if((*cIt)->bvUncommittedChanges != NULL && pTmp != NULL)
        { 
            tmpChanges = *((*cIt)->bvUncommittedChanges); 
        }

        fprintf(stderr, 
                "CE : %u %u 0x%016"PRIx64" 0x%016"PRIx64" (%p|%p) | %s\n",
                (*cIt)->uiEntryDesc,
                (*cIt)->uiContainerId,
                tmpChanges,
                (*cIt)->whichField,
                (*cIt),
                (*cIt)->bvUncommittedChanges,
                szTmp.c_str());

        ++cIt;
    }

    cIt  = _uncommitedChanges.begin();
    cEnd = _uncommitedChanges.end  ();

    fprintf(stderr, "CL uncommited dump\n");

    while(cIt != cEnd)
    {
        for(UInt32 i = 0; i < uiIndent + 4; ++i)
        {
            fprintf(stderr, " ");
        }

        FieldContainer *pTmp =
            FieldContainerFactory::the()->getContainer((*cIt)->uiContainerId);

        std::string szTmp("Unknown");

        if(pTmp != NULL)
        {
            szTmp.assign(pTmp->getType().getCName());
        }

        BitVector tmpChanges = 0xDEADBEEF;

        if((*cIt)->bvUncommittedChanges != NULL && pTmp != NULL)
        { 
            tmpChanges = *((*cIt)->bvUncommittedChanges); 
        }

        fprintf(stderr, 
                "CE : %u %u 0x%016"PRIx64" 0x%016"PRIx64" (%p|%p) | %s\n",
                (*cIt)->uiEntryDesc,
                (*cIt)->uiContainerId,
                tmpChanges,
                (*cIt)->whichField,
                (*cIt),
                (*cIt)->bvUncommittedChanges,
                szTmp.c_str());

        ++cIt;
    }

    cIt  = _workStore.begin();
    cEnd = _workStore.end  ();

    fprintf(stderr, "CL workstore dump\n");

    while(cIt != cEnd)
    {
        for(UInt32 i = 0; i < uiIndent + 4; ++i)
        {
            fprintf(stderr, " ");
        }

        FieldContainer *pTmp =
            FieldContainerFactory::the()->getContainer((*cIt)->uiContainerId);

        BitVector tmpChanges = 0xDEADBEEF;

        if((*cIt)->bvUncommittedChanges != NULL && pTmp != NULL)
        { 
            tmpChanges = *((*cIt)->bvUncommittedChanges); 
        }

        fprintf(stderr, "CE : %u %u 0x%016"PRIx64" 0x%016"PRIx64"\n",
                (*cIt)->uiEntryDesc,
                (*cIt)->uiContainerId,
                tmpChanges,
                (*cIt)->whichField);

        ++cIt;
    }
}
void ChangeList::doApply(bool bClear)
{
    if(_bReadOnly == true)
    {
        FWARNING(("Read-only changelist, can not apply\n"));
        return;
    }

#ifdef OSG_MT_CPTR_ASPECT
    FieldContainer      *pSrc  = NULL;
    FieldContainer      *pDst  = NULL;

    ChangedStoreConstIt  ccIt  = _createdStore.begin();
    ChangedStoreConstIt  ccEnd = _createdStore.end  ();


    while(ccIt != ccEnd)
    {
        AspectStoreP pHandler =
            FieldContainerFactory::the()->getContainerHandler(
                (*ccIt)->uiContainerId);

        if(pHandler == NULL)
        {
#ifndef SILENT_CPTR
            fprintf(stderr, "Strange handler nil %d %p\n", 
                    (*ccIt)->uiContainerId, 
                    pHandler);

#endif
            ++ccIt;
            continue;
        }

        pSrc = pHandler->getPtr(_uiAspect                 );
        pDst = pHandler->getPtr(Thread::getCurrentAspect());

        if(pSrc == NULL)
        {
#ifndef SILENT_CPTR
            fprintf(stderr, "Strange src nil %d %p\n", 
                    (*ccIt)->uiContainerId, 
                    pSrc);
            
#endif
            ++ccIt;
            continue;
        }

        if(pDst == NULL)
        {
            if(0x0000 == ((*ccIt)->whichField & FCLocal::MTMask))
            {
                pDst = pSrc->getType().createAspectCopy(pSrc,
                                                        (*ccIt)->uiContainerId);

                Thread::getCurrentChangeList()->addCreated(
                    (*ccIt)->uiContainerId, 
                    TypeTraits<BitVector>::BitsClear);

#ifndef SILENT_CPTR
                fprintf(stderr, "Setup store for %d %p \n",
                        (*ccIt)->uiContainerId,
                        pDst);
#endif

                if(pDst != NULL)
                    pDst->setupAspectStore(pHandler);
                
#ifndef SILENT_CPTR
                pHandler->dump();
#endif
            }
        }

        ++ccIt;
    }


    ChangedStoreIt      cIt  = _changedStore.begin();
    ChangedStoreConstIt cEnd = _changedStore.end  ();

#ifndef SILENT_CPTR
    fprintf(stderr, "CL apply %u -> %u\n",
            _uiAspect,
            Thread::getCurrentAspect());
#endif

    BitVector         syncMode = 0;

    AspectOffsetStore oOffsets;

    while(cIt != cEnd)
    {
        AspectStoreP pHandler =
            FieldContainerFactory::the()->getContainerHandler(
                (*cIt)->uiContainerId);

        if(pHandler == NULL)
        {
            ++cIt;
            continue;
        }

        pSrc = pHandler->getPtr(_uiAspect                 );
        pDst = pHandler->getPtr(Thread::getCurrentAspect());


#ifndef SILENT_CPTR
        fprintf(stderr, "process changes for %d %p %s %p %s\n",
                (*cIt)->uiContainerId,
                pSrc,
                pSrc != NULL ? pSrc->getType().getCName() : "null",
                pDst,
                pDst != NULL ? pDst->getType().getCName() : "null");
#endif

        if(pDst == NULL && 
           pSrc != NULL)
        {
            if((pSrc->getFieldFlags()->_bNamespaceMask & FCLocal::MTMask) != 
               TypeTraits<BitVector>::BitsClear             )
            {
                pDst = pSrc->getType().createAspectCopy(pSrc,
                                                        (*cIt)->uiContainerId);
            
                if(pDst != NULL) 
                {
                    Thread::getCurrentChangeList()->addCreated(
                        (*cIt)->uiContainerId, 
                        TypeTraits<BitVector>::BitsClear);

                    pDst->setupAspectStore(pHandler);
                }

#ifndef SILENT_CPTR
                pHandler->dump();
#endif
            }
            else
            {
                ++cIt;
                continue;
            }
        }

#ifndef SILENT_CPTR
        fprintf(stderr, "Xprocess changes for %d %p %s %p %s | %d %d %p\n",
                (*cIt)->uiContainerId,
                pSrc,
                pSrc != NULL ? pSrc->getType().getCName() : "null",
                pDst,
                pDst != NULL ? pDst->getType().getCName() : "null",
                _uiAspect,
                Thread::getCurrentAspect(),
                pHandler);
#endif

        if((*cIt)->uiEntryDesc == ContainerChangeEntry::Change)
        {
            if(pSrc != NULL && pDst != NULL) // be safe for now
            {
                BitVector mask = ((*cIt)->whichField & 
                                  pSrc->getFieldFlags()->_bThreadLocalFlags);

                if(mask != 0x0000)
                {
                    pHandler->fillOffsetArray(oOffsets, pDst);
                   
#ifndef SILENT_CPTR
                    for(UInt32 i = 0; i < ThreadManager::getNumAspects(); ++i)
                    {
                        fprintf(stderr, "offset %d %d\n", i, oOffsets[i]);
                    }
#endif
                    
                    UInt32 uiSInfo =
                        /*uiSyncInfo*/ 0 |
                        (_uiAspect << 24) |
                        (Thread::getCurrentAspect() << 16);
                    
                    pDst->execSyncV(*pSrc,
                                    mask,
                                    oOffsets,
                                    syncMode,
                                    uiSInfo);
                }
                
                if(bClear == true)
                {
                    pSrc->clearChangeEntry(*cIt);
                }
            }
        }
        else if((*cIt)->uiEntryDesc == ContainerChangeEntry::AddReference)
        {
#ifndef SILENT_CPTR
            fprintf(stderr, "Execute add Ref for %d %s\n",
                    (*cIt)->uiContainerId, pDst->getType().getCName());
#endif

            if(pDst != NULL)
                pDst->addReferenceRecorded();
        }
        else if((*cIt)->uiEntryDesc == ContainerChangeEntry::SubReference)// ||
//            (*cIt)->uiEntryDesc == ContainerChangeEntry::DepSubReference)
        {
#ifndef SILENT_CPTR
            fprintf(stderr, "Execute sub Ref for %d %s\n",
                    (*cIt)->uiContainerId, pDst->getType().getCName());
#endif
            
            if(pDst != NULL)
            {
                //pDst->subReferenceRecorded();
                this->addDelayedSubRef<RecordedRefCountPolicy>(pDst);
            }
        }

        ++cIt;
    }

    commitDelayedSubRefs();

    Thread::getCurrentChangeList()->commitDelayedSubRefs();
#endif
}