Esempio n. 1
0
bool InstanceCache::add( const ObjectVersion& rev, const uint32_t instanceID,
                         Command& command, const uint32_t usage )
{
#ifdef EQ_INSTRUMENT_CACHE
    ++nWrite;
#endif

    const NodeID nodeID = command.getNode()->getNodeID();

    base::ScopedMutex<> mutex( _items );
    ItemHash::const_iterator i = _items->find( rev.identifier );
    if( i == _items->end( ))
    {
        Item& item = _items.data[ rev.identifier ];
        item.data.masterInstanceID = instanceID;
        item.from = nodeID;
    }

    Item& item = _items.data[ rev.identifier ] ;
    if( item.data.masterInstanceID != instanceID || item.from != nodeID )
    {
        EQASSERT( !item.access ); // same master with different instance ID?!
        if( item.access != 0 ) // are accessed - don't add
            return false;
        // trash data from different master mapping
        _releaseStreams( item );
        item.data.masterInstanceID = instanceID;
        item.from = nodeID;
        item.used = usage;
    }
    else
        item.used = EQ_MAX( item.used, usage );

    if( item.data.versions.empty( ))
    {
        item.data.versions.push_back( new ObjectDataIStream ); 
        item.times.push_back( _clock.getTime64( ));
    }
    else if( item.data.versions.back()->getPendingVersion() == rev.version )
    {
        if( item.data.versions.back()->isReady( ))
        {
#ifdef EQ_INSTRUMENT_CACHE
            ++nWriteReady;
#endif
            return false; // Already have stream
        }
        // else append data to stream
    }
    else
    {
        const ObjectDataIStream* previous = item.data.versions.back();
        EQASSERT( previous->isReady( ));

        const uint128_t previousVersion = previous->getPendingVersion();
        if( previousVersion > rev.version )
        {
#ifdef EQ_INSTRUMENT_CACHE
            ++nWriteOld;
#endif
            return false;
        }
        if( ( previousVersion + 1 ) != rev.version ) // hole
        {
            EQASSERT( previousVersion < rev.version );

            if( item.access != 0 ) // are accessed - don't add
                return false;

            _releaseStreams( item );
        }
        else
        {
            EQASSERT( previous->isReady( ));
        }
        item.data.versions.push_back( new ObjectDataIStream ); 
        item.times.push_back( _clock.getTime64( ));
    }

    EQASSERT( !item.data.versions.empty( ));
    ObjectDataIStream* stream = item.data.versions.back();

    stream->addDataPacket( command );
    
    if( stream->isReady( ))
        _size += stream->getDataSize();

    _releaseItems( 1 );
    _releaseItems( 0 );

#ifdef EQ_INSTRUMENT_CACHE
    if( _items->find( rev.identifier ) != _items->end( ))
        ++nWriteHit;
    else
        ++nWriteMiss;
#endif
    return true;
}