Beispiel #1
0
/// Execute the async loading work.
void AsyncLoader::LoadWorker::Run()
{
	BufferedStream* pBufferedStream = new BufferedStream;
	HELIUM_ASSERT( pBufferedStream );

	while( m_stopCounter == 0 )
	{
		AtomicExchangeAcquire( m_processingCounter, 1 );

		Request* pRequest;
		{
			Locker< DynamicArray< Request* >, SpinLock >::Handle handle ( m_requestQueue );
			pRequest = handle->IsEmpty() ? NULL : handle->Pop();
		}
		if( !pRequest )
		{
			// Queue is empty, so sleep until notified.
			AtomicExchangeRelease( m_processingCounter, 0 );
			m_wakeUpCondition.Wait();

			continue;
		}

		HELIUM_ASSERT( pRequest );

		FileStream* pFileStream = FileStream::OpenFileStream( pRequest->fileName, FileStream::MODE_READ );
		if( !pFileStream )
		{
			SetInvalid( pRequest->bytesRead );
		}
		else
		{
			pRequest->bytesRead = 0;

			pBufferedStream->Open( pFileStream );
			int64_t offset = pBufferedStream->Seek( pRequest->offset, SeekOrigins::Begin );
			if( static_cast< uint64_t >( offset ) == pRequest->offset )
			{
				pRequest->bytesRead = pBufferedStream->Read( pRequest->pBuffer, 1, pRequest->size );
			}

			pBufferedStream->Open( NULL );

			delete pFileStream;
		}

		AtomicExchangeRelease( pRequest->processedCounter, 1 );

		Thread::Yield();
	}

	AtomicExchangeRelease( m_processingCounter, 0 );

	delete pBufferedStream;
}
Beispiel #2
0
Connection::Connection(Stream::ptr stream)
: m_stream(stream)
{
    MORDOR_ASSERT(stream);
    MORDOR_ASSERT(stream->supportsRead());
    MORDOR_ASSERT(stream->supportsWrite());
    if (!stream->supportsUnread() || !stream->supportsFind()) {
        BufferedStream *buffered = new BufferedStream(stream);
        buffered->allowPartialReads(true);
        m_stream.reset(buffered);
    }
}
Beispiel #3
0
/// Execute the async loading work.
void AsyncLoader::LoadWorker::Run()
{
    BufferedStream* pBufferedStream = new BufferedStream;
    HELIUM_ASSERT( pBufferedStream );

    while( m_stopCounter == 0 )
    {
        AtomicExchangeAcquire( m_processingCounter, 1 );

        Request* pRequest;
        if( !m_requestQueue.try_pop( pRequest ) )
        {
            // Queue is empty, so sleep until notified.
            AtomicExchangeRelease( m_processingCounter, 0 );
            m_wakeUpCondition.Wait();

            continue;
        }

        HELIUM_ASSERT( pRequest );

        FileStream* pFileStream = File::Open( pRequest->fileName, FileStream::MODE_READ );
        if( !pFileStream )
        {
            SetInvalid( pRequest->bytesRead );
        }
        else
        {
            pRequest->bytesRead = 0;

            pBufferedStream->Open( pFileStream );
            int64_t offset = pBufferedStream->Seek( pRequest->offset, SeekOrigins::SEEK_ORIGIN_BEGIN );
            if( static_cast< uint64_t >( offset ) == pRequest->offset )
            {
                pRequest->bytesRead = pBufferedStream->Read( pRequest->pBuffer, 1, pRequest->size );
            }

            pBufferedStream->Open( NULL );

            delete pFileStream;
        }

        AtomicExchangeRelease( pRequest->processedCounter, 1 );

        Thread::Yield();
    }

    AtomicExchangeRelease( m_processingCounter, 0 );

    delete pBufferedStream;
}
Beispiel #4
0
IContent* TextureReader::read(DataStream& stream)
{
   if ( !hasGraphicsDevice() )
   {
      return nullptr;
   }

   int width, height, format;
   stream >> width >> height >> format;

   BufferedStream datastream;
   stream.read(datastream);

   Graphics::TextureDescription desc;
   desc.width = width;
   desc.height = height;
   desc.format = Graphics::eFormat_BC3;
   desc.pinitData = datastream.getData();

   return getGraphicsDevice().createTexture(desc);
}
Beispiel #5
0
/// Add or update an entry in the cache.
///
/// @param[in] path          GameObject path.
/// @param[in] subDataIndex  Sub-data index associated with the cached data.
/// @param[in] pData         Data to cache.
/// @param[in] timestamp     Timestamp value to associate with the entry in the cache.
/// @param[in] size          Number of bytes to cache.
///
/// @return  True if the cache was updated successfully, false if not.
bool Cache::CacheEntry(
                       GameObjectPath path,
                       uint32_t subDataIndex,
                       const void* pData,
                       int64_t timestamp,
                       uint32_t size )
{
    HELIUM_ASSERT( pData || size == 0 );

	Status status;
	status.Read( m_cacheFileName.GetData() );
	int64_t cacheFileSize = status.m_Size;
    uint64_t entryOffset = ( cacheFileSize == -1 ? 0 : static_cast< uint64_t >( cacheFileSize ) );

    HELIUM_ASSERT( m_pEntryPool );
    Entry* pEntryUpdate = m_pEntryPool->Allocate();
    HELIUM_ASSERT( pEntryUpdate );
    pEntryUpdate->offset = entryOffset;
    pEntryUpdate->timestamp = timestamp;
    pEntryUpdate->path = path;
    pEntryUpdate->subDataIndex = subDataIndex;
    pEntryUpdate->size = size;

    uint64_t originalOffset = 0;
    int64_t originalTimestamp = 0;
    uint32_t originalSize = 0;

    EntryKey key;
    key.path = path;
    key.subDataIndex = subDataIndex;

    EntryMapType::Accessor entryAccessor;
    bool bNewEntry = m_entryMap.Insert( entryAccessor, KeyValue< EntryKey, Entry* >( key, pEntryUpdate ) );
    if( bNewEntry )
    {
        HELIUM_TRACE( TraceLevels::Info, TXT( "Cache: Adding \"%s\" to cache \"%s\".\n" ), *path.ToString(), *m_cacheFileName );

        m_entries.Push( pEntryUpdate );
    }
    else
    {
        HELIUM_TRACE( TraceLevels::Info, TXT( "Cache: Updating \"%s\" in cache \"%s\".\n" ), *path.ToString(), *m_cacheFileName );

        m_pEntryPool->Release( pEntryUpdate );

        pEntryUpdate = entryAccessor->Second();
        HELIUM_ASSERT( pEntryUpdate );

        originalOffset = pEntryUpdate->offset;
        originalTimestamp = pEntryUpdate->timestamp;
        originalSize = pEntryUpdate->size;

        if( originalSize < size )
        {
            pEntryUpdate->offset = entryOffset;
        }
        else
        {
            entryOffset = originalOffset;
        }

        pEntryUpdate->timestamp = timestamp;
        pEntryUpdate->size = size;
    }

    AsyncLoader& rLoader = AsyncLoader::GetStaticInstance();

    rLoader.Lock();

    bool bCacheSuccess = true;

    FileStream* pCacheStream = FileStream::OpenFileStream( m_cacheFileName, FileStream::MODE_WRITE, false );
    if( !pCacheStream )
    {
        HELIUM_TRACE( TraceLevels::Error, TXT( "Cache: Failed to open cache \"%s\" for writing.\n" ), *m_cacheFileName );

        bCacheSuccess = false;
    }
    else
    {
        HELIUM_TRACE(
            TraceLevels::Info,
            TXT( "Cache: Caching \"%s\" to \"%s\" (%" ) TPRIu32 TXT( " bytes @ offset %" ) TPRIu64 TXT( ").\n" ),
            *path.ToString(),
            *m_cacheFileName,
            size,
            entryOffset );

        uint64_t seekOffset = static_cast< uint64_t >( pCacheStream->Seek(
            static_cast< int64_t >( entryOffset ),
            SeekOrigins::SEEK_ORIGIN_BEGIN ) );
        if( seekOffset != entryOffset )
        {
            HELIUM_TRACE( TraceLevels::Error, TXT( "Cache: Cache file offset seek failed.\n" ) );

            if( bNewEntry )
            {
                m_entries.Pop();
                m_entryMap.Remove( entryAccessor );
                m_pEntryPool->Release( pEntryUpdate );
            }
            else
            {
                pEntryUpdate->offset = originalOffset;
                pEntryUpdate->timestamp = originalTimestamp;
                pEntryUpdate->size = originalSize;
            }

            bCacheSuccess = false;
        }
        else
        {
            size_t writeSize = pCacheStream->Write( pData, 1, size );
            if( writeSize != size )
            {
                HELIUM_TRACE(
                    TraceLevels::Error,
                    ( TXT( "Cache: Failed to write %" ) TPRIu32 TXT( " bytes to cache \"%s\" (%" ) TPRIuSZ
                    TXT( " bytes written).\n" ) ),
                    size,
                    *m_cacheFileName,
                    writeSize );

                if( bNewEntry )
                {
                    m_entries.Pop();
                    m_entryMap.Remove( entryAccessor );
                    m_pEntryPool->Release( pEntryUpdate );
                }
                else
                {
                    pEntryUpdate->offset = originalOffset;
                    pEntryUpdate->timestamp = originalTimestamp;
                    pEntryUpdate->size = originalSize;
                }

                bCacheSuccess = false;
            }
            else
            {
                HELIUM_TRACE( TraceLevels::Info, TXT( "Cache: Rewriting TOC file \"%s\".\n" ), *m_tocFileName );

                FileStream* pTocStream = FileStream::OpenFileStream( m_tocFileName, FileStream::MODE_WRITE, true );
                if( !pTocStream )
                {
                    HELIUM_TRACE( TraceLevels::Error, TXT( "Cache: Failed to open TOC \"%s\" for writing.\n" ), *m_tocFileName );
                }
                else
                {
                    BufferedStream* pBufferedStream = new BufferedStream( pTocStream );
                    HELIUM_ASSERT( pBufferedStream );

                    pBufferedStream->Write( &TOC_MAGIC, sizeof( TOC_MAGIC ), 1 );
                    pBufferedStream->Write( &sm_Version, sizeof( sm_Version ), 1 );

                    uint32_t entryCount = static_cast< uint32_t >( m_entries.GetSize() );
                    pBufferedStream->Write( &entryCount, sizeof( entryCount ), 1 );

                    String entryPath;
                    uint_fast32_t entryCountFast = entryCount;
                    for( uint_fast32_t entryIndex = 0; entryIndex < entryCountFast; ++entryIndex )
                    {
                        Entry* pEntry = m_entries[ entryIndex ];
                        HELIUM_ASSERT( pEntry );

                        pEntry->path.ToString( entryPath );
                        HELIUM_ASSERT( entryPath.GetSize() < UINT16_MAX );
                        uint16_t pathSize = static_cast< uint16_t >( entryPath.GetSize() );
                        pBufferedStream->Write( &pathSize, sizeof( pathSize ), 1 );

                        pBufferedStream->Write( *entryPath, sizeof( tchar_t ), pathSize );

                        pBufferedStream->Write( &pEntry->subDataIndex, sizeof( pEntry->subDataIndex ), 1 );

                        pBufferedStream->Write( &pEntry->offset, sizeof( pEntry->offset ), 1 );
                        pBufferedStream->Write( &pEntry->timestamp, sizeof( pEntry->timestamp ), 1 );
                        pBufferedStream->Write( &pEntry->size, sizeof( pEntry->size ), 1 );
                    }

                    delete pBufferedStream;
                    delete pTocStream;
                }
            }
        }

        delete pCacheStream;
    }

    rLoader.Unlock();

    return bCacheSuccess;
}